/* 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. */ #include "mod_perl.h" static const char *MP_error_strings[] = { "exit was called", /* MODPERL_RC_EXIT */ "filter handler has failed", /* MODPERL_FILTER_ERROR */ }; #define MP_error_strings_size \ sizeof(MP_error_strings) / sizeof(MP_error_strings[0]) char *modperl_error_strerror(pTHX_ apr_status_t rc) { char *ptr; char buf[256]; if (rc >= APR_OS_START_USERERR && rc < APR_OS_START_USERERR + MP_error_strings_size) { /* custom mod_perl errors */ ptr = (char*)MP_error_strings[(int)(rc - APR_OS_START_USERERR)]; } else { /* apache apr errors */ ptr = apr_strerror(rc, buf, sizeof(buf)); } /* must copy the string and not return a pointer to the local * address. Using a single (per interpreter) static buffer. */ return Perl_form(aTHX_ "%s", ptr ? ptr : "unknown error"); } /* modperl_croak notes: under -T we can't really do anything when die * was called in the stacked eval_sv (which is the case when a * response handler calls a filter handler and that filter calls die * ""). for example trying to require a file in modperl_croak(), will * cause 'panic: POPSTACK' and the process will exit. Dave fixed that * in perl Change 23209 by davem@davem-percy on 2004/08/09 19:48:57, * which will hopefully appear in perl 5.8.6. for now workaround this * perl bug by setting the taint mode off for the APR/Error loading. */ /* croak with $@ as a APR::Error object * rc - set to apr_status_t value * file - set to the callers filename * line - set to the callers line number * func - set to the function name */ void modperl_croak(pTHX_ apr_status_t rc, const char* func) { HV *stash; HV *data; int is_tainted = PL_tainted; /* see the explanation above */ if (is_tainted) { TAINT_NOT; } Perl_require_pv(aTHX_ "APR/Error.pm"); if (is_tainted) { TAINT; } if (SvTRUE(ERRSV)) { Perl_croak(aTHX_ "%s", SvPV_nolen(ERRSV)); } stash = gv_stashpvn("APR::Error", 10, FALSE); data = newHV(); /* $@ = bless {}, "APR::Error"; */ sv_setsv(ERRSV, sv_bless(newRV_noinc((SV*)data), stash)); sv_setiv(*hv_fetch(data, "rc", 2, 1), rc); sv_setpv(*hv_fetch(data, "file", 4, 1), CopFILE(PL_curcop)); sv_setiv(*hv_fetch(data, "line", 4, 1), CopLINE(PL_curcop)); sv_setpv(*hv_fetch(data, "func", 4, 1), func); Perl_croak(aTHX_ Nullch); }