#include "gwlib.h"#include <limits.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <time.h>#include <stdarg.h>#include <string.h>#include <execinfo.h>#include <syslog.h>Include dependency graph for log.c:

Go to the source code of this file.
Defines | |
| #define | MAX_LOGFILES 128 |
| #define | THREADTABLE_SIZE 1024 |
| #define | thread_slot() (gwthread_self() % THREADTABLE_SIZE) |
| #define | MAX_LOGGABLE_PLACES (10*1000) |
| #define | FORMAT_SIZE (1024) |
| #define | FUNCTION_GUTS(level, place) |
| #define | FUNCTION_GUTS_EXCL(level, place) |
Functions | |
| void | add_stderr (void) |
| void | log_init (void) |
| void | log_shutdown (void) |
| void | log_set_output_level (enum output_level level) |
| void | log_set_log_level (enum output_level level) |
| void | log_set_syslog (const char *ident, int syslog_level) |
| void | log_reopen (void) |
| void | log_close_all (void) |
| int | log_open (char *filename, int level, enum excl_state excl) |
| void | format (char *buf, int level, const char *place, int e, const char *fmt, int with_timestamp) |
| void | PRINTFLIKE (2, 0) |
| void | PRINTFLIKE (1, 0) |
| void | PRINTFLIKE (2, 3) |
| void | gw_panic (int err, const char *fmt,...) |
| void | error (int err, const char *fmt,...) |
| void | warning (int err, const char *fmt,...) |
| void | info (int err, const char *fmt,...) |
| int | place_matches (const char *place, const char *pat) |
| int | place_should_be_logged (const char *place) |
| int | place_is_not_logged (const char *place) |
| void | debug (const char *place, int err, const char *fmt,...) |
| void | log_set_debug_places (const char *places) |
| void | log_thread_to (unsigned int idx) |
Variables | |
| struct { | |
| FILE * file | |
| int minimum_output_level | |
| char filename [FILENAME_MAX+1] | |
| } | logfiles [MAX_LOGFILES] |
| int | num_logfiles = 0 |
| unsigned int | thread_to [(long) THREADTABLE_SIZE] |
| char * | loggable_places [MAX_LOGGABLE_PLACES] |
| int | num_places = 0 |
| RWLock | rwlock |
| int | sysloglevel |
| int | dosyslog = 0 |
|
|
|
|
|
Value: do { \ int i; \ char buf[FORMAT_SIZE]; \ va_list args; \ \ format(buf, level, place, err, fmt, 1); \ gw_rwlock_rdlock(&rwlock); \ for (i = 0; i < num_logfiles; ++i) { \ if (logfiles[i].exclusive == GW_NON_EXCL && \ level >= logfiles[i].minimum_output_level && \ logfiles[i].file != NULL) { \ va_start(args, fmt); \ output(logfiles[i].file, buf, args); \ va_end(args); \ } \ } \ gw_rwlock_unlock(&rwlock); \ if (dosyslog) { \ format(buf, level, place, err, fmt, 0); \ va_start(args, fmt); \ kannel_syslog(buf,args,level); \ va_end(args); \ } \ } while (0) Definition at line 470 of file log.c. Referenced by debug(), error(), gw_panic(), info(), PRINTFLIKE(), and warning(). |
|
|
Value: do { \ char buf[FORMAT_SIZE]; \ va_list args; \ \ format(buf, level, place, err, fmt, 1); \ gw_rwlock_rdlock(&rwlock); \ if (logfiles[e].exclusive == GW_EXCL && \ level >= logfiles[e].minimum_output_level && \ logfiles[e].file != NULL) { \ va_start(args, fmt); \ output(logfiles[e].file, buf, args); \ va_end(args); \ } \ gw_rwlock_unlock(&rwlock); \ } while (0) |
|
|
|
|
|
|
|
|
Definition at line 126 of file log.c. Referenced by debug(), error(), info(), log_thread_to(), and warning(). |
|
|
|
|
|
Definition at line 153 of file log.c. References logfiles. Referenced by log_init(). 00154 {
00155 int i;
00156
00157 for (i = 0; i < num_logfiles; ++i)
00158 if (logfiles[i].file == stderr)
00159 return;
00160 logfiles[num_logfiles].file = stderr;
00161 logfiles[num_logfiles].minimum_output_level = GW_DEBUG;
00162 logfiles[num_logfiles].exclusive = GW_NON_EXCL;
00163 ++num_logfiles;
00164 }
|
|
||||||||||||||||||||
|
Definition at line 640 of file log.c. References FUNCTION_GUTS, FUNCTION_GUTS_EXCL, GW_DEBUG, place_is_not_logged(), place_should_be_logged(), thread_slot, and thread_to. 00641 {
00642 int e;
00643
00644 if (place_should_be_logged(place) && place_is_not_logged(place) == 0) {
00645 /*
00646 * Note: giving `place' to FUNCTION_GUTS makes log lines
00647 * too long and hard to follow. We'll rely on an external
00648 * list of what places are used instead of reading them
00649 * from the log file.
00650 */
00651 if ((e = thread_to[thread_slot()])) {
00652 FUNCTION_GUTS_EXCL(GW_DEBUG, "");
00653 } else {
00654 FUNCTION_GUTS(GW_DEBUG, "");
00655 }
00656 }
00657 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
||||||||||||||||||||||||||||
|
Definition at line 356 of file log.c. References FORMAT_SIZE, gw_gmtime(), gw_localtime(), gwthread_self_ids(), and tid. Referenced by alog(), and PRINTFLIKE(). 00358 {
00359 static char *tab[] = {
00360 "DEBUG: ",
00361 "INFO: ",
00362 "WARNING: ",
00363 "ERROR: ",
00364 "PANIC: ",
00365 "LOG: "
00366 };
00367 static int tab_size = sizeof(tab) / sizeof(tab[0]);
00368 time_t t;
00369 struct tm tm;
00370 char *p, prefix[1024];
00371 long tid, pid;
00372
00373 p = prefix;
00374
00375 if (with_timestamp) {
00376 time(&t);
00377 #if LOG_TIMESTAMP_LOCALTIME
00378 tm = gw_localtime(t);
00379 #else
00380 tm = gw_gmtime(t);
00381 #endif
00382 sprintf(p, "%04d-%02d-%02d %02d:%02d:%02d ",
00383 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
00384 tm.tm_hour, tm.tm_min, tm.tm_sec);
00385
00386 p = strchr(p, '\0');
00387 }
00388
00389 gwthread_self_ids(&tid, &pid);
00390 sprintf(p, "[%ld] [%ld] ", pid, tid);
00391
00392 p = strchr(p, '\0');
00393 if (level < 0 || level >= tab_size)
00394 sprintf(p, "UNKNOWN: ");
00395 else
00396 sprintf(p, "%s", tab[level]);
00397
00398 p = strchr(p, '\0');
00399 if (place != NULL && *place != '\0')
00400 sprintf(p, "%s: ", place);
00401
00402 if (strlen(prefix) + strlen(fmt) > FORMAT_SIZE / 2) {
00403 sprintf(buf, "%s <OUTPUT message too long>\n", prefix);
00404 return;
00405 }
00406
00407 if (e == 0)
00408 sprintf(buf, "%s%s\n", prefix, fmt);
00409 else
00410 sprintf(buf, "%s%s\n%sSystem error %d: %s\n",
00411 prefix, fmt, prefix, e, strerror(e));
00412 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 521 of file log.c. References FUNCTION_GUTS, GW_PANIC, and size. 00522 {
00523 /*
00524 * we don't want PANICs to spread accross smsc logs, so
00525 * this will be always within the main core log.
00526 */
00527 FUNCTION_GUTS(GW_PANIC, "");
00528
00529 #ifdef HAVE_BACKTRACE
00530 {
00531 void *stack_frames[50];
00532 size_t size, i;
00533 char **strings;
00534
00535 size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
00536 strings = backtrace_symbols(stack_frames, size);
00537
00538 if (strings) {
00539 for (i = 0; i < size; i++)
00540 gw_panic_output(0, "%s", strings[i]);
00541 }
00542 else { /* hmm, no memory available */
00543 for (i = 0; i < size; i++)
00544 gw_panic_output(0, "%p", stack_frames[i]);
00545 }
00546
00547 /*
00548 * Note: we don't free 'strings' array because gw_free could panic's and we
00549 * have endless loop with SEGFAULT at the end. And this doesn't care
00550 * us in any case, because we are panic's and exiting immediately. (alex)
00551 */
00552 }
00553 #endif
00554
00555 #ifdef SEGFAULT_PANIC
00556 *((char*)0) = 0;
00557 #endif
00558
00559 exit(EXIT_FAILURE);
00560 }
|
|
||||||||||||||||
|
Definition at line 587 of file log.c. References FUNCTION_GUTS, FUNCTION_GUTS_EXCL, GW_INFO, thread_slot, and thread_to. Referenced by find_hb(), heartbeat_start(), heartbeat_stop(), heartbeat_thread(), octstr_dump_real(), producer(), smsc2_rout(), and smsc2_status(). 00588 {
00589 int e;
00590
00591 if ((e = thread_to[thread_slot()])) {
00592 FUNCTION_GUTS_EXCL(GW_INFO, "");
00593 } else {
00594 FUNCTION_GUTS(GW_INFO, "");
00595 }
00596 }
|
|
|
Definition at line 273 of file log.c. References dosyslog, file, gw_rwlock_unlock(), gw_rwlock_wrlock(), logfiles, num_logfiles, and rwlock. Referenced by get_and_set_debugs(), log_shutdown(), and main(). 00274 {
00275 /*
00276 * Writer lock.
00277 */
00278 gw_rwlock_wrlock(&rwlock);
00279
00280 while (num_logfiles > 0) {
00281 --num_logfiles;
00282 if (logfiles[num_logfiles].file != stderr &&
00283 logfiles[num_logfiles].file != NULL)
00284 fclose(logfiles[num_logfiles].file);
00285 logfiles[num_logfiles].file = NULL;
00286 }
00287
00288 /*
00289 * Unlock writer.
00290 */
00291 gw_rwlock_unlock(&rwlock);
00292
00293 /* close syslog if used */
00294 if (dosyslog) {
00295 closelog();
00296 dosyslog = 0;
00297 }
00298 }
|
Here is the call graph for this function:

|
|
Definition at line 167 of file log.c. References add_stderr(), gw_rwlock_init_static(), rwlock, and thread_to. Referenced by gwlib_init(). 00168 {
00169 unsigned long i;
00170
00171 /* Initialize rwlock */
00172 gw_rwlock_init_static(&rwlock);
00173
00174 /* default all possible thread to logging index 0, stderr */
00175 for (i = 0; i <= THREADTABLE_SIZE; i++) {
00176 thread_to[i] = 0;
00177 }
00178
00179 add_stderr();
00180 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 301 of file log.c. References error(), filename, gw_rwlock_unlock(), gw_rwlock_wrlock(), info(), logfiles, num_logfiles, and rwlock. Referenced by get_and_set_debugs(), init_bearerbox(), init_smsbox(), init_wapbox(), main(), and smscconn_create(). 00302 {
00303 FILE *f = NULL;
00304 int i;
00305
00306 gw_rwlock_wrlock(&rwlock);
00307
00308 if (num_logfiles == MAX_LOGFILES) {
00309 gw_rwlock_unlock(&rwlock);
00310 error(0, "Too many log files already open, not adding `%s'",
00311 filename);
00312 return -1;
00313 }
00314
00315 if (strlen(filename) > FILENAME_MAX) {
00316 gw_rwlock_unlock(&rwlock);
00317 error(0, "Log filename too long: `%s'.", filename);
00318 return -1;
00319 }
00320
00321 /*
00322 * Check if the file is already opened for logging.
00323 * If there is an open file, then assign the file descriptor
00324 * that is already existing for this log file.
00325 */
00326 for (i = 0; i < num_logfiles && f == NULL; ++i) {
00327 if (strcmp(logfiles[i].filename, filename) == 0)
00328 f = logfiles[i].file;
00329 }
00330
00331 /* if not previously opened, then open it now */
00332 if (f == NULL) {
00333 f = fopen(filename, "a");
00334 if (f == NULL) {
00335 gw_rwlock_unlock(&rwlock);
00336 error(errno, "Couldn't open logfile `%s'.", filename);
00337 return -1;
00338 }
00339 }
00340
00341 logfiles[num_logfiles].file = f;
00342 logfiles[num_logfiles].minimum_output_level = level;
00343 logfiles[num_logfiles].exclusive = excl;
00344 strcpy(logfiles[num_logfiles].filename, filename);
00345 ++num_logfiles;
00346 i = num_logfiles - 1;
00347 gw_rwlock_unlock(&rwlock);
00348
00349 info(0, "Added logfile `%s' with level `%d'.", filename, level);
00350
00351 return i;
00352 }
|
Here is the call graph for this function:

|
|
Definition at line 229 of file log.c. References error(), file, filename, gw_rwlock_unlock(), gw_rwlock_wrlock(), logfiles, and rwlock. Referenced by main(), and signal_handler(). 00230 {
00231 int i, j, found;
00232
00233 /*
00234 * Writer lock.
00235 */
00236 gw_rwlock_wrlock(&rwlock);
00237
00238 for (i = 0; i < num_logfiles; ++i) {
00239 if (logfiles[i].file != stderr) {
00240 found = 0;
00241
00242 /*
00243 * Reverse seek for allready reopened logfile.
00244 * If we find a previous file descriptor for the same file
00245 * name, then don't reopen that duplicate, but assign the
00246 * file pointer to it.
00247 */
00248 for (j = i-1; j >= 0 && found == 0; j--) {
00249 if (strcmp(logfiles[i].filename, logfiles[j].filename) == 0) {
00250 logfiles[i].file = logfiles[j].file;
00251 found = 1;
00252 }
00253 }
00254 if (found)
00255 continue;
00256 if (logfiles[i].file != NULL)
00257 fclose(logfiles[i].file);
00258 logfiles[i].file = fopen(logfiles[i].filename, "a");
00259 if (logfiles[i].file == NULL) {
00260 error(errno, "Couldn't re-open logfile `%s'.",
00261 logfiles[i].filename);
00262 }
00263 }
00264 }
00265
00266 /*
00267 * Unlock writer.
00268 */
00269 gw_rwlock_unlock(&rwlock);
00270 }
|
Here is the call graph for this function:

|
|
Definition at line 660 of file log.c. References loggable_places, and num_places. Referenced by get_and_set_debugs(). 00661 {
00662 char *p;
00663
00664 p = strtok(gw_strdup(places), " ,");
00665 num_places = 0;
00666 while (p != NULL && num_places < MAX_LOGGABLE_PLACES) {
00667 loggable_places[num_places++] = p;
00668 p = strtok(NULL, " ,");
00669 }
00670 }
|
|
|
Definition at line 202 of file log.c. References filename, info(), and logfiles. Referenced by config_reload(), and httpd_loglevel(). 00203 {
00204 int i;
00205
00206 /* change everything but stderr */
00207 for (i = 0; i < num_logfiles; ++i) {
00208 if (logfiles[i].file != stderr) {
00209 logfiles[i].minimum_output_level = level;
00210 info(0, "Changed logfile `%s' to level `%d'.", logfiles[i].filename, level);
00211 }
00212 }
00213 }
|
Here is the call graph for this function:

|
|
Definition at line 190 of file log.c. References logfiles. Referenced by get_and_set_debugs(), and main(). 00191 {
00192 int i;
00193
00194 for (i = 0; i < num_logfiles; ++i) {
00195 if (logfiles[i].file == stderr) {
00196 logfiles[i].minimum_output_level = level;
00197 break;
00198 }
00199 }
00200 }
|
|
||||||||||||
|
Definition at line 216 of file log.c. References debug(), dosyslog, and sysloglevel. Referenced by get_and_set_debugs(), and init_wapbox(). 00217 {
00218 if (ident == NULL)
00219 dosyslog = 0;
00220 else {
00221 dosyslog = 1;
00222 sysloglevel = syslog_level;
00223 openlog(ident, LOG_PID, LOG_DAEMON);
00224 debug("gwlib.log", 0, "Syslog logging enabled.");
00225 }
00226 }
|
Here is the call graph for this function:

|
|
Definition at line 182 of file log.c. References gw_rwlock_destroy(), log_close_all(), and rwlock. Referenced by gwlib_shutdown(). 00183 {
00184 log_close_all();
00185 /* destroy rwlock */
00186 gw_rwlock_destroy(&rwlock);
00187 }
|
Here is the call graph for this function:

|
|
Definition at line 673 of file log.c. References filename, info(), logfiles, minimum_output_level, thread_slot, and thread_to. Referenced by at2_device_thread(), cgw_listener(), cgw_sender(), emi2_listener(), emi2_sender(), fake_listener(), httpsmsc_receiver(), httpsmsc_send_cb(), io_thread(), smasi_thread(), wrapper_receiver(), and wrapper_sender(). 00674 {
00675 long thread_id = thread_slot();
00676
00677 if (idx > 0)
00678 info(0, "Logging thread `%ld' to logfile `%s' with level `%d'.",
00679 thread_id, logfiles[idx].filename, logfiles[idx].minimum_output_level);
00680 thread_to[thread_id] = idx;
00681 }
|
Here is the call graph for this function:

|
|
Definition at line 625 of file log.c. References loggable_places, num_places, and place_matches(). Referenced by debug(). 00626 {
00627 int i;
00628
00629 if (num_places == 0)
00630 return 0;
00631 for (i = 0; i < num_places; ++i) {
00632 if (*loggable_places[i] == '-' &&
00633 place_matches(place, loggable_places[i]+1))
00634 return 1;
00635 }
00636 return 0;
00637 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 599 of file log.c. Referenced by place_is_not_logged(), and place_should_be_logged(). 00600 {
00601 size_t len;
00602
00603 len = strlen(pat);
00604 if (pat[len-1] == '*')
00605 return (strncasecmp(place, pat, len - 1) == 0);
00606 return (strcasecmp(place, pat) == 0);
00607 }
|
|
|
Definition at line 610 of file log.c. References loggable_places, num_places, and place_matches(). Referenced by debug(). 00611 {
00612 int i;
00613
00614 if (num_places == 0)
00615 return 1;
00616 for (i = 0; i < num_places; ++i) {
00617 if (*loggable_places[i] != '-' &&
00618 place_matches(place, loggable_places[i]))
00619 return 1;
00620 }
00621 return 0;
00622 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 515 of file log.c. References FUNCTION_GUTS, and GW_PANIC. 00516 {
00517 FUNCTION_GUTS(GW_PANIC, "");
00518 }
|
|
||||||||||||
|
Definition at line 422 of file log.c. References format(), GW_DEBUG, GW_ERROR, GW_INFO, GW_PANIC, GW_WARNING, and sysloglevel. 00423 {
00424 char buf[4096]; /* Trying to syslog more than 4K could be bad */
00425 int translog;
00426
00427 if (level >= sysloglevel && dosyslog) {
00428 if (args == NULL) {
00429 strncpy(buf, format, sizeof(buf));
00430 buf[sizeof(buf) - 1] = '\0';
00431 } else {
00432 vsnprintf(buf, sizeof(buf), format, args);
00433 /* XXX vsnprint not 100% portable */
00434 }
00435
00436 switch(level) {
00437 case GW_DEBUG:
00438 translog = LOG_DEBUG;
00439 break;
00440 case GW_INFO:
00441 translog = LOG_INFO;
00442 break;
00443 case GW_WARNING:
00444 translog = LOG_WARNING;
00445 break;
00446 case GW_ERROR:
00447 translog = LOG_ERR;
00448 break;
00449 case GW_PANIC:
00450 translog = LOG_ALERT;
00451 break;
00452 default:
00453 translog = LOG_INFO;
00454 break;
00455 }
00456 syslog(translog, "%s", buf);
00457 }
00458 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 415 of file log.c. 00416 {
00417 vfprintf(f, buf, args);
00418 fflush(f);
00419 }
|
|
||||||||||||||||
|
Definition at line 575 of file log.c. References FUNCTION_GUTS, FUNCTION_GUTS_EXCL, GW_WARNING, thread_slot, and thread_to. Referenced by octstr_dump_real(), and pack_content_range(). 00576 {
00577 int e;
00578
00579 if ((e = thread_to[thread_slot()])) {
00580 FUNCTION_GUTS_EXCL(GW_WARNING, "");
00581 } else {
00582 FUNCTION_GUTS(GW_WARNING, "");
00583 }
00584 }
|
|
|
Definition at line 147 of file log.c. Referenced by log_close_all(), and log_set_syslog(). |
|
|
|
Definition at line 108 of file log.c. Referenced by cfg_create(), cfg_read(), cfgloc_create(), dispatch(), for_each_file(), gw_check_malloc(), gw_check_realloc(), gw_check_strdup(), is_executable(), log_open(), log_reopen(), log_set_log_level(), log_thread_to(), main(), octstr_read_file(), seems_valid_real(), send_file(), status_cb(), and store_spool_save(). |
|
|
Referenced by add_stderr(), log_close_all(), log_open(), log_reopen(), log_set_log_level(), log_set_output_level(), and log_thread_to(). |
|
|
Definition at line 134 of file log.c. Referenced by log_set_debug_places(), place_is_not_logged(), and place_should_be_logged(). |
|
|
Definition at line 107 of file log.c. Referenced by log_thread_to(). |
|
|
Definition at line 111 of file log.c. Referenced by log_close_all(), and log_open(). |
|
|
Definition at line 135 of file log.c. Referenced by log_set_debug_places(), place_is_not_logged(), and place_should_be_logged(). |
|
|
Definition at line 141 of file log.c. Referenced by log_close_all(), log_init(), log_open(), log_reopen(), and log_shutdown(). |
|
|
Definition at line 146 of file log.c. Referenced by log_set_syslog(), and PRINTFLIKE(). |
|
|
Definition at line 119 of file log.c. Referenced by debug(), error(), info(), log_init(), log_thread_to(), and warning(). |