71 #ifdef HAVE_EXECINFO_H 79 typedef struct _code {
84 CODE facilitynames[] = {
95 {
"security", LOG_AUTH },
96 {
"syslog", LOG_SYSLOG },
99 {
"local0", LOG_LOCAL0 },
100 {
"local1", LOG_LOCAL1 },
101 {
"local2", LOG_LOCAL2 },
102 {
"local3", LOG_LOCAL3 },
103 {
"local4", LOG_LOCAL4 },
104 {
"local5", LOG_LOCAL5 },
105 {
"local6", LOG_LOCAL6 },
106 {
"local7", LOG_LOCAL7 },
121 CODE *facilities = facilitynames;
123 if (isdigit(*
name)) {
126 for (c = facilities; c->c_name; c++) {
127 if (!strcasecmp(
name, c->c_name)) {
167 #define MAX_LOGFILES 4096 181 #define THREADTABLE_SIZE 1024 189 #define thread_slot() \ 190 (gwthread_self() % THREADTABLE_SIZE) 196 #define MAX_LOGGABLE_PLACES (10*1000) 259 logfiles[i].minimum_output_level = level;
272 logfiles[i].minimum_output_level = level;
280 if (facility != NULL)
292 debug(
"gwlib.log", 0,
"Syslog logging enabled.");
316 for (j = i-1; j >= 0 &&
found == 0; j--) {
328 error(errno,
"Couldn't re-open logfile `%s'.",
384 error(0,
"Too many log files already open, not adding `%s'",
389 if (strlen(
filename) > FILENAME_MAX) {
423 info(0,
"Added logfile `%s' with level `%d'.",
filename, level);
429 #define FORMAT_SIZE (1024) 430 static void format(
char *buf,
int level,
const char *place,
int e,
431 const char *fmt,
int with_timestamp_and_pid)
433 static char *tab[] = {
441 static int tab_size =
sizeof(tab) /
sizeof(tab[0]);
444 char *p, prefix[1024];
449 if (with_timestamp_and_pid) {
451 #if LOG_TIMESTAMP_LOCALTIME 456 sprintf(p,
"%04d-%02d-%02d %02d:%02d:%02d ",
457 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
458 tm.tm_hour, tm.tm_min, tm.tm_sec);
464 sprintf(p,
"[%ld] [%ld] ", pid, tid);
468 sprintf(p,
"[%ld] ", tid);
472 if (level < 0 || level >= tab_size)
473 sprintf(p,
"UNKNOWN: ");
475 sprintf(p,
"%s", tab[level]);
478 if (place != NULL && *place !=
'\0')
479 sprintf(p,
"%s: ", place);
481 if (strlen(prefix) + strlen(fmt) >
FORMAT_SIZE / 2) {
482 sprintf(buf,
"%s <OUTPUT message too long>\n", prefix);
487 sprintf(buf,
"%s%s\n", prefix, fmt);
489 sprintf(buf,
"%s%s\n%sSystem error %d: %s\n",
490 prefix, fmt, prefix, e, strerror(e));
494 static void PRINTFLIKE(2,0) output(FILE *f,
char *buf, va_list args)
496 vfprintf(f, buf, args);
507 vsnprintf(buf,
sizeof(buf),
format, args);
530 syslog(translog,
"%s", buf);
544 #define FUNCTION_GUTS(level, place) \ 548 char buf[FORMAT_SIZE]; \ 551 gw_rwlock_rdlock(&rwlock); \ 552 for (i = 0; i < num_logfiles; ++i) { \ 553 if (logfiles[i].exclusive == GW_NON_EXCL && \ 554 level >= logfiles[i].minimum_output_level && \ 555 logfiles[i].file != NULL) { \ 557 format(buf, level, place, err, fmt, 1); \ 560 va_start(args, fmt); \ 561 output(logfiles[i].file, buf, args); \ 565 gw_rwlock_unlock(&rwlock); \ 567 format(buf, level, place, err, fmt, 0); \ 568 va_start(args, fmt); \ 569 kannel_syslog(buf,args,level); \ 574 #define FUNCTION_GUTS_EXCL(level, place) \ 576 char buf[FORMAT_SIZE]; \ 579 gw_rwlock_rdlock(&rwlock); \ 580 if (logfiles[e].exclusive == GW_EXCL && \ 581 level >= logfiles[e].minimum_output_level && \ 582 logfiles[e].file != NULL) { \ 583 format(buf, level, place, err, fmt, 1); \ 584 va_start(args, fmt); \ 585 output(logfiles[e].file, buf, args); \ 588 gw_rwlock_unlock(&rwlock); \ 592 #ifdef HAVE_BACKTRACE 593 static void PRINTFLIKE(2,3) gw_panic_output(
int err, const
char *fmt, ...)
606 if (stack_frames == NULL) {
607 stack_frames = frames;
608 size = backtrace(stack_frames,
sizeof(frames) /
sizeof(
void*));
611 strings = backtrace_symbols(stack_frames,
size);
614 for (i = 0; i <
size; i++)
615 gw_panic_output(0,
"%s", strings[i]);
618 for (i = 0; i <
size; i++)
619 gw_panic_output(0,
"%p", stack_frames[i]);
640 #ifdef SEGFAULT_PANIC 648 void error(
int err,
const char *fmt, ...)
672 void info(
int err,
const char *fmt, ...)
689 if (pat[len-1] ==
'*')
690 return (strncasecmp(place, pat, len - 1) == 0);
692 return (strcasecmp(place, pat) == 0);
726 void debug(
const char *place,
int err,
const char *fmt, ...)
750 p = strtok(gw_strdup(places),
" ,");
754 p = strtok(NULL,
" ,");
764 info(0,
"Logging thread `%ld' to logfile `%s' with level `%d'.",
768 warning(0,
"Logging thread `%ld' to logfile `%s' with level `%d'.",
void error(int err, const char *fmt,...)
void info(int err, const char *fmt,...)
void log_set_debug_places(const char *places)
void gw_backtrace(void **stack_frames, size_t size, int lock)
void gw_native_free(void *ptr)
static struct @66 logfiles[MAX_LOGFILES]
struct tm gw_gmtime(time_t t)
#define FUNCTION_GUTS_EXCL(level, place)
void gw_rwlock_destroy(RWLock *lock)
int gw_rwlock_wrlock(RWLock *lock)
static unsigned int thread_to[(long) THREADTABLE_SIZE]
static void openlog(const char *ident, int option, int facility)
static char * loggable_places[MAX_LOGGABLE_PLACES]
void gwthread_self_ids(long *tid, long *pid)
void log_thread_to(int idx)
static struct pid_list * found
void gw_panic(int err, const char *fmt,...)
#define MAX_LOGGABLE_PLACES
void log_set_output_level(enum output_level level)
static int decode(char *name)
static void closelog(void)
void log_set_log_level(enum output_level level)
static void PRINTFLIKE(2, 0)
int gw_rwlock_unlock(RWLock *lock)
void warning(int err, const char *fmt,...)
void log_set_syslog_facility(char *facility)
char filename[FILENAME_MAX+1]
static int place_matches(const char *place, const char *pat)
void log_set_syslog(const char *ident, int syslog_level)
static void add_stderr(void)
static void syslog(int translog, const char *msg,...)
int log_open(char *filename, int level, enum excl_state excl)
static void format(char *buf, int level, const char *place, int e, const char *fmt, int with_timestamp_and_pid)
static int place_is_not_logged(const char *place)
void debug(const char *place, int err, const char *fmt,...)
struct tm gw_localtime(time_t t)
void gw_rwlock_init_static(RWLock *lock)
static XMLRPCDocument * msg
#define FUNCTION_GUTS(level, place)
enum excl_state exclusive
static int syslogfacility
static int place_should_be_logged(const char *place)