blob: e3c558baac78446c8e6f2d2c6baf415ad6bfaf33 [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
static void mpxs_Apache2__Log_BOOT(pTHX)
{
av_push(get_av("Apache2::Log::Request::ISA", TRUE),
newSVpv("Apache2::Log", 12));
av_push(get_av("Apache2::Log::Server::ISA", TRUE),
newSVpv("Apache2::Log", 12));
}
#define croak_inval_obj() \
Perl_croak(aTHX_ "Argument is not an Apache2::RequestRec " \
"or Apache2::ServerRec object")
static void mpxs_ap_log_error(pTHX_ int level, SV *sv, SV *msg)
{
char *file = NULL;
int line = 0;
char *str;
SV *svstr = (SV *)NULL;
STRLEN n_a;
int lmask = level & APLOG_LEVELMASK;
server_rec *s;
request_rec *r = NULL;
if (SvROK(sv) && sv_isa(sv, "Apache2::Log::Request")) {
r = INT2PTR(request_rec *, SvObjIV(sv));
s = r->server;
}
else if (SvROK(sv) && sv_isa(sv, "Apache2::Log::Server")) {
s = INT2PTR(server_rec *, SvObjIV(sv));
}
else {
s = modperl_global_get_server_rec();
}
if ((lmask >= APLOG_DEBUG) && (mp_loglevel(s) >= APLOG_DEBUG)) {
COP *cop = PL_curcop;
file = CopFILE(cop); /* (caller)[1] */
line = CopLINE(cop); /* (caller)[2] */
}
if ((mp_loglevel(s) >= lmask) &&
SvROK(msg) && (SvTYPE(SvRV(msg)) == SVt_PVCV)) {
dSP;
ENTER;SAVETMPS;
PUSHMARK(sp);
(void)call_sv(msg, G_SCALAR);
SPAGAIN;
svstr = POPs;
(void)SvREFCNT_inc(svstr);
PUTBACK;
FREETMPS;LEAVE;
str = SvPV(svstr,n_a);
}
else {
str = SvPV(msg,n_a);
}
if (r) {
ap_log_rerror(file, line, mp_module_index_ level, 0, r,
"%s", str);
}
else {
ap_log_error(file, line, mp_module_index_ level, 0, s,
"%s", str);
}
if (svstr) {
SvREFCNT_dec(svstr);
}
}
#define MP_LOG_REQUEST 1
#define MP_LOG_SERVER 2
static SV *mpxs_Apache2__Log_log(pTHX_ SV *sv, int logtype)
{
SV *svretval;
void *retval;
char *pclass;
switch (logtype) {
case MP_LOG_REQUEST:
pclass = "Apache2::Log::Request";
retval = (void *)modperl_sv2request_rec(aTHX_ sv);
break;
case MP_LOG_SERVER:
pclass = "Apache2::Log::Server";
retval = (void *)modperl_sv2server_rec(aTHX_ sv);
break;
default:
croak_inval_obj();
};
svretval = newSV(0);
sv_setref_pv(svretval, pclass, (void*)retval);
return svretval;
}
#define mpxs_Apache2__RequestRec_log(sv) \
mpxs_Apache2__Log_log(aTHX_ sv, MP_LOG_REQUEST)
#define mpxs_Apache2__ServerRec_log(sv) \
mpxs_Apache2__Log_log(aTHX_ sv, MP_LOG_SERVER)
static MP_INLINE SV *modperl_perl_do_join(pTHX_ SV **mark, SV **sp)
{
SV *sv = newSV(0);
SV *delim;
#ifdef WIN32
/* XXX: using PL_sv_no crashes on win32 with 5.6.1 */
delim = newSVpv("", 0);
#else
delim = SvREFCNT_inc(&PL_sv_no);
#endif
do_join(sv, delim, mark, sp);
SvREFCNT_dec(delim);
return sv;
}
#define my_do_join(m, s) \
modperl_perl_do_join(aTHX_ (m), (s))
MP_STATIC XS(MPXS_Apache2__Log_dispatch)
{
dXSARGS;
SV *msgsv;
int level;
char *name = GvNAME(CvGV(cv));
if (items < 2) {
Perl_croak(aTHX_ "usage: %s::%s(obj, ...)",
mpxs_cv_name());
}
if (items > 2) {
msgsv = my_do_join(MARK+1, SP);
}
else {
msgsv = ST(1);
(void)SvREFCNT_inc(msgsv);
}
switch (*name) {
case 'e':
if (*(name + 1) == 'r') {
level = APLOG_ERR;
break;
}
level = APLOG_EMERG;
break;
case 'w':
level = APLOG_WARNING;
break;
case 'n':
level = APLOG_NOTICE;
break;
case 'i':
level = APLOG_INFO;
break;
case 'd':
level = APLOG_DEBUG;
break;
case 'a':
level = APLOG_ALERT;
break;
case 'c':
level = APLOG_CRIT;
break;
default:
level = APLOG_ERR; /* should never get here */
break;
};
mpxs_ap_log_error(aTHX_ level, ST(0), msgsv);
SvREFCNT_dec(msgsv);
XSRETURN_EMPTY;
}
MP_STATIC XS(MPXS_Apache2__Log_LOG_MARK)
{
dXSARGS;
ax = ax; /* -Wall */;
mpxs_PPCODE({
COP *cop = PL_curcop;
if (items) {
Perl_croak(aTHX_ "usage %s::%s()", mpxs_cv_name());
}
EXTEND(SP, 2);
PUSHs_mortal_pv(CopFILE(cop));
PUSHs_mortal_iv(CopLINE(cop));
});
}
MP_STATIC XS(MPXS_Apache2__Log_log_xerror)
{
dXSARGS;
SV *msgsv = (SV *)NULL;
STRLEN n_a;
request_rec *r = NULL;
server_rec *s = NULL;
char *msgstr;
const char *file;
int line, level;
apr_status_t status;
if (items < 6) {
Perl_croak(aTHX_ "usage %s::%s(file, line, level, status, ...)",
mpxs_cv_name());
}
switch (*(GvNAME(CvGV(cv)) + 4)) { /* 4 == log_ */
case 'r':
r = modperl_xs_sv2request_rec(aTHX_ ST(0), NULL, cv);
break;
case 's':
s = modperl_sv2server_rec(aTHX_ ST(0));
break;
default:
croak_inval_obj();
};
file = (const char *)SvPV(ST(1), n_a);
line = (int)SvIV(ST(2));
level = (int)SvIV(ST(3));
status = (apr_status_t)SvIV(ST(4));
if (items > 6) {
msgsv = my_do_join(MARK+5, SP);
}
else {
msgsv = ST(5);
(void)SvREFCNT_inc(msgsv);
}
msgstr = SvPV(msgsv, n_a);
if (r) {
ap_log_rerror(file, line, mp_module_index_ level, status, r,
"%s", msgstr);
}
else {
ap_log_error(file, line, mp_module_index_ level, status, s,
"%s", msgstr);
}
SvREFCNT_dec(msgsv);
XSRETURN_EMPTY;
}
/*
* this function handles:
* $r->log_error
* $s->log_error
* $r->warn
* $s->warn
* Apache2::ServerRec::warn
*/
MP_STATIC XS(MPXS_Apache2__Log_log_error)
{
dXSARGS;
request_rec *r = NULL;
server_rec *s = NULL;
int i = 0;
char *errstr = NULL;
SV *sv = (SV *)NULL;
STRLEN n_a;
if (items > 1) {
if (sv_isa(ST(0), "Apache2::ServerRec")) {
s = INT2PTR(server_rec *, SvObjIV(ST(0)));
}
else if ((r = modperl_xs_sv2request_rec(aTHX_ ST(0),
"Apache2::RequestRec", cv))) {
s = r->server;
}
}
if (s) {
i = 1;
}
else {
request_rec *r = NULL;
(void)modperl_tls_get_request_rec(&r);
if (r) {
s = r->server;
}
else {
s = modperl_global_get_server_rec();
}
}
if (items > 1+i) {
sv = my_do_join(MARK+i, SP); /* $sv = join '', @_[1..$#_] */
errstr = SvPV(sv,n_a);
}
else {
errstr = SvPV(ST(i),n_a);
}
switch (*GvNAME(CvGV(cv))) {
case 'w':
modperl_log_warn(s, errstr);
break;
default:
modperl_log_error(s, errstr);
break;
}
if (sv) {
SvREFCNT_dec(sv);
}
XSRETURN_EMPTY;
}
/*
* Local Variables:
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/