/* Licensed to the Apache Software Foundation (ASF) under one or more *contributorlicenseagreements.SeetheNOTICEfiledistributedwith *thisworkforadditionalinformationregardingcopyrightownership. *TheASFlicensesthisfiletoYouundertheApacheLicense,Version2.0 *(the"License");youmaynotusethisfileexceptincompliancewith *theLicense.YoumayobtainacopyoftheLicenseat * *http://www.apache.org/licenses/LICENSE-2.0 * *Unlessrequiredbyapplicablelaworagreedtoinwriting,software *distributedundertheLicenseisdistributedonan"ASIS"BASIS, *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. *SeetheLicenseforthespecificlanguagegoverningpermissionsand *limitationsundertheLicense.
*/
/* track pipe handles to close in child process */ typedefstruct read_handle_t { struct read_handle_t *next;
apr_file_t *handle;
} read_handle_t;
static read_handle_t *read_handles;
/** *@briefThepipedloggingstructure. * *Pipedlogsareusedtomovefunctionalityoutofthemainserver. *Forexample,logrotationisdonewithpipedlogs.
*/ struct piped_log { /** The pool to use for the piped log */
apr_pool_t *p; /** The pipe between the server and the logging process */
apr_file_t *read_fd, *write_fd; #ifdef AP_HAVE_RELIABLE_PIPED_LOGS /** The name of the program the logging process is running */ char *program; /** The pid of the logging process */
apr_proc_t *pid; /** How to reinvoke program when it must be replaced */
apr_cmdtype_e cmdtype; #endif
};
/* remember to close this handle in the child process * *OnWin32thismakeszerosense,becausewedon't *taketheparentprocess'schildprocs. *Ifthewin32parentinsteadpassedeachandevery *loggerwritehandlefromitselfdowntothechild, *andtheparentmanagesallaspectsofkeepingthe *reliablepipelogchildrenalive,thiswouldstill *makenosense:)CrippleitonWin32.
*/ staticvoid close_handle_in_child(apr_pool_t *p, apr_file_t *f)
{ #ifndef WIN32
read_handle_t *new_handle;
/* Create a child process running PROGNAME with a pipe connected to *thechild'sstdin.Thewrite-endofthepipewillbeplacedin **FPINonsuccessfulreturn.Ifdummy_stderrisnon-zero,the *stderrforthechildwillbethesameasthestdoutoftheparent.
* Otherwise the child will inherit the stderr from the parent. */ staticint log_child(apr_pool_t *p, constchar *progname,
apr_file_t **fpin, apr_cmdtype_e cmdtype, int dummy_stderr)
{ /* Child process code for 'ErrorLog "|..."'; *maywantacommonframeworkforthis,sinceIexpectitwill *becommonforotherfoo-loggerstowantthissortofthing...
*/
apr_status_t rc;
apr_procattr_t *procattr;
apr_proc_t *procnew;
apr_file_t *errfile;
if (rc == APR_SUCCESS) {
apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT);
(*fpin) = procnew->in; /* read handle to pipe not kept open, so no need to call *close_handle_in_child()
*/
}
}
return rc;
}
/* Open the error log for the given server_rec. If IS_MAIN is
* non-zero, s is the main server. */ staticint open_error_log(server_rec *s, int is_main, apr_pool_t *p)
{ constchar *fname; int rc;
/* In 2.4 favor PROGRAM_ENV, accept "||prog" syntax for compatibility *and"|$cmd"tooverridethedefault. *Any2.2backportwouldcontinuetofavorSHELLCMD_ENVsothere *accept"||prog"tooverride,and"|$cmd"toeaseconversion.
*/ if (*fname == '|')
++fname; if (*fname == '$') {
cmdtype = APR_SHELLCMD_ENV;
++fname;
}
/* Spawn a new child logger. If this is the main server_rec, *thenewchildmustuseadummystderrsincethecurrent *stderrmightbeapipetotheoldlogger.Otherwise,the
* child inherits the parents stderr. */
rc = log_child(p, fname, &dummy, cmdtype, is_main); if (rc != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_STARTUP, rc, ap_server_conf, APLOGNO(00089) "Couldn't start ErrorLog process '%s'.",
s->error_fname + 1); return DONE;
}
s->error_log = dummy;
}
#ifdef HAVE_SYSLOG elseif (strcmp(s->error_fname, "syslog") == 0
|| strncmp(s->error_fname, "syslog:", 7) == 0) { if ((fname = strchr(s->error_fname, ':'))) { /* s->error_fname could be [level]:[tag] (see #60525) */ constchar *tag;
apr_size_t flen; const TRANS *fac;
fname++;
tag = ap_strchr_c(fname, ':'); if (tag) {
flen = tag - fname;
tag++; if (*tag == '\0') {
tag = ap_server_argv0;
}
} else {
flen = strlen(fname);
tag = ap_server_argv0;
} if (flen == 0) { /* Was something like syslog::foobar */
openlog(tag, LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7);
} else { for (fac = facilities; fac->t_name; fac++) { if (!strncasecmp(fname, fac->t_name, flen)) {
openlog(tag, LOG_NDELAY|LOG_CONS|LOG_PID,
fac->t_val);
s->error_log = NULL; return OK;
}
} /* Huh? Invalid level name? */
ap_log_error(APLOG_MARK, APLOG_STARTUP, APR_EBADPATH, NULL, APLOGNO(10036) "%s: could not open syslog error log %s.",
ap_server_argv0, fname); return DONE;
}
} else {
openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7);
}
int ap_open_logs(apr_pool_t *pconf, apr_pool_t *p /* plog */,
apr_pool_t *ptemp, server_rec *s_main)
{
apr_pool_t *stderr_p;
server_rec *virt, *q; int replace_stderr;
/* Register to throw away the read_handles list when we *cleanupplog.Uponfork()fortheapachechildren, *thisread_handleslistisclosedsoonlytheparent *canrelaunchalostlogchild.Thesereadhandles *arealwaysclosedonexec. *Wewon'tcarewhathappenstoourstderrlogchild *betweenlogphases,sowedon'tmindlosingstderr's *read_handlealittlebitearly.
*/
apr_pool_cleanup_register(p, &read_handles, ap_pool_cleanup_set_null,
apr_pool_cleanup_null);
/* HERE we need a stdout log that outlives plog. *We*presume*theparentofplogisaprocess *orglobalpoolwhichspansserverrestarts. *Createourstderr_poolasachildoftheplog's *parentpool.
*/
apr_pool_create(&stderr_p, apr_pool_parent_get(p));
apr_pool_tag(stderr_p, "stderr_pool");
if (open_error_log(s_main, 1, stderr_p) != OK) { return DONE;
}
replace_stderr = 1; if (s_main->error_log) {
apr_status_t rv;
/* Replace existing stderr with new log. */
apr_file_flush(s_main->error_log);
rv = apr_file_dup2(stderr_log, s_main->error_log, stderr_p); if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s_main, APLOGNO(00092) "unable to replace stderr with error_log");
} else { /* We are done with stderr_pool, close it, killing *thepreviousgeneration'sstderrlogger
*/ if (stderr_pool)
apr_pool_destroy(stderr_pool);
stderr_pool = stderr_p;
replace_stderr = 0; /* *Nowthatwehavedup'eds_main->error_logtostderr_log *closeitandsets_main->error_logtostderr_log.Thisavoids *thisfdbeinginheritedbythenextpipedloggerwhowould *keepopenthewritingendofthepipethatthisoneuses *asstdin.Thisinturnwouldpreventthepipedloggerfrom *exiting.
*/
apr_file_close(s_main->error_log);
s_main->error_log = stderr_log;
}
} /* note that stderr may still need to be replaced with something *becauseitpointstotheolderrorlog,orbacktothetty *ofthesubmitter. *XXX:ThisisBS-/dev/nullisnon-portable *errno-as-apr_status_tisalsonon-portable
*/
/* In OSD/POSIX, the compiler returns for __FILE__ *astringlike:__FILE__="*POSIX(/usr/include/stdio.h)" *(itevenreturnsanabsolutepathforsourcesin *thecurrentdirectory).Herewetrytostripthis *downtothebasename.
*/ if (e != NULL && e[1] != '\0') {
apr_snprintf(tmp, sizeof(tmp), "%s", &e[1]);
e = &tmp[strlen(tmp)-1]; if (*e == ')') {
*e = '\0';
}
file = tmp;
} #else/* _OSD_POSIX || WIN32 */ constchar *p; /* On Unix, __FILE__ may be an absolute path in a
* VPATH build. */ if (file[0] == '/' && (p = ap_strrchr_c(file, '/')) != NULL) {
file = p + 1;
} #endif/*_OSD_POSIX || WIN32 */ return apr_snprintf(buf, buflen, "%s(%d)", file, info->line);
}
}
staticint log_apr_status(const ap_errorlog_info *info, constchar *arg, char *buf, int buflen)
{
apr_status_t status = info->status; int len; if (!status) return0;
if (status < APR_OS_START_EAIERR) {
len = apr_snprintf(buf, buflen, "(%d)", status);
} elseif (status < APR_OS_START_SYSERR) {
len = apr_snprintf(buf, buflen, "(EAI %d)",
status - APR_OS_START_EAIERR);
} elseif (status < 100000 + APR_OS_START_SYSERR) {
len = apr_snprintf(buf, buflen, "(OS %d)",
status - APR_OS_START_SYSERR);
} else {
len = apr_snprintf(buf, buflen, "(os 0x%08x)",
status - APR_OS_START_SYSERR);
}
apr_strerror(status, buf + len, buflen - len);
len += strlen(buf + len); return len;
}
staticint log_server_name(const ap_errorlog_info *info, constchar *arg, char *buf, int buflen)
{ if (info->r) return cpystrn(buf, ap_get_server_name((request_rec *)info->r), buflen);
return0;
}
staticint log_virtual_host(const ap_errorlog_info *info, constchar *arg, char *buf, int buflen)
{ if (info->s) return cpystrn(buf, info->s->server_hostname, buflen);
staticint log_header(const ap_errorlog_info *info, constchar *arg, char *buf, int buflen)
{ if (info->r) return log_table_entry(info->r->headers_in, arg, buf, buflen);
return0;
}
staticint log_note(const ap_errorlog_info *info, constchar *arg, char *buf, int buflen)
{ /* XXX: maybe escaping the entry is not necessary for notes? */ if (info->r) return log_table_entry(info->r->notes, arg, buf, buflen);
return0;
}
staticint log_env_var(const ap_errorlog_info *info, constchar *arg, char *buf, int buflen)
{ if (info->r) return log_table_entry(info->r->subprocess_env, arg, buf, buflen);
/* do we need to log once-per-req or once-per-conn info? */ int log_conn_info = 0, log_req_info = 0;
apr_array_header_t **lines = NULL; int done = 0; int line_number = 0;
if (r) {
AP_DEBUG_ASSERT(r->connection != NULL);
c = r->connection;
}
if (s == NULL) { /* *Ifwearedoingstderrlogging(startup),don'tlogmessagesthatare *abovethedefaultserverloglevelunlessitisastartup/shutdown *notice
*/ #ifndef DEBUG if ((level_and_mask != APLOG_NOTICE)
&& (level_and_mask > ap_default_loglevel)) { return;
} #endif
logf = stderr_log;
/* Use the main ErrorLogFormat if any */ if (ap_server_conf) {
sconf = ap_get_core_module_config(ap_server_conf->module_config);
}
} else { int configured_level = r ? ap_get_request_module_loglevel(r, module_index) :
c ? ap_get_conn_server_module_loglevel(c, s, module_index) :
ap_get_server_module_loglevel(s, module_index); if (s->error_log) { /* *Ifwearedoingnormallogging,don'tlogmessagesthatare *abovethemodule'sloglevelunlessitisastartup/shutdownnotice
*/ if ((level_and_mask != APLOG_NOTICE)
&& (level_and_mask > configured_level)) { return;
}
/* the faked server_rec from mod_cgid does not have s->module_config */ if (s->module_config) {
sconf = ap_get_core_module_config(s->module_config); if (c && !c->log_id) {
add_log_id(c, NULL); if (sconf->error_log_conn && sconf->error_log_conn->nelts > 0)
log_conn_info = 1;
} if (r) { if (r->main)
rmain = r->main; else
rmain = r;
if (!rmain->log_id) { /* XXX: do we need separate log ids for subrequests? */ if (sconf->error_log_req && sconf->error_log_req->nelts > 0)
log_req_info = 1; /* *XXX:potentialoptimization:onlycreatelogidif%Lis *XXX:actuallyused
*/
add_log_id(c, rmain);
}
}
} elseif (ap_server_conf) { /* Use the main ErrorLogFormat if any */
sconf = ap_get_core_module_config(ap_server_conf->module_config);
}
}
AP_DECLARE(void) ap_log_command_line(apr_pool_t *plog, server_rec *s)
{ int i;
process_rec *process = s->process; char *result; int len_needed = 0;
/* Piece together the command line from the pieces *inprocess->argv,withspacesinbetween.
*/ for (i = 0; i < process->argc; i++) {
len_needed += strlen(process->argv[i]) + 1;
}
result = (char *) apr_palloc(plog, len_needed);
*result = '\0';
for (i = 0; i < process->argc; i++) {
strcat(result, process->argv[i]); if ((i+1)< process->argc) {
strcat(result, " ");
}
}
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(00094) "Command line: '%s'", result);
}
/* grab bag function to log commonly logged and shared info */
AP_DECLARE(void) ap_log_mpm_common(server_rec *s)
{
ap_log_error(APLOG_MARK, APLOG_DEBUG , 0, s, APLOGNO(02639) "Using SO_REUSEPORT: %s (%d)",
ap_have_so_reuseport ? "yes" : "no",
ap_num_listen_buckets);
}
/* If we fill the buffer, we're probably reading a corrupt pid file.
* To be nice, let's also ensure the first char is a digit. */ if (bytes_read == 0 || bytes_read == BUFFER_SIZE - 1 || !apr_isdigit(*buf)) { return APR_EGENERAL;
}
switch (reason) { case APR_OC_REASON_DEATH: case APR_OC_REASON_LOST:
pl->pid = NULL; /* in case we don't get it going again, this *tellsotherlogicnottotrytokillit
*/
apr_proc_other_child_unregister(pl);
rv = ap_mpm_query(AP_MPMQ_MPM_STATE, &mpm_state); if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00105) "can't query MPM state; not restarting " "piped log program '%s'",
pl->program);
} elseif (mpm_state != AP_MPMQ_STOPPING) {
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00106) "piped log program '%s' failed unexpectedly",
pl->program); if ((rv = piped_log_spawn(pl)) != APR_SUCCESS) { /* what can we do? This could be the error log we're having
* problems opening up... */
ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, NULL, APLOGNO(00107) "piped_log_maintenance: unable to respawn '%s'",
pl->program);
}
} break;
case APR_OC_REASON_UNWRITABLE: /* We should not kill off the pipe here, since it may only be full.
* If it really is locked, we should kill it off manually. */ break;
case APR_OC_REASON_RESTART: if (pl->pid != NULL) {
apr_proc_kill(pl->pid, SIGTERM);
pl->pid = NULL;
} break;
AP_DECLARE(constchar *) ap_parse_log_level(constchar *str, int *val)
{ constchar *err = "Log level keyword must be one of emerg/alert/crit/error/" "warn/notice/info/debug/trace1/.../trace8"; int i = 0;
if (str == NULL) return err;
while (priorities[i].t_name != NULL) { if (!strcasecmp(str, priorities[i].t_name)) {
*val = priorities[i].t_val; return NULL;
}
i++;
} return err;
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.33Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.