00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00022 #include "common.h"
00023
00024 #include <assert.h>
00025 #include <errno.h>
00026 #include <unistd.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <sys/types.h>
00030 #include <time.h>
00031
00032 #include "logger.h"
00033
00034 #include "buffer.h"
00035 #include "conftable.h"
00036 #include "fileplist.h"
00037 #include "loggerlist.h"
00038 #include "misc.h"
00039 #include "xmalloc.h"
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00051 #define lgGetSrcDescText(src) (((src) <= LOG_SRC_LAST) ? (log_src_info_tab[src][0]) : "unknown source")
00052
00054 #define lgGetSrcConfKey(src) (((src) <= LOG_SRC_LAST) ? (log_src_info_tab[src][1]) : "U")
00055
00057 #define lgGetSrcDescMaxLen() (lgGetSrcMaxLen(0))
00058
00059 #define lgGetSrcKeyMaxLen() (lgGetSrcMaxLen(1))
00060
00062 size_t lgGetSrcMaxLen(int which)
00063 {
00064 int src;
00065 size_t maxlen = 0;
00066
00067 assert(which == 0 || which == 1);
00068
00069 for(src = 0; src <= LOG_SRC_LAST; ++src)
00070 maxlen = MAX2(maxlen, strlen(log_src_info_tab[src][which]));
00071
00072 return MAX2(maxlen, strlen(LOG_SRC_PLACEHOLDER_ALL));
00073 }
00074
00075
00077 #define lgGetLvlConfKey(lvl) (((lvl) <= LOG_LVL_LAST) ? log_lvl_info_tab[lvl] : "u")
00078
00080 size_t lgGetLvlKeyMaxLen()
00081 {
00082 int lvl;
00083 size_t maxlen = 0;
00084
00085 for(lvl = 0; lvl <= LOG_LVL_LAST; ++lvl)
00086 maxlen = MAX2(maxlen, strlen(log_lvl_info_tab[lvl]));
00087
00088 return MAX2(maxlen, strlen(LOG_LVL_PLACEHOLDER_ALL));
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00103 struct Logger
00104 {
00106 FILE* lg_ostream;
00108 int manage_stream;
00110 char *format;
00112 size_t format_len;
00113 };
00114
00116 int logClose(Logger this) {
00117 int result = 0;
00118
00119 if (this->manage_stream && this->lg_ostream != NULL) {
00120 result = fclose(this->lg_ostream);
00121
00122 if (result == 0) this->lg_ostream = NULL;
00123 }
00124 return result;
00125 }
00126
00128 Logger logInitStream_int(FILE * log_stream, const char* format, int manage_stream)
00129 {
00130 Logger this = (Logger) pd_malloc(sizeof(struct Logger));
00131 this->lg_ostream = log_stream;
00132 this->format_len = strlen(format);
00133 this->format = (char*) pd_malloc(this->format_len + 1);
00134 strcpy(this->format, format);
00135
00136 if (log_stream != NULL)
00137 this->manage_stream = manage_stream;
00138
00139
00140 return this;
00141 }
00142
00143
00144 Logger logInit(const char* file_name, const char* format)
00145 {
00146 FILE* new_stream;
00147 if (file_name == NULL) file_name = CONFENTRY_KEY_STDLOGFILE;
00148
00149 if (!strcmp(file_name, LOG_NULL_STREAM))
00150 new_stream = NULL;
00151 else
00152 {
00153 new_stream = fopen(file_name, "a");
00154 if (!new_stream) return NULL;
00155 }
00156
00157 return logInitStream_int(new_stream, format, true);
00158 }
00159
00160
00161 Logger logInitStream(FILE * log_stream, const char* format)
00162 {
00163 return logInitStream_int(log_stream, format, false);
00164 }
00165
00166
00167 int logMessagev(Logger this,
00168 const unsigned int origin, __attribute__((unused)) const unsigned int severity,
00169 const int errno_val, const char *const log_text_format, va_list daten)
00170 {
00171 const int errno_orig = errno;
00172 const time_t tmptime = time(NULL);
00173 struct tm* now = localtime(&tmptime);
00174 size_t idx;
00175
00176 if (this->lg_ostream == NULL) return -1;
00177
00178 for (idx = 0; idx < this->format_len; ++idx)
00179 {
00180 char cur_char = *(this->format+idx);
00181 if (cur_char == MP)
00182 {
00183
00184 switch(*(this->format+idx+1))
00185 {
00186 case(MP_YEAR):
00187 fprintf(this->lg_ostream, "%d", now->tm_year+1900);
00188 break;
00189 case(MP_MONTH):
00190 fprintf(this->lg_ostream, "%02d", now->tm_mon+1);
00191 break;
00192 case(MP_DAY):
00193 fprintf(this->lg_ostream, "%02d", now->tm_mday);
00194 break;
00195 case(MP_WDAY):
00196 fputs(day_of_week[now->tm_wday][WD_SHORT], this->lg_ostream);
00197 break;
00198 case(MP_WDAYL):
00199 fputs(day_of_week[now->tm_wday][WD_LONG], this->lg_ostream);
00200 break;
00201 case(MP_HOUR):
00202 fprintf(this->lg_ostream, "%02d", now->tm_hour);
00203 break;
00204 case(MP_MIN):
00205 fprintf(this->lg_ostream, "%02d", now->tm_min);
00206 break;
00207 case(MP_SEC):
00208 fprintf(this->lg_ostream, "%02d", now->tm_sec);
00209 break;
00210 case(MP_SRC):
00211 fputs(lgGetSrcDescText(origin), this->lg_ostream);
00212 break;
00213 case(MP_LOG):
00214 vfprintf(this->lg_ostream, log_text_format, daten);
00215 if (errno_val != 0) fprintf(this->lg_ostream, ": %s", strerror(errno_val));
00216 break;
00217 default:
00218
00219
00220 --idx;
00221 }
00222
00223 ++idx;
00224 }
00225
00226
00227 else if (cur_char == '\\')
00228 {
00229 switch (*(this->format+idx+1))
00230 {
00231 case('n'):
00232 putc('\n', this->lg_ostream);
00233 break;
00234 case('t'):
00235 putc('\t', this->lg_ostream);
00236 break;
00237 case('\\'):
00238 putc('\\', this->lg_ostream);
00239 break;
00240 case(MP):
00241 putc(MP, this->lg_ostream);
00242 break;
00243 default:
00244
00245
00246
00247
00248 --idx;
00249 }
00250 ++idx;
00251 }
00252 else
00253 putc(cur_char, this->lg_ostream);
00254 }
00255
00256 fflush(this->lg_ostream);
00257
00258
00259 errno = errno_orig;
00260 return 0;
00261 }
00262
00263
00264 int logTerminate(Logger this)
00265 {
00266 logClose(this);
00267 pd_free(this->format);
00268 pd_free(this);
00269 return 0;
00270 }
00271
00272
00273
00274
00275
00276
00277
00279 LoggerList loggers[LOG_SRC_LAST+1][LOG_LVL_LAST+1];
00281 FilepList log_streams;
00282
00283
00284 inline int addLogger2List(Logger lgr, int src, int lvl, const char* origin_flags);
00285
00286 inline char* int2str(int i);
00287
00295 int logfilesInit()
00296 {
00297 const size_t log_file_name_key_len = MAX2(
00298 strlen(CONFENTRY_KEY_LOGFILE)-2+3+1,
00299 strlen(CONFENTRY_KEY_STDLOGFILE)+1
00300 );
00301 char* log_file_name_key = (char*) pd_malloc(log_file_name_key_len);
00302 const char* log_file_name;
00303 int lvl, cnt, src, at_least_one_added = false;
00304
00305 size_t lvl_key_max = lgGetLvlKeyMaxLen(), src_key_max = lgGetSrcKeyMaxLen();
00306
00307
00308
00309
00310 size_t std_format_key_len = strlen(CONFENTRY_KEY_LOGFORMAT) - 2 + 1;
00311
00312
00313 size_t log_format_key_id_len = 3 + 1 + src_key_max + 1;
00314 size_t log_format_key_len = std_format_key_len + log_format_key_id_len;
00315
00316 size_t src_format_key_id_len = log_format_key_id_len + lvl_key_max + 1;
00317
00318 size_t src_format_key_len = log_format_key_len + 1 + lvl_key_max;
00319
00320
00321 size_t src_lvl_format_key_id_len = src_format_key_id_len;
00322 size_t src_lvl_format_key_len = src_format_key_len;
00323
00324
00325 char* std_format_key = (char*) pd_malloc(std_format_key_len);
00326
00327
00328 char* log_format_key_id = (char*) pd_malloc(log_format_key_id_len);
00329
00330 char* log_format_key = (char*) pd_malloc(log_format_key_len);
00331
00332
00333 char* src_format_key_id = (char*) pd_malloc(src_format_key_id_len);
00334
00335 char* src_format_key = (char*) pd_malloc(src_format_key_len);
00336
00337
00338 char* src_lvl_format_key_id = (char*) pd_malloc(src_lvl_format_key_id_len);
00339
00340 char* src_lvl_format_key = (char*) pd_malloc(src_lvl_format_key_len);
00341
00342
00343
00344
00345 size_t std_origin_flags_key_len = strlen(CONFENTRY_KEY_LOGORIGINFLAGS) - 2 + 1;
00346
00347
00348 size_t log_origin_flags_key_len = strlen(CONFENTRY_KEY_LOGORIGINFLAGS) - 2 + 3 + 1;
00349
00350 char* std_origin_flags_key = (char*) pd_malloc(std_origin_flags_key_len);
00351 char* log_origin_flags_key = (char*) pd_malloc(log_origin_flags_key_len);
00352
00353 const char * std_origin_flags, * std_format;
00354
00355 log_streams = filepListInit();
00356
00357
00358 sprintf(std_origin_flags_key, CONFENTRY_KEY_LOGORIGINFLAGS, "");
00359 std_origin_flags = getEntryDefl(std_origin_flags_key, STD_CONFENTRY_VAL_LOGORIGINFLAGS);
00360
00361 sprintf(std_format_key, CONFENTRY_KEY_LOGFORMAT, "");
00362 std_format = getEntryDefl(std_format_key, STD_CONFENTRY_VAL_LOGFORMAT);
00363
00364
00365 for (src = 0; src <= LOG_SRC_LAST; ++src)
00366 for(lvl = 0; lvl <= LOG_LVL_LAST; ++lvl)
00367 {
00368 loggers[src][lvl] = logListInit();
00369 if (lvl >= CRITICAL)
00370 {
00371 Logger std_err_log = logInitStream(stderr, LOG_PANIC_FORMAT);
00372 #ifndef NDEBUG
00373 if (!
00374 #endif
00375 addLogger2List(std_err_log, src, lvl,
00376 LOG_LVL_PLACEHOLDER_ALL LOG_SRC_PLACEHOLDER_ALL)
00377 #ifndef NDEBUG
00378 )
00379 abort()
00380 #endif
00381 ;
00382 }
00383 }
00384
00385
00386
00387
00388 cnt = -1;
00389 snprintf(log_file_name_key, log_file_name_key_len, CONFENTRY_KEY_STDLOGFILE);
00390
00391 while((log_file_name = getEntry(log_file_name_key)) != NULL && cnt < 1000)
00392 {
00393 const char * log_origin_flags, * log_format;
00394 int added = false;
00395
00396
00397 FILE* log_stream = fopen(log_file_name, "a");
00398 if (log_stream == NULL)
00399 fprintf(stderr,
00400 "could not open logfile \"%s\": %s\n",
00401 log_file_name, strerror(errno));
00402 else
00403 {
00404
00405
00406 sprintf(log_format_key_id, "%d.%s", cnt, LOG_SRC_PLACEHOLDER_ALL);
00407 sprintf(log_format_key, CONFENTRY_KEY_LOGFORMAT, log_format_key_id);
00408
00409
00410 log_format = getEntry(log_format_key);
00411
00412 if (log_format == NULL)
00413 {
00414
00415
00416 sprintf(log_format_key_id, "%d", cnt);
00417 sprintf(log_format_key, CONFENTRY_KEY_LOGFORMAT, log_format_key_id);
00418
00419
00420 log_format = getEntryDefl(log_format_key, std_format);
00421 }
00422
00423
00424 snprintf(log_origin_flags_key, log_origin_flags_key_len,
00425 CONFENTRY_KEY_LOGORIGINFLAGS, int2str(cnt));
00426 log_origin_flags = getEntryDefl(log_origin_flags_key, std_origin_flags);
00427
00428
00429 for (src = 0; src <= LOG_SRC_LAST; ++src)
00430 {
00431 const char * src_format;
00432
00433
00434
00435 sprintf(src_format_key_id, "%s.%s.%s", int2str(cnt), lgGetSrcConfKey(src), LOG_LVL_PLACEHOLDER_ALL);
00436 sprintf(src_format_key, CONFENTRY_KEY_LOGFORMAT, src_format_key_id);
00437
00438
00439 src_format = getEntry(src_format_key);
00440
00441 if (src_format == NULL)
00442 {
00443
00444
00445 sprintf(src_format_key_id, "%s.%s", int2str(cnt), lgGetSrcConfKey(src));
00446 sprintf(src_format_key, CONFENTRY_KEY_LOGFORMAT, src_format_key_id);
00447
00448
00449 src_format = getEntryDefl(src_format_key, log_format);
00450 }
00451
00452
00453 for (lvl = 0; lvl <= LOG_LVL_LAST; ++lvl)
00454 {
00455 const char* src_lvl_format;
00456
00457
00458
00459
00460 sprintf(src_lvl_format_key_id, "%s.%s.%s",
00461 int2str(cnt), lgGetSrcConfKey(src), lgGetLvlConfKey(lvl));
00462 sprintf(src_lvl_format_key, CONFENTRY_KEY_LOGFORMAT, src_lvl_format_key_id);
00463
00464
00465 src_lvl_format = getEntry(src_lvl_format_key);
00466 if (src_lvl_format == NULL)
00467 {
00468 sprintf(src_lvl_format_key_id, "%s.%s.%s",
00469 int2str(cnt), LOG_SRC_PLACEHOLDER_ALL, lgGetLvlConfKey(lvl));
00470 sprintf(src_lvl_format_key, CONFENTRY_KEY_LOGFORMAT, src_lvl_format_key_id);
00471 src_lvl_format = getEntryDefl(src_lvl_format_key, src_format);
00472 }
00473
00474 if (strcmp(src_lvl_format, LOG_NULL_FORMAT) != 0)
00475 {
00476 Logger lgr;
00477 lgr = logInitStream(log_stream, src_lvl_format);
00478
00479 if (addLogger2List(lgr, src, lvl, log_origin_flags))
00480 added = true;
00481 else
00482 logTerminate(lgr);
00483 }
00484 }
00485 }
00486
00487 if (!added)
00488 fclose(log_stream);
00489 else
00490 {
00491 at_least_one_added = true;
00492 filepListAppend(log_streams, log_stream);
00493 }
00494 }
00495
00496
00497 snprintf(log_file_name_key, log_file_name_key_len,
00498 CONFENTRY_KEY_LOGFILE, int2str(++cnt));
00499 }
00500
00501
00502 if (!at_least_one_added)
00503 {
00504 for (src = 0; src <= LOG_SRC_LAST; ++src)
00505
00506 for (lvl = INFO; lvl < CRITICAL; ++lvl)
00507 {
00508 Logger panic_log = logInitStream(stderr, LOG_PANIC_FORMAT);
00509 #ifndef NDEBUG
00510 if (!
00511 #endif
00512 addLogger2List(panic_log, src, lvl,
00513 LOG_SRC_PLACEHOLDER_ALL LOG_LVL_PLACEHOLDER_ALL)
00514 #ifndef NDEBUG
00515 )
00516 abort()
00517 #endif
00518 ;
00519 }
00520
00521
00522
00523
00524
00525 }
00526
00527 pd_free(log_file_name_key);
00528 pd_free(std_format_key);
00529 pd_free(log_format_key);
00530 pd_free(log_format_key_id);
00531 pd_free(src_format_key);
00532 pd_free(src_format_key_id);
00533 pd_free(src_lvl_format_key);
00534 pd_free(src_lvl_format_key_id);
00535 pd_free(std_origin_flags_key);
00536 pd_free(log_origin_flags_key);
00537
00538 return 0;
00539 }
00540
00541
00542 int logfilesTerminate()
00543 {
00544 int src, lvl;
00545 for (src = 0; src <= LOG_SRC_LAST ; ++src)
00546 for (lvl = 0; lvl <= LOG_LVL_LAST; ++lvl)
00547 {
00548 logListFirst(loggers[src][lvl]);
00549 while(!logListIsTail(loggers[src][lvl]))
00550 {
00551 logTerminate(logListGetPayload(loggers[src][lvl]));
00552 logListDelete(loggers[src][lvl]);
00553 }
00554 logListTerminate(loggers[src][lvl]);
00555 }
00556
00557 filepListFirst(log_streams);
00558 while(!filepListIsTail(log_streams))
00559 {
00560 fclose(filepListGetPayload(log_streams));
00561 filepListDelete(log_streams);
00562 }
00563 filepListTerminate(log_streams);
00564
00565 return 0;
00566 }
00567
00568
00569 int logerr(const unsigned int origin, const unsigned int severity, const int errno_val,
00570 const char *const log_text_format, ...)
00571 {
00572 va_list args;
00573 int res = 0;
00574 LoggerList cur_list = loggers[origin][severity];
00575
00576 logListFirst(cur_list);
00577 while(!logListIsTail(cur_list))
00578 {
00579 va_start(args, log_text_format);
00580 if ( logMessagev(logListGetPayload(cur_list),
00581 origin, severity, errno_val, log_text_format, args) == -1 ) res = -1;
00582 va_end(args);
00583 logListNext(cur_list);
00584 }
00585 return res;
00586 }
00587
00588
00589 int logger(const unsigned int origin, const unsigned int severity,
00590 const char *const log_text_format, ...)
00591 {
00592 va_list args;
00593 int res = 0;
00594 LoggerList cur_list = loggers[origin][severity];
00595
00596 logListFirst(cur_list);
00597 while(!logListIsTail(cur_list))
00598 {
00599 va_start(args, log_text_format);
00600 if ( logMessagev(logListGetPayload(cur_list),
00601 origin, severity, 0, log_text_format, args) == -1 ) res = -1;
00602 va_end(args);
00603 logListNext(cur_list);
00604 }
00605 return res;
00606 }
00607
00609 inline int addLogger2List(Logger lgr, int src, int lvl, const char* origin_flags)
00610 {
00611 assert(src >= 0 && src <= LOG_SRC_LAST && lvl >= 0 && lvl <= LOG_LVL_LAST);
00612
00613
00614
00615
00616
00617
00618
00619 if ((strstr(origin_flags, lgGetSrcConfKey(src))
00620 || strstr(origin_flags, LOG_SRC_PLACEHOLDER_ALL))
00621 && (strstr(origin_flags, lgGetLvlConfKey(lvl))
00622 || (strstr(origin_flags, LOG_LVL_PLACEHOLDER_ALL) && lvl != DEBUG)))
00623 {
00624 logListAppend(loggers[src][lvl], lgr);
00625 return true;
00626 }
00627 return false;
00628 }
00629
00636 inline char* int2str(int i)
00637 {
00638 char tmp_buf[4];
00639
00640 ssize_t res = snprintf(tmp_buf, 4, "%d", i);
00641
00642 return (res == -1 || res >= 4) ? "" : tmp_buf;
00643 }