2 * Copyright (c) 1995 - 2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 #include <sys/types.h>
46 #ifdef HAVE_SYS_RESOURCE_H
47 #include <sys/resource.h>
58 #endif /* HAVE_SYSLOG */
66 * The structure for each logging method.
72 struct log_method
*method
;
74 const struct units
*unit
;
80 void (*open
)(Log_method
*, const char *progname
, char *fname
,
82 void (*vprint
)(Log_method
*, char *, va_list);
83 void (*print
)(Log_method
*, char *);
84 void (*close
)(Log_method
*);
91 struct log_unit
**units
;
94 struct log_method_file_data
{
97 #define LOGFILE_NO_TIME 1
102 static void log_open_syslog (Log_method
*lm
, const char *progname
,
103 char *fname
, char *extra_args
);
105 static void log_close_syslog (Log_method
*lm
);
107 static void log_vprint_syslog (Log_method
*lm
, char *, va_list);
108 #endif /* HAVE_VSYSLOG */
109 static void log_print_syslog (Log_method
*lm
, char *);
110 #endif /* HAVE_SYSLOG */
113 log_open_stderr (Log_method
*lm
, const char *progname
, char *fname
,
117 log_open_file (Log_method
*lm
, const char *progname
, char *fname
,
121 log_close_file (Log_method
*lm
);
124 log_print_file (Log_method
*lm
, char *);
127 log_vprint_file (Log_method
*lm
, char *, va_list);
130 * The names for which we do special handling in the logging routines.
134 Log_method special_names
[] = {
136 {"syslog", log_open_syslog
,
138 log_vprint_syslog
, log_print_syslog
140 NULL
, log_print_syslog
141 #endif /* HAVE_VSYSLOG */
143 #endif /* HAVE_SYSLOG */
144 {"/dev/stderr", log_open_stderr
, log_vprint_file
, log_print_file
, NULL
},
145 {NULL
, log_open_file
, log_vprint_file
, log_print_file
, log_close_file
}
151 struct units syslog_opt_units
[] = {
153 { "stderr", LOG_PERROR
},
156 { "no-delay", LOG_NDELAY
},
159 { "console", LOG_CONS
},
167 struct units syslog_facility_units
[] = {
169 { "auth", LOG_AUTH
},
172 { "authpriv", LOG_AUTHPRIV
},
175 { "cron", LOG_CRON
},
178 { "daemon", LOG_DAEMON
},
184 { "kern", LOG_KERN
},
190 { "mail", LOG_MAIL
},
193 { "news", LOG_NEWS
},
196 { "syslog", LOG_SYSLOG
},
199 { "user", LOG_USER
},
202 { "uucp", LOG_UUCP
},
205 { "local0", LOG_LOCAL0
},
208 { "local1", LOG_LOCAL1
},
211 { "local2", LOG_LOCAL2
},
214 { "local3", LOG_LOCAL3
},
217 { "local4", LOG_LOCAL4
},
220 { "local5", LOG_LOCAL5
},
223 { "local6", LOG_LOCAL6
},
226 { "local7", LOG_LOCAL7
},
232 log_open_syslog (Log_method
*lm
, const char *progname
, char *fname
,
235 int logopt
= LOG_PID
| LOG_NDELAY
;
236 int facility
= LOG_DAEMON
;
238 char *facility_str
= NULL
;
243 strsep (&facility_str
, ":");
245 logopt
= parse_flags (opt
, syslog_opt_units
, logopt
);
247 fprintf (stderr
, "log_open: error parsing syslog "
248 "optional flags: %s\n", opt
);
249 print_flags_table (syslog_opt_units
, stderr
);
254 struct units
*best_match
= NULL
, *u
= syslog_facility_units
;
255 int len
= strlen(facility_str
);
258 if (strcasecmp(u
->name
, facility_str
) == 0) {
262 if (strncasecmp(u
->name
, facility_str
, len
) == 0) {
264 errx (1, "log_open: log facility %s is ambiguous",
270 if (best_match
== NULL
)
271 errx (1, "log_open: unknown facility %s", facility_str
);
275 openlog (progname
, logopt
, facility
);
281 log_vprint_syslog (Log_method
*lm
, char *fmt
, va_list args
)
283 vsyslog (LOG_NOTICE
, fmt
, args
);
285 #endif /* HAVE_VSYSLOG */
288 log_print_syslog (Log_method
*lm
, char *str
)
290 syslog (LOG_NOTICE
, "%s", str
);
294 log_close_syslog (Log_method
*lm
)
299 #endif /* HAVE_SYSLOG */
302 file_parse_extra(FILE *f
, char *extra_args
)
306 if (extra_args
== NULL
)
309 if (strlen(extra_args
) == 0)
312 str
= strsep(&extra_args
, ":");
317 if (strncasecmp(str
, "notime", 6) == 0)
318 flags
|= LOGFILE_NO_TIME
;
320 fprintf (f
, "unknown flag: `%s'\n", str
);
321 } while (extra_args
!= NULL
);
327 log_open_file_common(struct log_method_file_data
*data
,
328 const char *progname
, char *extra_args
)
330 if (progname
!= NULL
)
331 data
->progname
= strdup(progname
);
333 progname
= "unknown-program";
334 if (data
->progname
== NULL
)
335 data
->progname
= "out of memory";
336 data
->flags
= file_parse_extra(data
->f
, extra_args
);
340 log_open_stderr (Log_method
*lm
, const char *progname
, char *fname
,
343 struct log_method_file_data
*data
;
344 data
= malloc(sizeof(*data
));
346 errx (1, "log_open_stderr: failed to malloc");
350 log_open_file_common(data
, progname
, extra_args
);
354 log_open_file (Log_method
*lm
, const char *progname
, char *fname
,
357 struct log_method_file_data
*data
;
358 data
= malloc(sizeof(*data
));
360 errx (1, "log_open_stderr: failed to malloc");
363 data
->f
= fopen (fname
, "a");
366 log_open_file_common(data
, progname
, extra_args
);
370 log_printf_file(Log_method
*lm
, char *fmt
, ...)
374 va_start (args
, fmt
);
375 log_vprint_file(lm
, fmt
, args
);
380 log_print_file(Log_method
*lm
, char *str
)
382 log_printf_file(lm
, "%s", str
);
386 log_vprint_file (Log_method
*lm
, char *fmt
, va_list args
)
388 struct timeval tv
= { 0, 0 };
391 struct log_method_file_data
*data
= lm
->data
.v
;
394 if ((data
->flags
& LOGFILE_NO_TIME
) == 0) {
396 gettimeofday(&tv
, NULL
);
398 strftime(time
, sizeof(time
), "%Y-%m-%d %H:%M:%S %Z",
399 localtime_r(&t
, &tm
));
400 time
[sizeof(time
)-1] = '\0';
401 fprintf (f
, "%s: ", time
);
404 fprintf (f
, "%s: ", data
->progname
);
405 vfprintf (f
, fmt
, args
);
411 log_close_file (Log_method
*lm
)
413 struct log_method_file_data
*data
= lm
->data
.v
;
419 log_open (const char *progname
, char *fname
)
425 name
= strdup(fname
);
429 logm
= (Log_method
*)malloc (sizeof(Log_method
));
434 for (i
= 0; i
< sizeof(special_names
) / sizeof(*special_names
);
437 if (special_names
[i
].name
)
438 len
= strlen(special_names
[i
].name
);
439 if (special_names
[i
].name
== NULL
440 || (strncmp (special_names
[i
].name
, fname
, len
) == 0 &&
441 (special_names
[i
].name
[len
] == '\0'
442 || special_names
[i
].name
[len
] == ':'))) {
443 *logm
= special_names
[i
];
451 (*logm
->open
)(logm
, progname
, name
, extra
);
457 log_setflags(Log_method
*method
, log_flags flags
)
461 oldflags
= method
->flags
;
462 method
->flags
= flags
;
467 log_getflags(Log_method
*method
)
469 return method
->flags
;
473 log_set_mask (Log_unit
*logu
, unsigned m
)
479 log_get_mask (Log_unit
*unit
)
485 _internal_vlog (Log_method
*method
, const char *fmt
, va_list args
)
487 if (method
->vprint
&& (method
->flags
& LOG_CPU_USAGE
) == 0)
488 (*method
->vprint
)(method
, (char *) fmt
, args
);
492 vasprintf (&buf
, fmt
, args
);
495 #ifdef HAVE_GETRUSAGE
496 if (method
->flags
& LOG_CPU_USAGE
) {
501 ret
= getrusage(RUSAGE_SELF
, &usage
);
503 asprintf(&rbuf
, "s: %d.%d u: %d.%d",
504 (int)usage
.ru_stime
.tv_sec
,
505 (int)usage
.ru_stime
.tv_usec
,
506 (int)usage
.ru_utime
.tv_sec
,
507 (int)usage
.ru_utime
.tv_usec
);
511 asprintf(&buf2
, "%s %s", buf
, rbuf
);
520 #endif /* HAVE_GETRUSAGE */
521 (*method
->print
)(method
, buf
);
523 (*method
->print
)(method
, "not enough memory to print");
529 _internal_log (Log_method
*method
, const char *fmt
, ...)
533 va_start (args
, fmt
);
534 _internal_vlog(method
, fmt
, args
);
539 log_vlog(Log_unit
*unit
, unsigned level
, const char *fmt
, va_list args
)
541 if (level
& unit
->mask
)
542 _internal_vlog (unit
->method
, fmt
, args
);
547 log_log (Log_unit
*logu
, unsigned level
, const char *fmt
, ...)
551 va_start (args
, fmt
);
552 log_vlog(logu
, level
, fmt
, args
);
557 log_close (Log_method
*method
)
561 (*method
->close
)(method
);
562 for (i
= 0 ; i
< method
->num_units
; i
++)
563 log_unit_free (method
, method
->units
[i
]);
564 free (method
->units
);
565 method
->units
= NULL
;
570 log_unit_init (Log_method
*method
, const char *name
, struct units
*unit
,
571 unsigned long default_mask
)
575 u
= malloc (sizeof(Log_unit
));
578 list
= realloc (method
->units
,
579 (method
->num_units
+ 1) * sizeof(Log_unit
*));
584 method
->units
= list
;
585 method
->units
[method
->num_units
] = u
;
586 method
->num_units
+= 1;
589 u
->name
= estrdup (name
);
591 u
->mask
= default_mask
;
596 log_unit_free (Log_method
*method
, Log_unit
*logu
)
601 for (i
= 0; i
< method
->num_units
; i
++)
602 if (logu
== method
->units
[method
->num_units
])
604 if (i
< method
->num_units
- 1)
605 memmove (&method
->units
[i
], &method
->units
[i
+1],
606 method
->num_units
- i
);
608 method
->num_units
-= 1;
609 list
= realloc (method
->units
, method
->num_units
* sizeof(Log_unit
*));
612 method
->units
= list
;
615 assert (logu
->method
== method
);
623 parse_word (Log_method
*m
, char **str
, Log_unit
**u
, char **log_str
)
628 if (**str
== '\0') return 1;
629 while (**str
!= '\0' && (isspace((unsigned char)**str
) || **str
== ';'))
631 if (**str
== '\0') return 1;
634 while (**str
!= '\0' && !isspace((unsigned char)**str
) && **str
!= ':')
641 str_len
= strlen(first
);
642 for (j
= 0; j
< m
->num_units
; j
++) {
643 if (strcasecmp(m
->units
[j
]->name
, first
) == 0)
645 if (strncasecmp(m
->units
[j
]->name
, first
, str_len
) == 0) {
651 if (j
== m
->num_units
) {
653 *u
= m
->units
[best_fit
];
663 while (**str
!= '\0' && **str
!= ';')
673 unit_parse_flags (const char *log_str
, struct log_unit
*unit
)
676 ret
= parse_flags (log_str
, unit
->unit
, log_get_mask(unit
));
679 log_set_mask (unit
, ret
);
684 log_set_mask_str (Log_method
*method
, Log_unit
*default_unit
, const char *str
)
686 char *log_str
, *ptr
, *str2
;
687 Log_unit
*unit
= NULL
;
690 str2
= ptr
= estrdup (str
);
691 while (parse_word (method
, &ptr
, &unit
, &log_str
) == 0) {
692 if (unit
|| default_unit
) {
693 if ((unit
&& default_unit
) && unit
!= default_unit
)
694 _internal_log (method
,
695 "log_set_mask_str: default with unit string"
696 "%s:%s", unit
->name
, log_str
);
699 ret
= unit_parse_flags (log_str
, unit
);
701 _internal_log (unit
->method
,
702 "log error parsing: %s:%s\n",
703 unit
->name
, log_str
);
708 /* If something matches, be merry */
709 for (i
= 0; i
< method
->num_units
; i
++) {
710 if (unit_parse_flags (log_str
, method
->units
[i
]) != -1)
714 _internal_log (method
,
715 "log error parsing: %s\n",
722 #define UPDATESZ(str,len,update) \
723 do { (str) += (update); (len) -= min((len),(update)); } while (0)
726 _print_unit (Log_unit
*unit
, char *buf
, size_t sz
)
728 size_t ret
, orig_sz
= sz
;
729 ret
= snprintf (buf
, sz
, "%s:", unit
->name
);
734 UPDATESZ(buf
,sz
,ret
);
735 ret
= unparse_flags (log_get_mask (unit
), unit
->unit
, buf
, sz
);
736 UPDATESZ(buf
,sz
,ret
);
741 log_mask2str (Log_method
*method
, Log_unit
*unit
, char *buf
, size_t sz
)
743 size_t ret
, orig_sz
= sz
;
746 if (sz
) buf
[0] = '\0';
749 return _print_unit (unit
, buf
, sz
);
751 for (i
= 0; i
< method
->num_units
; i
++) {
752 if (log_get_mask (method
->units
[i
])) {
754 ret
= snprintf (buf
, sz
, ";");
759 UPDATESZ(buf
,sz
,ret
);
761 ret
= _print_unit (method
->units
[i
], buf
, sz
);
762 UPDATESZ(buf
,sz
,ret
);