]> granicus.if.org Git - apache/blob - server/log.c
5de7bb89fc2c9eb7c0bd25cf6fc7cf410573ea3d
[apache] / server / log.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * http_log.c: Dealing with the logs and errors
19  *
20  * Rob McCool
21  *
22  */
23
24 #include "apr.h"
25 #include "apr_general.h"        /* for signal stuff */
26 #include "apr_strings.h"
27 #include "apr_errno.h"
28 #include "apr_thread_proc.h"
29 #include "apr_lib.h"
30 #include "apr_signal.h"
31
32 #define APR_WANT_STDIO
33 #define APR_WANT_STRFUNC
34 #include "apr_want.h"
35
36 #if APR_HAVE_STDARG_H
37 #include <stdarg.h>
38 #endif
39 #if APR_HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #include "ap_config.h"
44 #include "httpd.h"
45 #include "http_config.h"
46 #include "http_core.h"
47 #include "http_log.h"
48 #include "http_main.h"
49 #include "util_time.h"
50 #include "ap_mpm.h"
51
52 typedef struct {
53     char    *t_name;
54     int      t_val;
55 } TRANS;
56
57 APR_HOOK_STRUCT(
58     APR_HOOK_LINK(error_log)
59 )
60
61 int AP_DECLARE_DATA ap_default_loglevel = DEFAULT_LOGLEVEL;
62
63 #ifdef HAVE_SYSLOG
64
65 static const TRANS facilities[] = {
66     {"auth",    LOG_AUTH},
67 #ifdef LOG_AUTHPRIV
68     {"authpriv",LOG_AUTHPRIV},
69 #endif
70 #ifdef LOG_CRON
71     {"cron",    LOG_CRON},
72 #endif
73 #ifdef LOG_DAEMON
74     {"daemon",  LOG_DAEMON},
75 #endif
76 #ifdef LOG_FTP
77     {"ftp", LOG_FTP},
78 #endif
79 #ifdef LOG_KERN
80     {"kern",    LOG_KERN},
81 #endif
82 #ifdef LOG_LPR
83     {"lpr", LOG_LPR},
84 #endif
85 #ifdef LOG_MAIL
86     {"mail",    LOG_MAIL},
87 #endif
88 #ifdef LOG_NEWS
89     {"news",    LOG_NEWS},
90 #endif
91 #ifdef LOG_SYSLOG
92     {"syslog",  LOG_SYSLOG},
93 #endif
94 #ifdef LOG_USER
95     {"user",    LOG_USER},
96 #endif
97 #ifdef LOG_UUCP
98     {"uucp",    LOG_UUCP},
99 #endif
100 #ifdef LOG_LOCAL0
101     {"local0",  LOG_LOCAL0},
102 #endif
103 #ifdef LOG_LOCAL1
104     {"local1",  LOG_LOCAL1},
105 #endif
106 #ifdef LOG_LOCAL2
107     {"local2",  LOG_LOCAL2},
108 #endif
109 #ifdef LOG_LOCAL3
110     {"local3",  LOG_LOCAL3},
111 #endif
112 #ifdef LOG_LOCAL4
113     {"local4",  LOG_LOCAL4},
114 #endif
115 #ifdef LOG_LOCAL5
116     {"local5",  LOG_LOCAL5},
117 #endif
118 #ifdef LOG_LOCAL6
119     {"local6",  LOG_LOCAL6},
120 #endif
121 #ifdef LOG_LOCAL7
122     {"local7",  LOG_LOCAL7},
123 #endif
124     {NULL,      -1},
125 };
126 #endif
127
128 static const TRANS priorities[] = {
129     {"emerg",   APLOG_EMERG},
130     {"alert",   APLOG_ALERT},
131     {"crit",    APLOG_CRIT},
132     {"error",   APLOG_ERR},
133     {"warn",    APLOG_WARNING},
134     {"notice",  APLOG_NOTICE},
135     {"info",    APLOG_INFO},
136     {"debug",   APLOG_DEBUG},
137     {NULL,      -1},
138 };
139
140 static apr_pool_t *stderr_pool = NULL;
141
142 static apr_file_t *stderr_log = NULL;
143
144 /* wrap a piped_log* with additional info
145  * about special stderr treatment used for main
146  * error logger */
147 typedef struct piped_log_wrapper {
148     piped_log *pl;
149     int special_stderr;
150 } piped_log_wrapper;
151
152 /* track pipe handles to close in child process */
153 typedef struct read_handle_t {
154     struct read_handle_t *next;
155     apr_file_t *handle;
156 } read_handle_t;
157
158 static read_handle_t *read_handles;
159
160 /* clear_handle_list() is called when plog is cleared; at that
161  * point we need to forget about our old list of pipe read
162  * handles.  We let the plog cleanups close the actual pipes.
163  */
164 static apr_status_t clear_handle_list(void *v)
165 {
166     read_handles = NULL;
167     return APR_SUCCESS;
168 }
169
170 /* remember to close this handle in the child process
171  *
172  * On Win32 this makes zero sense, because we don't
173  * take the parent process's child procs.
174  * If the win32 parent instead passed each and every
175  * logger write handle from itself down to the child,
176  * and the parent manages all aspects of keeping the 
177  * reliable pipe log children alive, this would still
178  * make no sense :)  Cripple it on Win32.
179  */
180 static void close_handle_in_child(apr_pool_t *p, apr_file_t *f)
181 {
182 #ifndef WIN32
183     read_handle_t *new_handle;
184
185     new_handle = apr_pcalloc(p, sizeof(read_handle_t));
186     new_handle->next = read_handles;
187     new_handle->handle = f;
188     read_handles = new_handle;
189 #endif
190 }
191
192 void ap_logs_child_init(apr_pool_t *p, server_rec *s)
193 {
194     read_handle_t *cur = read_handles;
195
196     while (cur) {
197         apr_file_close(cur->handle);
198         cur = cur->next;
199     }
200 }
201
202 AP_DECLARE(void) ap_open_stderr_log(apr_pool_t *p)
203 {
204     apr_file_open_stderr(&stderr_log, p);
205 }
206
207 AP_DECLARE(apr_status_t) ap_replace_stderr_log(apr_pool_t *p,
208                                                const char *fname)
209 {
210     apr_file_t *stderr_file;
211     apr_status_t rc;
212     char *filename = ap_server_root_relative(p, fname);
213     if (!filename) {
214         ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT,
215                      APR_EBADPATH, NULL, "Invalid -E error log file %s",
216                      fname);
217         return APR_EBADPATH;
218     }
219     if ((rc = apr_file_open(&stderr_file, filename,
220                             APR_APPEND | APR_WRITE | APR_CREATE | APR_LARGEFILE,
221                             APR_OS_DEFAULT, p)) != APR_SUCCESS) {
222         ap_log_error(APLOG_MARK, APLOG_STARTUP, rc, NULL,
223                      "%s: could not open error log file %s.",
224                      ap_server_argv0, fname);
225         return rc;
226     }
227     if (!stderr_pool) {
228         /* This is safe provided we revert it when we are finished.
229          * We don't manager the callers pool!
230          */
231         stderr_pool = p;
232     }
233     if ((rc = apr_file_open_stderr(&stderr_log, stderr_pool)) 
234             == APR_SUCCESS) {
235         apr_file_flush(stderr_log);
236         if ((rc = apr_file_dup2(stderr_log, stderr_file, stderr_pool)) 
237                 == APR_SUCCESS) {
238             apr_file_close(stderr_file);
239             /*
240              * You might ponder why stderr_pool should survive?
241              * The trouble is, stderr_pool may have s_main->error_log,
242              * so we aren't in a position to destory stderr_pool until
243              * the next recycle.  There's also an apparent bug which 
244              * is not; if some folk decided to call this function before 
245              * the core open error logs hook, this pool won't survive.
246              * Neither does the stderr logger, so this isn't a problem.
247              */
248         }
249     }
250     /* Revert, see above */
251     if (stderr_pool == p)
252         stderr_pool = NULL;
253
254     if (rc != APR_SUCCESS) {
255         ap_log_error(APLOG_MARK, APLOG_CRIT, rc, NULL,
256                      "unable to replace stderr with error log file");
257     }
258     return rc;
259 }
260
261 static void log_child_errfn(apr_pool_t *pool, apr_status_t err,
262                             const char *description)
263 {
264     ap_log_error(APLOG_MARK, APLOG_ERR, err, NULL,
265                  "%s", description);
266 }
267
268 #ifndef AP_HAVE_RELIABLE_PIPED_LOGS
269 /* Create a child process running PROGNAME with a pipe connected to
270  * the childs stdin.  The write-end of the pipe will be placed in
271  * *FPIN on successful return.  If dummy_stderr is non-zero, the
272  * stderr for the child will be the same as the stdout of the parent.
273  * Otherwise the child will inherit the stderr from the parent. */
274 static int log_child(apr_pool_t *p, const char *progname,
275                      apr_file_t **fpin, int dummy_stderr)
276 {
277     /* Child process code for 'ErrorLog "|..."';
278      * may want a common framework for this, since I expect it will
279      * be common for other foo-loggers to want this sort of thing...
280      */
281     apr_status_t rc;
282     apr_procattr_t *procattr;
283     apr_proc_t *procnew;
284     apr_file_t *errfile;
285
286     if (((rc = apr_procattr_create(&procattr, p)) == APR_SUCCESS)
287         && ((rc = apr_procattr_cmdtype_set(procattr,
288                                            APR_SHELLCMD_ENV)) == APR_SUCCESS)
289         && ((rc = apr_procattr_io_set(procattr,
290                                       APR_FULL_BLOCK,
291                                       APR_NO_PIPE,
292                                       APR_NO_PIPE)) == APR_SUCCESS)
293         && ((rc = apr_procattr_error_check_set(procattr, 1)) == APR_SUCCESS)
294         && ((rc = apr_procattr_child_errfn_set(procattr, log_child_errfn)) 
295                 == APR_SUCCESS)) {
296         char **args;
297         const char *pname;
298
299         apr_tokenize_to_argv(progname, &args, p);
300         pname = apr_pstrdup(p, args[0]);
301         procnew = (apr_proc_t *)apr_pcalloc(p, sizeof(*procnew));
302
303         if (dummy_stderr) {
304             if ((rc = apr_file_open_stdout(&errfile, p)) == APR_SUCCESS)
305                 rc = apr_procattr_child_err_set(procattr, errfile, NULL);
306         }
307
308         rc = apr_proc_create(procnew, pname, (const char * const *)args,
309                              NULL, procattr, p);
310
311         if (rc == APR_SUCCESS) {
312             apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT);
313             (*fpin) = procnew->in;
314             /* read handle to pipe not kept open, so no need to call
315              * close_handle_in_child()
316              */
317         }
318     }
319
320     return rc;
321 }
322 #endif
323
324 /* forward declaration */
325 static piped_log* piped_log_open(apr_pool_t *p, const char *program,
326                                  int special_stderr);
327
328 /* Open the error log for the given server_rec.  If IS_MAIN is
329  * non-zero, s is the main server. */
330 static int open_error_log(server_rec *s, int is_main, apr_pool_t *p)
331 {
332     const char *fname;
333     int rc;
334
335     if (*s->error_fname == '|') {
336         piped_log *pl;
337         fname = ap_server_root_relative(p, s->error_fname + 1);
338
339         if (!fname) {
340             ap_log_error(APLOG_MARK, APLOG_STARTUP, APR_EBADPATH, NULL,
341                          "%s: Invalid error log path '%s'.",
342                          ap_server_argv0, s->error_fname);
343             return NULL;
344         }
345
346         /* Spawn a new child logger.  If this is the main server_rec,
347          * the new child must use a dummy stderr since the current
348          * stderr might be a pipe to the old logger.  Otherwise, the
349          * child inherits the parents stderr. */
350         pl = piped_log_open(p, fname, is_main);
351         if (pl == NULL) {
352             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
353                          "%s: Couldn't start ErrorLog process '%s'.",
354                          ap_server_argv0, fname);
355             return DONE;
356         }
357         s->error_log = ap_piped_log_write_fd(pl);
358     }
359
360 #ifdef HAVE_SYSLOG
361     else if (!strncasecmp(s->error_fname, "syslog", 6)) {
362         if ((fname = strchr(s->error_fname, ':'))) {
363             const TRANS *fac;
364
365             fname++;
366             for (fac = facilities; fac->t_name; fac++) {
367                 if (!strcasecmp(fname, fac->t_name)) {
368                     openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID,
369                             fac->t_val);
370                     s->error_log = NULL;
371                     return OK;
372                 }
373             }
374         }
375         else {
376             openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7);
377         }
378
379         s->error_log = NULL;
380     }
381 #endif
382     else {
383         fname = ap_server_root_relative(p, s->error_fname);
384         if (!fname) {
385             ap_log_error(APLOG_MARK, APLOG_STARTUP, APR_EBADPATH, NULL,
386                          "%s: Invalid error log path '%s'.",
387                          ap_server_argv0, s->error_fname);
388             return DONE;
389         }
390         if ((rc = apr_file_open(&s->error_log, fname,
391                                APR_APPEND | APR_WRITE | APR_CREATE | APR_LARGEFILE,
392                                APR_OS_DEFAULT, p)) != APR_SUCCESS) {
393             ap_log_error(APLOG_MARK, APLOG_STARTUP, rc, NULL,
394                          "%s: could not open error log file '%s'.",
395                          ap_server_argv0, fname);
396             return DONE;
397         }
398     }
399
400     return OK;
401 }
402
403 int ap_open_logs(apr_pool_t *pconf, apr_pool_t *p /* plog */,
404                  apr_pool_t *ptemp, server_rec *s_main)
405 {
406     apr_pool_t *stderr_p;
407     server_rec *virt, *q;
408     int replace_stderr;
409
410
411     /* Register to throw away the read_handles list when we
412      * cleanup plog.  Upon fork() for the apache children,
413      * this read_handles list is closed so only the parent
414      * can relaunch a lost log child.  These read handles 
415      * are always closed on exec.
416      * We won't care what happens to our stderr log child 
417      * between log phases, so we don't mind losing stderr's 
418      * read_handle a little bit early.
419      */
420     apr_pool_cleanup_register(p, NULL, clear_handle_list,
421                               apr_pool_cleanup_null);
422
423     /* HERE we need a stdout log that outlives plog.
424      * We *presume* the parent of plog is a process 
425      * or global pool which spans server restarts.
426      * Create our stderr_pool as a child of the plog's
427      * parent pool.
428      */
429     apr_pool_create(&stderr_p, apr_pool_parent_get(p));
430     apr_pool_tag(stderr_p, "stderr_pool");
431
432     if (open_error_log(s_main, 1, stderr_p) != OK) {
433         return DONE;
434     }
435
436     replace_stderr = 1;
437     if (s_main->error_log) {
438         apr_status_t rv;
439
440         /* Replace existing stderr with new log. */
441         apr_file_flush(s_main->error_log);
442         rv = apr_file_dup2(stderr_log, s_main->error_log, stderr_p);
443         if (rv != APR_SUCCESS) {
444             ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s_main,
445                          "unable to replace stderr with error_log");
446         }
447         else {
448             /* We are done with stderr_pool, close it, killing
449              * the previous generation's stderr logger
450              */
451             if (stderr_pool)
452                 apr_pool_destroy(stderr_pool);
453             stderr_pool = stderr_p;
454             replace_stderr = 0;
455             /*
456              * Now that we have dup'ed s_main->error_log to stderr_log
457              * close it and set s_main->error_log to stderr_log. This avoids
458              * this fd being inherited by the next piped logger who would
459              * keep open the writing end of the pipe that this one uses
460              * as stdin. This in turn would prevent the piped logger from
461              * exiting.
462              */
463              apr_file_close(s_main->error_log);
464              s_main->error_log = stderr_log;
465         }
466     }
467     /* note that stderr may still need to be replaced with something
468      * because it points to the old error log, or back to the tty
469      * of the submitter.
470      * XXX: This is BS - /dev/null is non-portable
471      */
472     if (replace_stderr && freopen("/dev/null", "w", stderr) == NULL) {
473         ap_log_error(APLOG_MARK, APLOG_CRIT, errno, s_main,
474                      "unable to replace stderr with /dev/null");
475     }
476
477     for (virt = s_main->next; virt; virt = virt->next) {
478         if (virt->error_fname) {
479             for (q=s_main; q != virt; q = q->next) {
480                 if (q->error_fname != NULL
481                     && strcmp(q->error_fname, virt->error_fname) == 0) {
482                     break;
483                 }
484             }
485
486             if (q == virt) {
487                 if (open_error_log(virt, 0, p) != OK) {
488                     return DONE;
489                 }
490             }
491             else {
492                 virt->error_log = q->error_log;
493             }
494         }
495         else {
496             virt->error_log = s_main->error_log;
497         }
498     }
499     return OK;
500 }
501
502 AP_DECLARE(void) ap_error_log2stderr(server_rec *s) {
503     apr_file_t *errfile = NULL;
504
505     apr_file_open_stderr(&errfile, s->process->pool);
506     if (s->error_log != NULL) {
507         apr_file_dup2(s->error_log, errfile, s->process->pool);
508     }
509 }
510
511 static void log_error_core(const char *file, int line, int level,
512                            apr_status_t status, const server_rec *s,
513                            const conn_rec *c,
514                            const request_rec *r, apr_pool_t *pool,
515                            const char *fmt, va_list args)
516 {
517     char errstr[MAX_STRING_LEN];
518 #ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
519     char scratch[MAX_STRING_LEN];
520 #endif
521     apr_size_t len, errstrlen;
522     apr_file_t *logf = NULL;
523     const char *referer;
524     int level_and_mask = level & APLOG_LEVELMASK;
525
526     if (r && r->connection) {
527         c = r->connection;
528     }
529
530     if (s == NULL) {
531         /*
532          * If we are doing stderr logging (startup), don't log messages that are
533          * above the default server log level unless it is a startup/shutdown
534          * notice
535          */
536 #ifndef DEBUG
537         if ((level_and_mask != APLOG_NOTICE)
538             && (level_and_mask > ap_default_loglevel)) {
539             return;
540         }
541 #endif
542
543         logf = stderr_log;
544     }
545     else if (s->error_log) {
546         /*
547          * If we are doing normal logging, don't log messages that are
548          * above the server log level unless it is a startup/shutdown notice
549          */
550         if ((level_and_mask != APLOG_NOTICE)
551             && (level_and_mask > s->loglevel)) {
552             return;
553         }
554
555         logf = s->error_log;
556     }
557 #ifdef TPF
558     else if (tpf_child) {
559         /*
560          * If we are doing normal logging, don't log messages that are
561          * above the server log level unless it is a startup/shutdown notice
562          */
563         if ((level_and_mask != APLOG_NOTICE)
564             && (level_and_mask > s->loglevel)) {
565             return;
566         }
567
568         logf = stderr;
569     }
570 #endif /* TPF */
571     else {
572         /*
573          * If we are doing syslog logging, don't log messages that are
574          * above the server log level (including a startup/shutdown notice)
575          */
576         if (level_and_mask > s->loglevel) {
577             return;
578         }
579     }
580
581     if (logf && ((level & APLOG_STARTUP) != APLOG_STARTUP)) {
582         errstr[0] = '[';
583         ap_recent_ctime(errstr + 1, apr_time_now());
584         errstr[1 + APR_CTIME_LEN - 1] = ']';
585         errstr[1 + APR_CTIME_LEN    ] = ' ';
586         len = 1 + APR_CTIME_LEN + 1;
587     } else {
588         len = 0;
589     }
590
591     if ((level & APLOG_STARTUP) != APLOG_STARTUP) {
592         len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
593                             "[%s] ", priorities[level_and_mask].t_name);
594     }
595
596 #ifndef TPF
597     if (file && level_and_mask == APLOG_DEBUG) {
598 #if defined(_OSD_POSIX) || defined(WIN32) || defined(__MVS__)
599         char tmp[256];
600         char *e = strrchr(file, '/');
601 #ifdef WIN32
602         if (!e) {
603             e = strrchr(file, '\\');
604         }
605 #endif
606
607         /* In OSD/POSIX, the compiler returns for __FILE__
608          * a string like: __FILE__="*POSIX(/usr/include/stdio.h)"
609          * (it even returns an absolute path for sources in
610          * the current directory). Here we try to strip this
611          * down to the basename.
612          */
613         if (e != NULL && e[1] != '\0') {
614             apr_snprintf(tmp, sizeof(tmp), "%s", &e[1]);
615             e = &tmp[strlen(tmp)-1];
616             if (*e == ')') {
617                 *e = '\0';
618             }
619             file = tmp;
620         }
621 #else /* _OSD_POSIX || WIN32 */
622         const char *p;
623         /* On Unix, __FILE__ may be an absolute path in a
624          * VPATH build. */
625         if (file[0] == '/' && (p = ap_strrchr_c(file, '/')) != NULL) {
626             file = p + 1;
627         }
628 #endif /*_OSD_POSIX || WIN32 */
629         len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
630                             "%s(%d): ", file, line);
631     }
632 #endif /* TPF */
633
634     if (c) {
635         /* XXX: TODO: add a method of selecting whether logged client
636          * addresses are in dotted quad or resolved form... dotted
637          * quad is the most secure, which is why I'm implementing it
638          * first. -djg
639          */
640         len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
641                             "[client %s] ", c->remote_ip);
642     }
643     if (status != 0) {
644         if (status < APR_OS_START_EAIERR) {
645             len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
646                                 "(%d)", status);
647         }
648         else if (status < APR_OS_START_SYSERR) {
649             len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
650                                 "(EAI %d)", status - APR_OS_START_EAIERR);
651         }
652         else if (status < 100000 + APR_OS_START_SYSERR) {
653             len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
654                                 "(OS %d)", status - APR_OS_START_SYSERR);
655         }
656         else {
657             len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
658                                 "(os 0x%08x)", status - APR_OS_START_SYSERR);
659         }
660         apr_strerror(status, errstr + len, MAX_STRING_LEN - len);
661         len += strlen(errstr + len);
662         if (MAX_STRING_LEN - len > 2) {
663             errstr[len++] = ':';
664             errstr[len++] = ' ';
665             errstr[len] = '\0';
666         }
667     }
668
669     errstrlen = len;
670 #ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
671     if (apr_vsnprintf(scratch, MAX_STRING_LEN - len, fmt, args)) {
672         len += ap_escape_errorlog_item(errstr + len, scratch,
673                                        MAX_STRING_LEN - len);
674     }
675 #else
676     len += apr_vsnprintf(errstr + len, MAX_STRING_LEN - len, fmt, args);
677 #endif
678
679     if (   r && (referer = apr_table_get(r->headers_in, "Referer"))
680 #ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
681         && ap_escape_errorlog_item(scratch, referer, MAX_STRING_LEN - len)
682 #endif
683         ) {
684         len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
685                             ", referer: %s",
686 #ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
687                             scratch
688 #else
689                             referer
690 #endif
691                             );
692     }
693
694     /* NULL if we are logging to syslog */
695     if (logf) {
696         /* Truncate for the terminator (as apr_snprintf does) */
697         if (len > MAX_STRING_LEN - sizeof(APR_EOL_STR)) {
698             len = MAX_STRING_LEN - sizeof(APR_EOL_STR);
699         }
700         strcpy(errstr + len, APR_EOL_STR);
701         apr_file_puts(errstr, logf);
702         apr_file_flush(logf);
703     }
704 #ifdef HAVE_SYSLOG
705     else {
706         syslog(level_and_mask, "%s", errstr);
707     }
708 #endif
709
710     ap_run_error_log(file, line, level, status, s, r, pool, errstr + errstrlen);
711 }
712
713 AP_DECLARE(void) ap_log_error(const char *file, int line, int level,
714                               apr_status_t status, const server_rec *s,
715                               const char *fmt, ...)
716 {
717     va_list args;
718
719     va_start(args, fmt);
720     log_error_core(file, line, level, status, s, NULL, NULL, NULL, fmt, args);
721     va_end(args);
722 }
723
724 AP_DECLARE(void) ap_log_perror(const char *file, int line, int level,
725                                apr_status_t status, apr_pool_t *p,
726                                const char *fmt, ...)
727 {
728     va_list args;
729
730     va_start(args, fmt);
731     log_error_core(file, line, level, status, NULL, NULL, NULL, p, fmt, args);
732     va_end(args);
733 }
734
735 AP_DECLARE(void) ap_log_rerror(const char *file, int line, int level,
736                                apr_status_t status, const request_rec *r,
737                                const char *fmt, ...)
738 {
739     va_list args;
740
741     va_start(args, fmt);
742     log_error_core(file, line, level, status, r->server, NULL, r, NULL, fmt,
743                    args);
744
745     /*
746      * IF APLOG_TOCLIENT is set,
747      * AND the error level is 'warning' or more severe,
748      * AND there isn't already error text associated with this request,
749      * THEN make the message text available to ErrorDocument and
750      * other error processors.
751      */
752     va_end(args);
753     va_start(args,fmt);
754     if ((level & APLOG_TOCLIENT)
755         && ((level & APLOG_LEVELMASK) <= APLOG_WARNING)
756         && (apr_table_get(r->notes, "error-notes") == NULL)) {
757         apr_table_setn(r->notes, "error-notes",
758                        ap_escape_html(r->pool, apr_pvsprintf(r->pool, fmt,
759                                                              args)));
760     }
761     va_end(args);
762 }
763
764 AP_DECLARE(void) ap_log_cerror(const char *file, int line, int level,
765                                apr_status_t status, const conn_rec *c,
766                                const char *fmt, ...)
767 {
768     va_list args;
769
770     va_start(args, fmt);
771     log_error_core(file, line, level, status, c->base_server, c, NULL, NULL,
772                    fmt, args);
773     va_end(args);
774 }
775
776 AP_DECLARE(void) ap_log_pid(apr_pool_t *p, const char *filename)
777 {
778     apr_file_t *pid_file = NULL;
779     apr_finfo_t finfo;
780     static pid_t saved_pid = -1;
781     pid_t mypid;
782     apr_status_t rv;
783     const char *fname;
784
785     if (!filename) {
786         return;
787     }
788
789     fname = ap_server_root_relative(p, filename);
790     if (!fname) {
791         ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, APR_EBADPATH,
792                      NULL, "Invalid PID file path %s, ignoring.", filename);
793         return;
794     }
795
796     mypid = getpid();
797     if (mypid != saved_pid
798         && apr_stat(&finfo, fname, APR_FINFO_MTIME, p) == APR_SUCCESS) {
799         /* AP_SIG_GRACEFUL and HUP call this on each restart.
800          * Only warn on first time through for this pid.
801          *
802          * XXX: Could just write first time through too, although
803          *      that may screw up scripts written to do something
804          *      based on the last modification time of the pid file.
805          */
806         ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, p,
807                       "pid file %s overwritten -- Unclean "
808                       "shutdown of previous Apache run?",
809                       fname);
810     }
811
812     if ((rv = apr_file_open(&pid_file, fname,
813                             APR_WRITE | APR_CREATE | APR_TRUNCATE,
814                             APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD, p))
815         != APR_SUCCESS) {
816         ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
817                      "could not create %s", fname);
818         ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
819                      "%s: could not log pid to file %s",
820                      ap_server_argv0, fname);
821         exit(1);
822     }
823     apr_file_printf(pid_file, "%ld" APR_EOL_STR, (long)mypid);
824     apr_file_close(pid_file);
825     saved_pid = mypid;
826 }
827
828 AP_DECLARE(apr_status_t) ap_read_pid(apr_pool_t *p, const char *filename,
829                                      pid_t *mypid)
830 {
831     const apr_size_t BUFFER_SIZE = sizeof(long) * 3 + 2; /* see apr_ltoa */
832     apr_file_t *pid_file = NULL;
833     apr_status_t rv;
834     const char *fname;
835     char *buf, *endptr;
836     apr_size_t bytes_read;
837
838     if (!filename) {
839         return APR_EGENERAL;
840     }
841
842     fname = ap_server_root_relative(p, filename);
843     if (!fname) {
844         ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, APR_EBADPATH,
845                      NULL, "Invalid PID file path %s, ignoring.", filename);
846         return APR_EGENERAL;
847     }
848
849     rv = apr_file_open(&pid_file, fname, APR_READ, APR_OS_DEFAULT, p);
850     if (rv != APR_SUCCESS) {
851         return rv;
852     }
853
854     buf = apr_palloc(p, BUFFER_SIZE);
855
856     rv = apr_file_read_full(pid_file, buf, BUFFER_SIZE - 1, &bytes_read);
857     if (rv != APR_SUCCESS && rv != APR_EOF) {
858         return rv;
859     }
860
861     /* If we fill the buffer, we're probably reading a corrupt pid file.
862      * To be nice, let's also ensure the first char is a digit. */
863     if (bytes_read == 0 || bytes_read == BUFFER_SIZE - 1 || !apr_isdigit(*buf)) {
864         return APR_EGENERAL;
865     }
866
867     buf[bytes_read] = '\0';
868     *mypid = strtol(buf, &endptr, 10);
869
870     apr_file_close(pid_file);
871     return APR_SUCCESS;
872 }
873
874 AP_DECLARE(void) ap_log_assert(const char *szExp, const char *szFile,
875                                int nLine)
876 {
877     char time_str[APR_CTIME_LEN];
878
879     apr_ctime(time_str, apr_time_now());
880     ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL,
881                  "[%s] file %s, line %d, assertion \"%s\" failed",
882                  time_str, szFile, nLine, szExp);
883 #if defined(WIN32)
884     DebugBreak();
885 #else
886     /* unix assert does an abort leading to a core dump */
887     abort();
888 #endif
889 }
890
891 /* piped log support */
892
893 AP_DECLARE(piped_log *) ap_open_piped_log(apr_pool_t *p, const char *program)
894 {
895    return piped_log_open(p, program, 0);
896 }
897
898 #ifdef AP_HAVE_RELIABLE_PIPED_LOGS
899 /* forward declaration */
900 static void piped_log_maintenance(int reason, void *data, apr_wait_t status);
901
902 /* Spawn the piped logger process pl->program. */
903 static apr_status_t piped_log_spawn(piped_log_wrapper *plw)
904 {
905     apr_procattr_t *procattr;
906     apr_proc_t *procnew = NULL;
907     apr_file_t *errfile;
908     apr_status_t status;
909     piped_log *pl = plw->pl;
910
911     if (((status = apr_procattr_create(&procattr, pl->p)) != APR_SUCCESS) ||
912         ((status = apr_procattr_cmdtype_set(procattr,
913                                             APR_SHELLCMD_ENV)) != APR_SUCCESS) ||
914         ((status = apr_procattr_child_in_set(procattr,
915                                              ap_piped_log_read_fd(pl),
916                                              ap_piped_log_write_fd(pl)))
917         != APR_SUCCESS) ||
918         /* If special_stderr is non-zero, the stderr for the child will
919          * be the same as the stdout of the parent. Otherwise the child
920          * will inherit the stderr from the parent. */
921         (plw->special_stderr && (status = apr_file_open_stdout(&errfile, pl->p))
922          != APR_SUCCESS) ||
923         (plw->special_stderr && (status = apr_procattr_child_err_set(procattr,
924                                                                      errfile, NULL))
925          != APR_SUCCESS) ||
926         ((status = apr_procattr_child_errfn_set(procattr, log_child_errfn))
927          != APR_SUCCESS) ||
928         ((status = apr_procattr_error_check_set(procattr, 1)) != APR_SUCCESS)) {
929         char buf[120];
930         /* Something bad happened, give up and go away. */
931         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
932                      "piped_log_spawn: unable to setup child process '%s': %s",
933                      pl->program, apr_strerror(status, buf, sizeof(buf)));
934     }
935
936     else {
937         char **args;
938         const char *pname;
939
940         apr_tokenize_to_argv(pl->program, &args, pl->p);
941         pname = apr_pstrdup(pl->p, args[0]);
942         procnew = apr_pcalloc(pl->p, sizeof(apr_proc_t));
943         status = apr_proc_create(procnew, pname, (const char * const *) args,
944                                  NULL, procattr, pl->p);
945
946         if (status == APR_SUCCESS) {
947             pl->pid = procnew;
948             /* procnew->in was dup2'd from ap_piped_log_write_fd(pl);
949              * since the original fd is still valid, close the copy to
950              * avoid a leak. */
951             apr_file_close(procnew->in);
952             procnew->in = NULL;
953             apr_proc_other_child_register(procnew, piped_log_maintenance, plw,
954                                           ap_piped_log_write_fd(pl), pl->p);
955             close_handle_in_child(pl->p, ap_piped_log_read_fd(pl));
956         }
957         else {
958             char buf[120];
959             /* Something bad happened, give up and go away. */
960             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
961                          "unable to start piped log program '%s': %s",
962                          pl->program, apr_strerror(status, buf, sizeof(buf)));
963         }
964     }
965
966     return status;
967 }
968
969
970 static void piped_log_maintenance(int reason, void *data, apr_wait_t status)
971 {
972     piped_log_wrapper *plw = data;
973     piped_log *pl = plw->pl;
974     apr_status_t stats;
975     int mpm_state;
976
977     switch (reason) {
978     case APR_OC_REASON_DEATH:
979     case APR_OC_REASON_LOST:
980         pl->pid = NULL; /* in case we don't get it going again, this
981                          * tells other logic not to try to kill it
982                          */
983         apr_proc_other_child_unregister(plw);
984         stats = ap_mpm_query(AP_MPMQ_MPM_STATE, &mpm_state);
985         if (stats != APR_SUCCESS) {
986             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
987                          "can't query MPM state; not restarting "
988                          "piped log program '%s'",
989                          pl->program);
990         }
991         else if (mpm_state != AP_MPMQ_STOPPING) {
992             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
993                          "piped log program '%s' failed unexpectedly",
994                          pl->program);
995
996             /* If special_stderr is non-zero, we need to get the write
997              * end of the pipe back from stderr before spawning. */
998             if ((plw->special_stderr && (stats = apr_file_dup(&ap_piped_log_write_fd(pl),
999                                                               stderr_log, pl->p))
1000                 != APR_SUCCESS) ||
1001                ((stats = piped_log_spawn(plw)) != APR_SUCCESS) ||
1002             /* If special_stderr is non-zero, we need to close the write
1003              * end of the pipe after spawning, because we write to it via
1004              * stderr. */
1005                (plw->special_stderr && (stats = apr_file_close(ap_piped_log_write_fd(pl)))
1006                 != APR_SUCCESS)) {
1007
1008                 char buf[120];
1009
1010                 /* what can we do?  This could be the error log we're having
1011                  * problems opening up... */
1012                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1013                              "piped_log_maintenance: unable to respawn '%s': %s",
1014                          pl->program, apr_strerror(stats, buf, sizeof(buf)));
1015             }
1016         }
1017         break;
1018
1019     case APR_OC_REASON_UNWRITABLE:
1020         /* We should not kill off the pipe here, since it may only be full.
1021          * If it really is locked, we should kill it off manually. */
1022     break;
1023
1024     case APR_OC_REASON_RESTART:
1025         if (pl->pid != NULL) {
1026             apr_proc_kill(pl->pid, SIGTERM);
1027             pl->pid = NULL;
1028         }
1029         break;
1030
1031     case APR_OC_REASON_UNREGISTER:
1032         break;
1033     }
1034 }
1035
1036
1037 static apr_status_t piped_log_cleanup_for_exec(void *data)
1038 {
1039     piped_log *pl = data;
1040
1041     apr_file_close(ap_piped_log_read_fd(pl));
1042     apr_file_close(ap_piped_log_write_fd(pl));
1043     return APR_SUCCESS;
1044 }
1045
1046
1047 static apr_status_t piped_log_cleanup(void *data)
1048 {
1049     piped_log *pl = data;
1050
1051     if (pl->pid != NULL) {
1052         apr_proc_kill(pl->pid, SIGTERM);
1053     }
1054     return piped_log_cleanup_for_exec(data);
1055 }
1056
1057
1058 static piped_log* piped_log_open(apr_pool_t *p, const char *program,
1059                                  int special_stderr)
1060 {
1061     piped_log *pl;
1062     piped_log_wrapper *plw;
1063
1064     pl = apr_palloc(p, sizeof (*pl));
1065     pl->p = p;
1066     pl->program = apr_pstrdup(p, program);
1067     pl->pid = NULL;
1068     plw = apr_palloc(p, sizeof (*plw));
1069     plw->special_stderr = special_stderr;
1070     plw->pl = pl;
1071     if (apr_file_pipe_create_ex(&ap_piped_log_read_fd(pl),
1072                                 &ap_piped_log_write_fd(pl),
1073                                 APR_FULL_BLOCK, p) != APR_SUCCESS) {
1074         return NULL;
1075     }
1076     apr_pool_cleanup_register(p, pl, piped_log_cleanup,
1077                               piped_log_cleanup_for_exec);
1078     if (piped_log_spawn(plw) != APR_SUCCESS) {
1079         apr_pool_cleanup_kill(p, pl, piped_log_cleanup);
1080         apr_file_close(ap_piped_log_read_fd(pl));
1081         apr_file_close(ap_piped_log_write_fd(pl));
1082         return NULL;
1083     }
1084     return pl;
1085 }
1086
1087 #else /* !AP_HAVE_RELIABLE_PIPED_LOGS */
1088
1089 static apr_status_t piped_log_cleanup(void *data)
1090 {
1091     piped_log *pl = data;
1092
1093     apr_file_close(ap_piped_log_write_fd(pl));
1094     return APR_SUCCESS;
1095 }
1096
1097 static piped_log* piped_log_open(apr_pool_t *p, const char *program,
1098                                  int special_stderr)
1099 {
1100     piped_log *pl;
1101     apr_file_t *dummy = NULL;
1102     int rc;
1103
1104     rc = log_child(p, program, &dummy, special_stderr);
1105     if (rc != APR_SUCCESS) {
1106         ap_log_error(APLOG_MARK, APLOG_STARTUP, rc, NULL,
1107                      "Couldn't start piped log process for '%s'",
1108                      (program == NULL) ? "NULL" : program);
1109         return NULL;
1110     }
1111
1112     pl = apr_palloc(p, sizeof (*pl));
1113     pl->p = p;
1114     ap_piped_log_read_fd(pl) = NULL;
1115     ap_piped_log_write_fd(pl) = dummy;
1116     apr_pool_cleanup_register(p, pl, piped_log_cleanup, piped_log_cleanup);
1117
1118     return pl;
1119 }
1120
1121 #endif
1122
1123 AP_DECLARE(void) ap_close_piped_log(piped_log *pl)
1124 {
1125     apr_pool_cleanup_run(pl->p, pl, piped_log_cleanup);
1126 }
1127
1128 AP_IMPLEMENT_HOOK_VOID(error_log,
1129                        (const char *file, int line, int level,
1130                         apr_status_t status, const server_rec *s,
1131                         const request_rec *r, apr_pool_t *pool,
1132                         const char *errstr), (file, line, level,
1133                         status, s, r, pool, errstr))