Apache HTTPD
log.c
Go to the documentation of this file.
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#include "apr_portable.h"
32#include "apr_base64.h"
33
34#define APR_WANT_STDIO
35#define APR_WANT_STRFUNC
36#include "apr_want.h"
37
38#if APR_HAVE_STDARG_H
39#include <stdarg.h>
40#endif
41#if APR_HAVE_UNISTD_H
42#include <unistd.h>
43#endif
44#if APR_HAVE_PROCESS_H
45#include <process.h> /* for getpid() on Win32 */
46#endif
47
48#include "ap_config.h"
49#include "httpd.h"
50#include "http_config.h"
51#include "http_core.h"
52#include "http_log.h"
53#include "http_main.h"
54#include "util_time.h"
55#include "ap_mpm.h"
56#include "ap_listen.h"
57
58#ifdef HAVE_SYS_GETTID
59#include <sys/syscall.h>
60#include <sys/types.h>
61#endif
62
63/* we know core's module_index is 0 */
64#undef APLOG_MODULE_INDEX
65#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
66
67#ifndef DEFAULT_LOG_TID
68#define DEFAULT_LOG_TID NULL
69#endif
70
71typedef struct {
72 const char *t_name;
73 int t_val;
74} TRANS;
75
77 APR_HOOK_LINK(error_log)
80
82
83#ifdef HAVE_SYSLOG
84
85static const TRANS facilities[] = {
86 {"auth", LOG_AUTH},
87#ifdef LOG_AUTHPRIV
88 {"authpriv",LOG_AUTHPRIV},
89#endif
90#ifdef LOG_CRON
91 {"cron", LOG_CRON},
92#endif
93#ifdef LOG_DAEMON
94 {"daemon", LOG_DAEMON},
95#endif
96#ifdef LOG_FTP
97 {"ftp", LOG_FTP},
98#endif
99#ifdef LOG_KERN
100 {"kern", LOG_KERN},
101#endif
102#ifdef LOG_LPR
103 {"lpr", LOG_LPR},
104#endif
105#ifdef LOG_MAIL
106 {"mail", LOG_MAIL},
107#endif
108#ifdef LOG_NEWS
109 {"news", LOG_NEWS},
110#endif
111#ifdef LOG_SYSLOG
112 {"syslog", LOG_SYSLOG},
113#endif
114#ifdef LOG_USER
115 {"user", LOG_USER},
116#endif
117#ifdef LOG_UUCP
118 {"uucp", LOG_UUCP},
119#endif
120#ifdef LOG_LOCAL0
121 {"local0", LOG_LOCAL0},
122#endif
123#ifdef LOG_LOCAL1
124 {"local1", LOG_LOCAL1},
125#endif
126#ifdef LOG_LOCAL2
127 {"local2", LOG_LOCAL2},
128#endif
129#ifdef LOG_LOCAL3
130 {"local3", LOG_LOCAL3},
131#endif
132#ifdef LOG_LOCAL4
133 {"local4", LOG_LOCAL4},
134#endif
135#ifdef LOG_LOCAL5
136 {"local5", LOG_LOCAL5},
137#endif
138#ifdef LOG_LOCAL6
139 {"local6", LOG_LOCAL6},
140#endif
141#ifdef LOG_LOCAL7
142 {"local7", LOG_LOCAL7},
143#endif
144 {NULL, -1},
145};
146#endif
147
148static const TRANS priorities[] = {
149 {"emerg", APLOG_EMERG},
150 {"alert", APLOG_ALERT},
151 {"crit", APLOG_CRIT},
152 {"error", APLOG_ERR},
153 {"warn", APLOG_WARNING},
154 {"notice", APLOG_NOTICE},
155 {"info", APLOG_INFO},
156 {"debug", APLOG_DEBUG},
157 {"trace1", APLOG_TRACE1},
158 {"trace2", APLOG_TRACE2},
159 {"trace3", APLOG_TRACE3},
160 {"trace4", APLOG_TRACE4},
161 {"trace5", APLOG_TRACE5},
162 {"trace6", APLOG_TRACE6},
163 {"trace7", APLOG_TRACE7},
164 {"trace8", APLOG_TRACE8},
165 {NULL, -1},
166};
167
169
171
172/* track pipe handles to close in child process */
177
179
186struct piped_log {
191#ifdef AP_HAVE_RELIABLE_PIPED_LOGS
193 char *program;
195 apr_proc_t *pid;
197 apr_cmdtype_e cmdtype;
198#endif
199};
200
202{
203 return pl->read_fd;
204}
205
207{
208 return pl->write_fd;
209}
210
211/* remember to close this handle in the child process
212 *
213 * On Win32 this makes zero sense, because we don't
214 * take the parent process's child procs.
215 * If the win32 parent instead passed each and every
216 * logger write handle from itself down to the child,
217 * and the parent manages all aspects of keeping the
218 * reliable pipe log children alive, this would still
219 * make no sense :) Cripple it on Win32.
220 */
222{
223#ifndef WIN32
225
227 new_handle->next = read_handles;
230#endif
231}
232
234{
236
237 while (cur) {
238 apr_file_close(cur->handle);
239 cur = cur->next;
240 }
241}
242
247
249 const char *fname)
250{
254 if (!filename) {
256 APR_EBADPATH, ap_server_conf, APLOGNO(00085) "Invalid -E error log file %s",
257 fname);
258 return APR_EBADPATH;
259 }
264 "%s: could not open error log file %s.",
266 return rc;
267 }
268 if (!stderr_pool) {
269 /* This is safe provided we revert it when we are finished.
270 * We don't manager the callers pool!
271 */
272 stderr_pool = p;
273 }
275 == APR_SUCCESS) {
278 == APR_SUCCESS) {
280 /*
281 * You might ponder why stderr_pool should survive?
282 * The trouble is, stderr_pool may have s_main->error_log,
283 * so we aren't in a position to destroy stderr_pool until
284 * the next recycle. There's also an apparent bug which
285 * is not; if some folk decided to call this function before
286 * the core open error logs hook, this pool won't survive.
287 * Neither does the stderr logger, so this isn't a problem.
288 */
289 }
290 }
291 /* Revert, see above */
292 if (stderr_pool == p)
294
295 if (rc != APR_SUCCESS) {
297 "unable to replace stderr with error log file");
298 }
299 return rc;
300}
301
303 const char *description)
304{
306 "%s", description);
307}
308
309/* Create a child process running PROGNAME with a pipe connected to
310 * the child's stdin. The write-end of the pipe will be placed in
311 * *FPIN on successful return. If dummy_stderr is non-zero, the
312 * stderr for the child will be the same as the stdout of the parent.
313 * Otherwise the child will inherit the stderr from the parent. */
314static int log_child(apr_pool_t *p, const char *progname,
315 apr_file_t **fpin, apr_cmdtype_e cmdtype,
316 int dummy_stderr)
317{
318 /* Child process code for 'ErrorLog "|..."';
319 * may want a common framework for this, since I expect it will
320 * be common for other foo-loggers to want this sort of thing...
321 */
323 apr_procattr_t *procattr;
326
327 if (((rc = apr_procattr_create(&procattr, p)) == APR_SUCCESS)
328 && ((rc = apr_procattr_dir_set(procattr,
330 && ((rc = apr_procattr_cmdtype_set(procattr, cmdtype)) == APR_SUCCESS)
331 && ((rc = apr_procattr_io_set(procattr,
335 && ((rc = apr_procattr_error_check_set(procattr, 1)) == APR_SUCCESS)
337 == APR_SUCCESS)) {
338 char **args;
339
341 procnew = (apr_proc_t *)apr_pcalloc(p, sizeof(*procnew));
342
343 if (dummy_stderr) {
346 }
347
348 if (rc == APR_SUCCESS) {
349 rc = apr_proc_create(procnew, args[0], (const char * const *)args,
350 NULL, procattr, p);
351 }
352
353 if (rc == APR_SUCCESS) {
355 (*fpin) = procnew->in;
356 /* read handle to pipe not kept open, so no need to call
357 * close_handle_in_child()
358 */
359 }
360 }
361
362 return rc;
363}
364
365/* Open the error log for the given server_rec. If IS_MAIN is
366 * non-zero, s is the main server. */
368{
369 const char *fname;
370 int rc;
371
372 if (*s->error_fname == '|') {
375 fname = s->error_fname + 1;
376
377 /* In 2.4 favor PROGRAM_ENV, accept "||prog" syntax for compatibility
378 * and "|$cmd" to override the default.
379 * Any 2.2 backport would continue to favor SHELLCMD_ENV so there
380 * accept "||prog" to override, and "|$cmd" to ease conversion.
381 */
382 if (*fname == '|')
383 ++fname;
384 if (*fname == '$') {
385 cmdtype = APR_SHELLCMD_ENV;
386 ++fname;
387 }
388
389 /* Spawn a new child logger. If this is the main server_rec,
390 * the new child must use a dummy stderr since the current
391 * stderr might be a pipe to the old logger. Otherwise, the
392 * child inherits the parents stderr. */
393 rc = log_child(p, fname, &dummy, cmdtype, is_main);
394 if (rc != APR_SUCCESS) {
396 "Couldn't start ErrorLog process '%s'.",
397 s->error_fname + 1);
398 return DONE;
399 }
400
401 s->error_log = dummy;
402 }
403
404#ifdef HAVE_SYSLOG
405 else if (strcmp(s->error_fname, "syslog") == 0
406 || strncmp(s->error_fname, "syslog:", 7) == 0) {
407 if ((fname = strchr(s->error_fname, ':'))) {
408 /* s->error_fname could be [level]:[tag] (see #60525) */
409 const char *tag;
411 const TRANS *fac;
412
413 fname++;
414 tag = ap_strchr_c(fname, ':');
415 if (tag) {
416 flen = tag - fname;
417 tag++;
418 if (*tag == '\0') {
420 }
421 } else {
422 flen = strlen(fname);
424 }
425 if (flen == 0) {
426 /* Was something like syslog::foobar */
428 } else {
429 for (fac = facilities; fac->t_name; fac++) {
430 if (!strncasecmp(fname, fac->t_name, flen)) {
432 fac->t_val);
433 s->error_log = NULL;
434 return OK;
435 }
436 }
437 /* Huh? Invalid level name? */
439 "%s: could not open syslog error log %s.",
441 return DONE;
442 }
443 }
444 else {
446 }
447
448 s->error_log = NULL;
449 }
450#endif
451 else {
452 fname = ap_server_root_relative(p, s->error_fname);
453 if (!fname) {
455 "%s: Invalid error log path %s.",
457 return DONE;
458 }
459 if ((rc = apr_file_open(&s->error_log, fname,
463 "%s: could not open error log file %s.",
465 return DONE;
466 }
467 }
468
469 return OK;
470}
471
474{
476 server_rec *virt, *q;
477 int replace_stderr;
478
479
480 /* Register to throw away the read_handles list when we
481 * cleanup plog. Upon fork() for the apache children,
482 * this read_handles list is closed so only the parent
483 * can relaunch a lost log child. These read handles
484 * are always closed on exec.
485 * We won't care what happens to our stderr log child
486 * between log phases, so we don't mind losing stderr's
487 * read_handle a little bit early.
488 */
491
492 /* HERE we need a stdout log that outlives plog.
493 * We *presume* the parent of plog is a process
494 * or global pool which spans server restarts.
495 * Create our stderr_pool as a child of the plog's
496 * parent pool.
497 */
499 apr_pool_tag(stderr_p, "stderr_pool");
500
501 if (open_error_log(s_main, 1, stderr_p) != OK) {
502 return DONE;
503 }
504
505 replace_stderr = 1;
506 if (s_main->error_log) {
507 apr_status_t rv;
508
509 /* Replace existing stderr with new log. */
510 apr_file_flush(s_main->error_log);
511 rv = apr_file_dup2(stderr_log, s_main->error_log, stderr_p);
512 if (rv != APR_SUCCESS) {
514 "unable to replace stderr with error_log");
515 }
516 else {
517 /* We are done with stderr_pool, close it, killing
518 * the previous generation's stderr logger
519 */
520 if (stderr_pool)
523 replace_stderr = 0;
524 /*
525 * Now that we have dup'ed s_main->error_log to stderr_log
526 * close it and set s_main->error_log to stderr_log. This avoids
527 * this fd being inherited by the next piped logger who would
528 * keep open the writing end of the pipe that this one uses
529 * as stdin. This in turn would prevent the piped logger from
530 * exiting.
531 */
532 apr_file_close(s_main->error_log);
533 s_main->error_log = stderr_log;
534 }
535 }
536 /* note that stderr may still need to be replaced with something
537 * because it points to the old error log, or back to the tty
538 * of the submitter.
539 * XXX: This is BS - /dev/null is non-portable
540 * errno-as-apr_status_t is also non-portable
541 */
542
543#ifdef WIN32
544#define NULL_DEVICE "nul"
545#else
546#define NULL_DEVICE "/dev/null"
547#endif
548
549 if (replace_stderr && freopen(NULL_DEVICE, "w", stderr) == NULL) {
551 "unable to replace stderr with %s", NULL_DEVICE);
552 }
553
554 for (virt = s_main->next; virt; virt = virt->next) {
555 if (virt->error_fname) {
556 for (q=s_main; q != virt; q = q->next) {
557 if (q->error_fname != NULL
558 && strcmp(q->error_fname, virt->error_fname) == 0) {
559 break;
560 }
561 }
562
563 if (q == virt) {
564 if (open_error_log(virt, 0, p) != OK) {
565 return DONE;
566 }
567 }
568 else {
569 virt->error_log = q->error_log;
570 }
571 }
572 else {
573 virt->error_log = s_main->error_log;
574 }
575 }
576 return OK;
577}
578
581
582 apr_file_open_stderr(&errfile, s->process->pool);
583 if (s->error_log != NULL) {
584 apr_file_dup2(s->error_log, errfile, s->process->pool);
585 }
586}
587
588static int cpystrn(char *buf, const char *arg, int buflen)
589{
590 char *end;
591 if (!arg)
592 return 0;
594 return end - buf;
595}
596
597
598static int log_remote_address(const ap_errorlog_info *info, const char *arg,
599 char *buf, int buflen)
600{
601 if (info->r && !(arg && *arg == 'c'))
602 return apr_snprintf(buf, buflen, "%s:%d", info->r->useragent_ip,
603 info->r->useragent_addr ? info->r->useragent_addr->port : 0);
604 else if (info->c)
605 return apr_snprintf(buf, buflen, "%s:%d", info->c->client_ip,
606 info->c->client_addr ? info->c->client_addr->port : 0);
607 else
608 return 0;
609}
610
611static int log_local_address(const ap_errorlog_info *info, const char *arg,
612 char *buf, int buflen)
613{
614 if (info->c)
615 return apr_snprintf(buf, buflen, "%s:%d", info->c->local_ip,
616 info->c->local_addr->port);
617 else
618 return 0;
619}
620
621static int log_pid(const ap_errorlog_info *info, const char *arg,
622 char *buf, int buflen)
623{
624 pid_t pid = getpid();
625 return apr_snprintf(buf, buflen, "%" APR_PID_T_FMT, pid);
626}
627
628static int log_tid(const ap_errorlog_info *info, const char *arg,
629 char *buf, int buflen)
630{
631#if APR_HAS_THREADS
632 int result;
633#endif
634#if defined(HAVE_GETTID) || defined(HAVE_SYS_GETTID)
635 if (arg && *arg == 'g') {
636#ifdef HAVE_GETTID
637 pid_t tid = gettid();
638#else
639 pid_t tid = syscall(SYS_gettid);
640#endif
641 if (tid == -1)
642 return 0;
643 return apr_snprintf(buf, buflen, "%"APR_PID_T_FMT, tid);
644 }
645#endif /* HAVE_GETTID || HAVE_SYS_GETTID */
646#if APR_HAS_THREADS
649 {
651 return apr_snprintf(buf, buflen, "%pT", &tid);
652 }
653#endif
654 return 0;
655}
656
657static int log_ctime(const ap_errorlog_info *info, const char *arg,
658 char *buf, int buflen)
659{
660 int time_len = buflen;
662
663 if (arg) {
664 if (arg[0] == 'u' && !arg[1]) { /* no ErrorLogFormat (fast path) */
666 }
667 else if (!ap_strchr_c(arg, '%')) { /* special "%{cuz}t" formats */
668 while (*arg) {
669 switch (*arg++) {
670 case 'u':
672 break;
673 case 'c':
675 break;
676 case 'z':
678 break;
679 }
680 }
681 }
682 else { /* "%{strftime %-format}t" */
683 apr_size_t len = 0;
687 return (int)len;
688 }
689 }
690
692
693 /* ap_recent_ctime_ex includes the trailing \0 in time_len */
694 return time_len - 1;
695}
696
697static int log_loglevel(const ap_errorlog_info *info, const char *arg,
698 char *buf, int buflen)
699{
700 if (info->level < 0)
701 return 0;
702 else
703 return cpystrn(buf, priorities[info->level].t_name, buflen);
704}
705
706static int log_log_id(const ap_errorlog_info *info, const char *arg,
707 char *buf, int buflen)
708{
709 /*
710 * C: log conn log_id if available,
711 * c: log conn log id if available and not a once-per-request log line
712 * else: log request log id if available
713 */
714 if (arg && !strcasecmp(arg, "c")) {
715 if (info->c && (*arg != 'C' || !info->r)) {
716 return cpystrn(buf, info->c->log_id, buflen);
717 }
718 }
719 else if (info->rmain) {
720 return cpystrn(buf, info->rmain->log_id, buflen);
721 }
722 return 0;
723}
724
725static int log_keepalives(const ap_errorlog_info *info, const char *arg,
726 char *buf, int buflen)
727{
728 if (!info->c)
729 return 0;
730
731 return apr_snprintf(buf, buflen, "%d", info->c->keepalives);
732}
733
734static int log_module_name(const ap_errorlog_info *info, const char *arg,
735 char *buf, int buflen)
736{
737 return cpystrn(buf, ap_find_module_short_name(info->module_index), buflen);
738}
739
740static int log_file_line(const ap_errorlog_info *info, const char *arg,
741 char *buf, int buflen)
742{
743 if (info->file == NULL) {
744 return 0;
745 }
746 else {
747 const char *file = info->file;
748#if defined(_OSD_POSIX) || defined(WIN32) || defined(__MVS__)
749 char tmp[256];
750 char *e = strrchr(file, '/');
751#ifdef WIN32
752 if (!e) {
753 e = strrchr(file, '\\');
754 }
755#endif
756
757 /* In OSD/POSIX, the compiler returns for __FILE__
758 * a string like: __FILE__="*POSIX(/usr/include/stdio.h)"
759 * (it even returns an absolute path for sources in
760 * the current directory). Here we try to strip this
761 * down to the basename.
762 */
763 if (e != NULL && e[1] != '\0') {
764 apr_snprintf(tmp, sizeof(tmp), "%s", &e[1]);
765 e = &tmp[strlen(tmp)-1];
766 if (*e == ')') {
767 *e = '\0';
768 }
769 file = tmp;
770 }
771#else /* _OSD_POSIX || WIN32 */
772 const char *p;
773 /* On Unix, __FILE__ may be an absolute path in a
774 * VPATH build. */
775 if (file[0] == '/' && (p = ap_strrchr_c(file, '/')) != NULL) {
776 file = p + 1;
777 }
778#endif /*_OSD_POSIX || WIN32 */
779 return apr_snprintf(buf, buflen, "%s(%d)", file, info->line);
780 }
781}
782
783static int log_apr_status(const ap_errorlog_info *info, const char *arg,
784 char *buf, int buflen)
785{
786 apr_status_t status = info->status;
787 int len;
788 if (!status)
789 return 0;
790
792 len = apr_snprintf(buf, buflen, "(%d)", status);
793 }
794 else if (status < APR_OS_START_SYSERR) {
795 len = apr_snprintf(buf, buflen, "(EAI %d)",
797 }
798 else if (status < 100000 + APR_OS_START_SYSERR) {
799 len = apr_snprintf(buf, buflen, "(OS %d)",
801 }
802 else {
803 len = apr_snprintf(buf, buflen, "(os 0x%08x)",
805 }
807 len += strlen(buf + len);
808 return len;
809}
810
811static int log_server_name(const ap_errorlog_info *info, const char *arg,
812 char *buf, int buflen)
813{
814 if (info->r)
816
817 return 0;
818}
819
820static int log_virtual_host(const ap_errorlog_info *info, const char *arg,
821 char *buf, int buflen)
822{
823 if (info->s)
824 return cpystrn(buf, info->s->server_hostname, buflen);
825
826 return 0;
827}
828
829
830static int log_table_entry(const apr_table_t *table, const char *name,
831 char *buf, int buflen)
832{
833#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
834 const char *value;
835 char scratch[MAX_STRING_LEN];
836
837 if ((value = apr_table_get(table, name)) != NULL) {
839 return cpystrn(buf, scratch, buflen);
840 }
841
842 return 0;
843#else
844 return cpystrn(buf, apr_table_get(table, name), buflen);
845#endif
846}
847
848static int log_header(const ap_errorlog_info *info, const char *arg,
849 char *buf, int buflen)
850{
851 if (info->r)
852 return log_table_entry(info->r->headers_in, arg, buf, buflen);
853
854 return 0;
855}
856
857static int log_note(const ap_errorlog_info *info, const char *arg,
858 char *buf, int buflen)
859{
860 /* XXX: maybe escaping the entry is not necessary for notes? */
861 if (info->r)
862 return log_table_entry(info->r->notes, arg, buf, buflen);
863
864 return 0;
865}
866
867static int log_env_var(const ap_errorlog_info *info, const char *arg,
868 char *buf, int buflen)
869{
870 if (info->r)
871 return log_table_entry(info->r->subprocess_env, arg, buf, buflen);
872
873 return 0;
874}
875
876static int core_generate_log_id(const conn_rec *c, const request_rec *r,
877 const char **idstring)
878{
879 apr_uint64_t id, tmp;
880 pid_t pid;
881 int len;
882 char *encoded;
883
884 if (r && r->request_time) {
886 }
887 else {
889 }
890
891 pid = getpid();
892 if (sizeof(pid_t) > 2) {
893 tmp = pid;
894 tmp = tmp << 40;
895 id ^= tmp;
896 pid = pid >> 24;
897 tmp = pid;
898 tmp = tmp << 56;
899 id ^= tmp;
900 }
901 else {
902 tmp = pid;
903 tmp = tmp << 40;
904 id ^= tmp;
905 }
906#if APR_HAS_THREADS
907 {
908 apr_uintptr_t tmp2 = (apr_uintptr_t)c->current_thread;
909 tmp = tmp2;
910 tmp = tmp << 32;
911 id ^= tmp;
912 }
913#endif
914
915 len = apr_base64_encode_len(sizeof(id)); /* includes trailing \0 */
916 encoded = apr_palloc(r ? r->pool : c->pool, len);
917 apr_base64_encode(encoded, (char *)&id, sizeof(id));
918
919 /* Skip the last char, it is always '=' */
920 encoded[len - 2] = '\0';
921
922 *idstring = encoded;
923
924 return OK;
925}
926
927static void add_log_id(const conn_rec *c, const request_rec *r)
928{
929 const char **id;
930 /* need to cast const away */
931 if (r) {
932 id = &((request_rec *)r)->log_id;
933 }
934 else {
935 id = &((conn_rec *)c)->log_id;
936 }
937
939}
940
963
964/*
965 * This is used if no error log format is defined and during startup.
966 * It automatically omits the timestamp if logging to syslog.
967 */
969 int buflen, int *errstr_start, int *errstr_end,
970 const char *errstr_fmt, va_list args)
971{
972 int len = 0;
973 int field_start = 0;
974 int item_len;
975#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
976 char scratch[MAX_STRING_LEN];
977#endif
978
979 if (!info->using_syslog && !info->startup) {
980 buf[len++] = '[';
981 len += log_ctime(info, "u", buf + len, buflen - len);
982 buf[len++] = ']';
983 buf[len++] = ' ';
984 }
985
986 if (!info->startup) {
987 buf[len++] = '[';
989 buf[len++] = ':';
991 len += cpystrn(buf + len, "] [pid ", buflen - len);
992
993 len += log_pid(info, NULL, buf + len, buflen - len);
994#if APR_HAS_THREADS
996 len += cpystrn(buf + len, ":tid ", buflen - len);
998 if (!item_len)
1000 else
1001 len += item_len;
1002#endif
1003 buf[len++] = ']';
1004 buf[len++] = ' ';
1005 }
1006
1007 if (info->level >= APLOG_DEBUG) {
1009 if (item_len) {
1010 len += item_len;
1011 len += cpystrn(buf + len, ": ", buflen - len);
1012 }
1013 }
1014
1015 if (info->status) {
1017 if (item_len) {
1018 len += item_len;
1019 len += cpystrn(buf + len, ": ", buflen - len);
1020 }
1021 }
1022
1023 /*
1024 * useragent_ip/client_ip can be client or backend server. If we have
1025 * a scoreboard handle, it is likely a client.
1026 */
1027 if (info->r) {
1028 len += apr_snprintf(buf + len, buflen - len,
1029 info->r->connection->sbh ? "[client %s:%d] " : "[remote %s:%d] ",
1030 info->r->useragent_ip,
1031 info->r->useragent_addr ? info->r->useragent_addr->port : 0);
1032 }
1033 else if (info->c) {
1034 len += apr_snprintf(buf + len, buflen - len,
1035 info->c->sbh ? "[client %s:%d] " : "[remote %s:%d] ",
1036 info->c->client_ip,
1037 info->c->client_addr ? info->c->client_addr->port : 0);
1038 }
1039
1040 /* the actual error message */
1041 *errstr_start = len;
1042#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
1043 if (apr_vsnprintf(scratch, MAX_STRING_LEN, errstr_fmt, args)) {
1044 len += ap_escape_errorlog_item(buf + len, scratch,
1045 buflen - len);
1046
1047 }
1048#else
1050#endif
1051 *errstr_end = len;
1052
1053 field_start = len;
1054 len += cpystrn(buf + len, ", referer: ", buflen - len);
1055 item_len = log_header(info, "Referer", buf + len, buflen - len);
1056 if (item_len)
1057 len += item_len;
1058 else
1059 len = field_start;
1060
1061 return len;
1062}
1063
1065 char *buf, int buflen, int *errstr_start,
1066 int *errstr_end, const char *err_fmt, va_list args)
1067{
1068#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
1069 char scratch[MAX_STRING_LEN];
1070#endif
1071 int i;
1072 int len = 0;
1073 int field_start = 0;
1074 int skipping = 0;
1076
1077 AP_DEBUG_ASSERT(fmt->nelts > 0);
1078 for (i = 0; i < fmt->nelts; ++i) {
1080 if (item->flags & AP_ERRORLOG_FLAG_FIELD_SEP) {
1081 if (skipping) {
1082 skipping = 0;
1083 }
1084 else {
1085 field_start = len;
1086 }
1087 }
1088
1089 if (item->flags & AP_ERRORLOG_FLAG_MESSAGE) {
1090 /* the actual error message */
1091 *errstr_start = len;
1092#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
1093 if (apr_vsnprintf(scratch, MAX_STRING_LEN, err_fmt, args)) {
1094 len += ap_escape_errorlog_item(buf + len, scratch,
1095 buflen - len);
1096
1097 }
1098#else
1100#endif
1101 *errstr_end = len;
1102 }
1103 else if (skipping) {
1104 continue;
1105 }
1106 else if (info->level != -1 && (int)item->min_loglevel > info->level) {
1107 len = field_start;
1108 skipping = 1;
1109 }
1110 else {
1111 int item_len = (*item->func)(info, item->arg, buf + len,
1112 buflen - len);
1113 if (!item_len) {
1114 if (item->flags & AP_ERRORLOG_FLAG_REQUIRED) {
1115 /* required item is empty. skip whole line */
1116 buf[0] = '\0';
1117 return 0;
1118 }
1119 else if (item->flags & AP_ERRORLOG_FLAG_NULL_AS_HYPHEN) {
1120 buf[len++] = '-';
1121 }
1122 else {
1123 len = field_start;
1124 skipping = 1;
1125 }
1126 }
1127 else {
1128 len += item_len;
1129 }
1130 }
1131 }
1132 return len;
1133}
1134
1135static void write_logline(char *errstr, apr_size_t len, apr_file_t *logf,
1136 int level)
1137{
1138 /* NULL if we are logging to syslog */
1139 if (logf) {
1140 /* Truncate for the terminator (as apr_snprintf does) */
1141 if (len > MAX_STRING_LEN - sizeof(APR_EOL_STR)) {
1142 len = MAX_STRING_LEN - sizeof(APR_EOL_STR);
1143 }
1144 strcpy(errstr + len, APR_EOL_STR);
1145 apr_file_puts(errstr, logf);
1147 }
1148#ifdef HAVE_SYSLOG
1149 else {
1150 syslog(level < LOG_PRIMASK ? level : APLOG_DEBUG, "%.*s",
1151 (int)len, errstr);
1152 }
1153#endif
1154}
1155
1156static void log_error_core(const char *file, int line, int module_index,
1157 int level,
1159 const conn_rec *c,
1160 const request_rec *r, apr_pool_t *pool,
1161 const char *fmt, va_list args)
1162{
1163 char errstr[MAX_STRING_LEN];
1164 apr_file_t *logf = NULL;
1165 int level_and_mask = level & APLOG_LEVELMASK;
1166 const request_rec *rmain = NULL;
1169
1170 /* do we need to log once-per-req or once-per-conn info? */
1171 int log_conn_info = 0, log_req_info = 0;
1173 int done = 0;
1174 int line_number = 0;
1175
1176 if (r) {
1178 c = r->connection;
1179 }
1180
1181 if (s == NULL) {
1182 /*
1183 * If we are doing stderr logging (startup), don't log messages that are
1184 * above the default server log level unless it is a startup/shutdown
1185 * notice
1186 */
1187#ifndef DEBUG
1190 return;
1191 }
1192#endif
1193
1194 logf = stderr_log;
1195
1196 /* Use the main ErrorLogFormat if any */
1197 if (ap_server_conf) {
1199 }
1200 }
1201 else {
1202 int configured_level = r ? ap_get_request_module_loglevel(r, module_index) :
1203 c ? ap_get_conn_server_module_loglevel(c, s, module_index) :
1204 ap_get_server_module_loglevel(s, module_index);
1205 if (s->error_log) {
1206 /*
1207 * If we are doing normal logging, don't log messages that are
1208 * above the module's log level unless it is a startup/shutdown notice
1209 */
1212 return;
1213 }
1214
1215 logf = s->error_log;
1216 }
1217 else {
1218 /*
1219 * If we are doing syslog logging, don't log messages that are
1220 * above the module's log level (including a startup/shutdown notice)
1221 */
1223 return;
1224 }
1225 }
1226
1227 /* the faked server_rec from mod_cgid does not have s->module_config */
1228 if (s->module_config) {
1229 sconf = ap_get_core_module_config(s->module_config);
1230 if (c && !c->log_id) {
1231 add_log_id(c, NULL);
1232 if (sconf->error_log_conn && sconf->error_log_conn->nelts > 0)
1233 log_conn_info = 1;
1234 }
1235 if (r) {
1236 if (r->main)
1237 rmain = r->main;
1238 else
1239 rmain = r;
1240
1241 if (!rmain->log_id) {
1242 /* XXX: do we need separate log ids for subrequests? */
1243 if (sconf->error_log_req && sconf->error_log_req->nelts > 0)
1244 log_req_info = 1;
1245 /*
1246 * XXX: potential optimization: only create log id if %L is
1247 * XXX: actually used
1248 */
1249 add_log_id(c, rmain);
1250 }
1251 }
1252 }
1253 else if (ap_server_conf) {
1254 /* Use the main ErrorLogFormat if any */
1256 }
1257 }
1258
1259 info.s = s;
1260 info.c = c;
1261 info.pool = pool;
1262 info.file = NULL;
1263 info.line = 0;
1264 info.status = 0;
1265 info.using_syslog = (logf == NULL);
1266 info.startup = ((level & APLOG_STARTUP) == APLOG_STARTUP);
1267 info.format = fmt;
1268
1269 while (!done) {
1271 int len = 0, errstr_start = 0, errstr_end = 0;
1272 /* XXX: potential optimization: format common prefixes only once */
1273 if (log_conn_info) {
1274 /* once-per-connection info */
1275 if (line_number == 0) {
1276 lines = (apr_array_header_t **)sconf->error_log_conn->elts;
1277 info.r = NULL;
1278 info.rmain = NULL;
1279 info.level = -1;
1280 info.module_index = APLOG_NO_MODULE;
1281 }
1282
1283 log_format = lines[line_number++];
1284
1285 if (line_number == sconf->error_log_conn->nelts) {
1286 /* this is the last line of once-per-connection info */
1287 line_number = 0;
1288 log_conn_info = 0;
1289 }
1290 }
1291 else if (log_req_info) {
1292 /* once-per-request info */
1293 if (line_number == 0) {
1294 lines = (apr_array_header_t **)sconf->error_log_req->elts;
1295 info.r = rmain;
1296 info.rmain = rmain;
1297 info.level = -1;
1298 info.module_index = APLOG_NO_MODULE;
1299 }
1300
1301 log_format = lines[line_number++];
1302
1303 if (line_number == sconf->error_log_req->nelts) {
1304 /* this is the last line of once-per-request info */
1305 line_number = 0;
1306 log_req_info = 0;
1307 }
1308 }
1309 else {
1310 /* the actual error message */
1311 info.r = r;
1312 info.rmain = rmain;
1313 info.level = level_and_mask;
1314 info.module_index = module_index;
1315 info.file = file;
1316 info.line = line;
1317 info.status = status;
1318 log_format = sconf ? sconf->error_log_format : NULL;
1319 done = 1;
1320 }
1321
1322 /*
1323 * prepare and log one line
1324 */
1325
1326 if (log_format && !info.startup) {
1327 len += do_errorlog_format(log_format, &info, errstr + len,
1330 }
1331 else {
1334 }
1335
1336 if (!*errstr) {
1337 /*
1338 * Don't log empty lines. This can happen with once-per-conn/req
1339 * info if an item with AP_ERRORLOG_FLAG_REQUIRED is NULL.
1340 */
1341 continue;
1342 }
1344
1345 if (done) {
1346 /*
1347 * We don't call the error_log hook for per-request/per-conn
1348 * lines, and we only pass the actual log message, not the
1349 * prefix and suffix.
1350 */
1351 errstr[errstr_end] = '\0';
1353 }
1354
1355 *errstr = '\0';
1356 }
1357}
1358
1359/* For internal calls to log_error_core with self-composed arg lists */
1360static void log_error_va_glue(const char *file, int line, int module_index,
1361 int level, apr_status_t status,
1362 const server_rec *s, const conn_rec *c,
1363 const request_rec *r, apr_pool_t *pool,
1364 const char *fmt, ...)
1365{
1366 va_list args;
1367
1368 va_start(args, fmt);
1369 log_error_core(file, line, module_index, level, status, s, c, r, pool,
1370 fmt, args);
1371 va_end(args);
1372}
1373
1374AP_DECLARE(void) ap_log_error_(const char *file, int line, int module_index,
1375 int level, apr_status_t status,
1376 const server_rec *s, const char *fmt, ...)
1377{
1378 va_list args;
1379
1380 va_start(args, fmt);
1381 log_error_core(file, line, module_index, level, status, s, NULL, NULL,
1382 NULL, fmt, args);
1383 va_end(args);
1384}
1385
1386AP_DECLARE(void) ap_log_perror_(const char *file, int line, int module_index,
1387 int level, apr_status_t status, apr_pool_t *p,
1388 const char *fmt, ...)
1389{
1390 va_list args;
1391
1392 va_start(args, fmt);
1393 log_error_core(file, line, module_index, level, status, NULL, NULL, NULL,
1394 p, fmt, args);
1395 va_end(args);
1396}
1397
1398AP_DECLARE(void) ap_log_rerror_(const char *file, int line, int module_index,
1399 int level, apr_status_t status,
1400 const request_rec *r, const char *fmt, ...)
1401{
1402 va_list args;
1403
1404 va_start(args, fmt);
1405 log_error_core(file, line, module_index, level, status, r->server, NULL, r,
1406 NULL, fmt, args);
1407
1408 /*
1409 * IF APLOG_TOCLIENT is set,
1410 * AND the error level is 'warning' or more severe,
1411 * AND there isn't already error text associated with this request,
1412 * THEN make the message text available to ErrorDocument and
1413 * other error processors.
1414 */
1415 va_end(args);
1416 va_start(args,fmt);
1417 if ((level & APLOG_TOCLIENT)
1418 && ((level & APLOG_LEVELMASK) <= APLOG_WARNING)
1419 && (apr_table_get(r->notes, "error-notes") == NULL)) {
1420 apr_table_setn(r->notes, "error-notes",
1422 args)));
1423 }
1424 va_end(args);
1425}
1426
1427AP_DECLARE(void) ap_log_cserror_(const char *file, int line, int module_index,
1428 int level, apr_status_t status,
1429 const conn_rec *c, const server_rec *s,
1430 const char *fmt, ...)
1431{
1432 va_list args;
1433
1434 va_start(args, fmt);
1435 log_error_core(file, line, module_index, level, status, s, c,
1436 NULL, NULL, fmt, args);
1437 va_end(args);
1438}
1439
1440AP_DECLARE(void) ap_log_cerror_(const char *file, int line, int module_index,
1441 int level, apr_status_t status,
1442 const conn_rec *c, const char *fmt, ...)
1443{
1444 va_list args;
1445
1446 va_start(args, fmt);
1447 log_error_core(file, line, module_index, level, status, c->base_server, c,
1448 NULL, NULL, fmt, args);
1449 va_end(args);
1450}
1451
1452#define BYTES_LOGGED_PER_LINE 16
1453#define LOG_BYTES_BUFFER_SIZE (BYTES_LOGGED_PER_LINE * 3 + 2)
1454
1455static void fmt_data(unsigned char *buf, const void *vdata, apr_size_t len, apr_size_t *off)
1456{
1457 const unsigned char *data = (const unsigned char *)vdata;
1458 unsigned char *chars;
1459 unsigned char *hex;
1461
1462 memset(buf, ' ', LOG_BYTES_BUFFER_SIZE - 1);
1463 buf[LOG_BYTES_BUFFER_SIZE - 1] = '\0';
1464
1465 chars = buf; /* start character dump here */
1466 hex = buf + BYTES_LOGGED_PER_LINE + 1; /* start hex dump here */
1467 while (*off < len && this_time < BYTES_LOGGED_PER_LINE) {
1468 unsigned char c = data[*off];
1469
1470 if (apr_isprint(c)
1471 && c != '\\') { /* backslash will be escaped later, which throws
1472 * off the formatting
1473 */
1474 *chars = c;
1475 }
1476 else {
1477 *chars = '.';
1478 }
1479
1480 if ((c >> 4) >= 10) {
1481 *hex = 'a' + ((c >> 4) - 10);
1482 }
1483 else {
1484 *hex = '0' + (c >> 4);
1485 }
1486
1487 if ((c & 0x0F) >= 10) {
1488 *(hex + 1) = 'a' + ((c & 0x0F) - 10);
1489 }
1490 else {
1491 *(hex + 1) = '0' + (c & 0x0F);
1492 }
1493
1494 chars += 1;
1495 hex += 2;
1496 *off += 1;
1497 ++this_time;
1498 }
1499}
1500
1501static void log_data_core(const char *file, int line, int module_index,
1502 int level, const server_rec *s,
1503 const conn_rec *c, const request_rec *r,
1504 const char *label, const void *data, apr_size_t len,
1505 unsigned int flags)
1506{
1507 unsigned char buf[LOG_BYTES_BUFFER_SIZE];
1509 char prefix[20];
1510
1511 if (!(flags & AP_LOG_DATA_SHOW_OFFSET)) {
1512 prefix[0] = '\0';
1513 }
1514
1515 if (len > 0xffff) { /* bug in caller? */
1516 len = 0xffff;
1517 }
1518
1519 if (label) {
1520 log_error_va_glue(file, line, module_index, level, APR_SUCCESS, s,
1521 c, r, NULL, "%s (%" APR_SIZE_T_FMT " bytes)",
1522 label, len);
1523 }
1524
1525 off = 0;
1526 while (off < len) {
1528 apr_snprintf(prefix, sizeof prefix, "%04x: ", (unsigned int)off);
1529 }
1530 fmt_data(buf, data, len, &off);
1531 log_error_va_glue(file, line, module_index, level, APR_SUCCESS, s,
1532 c, r, NULL, "%s%s", prefix, buf);
1533 }
1534}
1535
1536AP_DECLARE(void) ap_log_data_(const char *file, int line,
1537 int module_index, int level,
1538 const server_rec *s, const char *label,
1539 const void *data, apr_size_t len,
1540 unsigned int flags)
1541{
1542 log_data_core(file, line, module_index, level, s, NULL, NULL, label,
1543 data, len, flags);
1544}
1545
1546AP_DECLARE(void) ap_log_rdata_(const char *file, int line,
1547 int module_index, int level,
1548 const request_rec *r, const char *label,
1549 const void *data, apr_size_t len,
1550 unsigned int flags)
1551{
1552 log_data_core(file, line, module_index, level, r->server, NULL, r, label,
1553 data, len, flags);
1554}
1555
1556AP_DECLARE(void) ap_log_cdata_(const char *file, int line,
1557 int module_index, int level,
1558 const conn_rec *c, const char *label,
1559 const void *data, apr_size_t len,
1560 unsigned int flags)
1561{
1562 log_data_core(file, line, module_index, level, c->base_server, c, NULL,
1563 label, data, len, flags);
1564}
1565
1566AP_DECLARE(void) ap_log_csdata_(const char *file, int line, int module_index,
1567 int level, const conn_rec *c, const server_rec *s,
1568 const char *label, const void *data,
1569 apr_size_t len, unsigned int flags)
1570{
1571 log_data_core(file, line, module_index, level, s, c, NULL, label, data,
1572 len, flags);
1573}
1574
1576{
1577 int i;
1578 process_rec *process = s->process;
1579 char *result;
1580 int len_needed = 0;
1581
1582 /* Piece together the command line from the pieces
1583 * in process->argv, with spaces in between.
1584 */
1585 for (i = 0; i < process->argc; i++) {
1586 len_needed += strlen(process->argv[i]) + 1;
1587 }
1588
1589 result = (char *) apr_palloc(plog, len_needed);
1590 *result = '\0';
1591
1592 for (i = 0; i < process->argc; i++) {
1593 strcat(result, process->argv[i]);
1594 if ((i+1)< process->argc) {
1595 strcat(result, " ");
1596 }
1597 }
1599 "Command line: '%s'", result);
1600}
1601
1602/* grab bag function to log commonly logged and shared info */
1604{
1606 "Using SO_REUSEPORT: %s (%d)",
1607 ap_have_so_reuseport ? "yes" : "no",
1609}
1610
1612{
1613 apr_status_t rv;
1614 const char *fname = ap_server_root_relative(p, rel_fname);
1615
1616 if (fname != NULL) {
1617 rv = apr_file_remove(fname, p);
1618 if (rv != APR_SUCCESS) {
1620 "failed to remove PID file %s", fname);
1621 }
1622 else {
1624 "removed PID file %s (pid=%" APR_PID_T_FMT ")",
1625 fname, getpid());
1626 }
1627 }
1628}
1629
1631{
1633 apr_finfo_t finfo;
1634 static pid_t saved_pid = -1;
1635 pid_t mypid;
1636 apr_status_t rv;
1637 const char *fname;
1638 char *temp_fname;
1640 char pidstr[64];
1641
1642 if (!filename) {
1643 return;
1644 }
1645
1647 if (!fname) {
1649 ap_server_conf, APLOGNO(00097) "Invalid PID file path %s, ignoring.", filename);
1650 return;
1651 }
1652
1653 mypid = getpid();
1654 if (mypid != saved_pid
1655 && apr_stat(&finfo, fname, APR_FINFO_MTIME, p) == APR_SUCCESS) {
1656 /* AP_SIG_GRACEFUL and HUP call this on each restart.
1657 * Only warn on first time through for this pid.
1658 *
1659 * XXX: Could just write first time through too, although
1660 * that may screw up scripts written to do something
1661 * based on the last modification time of the pid file.
1662 */
1664 "pid file %s overwritten -- Unclean "
1665 "shutdown of previous Apache run?",
1666 fname);
1667 }
1668
1669 temp_fname = apr_pstrcat(p, fname, ".XXXXXX", NULL);
1672 if (rv != APR_SUCCESS) {
1674 "could not create %s", temp_fname);
1676 "%s: could not log pid to file %s",
1678 exit(1);
1679 }
1680
1682
1685 || (rv = apr_file_write_full(pid_file, pidstr, strlen(pidstr), NULL)) != APR_SUCCESS
1686 || (rv = apr_file_close(pid_file)) != APR_SUCCESS
1687 || (rv = apr_file_rename(temp_fname, fname, p)) != APR_SUCCESS) {
1689 "%s: Failed creating pid file %s",
1691 exit(1);
1692 }
1693
1694 saved_pid = mypid;
1695}
1696
1698 pid_t *mypid)
1699{
1700 const apr_size_t BUFFER_SIZE = sizeof(long) * 3 + 2; /* see apr_ltoa */
1702 apr_status_t rv;
1703 const char *fname;
1704 char *buf, *endptr;
1706
1707 if (!filename) {
1708 return APR_EGENERAL;
1709 }
1710
1712 if (!fname) {
1714 ap_server_conf, APLOGNO(00101) "Invalid PID file path %s, ignoring.", filename);
1715 return APR_EGENERAL;
1716 }
1717
1719 if (rv != APR_SUCCESS) {
1720 return rv;
1721 }
1722
1724
1726 if (rv != APR_SUCCESS && rv != APR_EOF) {
1727 return rv;
1728 }
1729
1730 /* If we fill the buffer, we're probably reading a corrupt pid file.
1731 * To be nice, let's also ensure the first char is a digit. */
1732 if (bytes_read == 0 || bytes_read == BUFFER_SIZE - 1 || !apr_isdigit(*buf)) {
1733 return APR_EGENERAL;
1734 }
1735
1736 buf[bytes_read] = '\0';
1737 *mypid = strtol(buf, &endptr, 10);
1738
1740 return APR_SUCCESS;
1741}
1742
1743AP_DECLARE(void) ap_log_assert(const char *szExp, const char *szFile,
1744 int nLine)
1745{
1746 char time_str[APR_CTIME_LEN];
1747
1748 apr_ctime(time_str, apr_time_now());
1750 "[%s] file %s, line %d, assertion \"%s\" failed",
1751 time_str, szFile, nLine, szExp);
1752#if defined(WIN32)
1753 DebugBreak();
1754#else
1755 /* unix assert does an abort leading to a core dump */
1756 abort();
1757#endif
1758}
1759
1760/* piped log support */
1761
1762#ifdef AP_HAVE_RELIABLE_PIPED_LOGS
1763/* forward declaration */
1764static void piped_log_maintenance(int reason, void *data, apr_wait_t status);
1765
1766/* Spawn the piped logger process pl->program. */
1768{
1769 apr_procattr_t *procattr;
1772
1773 if (((status = apr_procattr_create(&procattr, pl->p)) != APR_SUCCESS) ||
1775 != APR_SUCCESS) ||
1776 ((status = apr_procattr_cmdtype_set(procattr, pl->cmdtype))
1777 != APR_SUCCESS) ||
1778 ((status = apr_procattr_child_in_set(procattr,
1779 pl->read_fd,
1780 pl->write_fd))
1781 != APR_SUCCESS) ||
1783 != APR_SUCCESS) ||
1784 ((status = apr_procattr_error_check_set(procattr, 1)) != APR_SUCCESS)) {
1785 /* Something bad happened, give up and go away. */
1787 "piped_log_spawn: unable to setup child process '%s'",
1788 pl->program);
1789 }
1790 else {
1791 char **args;
1792
1793 apr_tokenize_to_argv(pl->program, &args, pl->p);
1794 procnew = apr_pcalloc(pl->p, sizeof(apr_proc_t));
1795 status = apr_proc_create(procnew, args[0], (const char * const *) args,
1796 NULL, procattr, pl->p);
1797
1798 if (status == APR_SUCCESS) {
1799 pl->pid = procnew;
1800 /* procnew->in was dup2'd from pl->write_fd;
1801 * since the original fd is still valid, close the copy to
1802 * avoid a leak. */
1804 procnew->in = NULL;
1806 pl->write_fd, pl->p);
1807 close_handle_in_child(pl->p, pl->read_fd);
1808 }
1809 else {
1810 /* Something bad happened, give up and go away. */
1812 "unable to start piped log program '%s'",
1813 pl->program);
1814 }
1815 }
1816
1817 return status;
1818}
1819
1820
1821static void piped_log_maintenance(int reason, void *data, apr_wait_t status)
1822{
1823 piped_log *pl = data;
1824 apr_status_t rv;
1825 int mpm_state;
1826
1827 switch (reason) {
1829 case APR_OC_REASON_LOST:
1830 pl->pid = NULL; /* in case we don't get it going again, this
1831 * tells other logic not to try to kill it
1832 */
1835 if (rv != APR_SUCCESS) {
1837 "can't query MPM state; not restarting "
1838 "piped log program '%s'",
1839 pl->program);
1840 }
1841 else if (mpm_state != AP_MPMQ_STOPPING) {
1843 "piped log program '%s' failed unexpectedly",
1844 pl->program);
1845 if ((rv = piped_log_spawn(pl)) != APR_SUCCESS) {
1846 /* what can we do? This could be the error log we're having
1847 * problems opening up... */
1849 "piped_log_maintenance: unable to respawn '%s'",
1850 pl->program);
1851 }
1852 }
1853 break;
1854
1856 /* We should not kill off the pipe here, since it may only be full.
1857 * If it really is locked, we should kill it off manually. */
1858 break;
1859
1861 if (pl->pid != NULL) {
1862 apr_proc_kill(pl->pid, SIGTERM);
1863 pl->pid = NULL;
1864 }
1865 break;
1866
1868 break;
1869 }
1870}
1871
1872
1874{
1875 piped_log *pl = data;
1876
1877 apr_file_close(pl->read_fd);
1878 apr_file_close(pl->write_fd);
1879 return APR_SUCCESS;
1880}
1881
1882
1884{
1885 piped_log *pl = data;
1886
1887 if (pl->pid != NULL) {
1888 apr_proc_kill(pl->pid, SIGTERM);
1889 }
1891}
1892
1893
1895 const char *program,
1896 apr_cmdtype_e cmdtype)
1897{
1898 piped_log *pl;
1899
1900 pl = apr_palloc(p, sizeof (*pl));
1901 pl->p = p;
1902 pl->program = apr_pstrdup(p, program);
1903 pl->pid = NULL;
1904 pl->cmdtype = cmdtype;
1905 if (apr_file_pipe_create_ex(&pl->read_fd,
1906 &pl->write_fd,
1908 return NULL;
1909 }
1912 if (piped_log_spawn(pl) != APR_SUCCESS) {
1914 apr_file_close(pl->read_fd);
1915 apr_file_close(pl->write_fd);
1916 return NULL;
1917 }
1918 return pl;
1919}
1920
1921#else /* !AP_HAVE_RELIABLE_PIPED_LOGS */
1922
1924{
1925 piped_log *pl = data;
1926
1927 apr_file_close(pl->write_fd);
1928 return APR_SUCCESS;
1929}
1930
1932 const char *program,
1933 apr_cmdtype_e cmdtype)
1934{
1935 piped_log *pl;
1937 int rc;
1938
1939 rc = log_child(p, program, &dummy, cmdtype, 0);
1940 if (rc != APR_SUCCESS) {
1942 "Couldn't start piped log process '%s'.",
1943 (program == NULL) ? "NULL" : program);
1944 return NULL;
1945 }
1946
1947 pl = apr_palloc(p, sizeof (*pl));
1948 pl->p = p;
1949 pl->read_fd = NULL;
1950 pl->write_fd = dummy;
1952
1953 return pl;
1954}
1955
1956#endif
1957
1959 const char *program)
1960{
1962
1963 /* In 2.4 favor PROGRAM_ENV, accept "||prog" syntax for compatibility
1964 * and "|$cmd" to override the default.
1965 * Any 2.2 backport would continue to favor SHELLCMD_ENV so there
1966 * accept "||prog" to override, and "|$cmd" to ease conversion.
1967 */
1968 if (*program == '|')
1969 ++program;
1970 if (*program == '$') {
1971 cmdtype = APR_SHELLCMD_ENV;
1972 ++program;
1973 }
1974
1975 return ap_open_piped_log_ex(p, program, cmdtype);
1976}
1977
1982
1983AP_DECLARE(const char *) ap_parse_log_level(const char *str, int *val)
1984{
1985 const char *err = "Log level keyword must be one of emerg/alert/crit/error/"
1986 "warn/notice/info/debug/trace1/.../trace8";
1987 int i = 0;
1988
1989 if (str == NULL)
1990 return err;
1991
1992 while (priorities[i].t_name != NULL) {
1993 if (!strcasecmp(str, priorities[i].t_name)) {
1994 *val = priorities[i].t_val;
1995 return NULL;
1996 }
1997 i++;
1998 }
1999 return err;
2000}
2001
2002AP_IMPLEMENT_HOOK_VOID(error_log,
2003 (const ap_errorlog_info *info, const char *errstr),
2004 (info, errstr))
2005
2007 (const conn_rec *c, const request_rec *r,
2008 const char **id),
2009 (c, r, id), DECLINED)
Symbol export macros and hook functions.
#define AP_DECLARE_DATA
Definition ap_config.h:89
#define AP_DECLARE(type)
Definition ap_config.h:67
#define AP_IMPLEMENT_HOOK_VOID(name, args_decl, args_use)
Definition ap_hooks.h:94
#define AP_IMPLEMENT_HOOK_RUN_FIRST(ret, name, args_decl, args_use, decline)
Definition ap_hooks.h:137
Apache Listeners Library.
Apache Multi-Processing Module library.
const char apr_size_t len
Definition ap_regex.h:187
APR-UTIL Base64 Encoding.
APR Error Codes.
APR Miscellaneous library routines.
APR general purpose library routines.
#define BUFFER_SIZE
APR Portability Routines.
APR Signal Handling.
APR Strings library.
APR Thread and Process Library.
APR Standard Headers Support.
static apr_pool_t * pconf
Definition event.c:441
const char * ap_parse_log_level(const char *str, int *val)
Definition log.c:1983
apr_status_t ap_pool_cleanup_set_null(void *data)
Definition util.c:2710
#define ap_get_request_module_loglevel(r, i)
#define ap_get_server_module_loglevel(s, i)
#define ap_get_conn_server_module_loglevel(c, s, i)
char * ap_server_root_relative(apr_pool_t *p, const char *fname)
Definition config.c:1594
const char * ap_find_module_short_name(int module_index)
Definition config.c:823
request_rec * r
#define MAX_STRING_LEN
Definition httpd.h:300
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
#define DONE
Definition httpd.h:458
void ap_register_log_hooks(apr_pool_t *p)
Definition log.c:941
#define AP_ERRORLOG_FLAG_MESSAGE
Definition http_core.h:960
#define AP_ERRORLOG_FLAG_NULL_AS_HYPHEN
Definition http_core.h:964
void ap_run_error_log(const ap_errorlog_info *info, const char *errstr)
Definition log.c:2004
const char * ap_get_server_name(request_rec *r)
Definition core.c:1145
#define ap_get_core_module_config(v)
Definition http_core.h:383
#define AP_ERRORLOG_FLAG_FIELD_SEP
Definition http_core.h:958
void ap_register_errorlog_handler(apr_pool_t *p, char *tag, ap_errorlog_handler_fn_t *handler, int flags)
Definition core.c:4407
#define AP_ERRORLOG_FLAG_REQUIRED
Definition http_core.h:962
int ap_num_listen_buckets
Definition listen.c:49
int ap_have_so_reuseport
Definition listen.c:56
void ap_log_rdata_(const char *file, int line, int module_index, int level, const request_rec *r, const char *label, const void *data, apr_size_t len, unsigned int flags)
Definition log.c:1546
#define APLOG_TRACE8
Definition http_log.h:79
apr_status_t ap_replace_stderr_log(apr_pool_t *p, const char *fname)
Definition log.c:248
#define AP_LOG_DATA_SHOW_OFFSET
Definition http_log.h:569
void ap_log_data_(const char *file, int line, int module_index, int level, const server_rec *s, const char *label, const void *data, apr_size_t len, unsigned int flags)
Definition log.c:1536
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_NOTICE
Definition http_log.h:69
void ap_hook_generate_log_id(ap_HOOK_generate_log_id_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition log.c:2009
#define APLOG_STARTUP
Definition http_log.h:105
int ap_default_loglevel
Definition log.c:81
#define APLOG_TRACE4
Definition http_log.h:75
#define APLOG_INFO
Definition http_log.h:70
void ap_close_piped_log(piped_log *pl)
Definition log.c:1978
apr_file_t * ap_piped_log_write_fd(piped_log *pl)
Definition log.c:206
#define APLOG_ERR
Definition http_log.h:67
#define APLOG_TOCLIENT
Definition http_log.h:102
#define APLOG_TRACE3
Definition http_log.h:74
#define ap_log_error
Definition http_log.h:370
apr_status_t ap_read_pid(apr_pool_t *p, const char *filename, pid_t *mypid)
Definition log.c:1697
#define APLOG_MARK
Definition http_log.h:283
#define ap_log_perror
Definition http_log.h:412
int ap_run_generate_log_id(const conn_rec *c, const request_rec *r, const char **id)
Definition log.c:2009
piped_log * ap_open_piped_log_ex(apr_pool_t *p, const char *program, apr_cmdtype_e cmdtype)
Definition log.c:1931
apr_file_t * ap_piped_log_read_fd(piped_log *pl)
Definition log.c:201
#define APLOG_WARNING
Definition http_log.h:68
piped_log * ap_open_piped_log(apr_pool_t *p, const char *program)
Definition log.c:1958
void ap_remove_pid(apr_pool_t *p, const char *rel_fname)
Definition log.c:1611
#define APLOG_ALERT
Definition http_log.h:65
void ap_open_stderr_log(apr_pool_t *p)
Definition log.c:243
void ap_error_log2stderr(server_rec *s)
Definition log.c:579
#define APLOG_TRACE7
Definition http_log.h:78
#define APLOG_CRIT
Definition http_log.h:66
#define APLOG_EMERG
Definition http_log.h:64
#define APLOG_TRACE2
Definition http_log.h:73
void ap_logs_child_init(apr_pool_t *p, server_rec *s)
Definition log.c:233
#define APLOG_TRACE1
Definition http_log.h:72
#define APLOG_TRACE5
Definition http_log.h:76
int ap_open_logs(apr_pool_t *pconf, apr_pool_t *p, apr_pool_t *ptemp, server_rec *s_main)
Definition log.c:472
void ap_log_mpm_common(server_rec *s)
Definition log.c:1603
void ap_log_pid(apr_pool_t *p, const char *filename)
Definition log.c:1630
void ap_log_cdata_(const char *file, int line, int module_index, int level, const conn_rec *c, const char *label, const void *data, apr_size_t len, unsigned int flags)
Definition log.c:1556
#define APLOG_NO_MODULE
Definition http_log.h:129
#define APLOG_TRACE6
Definition http_log.h:77
#define APLOG_LEVELMASK
Definition http_log.h:81
#define APLOG_DEBUG
Definition http_log.h:71
#define DEFAULT_LOGLEVEL
Definition http_log.h:108
void ap_log_csdata_(const char *file, int line, int module_index, int level, const conn_rec *c, const server_rec *s, const char *label, const void *data, apr_size_t len, unsigned int flags)
Definition log.c:1566
void ap_log_command_line(apr_pool_t *plog, server_rec *s)
Definition log.c:1575
const char * ap_server_argv0
Definition config.c:60
const char * ap_server_root
Definition config.c:61
server_rec * ap_server_conf
Definition config.c:62
const unsigned char * buf
Definition util_md5.h:50
apr_status_t ap_explode_recent_localtime(apr_time_exp_t *tm, apr_time_t t)
Definition util_time.c:146
#define AP_CTIME_OPTION_GMTOFF
Definition util_time.h:51
apr_status_t ap_recent_ctime_ex(char *date_str, apr_time_t t, int option, int *len)
Definition util_time.c:164
#define AP_CTIME_OPTION_USEC
Definition util_time.h:47
#define AP_CTIME_OPTION_NONE
Definition util_time.h:45
#define AP_CTIME_OPTION_COMPACT
Definition util_time.h:49
void * dummy
Definition http_vhost.h:62
void const char * arg
Definition http_vhost.h:63
#define APR_EBADPATH
Definition apr_errno.h:332
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_EOF
Definition apr_errno.h:461
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_OC_REASON_RESTART
#define APR_OC_REASON_LOST
#define APR_OC_REASON_UNREGISTER
#define APR_OC_REASON_DEATH
#define APR_OC_REASON_UNWRITABLE
apr_file_t * f
apr_bucket * e
apr_pool_t apr_dbd_t const char const char * label
Definition apr_dbd.h:397
const char apr_ssize_t int flags
Definition apr_encode.h:168
#define APR_HOOK_LINK(name)
Definition apr_hooks.h:139
#define APR_HOOK_STRUCT(members)
Definition apr_hooks.h:135
#define APR_HOOK_REALLY_LAST
Definition apr_hooks.h:307
apr_redis_t * rc
Definition apr_redis.h:173
#define ap_strrchr_c(s, c)
Definition httpd.h:2357
void ap_log_assert(const char *szExp, const char *szFile, int nLine)
Definition log.c:1743
#define ap_strchr_c(s, c)
Definition httpd.h:2353
#define AP_DEBUG_ASSERT(exp)
Definition httpd.h:2283
#define ap_escape_html(p, s)
Definition httpd.h:1860
apr_size_t ap_escape_errorlog_item(char *dest, const char *source, apr_size_t buflen)
Definition util.c:2251
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define apr_isprint(c)
Definition apr_lib.h:221
#define apr_isdigit(c)
Definition apr_lib.h:209
const char * value
Definition apr_env.h:51
#define APR_OS_START_EAIERR
Definition apr_errno.h:180
#define APR_SUCCESS
Definition apr_errno.h:225
#define APR_OS_START_SYSERR
Definition apr_errno.h:185
int apr_status_t
Definition apr_errno.h:44
apr_int32_t apr_fileperms_t
const char apr_fileperms_t perms
void apr_size_t apr_size_t * bytes_read
void * data
const char apr_file_t * file
#define APR_READ
Definition apr_file_io.h:93
#define APR_FOPEN_TRUNCATE
Definition apr_file_io.h:58
#define APR_APPEND
Definition apr_file_io.h:96
#define APR_WRITE
Definition apr_file_io.h:94
#define APR_LARGEFILE
#define APR_CREATE
Definition apr_file_io.h:95
#define APR_FOPEN_WRITE
Definition apr_file_io.h:55
#define APR_FOPEN_CREATE
Definition apr_file_io.h:56
#define APR_GREAD
#define APR_UWRITE
#define APR_UREAD
#define APR_WREAD
#define APR_OS_DEFAULT
const char * fname
#define APR_FINFO_MTIME
apr_array_header_t ** result
int strcasecmp(const char *a, const char *b)
int strncasecmp(const char *a, const char *b, size_t n)
apr_vformatter_buff_t const char * fmt
Definition apr_lib.h:175
apr_vformatter_buff_t * c
Definition apr_lib.h:175
apr_size_t buflen
const char apr_uint32_t * id
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
apr_size_t const char * filename
Definition apr_shm.h:72
const char char ** end
const char * s
Definition apr_strings.h:95
apr_int32_t apr_int32_t apr_int32_t err
#define APR_FULL_BLOCK
const char const char *const * args
#define APR_NO_PIPE
int reason
const char * progname
apr_cmdtype_e
int int status
@ APR_KILL_AFTER_TIMEOUT
@ APR_PROGRAM_ENV
@ APR_SHELLCMD_ENV
#define APR_CTIME_LEN
Definition apr_time.h:198
apr_status_t ap_mpm_query(int query_code, int *result)
Definition mpm_common.c:421
#define AP_MPMQ_MPM_STATE
Definition ap_mpm.h:174
#define AP_MPMQ_IS_THREADED
Definition ap_mpm.h:152
#define AP_MPMQ_STOPPING
Definition ap_mpm.h:142
#define AP_MPMQ_NOT_SUPPORTED
Definition ap_mpm.h:125
Apache Configuration.
CORE HTTP Daemon.
Apache Logging library.
Command line options.
HTTP Daemon routines.
#define NULL_DEVICE
static int do_errorlog_default(const ap_errorlog_info *info, char *buf, int buflen, int *errstr_start, int *errstr_end, const char *errstr_fmt, va_list args)
Definition log.c:968
static int log_log_id(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:706
static apr_status_t piped_log_cleanup(void *data)
Definition log.c:1923
static apr_file_t * stderr_log
Definition log.c:170
static int log_local_address(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:611
static void log_error_va_glue(const char *file, int line, int module_index, int level, apr_status_t status, const server_rec *s, const conn_rec *c, const request_rec *r, apr_pool_t *pool, const char *fmt,...)
Definition log.c:1360
static void log_error_core(const char *file, int line, int module_index, int level, apr_status_t status, const server_rec *s, const conn_rec *c, const request_rec *r, apr_pool_t *pool, const char *fmt, va_list args)
Definition log.c:1156
static int log_header(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:848
#define BYTES_LOGGED_PER_LINE
Definition log.c:1452
static int open_error_log(server_rec *s, int is_main, apr_pool_t *p)
Definition log.c:367
static int log_file_line(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:740
#define DEFAULT_LOG_TID
Definition log.c:68
static read_handle_t * read_handles
Definition log.c:178
static void fmt_data(unsigned char *buf, const void *vdata, apr_size_t len, apr_size_t *off)
Definition log.c:1455
static int log_apr_status(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:783
static int log_keepalives(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:725
static int log_module_name(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:734
static int log_note(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:857
static int do_errorlog_format(apr_array_header_t *fmt, ap_errorlog_info *info, char *buf, int buflen, int *errstr_start, int *errstr_end, const char *err_fmt, va_list args)
Definition log.c:1064
static int core_generate_log_id(const conn_rec *c, const request_rec *r, const char **idstring)
Definition log.c:876
static int log_loglevel(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:697
static int log_remote_address(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:598
static int log_tid(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:628
static int log_pid(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:621
static int log_virtual_host(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:820
#define LOG_BYTES_BUFFER_SIZE
Definition log.c:1453
void ap_log_perror_(const char *file, int line, int module_index, int level, apr_status_t status, apr_pool_t *p, const char *fmt,...)
Definition log.c:1386
void ap_log_cserror_(const char *file, int line, int module_index, int level, apr_status_t status, const conn_rec *c, const server_rec *s, const char *fmt,...)
Definition log.c:1427
void ap_log_cerror_(const char *file, int line, int module_index, int level, apr_status_t status, const conn_rec *c, const char *fmt,...)
Definition log.c:1440
static int log_server_name(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:811
static int log_env_var(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:867
static void close_handle_in_child(apr_pool_t *p, apr_file_t *f)
Definition log.c:221
static int cpystrn(char *buf, const char *arg, int buflen)
Definition log.c:588
void ap_log_error_(const char *file, int line, int module_index, int level, apr_status_t status, const server_rec *s, const char *fmt,...)
Definition log.c:1374
void ap_log_rerror_(const char *file, int line, int module_index, int level, apr_status_t status, const request_rec *r, const char *fmt,...)
Definition log.c:1398
static void log_data_core(const char *file, int line, int module_index, int level, const server_rec *s, const conn_rec *c, const request_rec *r, const char *label, const void *data, apr_size_t len, unsigned int flags)
Definition log.c:1501
static int log_child(apr_pool_t *p, const char *progname, apr_file_t **fpin, apr_cmdtype_e cmdtype, int dummy_stderr)
Definition log.c:314
static void add_log_id(const conn_rec *c, const request_rec *r)
Definition log.c:927
static apr_pool_t * stderr_pool
Definition log.c:168
static const TRANS priorities[]
Definition log.c:148
static int log_ctime(const ap_errorlog_info *info, const char *arg, char *buf, int buflen)
Definition log.c:657
static int log_table_entry(const apr_table_t *table, const char *name, char *buf, int buflen)
Definition log.c:830
static void log_child_errfn(apr_pool_t *pool, apr_status_t err, const char *description)
Definition log.c:302
static void write_logline(char *errstr, apr_size_t len, apr_file_t *logf, int level)
Definition log.c:1135
apr_pool_t * p
Definition md_event.c:32
static const char * log_format(cmd_parms *cmd, void *dummy, const char *fmt, const char *name)
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
sconf
Definition mod_so.c:349
static int generate_log_id(const conn_rec *c, const request_rec *r, const char **id)
static int mpm_state
apr_os_thread_t apr_os_thread_current()
Definition thread.c:142
char * name
Definition log.c:71
const char * t_name
Definition log.c:72
int t_val
Definition log.c:73
Structure to store things which are per connection.
Definition httpd.h:1152
The piped logging structure.
Definition log.c:186
apr_file_t * write_fd
Definition log.c:190
apr_pool_t * p
Definition log.c:188
apr_file_t * read_fd
Definition log.c:190
A structure that represents one process.
Definition httpd.h:829
int argc
Definition httpd.h:839
const char *const * argv
Definition httpd.h:837
apr_file_t * handle
Definition log.c:175
struct read_handle_t * next
Definition log.c:174
A structure that represents the current request.
Definition httpd.h:845
apr_table_t * notes
Definition httpd.h:985
apr_pool_t * pool
Definition httpd.h:847
apr_time_t request_time
Definition httpd.h:886
conn_rec * connection
Definition httpd.h:849
const char * log_id
Definition httpd.h:1059
request_rec * main
Definition httpd.h:860
server_rec * server
Definition httpd.h:851
A structure to store information for each virtual server.
Definition httpd.h:1322
apr_file_t * error_log
Definition httpd.h:1333
server_rec * next
Definition httpd.h:1326
char * error_fname
Definition httpd.h:1331
struct ap_conf_vector_t * module_config
Definition httpd.h:1341
apr_status_t apr_strftime(char *s, apr_size_t *retsize, apr_size_t max, const char *format, apr_time_exp_t *xt)
Definition timestr.c:132
apr_status_t apr_ctime(char *date_str, apr_time_t t)
Definition timestr.c:90
#define str
Apache date-time handling functions.
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray
INT info