00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifdef HAVE_CONFIG_H
00030 # include <config.h>
00031 #endif
00032
00033 #include <gwenhywfar/gwenhywfarapi.h>
00034 #include <gwenhywfar/misc.h>
00035 #include <gwenhywfar/buffer.h>
00036 #include <gwenhywfar/gui.h>
00037
00038 #include "logger_p.h"
00039
00040 #include <stdlib.h>
00041 #include <stdio.h>
00042 #include <errno.h>
00043 #ifdef HAVE_SYSLOG_H
00044 # include <syslog.h>
00045 #endif
00046 #include <string.h>
00047 #ifdef HAVE_STRINGS_H
00048 # include <strings.h>
00049 #endif
00050 #ifdef HAVE_TIME_H
00051 # include <time.h>
00052 #endif
00053 #ifdef HAVE_UNISTD_H
00054 # include <unistd.h>
00055 #endif
00056
00057
00058 static GWEN_LOGGER_DOMAIN *gwen_loggerdomains=0;
00059
00060
00061
00062 int GWEN_Logger_ModuleInit(){
00063 const char *s;
00064 GWEN_LOGGER_LEVEL ll=GWEN_LoggerLevel_Warning;
00065
00066 GWEN_Logger_Open(GWEN_LOGDOMAIN,
00067 "gwen",
00068 0,
00069 GWEN_LoggerType_Console,
00070 GWEN_LoggerFacility_User);
00071 s=getenv("GWEN_LOGLEVEL");
00072 if (s) {
00073 ll=GWEN_Logger_Name2Level(s);
00074 if (ll==GWEN_LoggerLevel_Unknown)
00075 ll=GWEN_LoggerLevel_Warning;
00076 }
00077 GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, ll);
00078 return 0;
00079 }
00080
00081
00082
00083 int GWEN_Logger_ModuleFini(){
00084 GWEN_LOGGER_DOMAIN *ld;
00085
00086 while((ld=gwen_loggerdomains)) {
00087 GWEN_LoggerDomain_Del(ld);
00088 GWEN_LoggerDomain_free(ld);
00089 }
00090 return 0;
00091 }
00092
00093
00094
00095 GWEN_LOGGER_DOMAIN *GWEN_LoggerDomain_new(const char *name){
00096 GWEN_LOGGER_DOMAIN *ld;
00097
00098 assert(name);
00099 GWEN_NEW_OBJECT(GWEN_LOGGER_DOMAIN, ld);
00100 ld->name=strdup(name);
00101 return ld;
00102 }
00103
00104
00105
00106 void GWEN_LoggerDomain_free(GWEN_LOGGER_DOMAIN *ld){
00107 if (ld) {
00108 free(ld->name);
00109 GWEN_Logger_free(ld->logger);
00110 GWEN_FREE_OBJECT(ld);
00111 }
00112 }
00113
00114
00115 GWEN_LOGGER_DOMAIN *GWEN_LoggerDomain_Find(const char *name) {
00116 GWEN_LOGGER_DOMAIN *ld;
00117
00118 assert(name);
00119 ld=gwen_loggerdomains;
00120 while(ld) {
00121 if (strcasecmp(ld->name, name)==0)
00122 break;
00123 ld=ld->next;
00124 }
00125
00126 return ld;
00127 }
00128
00129
00130
00131 void GWEN_LoggerDomain_Add(GWEN_LOGGER_DOMAIN *ld){
00132 assert(ld);
00133 GWEN_LIST_INSERT(GWEN_LOGGER_DOMAIN, ld, &gwen_loggerdomains);
00134 }
00135
00136
00137
00138 void GWEN_LoggerDomain_Del(GWEN_LOGGER_DOMAIN *ld){
00139 assert(ld);
00140 GWEN_LIST_DEL(GWEN_LOGGER_DOMAIN, ld, &gwen_loggerdomains);
00141 }
00142
00143
00144
00145 GWEN_LOGGER *GWEN_LoggerDomain_GetLogger(const char *name) {
00146 GWEN_LOGGER_DOMAIN *ld;
00147
00148 if (!name)
00149 name="default";
00150
00151 ld=GWEN_LoggerDomain_Find(name);
00152 if (ld) {
00153 return ld->logger;
00154 }
00155 ld=GWEN_LoggerDomain_new(name);
00156 ld->logger=GWEN_Logger_new(ld);
00157
00158 GWEN_LoggerDomain_Add(ld);
00159 return ld->logger;
00160 }
00161
00162
00163
00164 GWEN_LOGGER *GWEN_Logger_new(GWEN_LOGGER_DOMAIN *domain){
00165 GWEN_LOGGER *lg;
00166
00167 GWEN_NEW_OBJECT(GWEN_LOGGER, lg);
00168 lg->usage=1;
00169 lg->enabled=1;
00170 lg->logType=GWEN_LoggerType_Console;
00171 lg->logLevel=GWEN_LoggerLevel_Error;
00172 lg->domain=domain;
00173 return lg;
00174 }
00175
00176
00177
00178 void GWEN_Logger_free(GWEN_LOGGER *lg){
00179 if (lg) {
00180 assert(lg->usage);
00181 if (--(lg->usage)==0) {
00182 free(lg->logFile);
00183 free(lg->logIdent);
00184 GWEN_FREE_OBJECT(lg);
00185 }
00186 }
00187 }
00188
00189
00190
00191 void GWEN_Logger_Attach(GWEN_LOGGER *lg){
00192 assert(lg);
00193 lg->usage++;
00194 }
00195
00196
00197
00198 void GWEN_Logger_AddLogger(GWEN_LOGGER *oldLogger, GWEN_LOGGER *newLogger){
00199 assert(newLogger);
00200
00201 assert(oldLogger);
00202 GWEN_LIST_ADD(GWEN_LOGGER, newLogger, &(oldLogger->next));
00203 }
00204
00205
00206
00207 void GWEN_Logger_SetDefaultLogger(GWEN_LOGGER *lg){
00208 fprintf(stderr, "GWEN_Logger_SetDefaultLogger: Deprecated function\n");
00209 }
00210
00211
00212
00213 int GWEN_Logger_Open(const char *logDomain,
00214 const char *ident,
00215 const char *file,
00216 GWEN_LOGGER_LOGTYPE logtype,
00217 GWEN_LOGGER_FACILITY facility){
00218 GWEN_LOGGER *lg;
00219
00220 lg=GWEN_LoggerDomain_GetLogger(logDomain);
00221 assert(lg);
00222 lg->logType=logtype;
00223
00224 GWEN_Logger_SetIdent(logDomain, ident);
00225 GWEN_Logger_SetFilename(logDomain, file);
00226
00227 if (logtype==GWEN_LoggerType_File) {
00228
00229 if (file==0) {
00230 lg->logType=GWEN_LoggerType_Console;
00231 lg->enabled=1;
00232 fprintf(stderr,"LOGGER: No filename given, will log to console.\n");
00233 }
00234 else {
00235 lg->logType=GWEN_LoggerType_File;
00236 lg->enabled=1;
00237 }
00238 }
00239 #ifdef HAVE_SYSLOG_H
00240 else if (logtype==GWEN_LoggerType_Syslog) {
00241
00242 int fac;
00243
00244 switch(facility) {
00245 case GWEN_LoggerFacility_Auth:
00246 fac=LOG_AUTH;
00247 break;
00248 case GWEN_LoggerFacility_Daemon:
00249 fac=LOG_DAEMON;
00250 break;
00251 case GWEN_LoggerFacility_Mail:
00252 fac=LOG_MAIL;
00253 break;
00254 case GWEN_LoggerFacility_News:
00255 fac=LOG_NEWS;
00256 break;
00257 case GWEN_LoggerFacility_User:
00258 default:
00259 fac=LOG_USER;
00260 break;
00261 }
00262
00263 openlog(ident,
00264 LOG_CONS |
00265 LOG_PID,
00266 fac);
00267 lg->enabled=1;
00268 }
00269 #endif
00270
00271 else {
00272
00273 lg->enabled=1;
00274 }
00275
00276 lg->open=1;
00277
00278 return GWEN_Logger_Log(logDomain, GWEN_LoggerLevel_Debug, "started");
00279 }
00280
00281
00282
00283 void GWEN_Logger_Close(const char *logDomain){
00284 GWEN_LOGGER *lg;
00285
00286 lg=GWEN_LoggerDomain_GetLogger(logDomain);
00287 assert(lg);
00288 GWEN_Logger_Log(logDomain, GWEN_LoggerLevel_Debug, "stopped");
00289 lg->logType=GWEN_LoggerType_Console;
00290 lg->enabled=0;
00291 #ifdef HAVE_SYSLOG_H
00292 closelog();
00293 #endif
00294 lg->open=0;
00295
00296 GWEN_LoggerDomain_Del(lg->domain);
00297 GWEN_LoggerDomain_free(lg->domain);
00298 }
00299
00300
00301
00302 int GWEN_Logger_IsOpen(const char *logDomain){
00303 GWEN_LOGGER_DOMAIN *ld;
00304
00305 if (!logDomain)
00306 logDomain="default";
00307 ld=GWEN_LoggerDomain_Find(logDomain);
00308 if (ld)
00309 return ld->logger->open;
00310 return 0;
00311 }
00312
00313
00314 int GWEN_Logger__CreateMessage(GWEN_LOGGER *lg,
00315 GWEN_LOGGER_LEVEL priority, const char *s,
00316 GWEN_BUFFER *mbuf) {
00317 #ifdef HAVE_SNPRINTF
00318 unsigned int i;
00319 #endif
00320 #ifdef HAVE_TIME_H
00321 struct tm *t;
00322 time_t tt;
00323 #endif
00324 char buffer[256];
00325
00326 assert(lg);
00327 if (lg->logIdent) {
00328 if (strlen(lg->logIdent)+32>=sizeof(buffer)) {
00329 fprintf(stderr," LOGGER: Logbuffer too small (1).\n");
00330 return 1;
00331 }
00332 }
00333
00334 #ifdef HAVE_TIME_H
00335 tt=time(0);
00336 t=localtime(&tt);
00337
00338 # ifdef HAVE_SNPRINTF
00339 # ifdef HAVE_GETPID
00340 i=snprintf(buffer, sizeof(buffer)-1,
00341 "%d:%04d/%02d/%02d %02d-%02d-%02d:%s(%d):",priority,
00342 t->tm_year+1900, t->tm_mon+1, t->tm_mday,
00343 t->tm_hour, t->tm_min, t->tm_sec,
00344 lg->logIdent, (int)getpid());
00345 # else
00346 i=snprintf(buffer, sizeof(buffer)-1,
00347 "%d:%04d/%02d/%02d %02d-%02d-%02d:%s:",priority,
00348 t->tm_year+1900, t->tm_mon+1, t->tm_mday,
00349 t->tm_hour, t->tm_min, t->tm_sec,
00350 lg->logIdent);
00351 # endif
00352 if (i>=sizeof(buffer)) {
00353 fprintf(stderr," LOGGER: Logbuffer too small (2).\n");
00354 return 1;
00355 }
00356 # else
00357 # ifdef HAVE_GETPID
00358 sprintf(buffer,"%d:%04d/%02d/%02d %02d-%02d-%02d:%s(%d):",priority,
00359 t->tm_year+1900, t->tm_mon+1, t->tm_mday,
00360 t->tm_hour, t->tm_min, t->tm_sec,
00361 lg->logIdent, (int)getpid());
00362 # else
00363 sprintf(buffer,"%d:%04d/%02d/%02d %02d-%02d-%02d:%s:",priority,
00364 t->tm_year+1900, t->tm_mon+1, t->tm_mday,
00365 t->tm_hour, t->tm_min, t->tm_sec,
00366 lg->logIdent);
00367 # endif
00368 # endif
00369 #else
00370 # ifdef HAVE_SNPRINTF
00371 buffer[sizeof(buffer)-1]=0;
00372 i=snprintf(buffer, sizeof(buffer)-1,
00373 "%d:%s:",priority,
00374 lg->logIdent);
00375 if (i>=sizeof(buffer)) {
00376 fprintf(stderr," LOGGER: Logbuffer too small (3).\n");
00377 return 1;
00378 }
00379 # else
00380 sprintf(buffer,"%d:%s:",priority,
00381 lg->logIdent);
00382 # endif
00383 #endif
00384 GWEN_Buffer_AppendString(mbuf, buffer);
00385 GWEN_Buffer_AppendString(mbuf, s);
00386 GWEN_Buffer_AppendByte(mbuf, '\n');
00387 return 0;
00388 }
00389
00390
00391
00392 int GWEN_Logger__Log(GWEN_LOGGER *lg,
00393 GWEN_LOGGER_LEVEL priority, const char *s){
00394 while(lg) {
00395 FILE *f;
00396 #ifdef HAVE_SYSLOG_H
00397 int pri;
00398 #endif
00399 GWEN_BUFFER *mbuf;
00400 int rv;
00401
00402 assert(lg);
00403 if (priority>lg->logLevel)
00404
00405 return 0;
00406
00407 mbuf=GWEN_Buffer_new(0, 256, 0, 1);
00408 switch(lg->logType) {
00409 case GWEN_LoggerType_File:
00410 rv=GWEN_Logger__CreateMessage(lg, priority, s, mbuf);
00411 if (rv) {
00412 GWEN_Buffer_free(mbuf);
00413 return rv;
00414 }
00415
00416 f=fopen(lg->logFile,"a+");
00417 if (f==0) {
00418 fprintf(stderr,
00419 "LOGGER: Unable to open file \"%s\" (%s)\n",
00420 lg->logFile,
00421 strerror(errno));
00422 lg->logType=GWEN_LoggerType_Console;
00423 GWEN_Buffer_free(mbuf);
00424 return 1;
00425 }
00426
00427 if (fwrite(GWEN_Buffer_GetStart(mbuf),
00428 GWEN_Buffer_GetUsedBytes(mbuf), 1, f)!=1) {
00429 fprintf(stderr,
00430 "LOGGER: Unable to write to file \"%s\" (%s)\n",
00431 lg->logFile,
00432 strerror(errno));
00433 fclose(f);
00434 lg->logType=GWEN_LoggerType_Console;
00435 GWEN_Buffer_free(mbuf);
00436 return 1;
00437 }
00438 if (fclose(f)) {
00439 fprintf(stderr,
00440 "LOGGER: Unable to close file \"%s\" (%s)\n",
00441 lg->logFile,
00442 strerror(errno));
00443 lg->logType=GWEN_LoggerType_Console;
00444 GWEN_Buffer_free(mbuf);
00445 return 1;
00446 }
00447 break;
00448
00449 #ifdef HAVE_SYSLOG_H
00450 case GWEN_LoggerType_Syslog:
00451 switch(priority) {
00452 case GWEN_LoggerLevel_Emergency:
00453 pri=LOG_EMERG;
00454 break;
00455 case GWEN_LoggerLevel_Alert:
00456 pri=LOG_ALERT;
00457 break;
00458 case GWEN_LoggerLevel_Critical:
00459 pri=LOG_CRIT;
00460 break;
00461 case GWEN_LoggerLevel_Error:
00462 pri=LOG_ERR;
00463 break;
00464 case GWEN_LoggerLevel_Warning:
00465 pri=LOG_WARNING;
00466 break;
00467 case GWEN_LoggerLevel_Notice:
00468 pri=LOG_NOTICE;
00469 break;
00470 case GWEN_LoggerLevel_Info:
00471 pri=LOG_NOTICE;
00472 break;
00473
00474 case GWEN_LoggerLevel_Debug:
00475 case GWEN_LoggerLevel_Verbous:
00476 default:
00477 pri=LOG_DEBUG;
00478 break;
00479 }
00480 syslog(pri,"%s",s);
00481 break;
00482 #endif
00483
00484 case GWEN_LoggerType_Function:
00485 if (lg->logFunction==0) {
00486 fprintf(stderr,
00487 "LOGGER: Logtype is \"Function\", but no function is set.\n");
00488 GWEN_Buffer_free(mbuf);
00489 return 1;
00490 }
00491 rv=GWEN_Logger__CreateMessage(lg, priority, s, mbuf);
00492 if (rv) {
00493 GWEN_Buffer_free(mbuf);
00494 return rv;
00495 }
00496 (lg->logFunction)(GWEN_Buffer_GetStart(mbuf));
00497 break;
00498
00499 case GWEN_LoggerType_Console:
00500 default:
00501 rv=GWEN_Logger__CreateMessage(lg, priority, s, mbuf);
00502 if (rv) {
00503 GWEN_Buffer_free(mbuf);
00504 return rv;
00505 }
00506
00507 fprintf(stderr, "%s", GWEN_Buffer_GetStart(mbuf));
00508 break;
00509 }
00510 lg=lg->next;
00511 GWEN_Buffer_free(mbuf);
00512 }
00513 return 0;
00514 }
00515
00516
00517
00518 int GWEN_Logger_Log(const char *logDomain,
00519 GWEN_LOGGER_LEVEL priority, const char *s){
00520 if (!GWEN_Gui_LogHook(logDomain, priority, s)) {
00521 const char *p;
00522 int rv;
00523 unsigned int i;
00524 GWEN_BUFFER *mbuf;
00525 GWEN_LOGGER *lg;
00526
00527 lg=GWEN_LoggerDomain_GetLogger(logDomain);
00528 assert(lg);
00529
00530 if (!lg->enabled)
00531 return 1;
00532
00533 if (priority>lg->logLevel)
00534
00535 return 0;
00536
00537
00538 lg->enabled=0;
00539
00540 mbuf=GWEN_Buffer_new(0, strlen(s)+1, 0, 1);
00541 for (i=0; i<strlen(s)+1; i++) {
00542 if (s[i]=='\n') {
00543 GWEN_Buffer_AppendByte(mbuf, 0);
00544 }
00545 else
00546 GWEN_Buffer_AppendByte(mbuf, s[i]);
00547 }
00548
00549
00550 rv=0;
00551 p=GWEN_Buffer_GetStart(mbuf);
00552 while (*p) {
00553 rv|=GWEN_Logger__Log(lg, priority, p);
00554 while(*p)
00555 p++;
00556 p++;
00557 }
00558 GWEN_Buffer_free(mbuf);
00559
00560 lg->enabled=1;
00561 return rv;
00562 }
00563 else
00564 return 0;
00565 }
00566
00567
00568
00569 void GWEN_Logger_Enable(const char *logDomain, int f){
00570 GWEN_LOGGER *lg;
00571
00572 lg=GWEN_LoggerDomain_GetLogger(logDomain);
00573 assert(lg);
00574 lg->enabled=f;
00575 }
00576
00577
00578
00579 int GWEN_Logger_IsEnabled(const char *logDomain){
00580 GWEN_LOGGER *lg;
00581
00582 lg=GWEN_LoggerDomain_GetLogger(logDomain);
00583 assert(lg);
00584 return lg->enabled;
00585 }
00586
00587
00588
00589 void GWEN_Logger_SetLevel(const char *logDomain, GWEN_LOGGER_LEVEL l){
00590 GWEN_LOGGER *lg;
00591
00592 lg=GWEN_LoggerDomain_GetLogger(logDomain);
00593 assert(lg);
00594 lg->logLevel=l;
00595 }
00596
00597
00598
00599 int GWEN_Logger_GetLevel(const char *logDomain) {
00600 GWEN_LOGGER *lg;
00601
00602 lg=GWEN_LoggerDomain_GetLogger(logDomain);
00603 assert(lg);
00604
00605 return lg->logLevel;
00606 }
00607
00608
00609
00610 void GWEN_Logger_SetIdent(const char *logDomain, const char *id){
00611 GWEN_LOGGER *lg;
00612
00613 lg=GWEN_LoggerDomain_GetLogger(logDomain);
00614 assert(lg);
00615
00616 free(lg->logIdent);
00617 if (id)
00618 lg->logIdent=strdup(id);
00619 else
00620 lg->logIdent=strdup("No ident, please adjust your program");
00621 }
00622
00623
00624
00625 void GWEN_Logger_SetFilename(const char *logDomain, const char *name){
00626 GWEN_LOGGER *lg;
00627
00628 lg=GWEN_LoggerDomain_GetLogger(logDomain);
00629 assert(lg);
00630
00631 free(lg->logFile);
00632 if (name)
00633 lg->logFile=strdup(name);
00634 else
00635 lg->logFile=strdup("");
00636 }
00637
00638
00639
00640 GWEN_LOGGERFUNCTIONLOG GWEN_Logger_SetLogFunction(const char *logDomain,
00641 GWEN_LOGGERFUNCTIONLOG fn){
00642 GWEN_LOGGER *lg;
00643 GWEN_LOGGERFUNCTIONLOG oldFn;
00644
00645 lg=GWEN_LoggerDomain_GetLogger(logDomain);
00646 assert(lg);
00647 oldFn=lg->logFunction;
00648 lg->logFunction=fn;
00649 return oldFn;
00650 }
00651
00652
00653
00654 GWEN_LOGGER_LEVEL GWEN_Logger_Name2Level(const char *name) {
00655 if (strcasecmp(name, "emergency")==0)
00656 return GWEN_LoggerLevel_Emergency;
00657 else if (strcasecmp(name, "alert")==0)
00658 return GWEN_LoggerLevel_Alert;
00659 else if (strcasecmp(name, "critical")==0)
00660 return GWEN_LoggerLevel_Critical;
00661 else if (strcasecmp(name, "error")==0)
00662 return GWEN_LoggerLevel_Error;
00663 else if (strcasecmp(name, "warning")==0)
00664 return GWEN_LoggerLevel_Warning;
00665 else if (strcasecmp(name, "notice")==0)
00666 return GWEN_LoggerLevel_Notice;
00667 else if (strcasecmp(name, "info")==0)
00668 return GWEN_LoggerLevel_Info;
00669 else if (strcasecmp(name, "debug")==0)
00670 return GWEN_LoggerLevel_Debug;
00671 else if (strcasecmp(name, "verbous")==0)
00672 return GWEN_LoggerLevel_Verbous;
00673 else {
00674 return GWEN_LoggerLevel_Unknown;
00675 }
00676 }
00677
00678
00679
00680 const char *GWEN_Logger_Level2Name(GWEN_LOGGER_LEVEL level) {
00681 const char *s;
00682
00683 switch(level) {
00684 case GWEN_LoggerLevel_Emergency:
00685 s="emergency"; break;
00686 case GWEN_LoggerLevel_Alert:
00687 s="alert"; break;
00688 case GWEN_LoggerLevel_Critical:
00689 s="critical"; break;
00690 case GWEN_LoggerLevel_Error:
00691 s="error"; break;
00692 case GWEN_LoggerLevel_Warning:
00693 s="warning"; break;
00694 case GWEN_LoggerLevel_Notice:
00695 s="notice"; break;
00696 case GWEN_LoggerLevel_Info:
00697 s="info"; break;
00698 case GWEN_LoggerLevel_Debug:
00699 s="debug"; break;
00700 case GWEN_LoggerLevel_Verbous:
00701 s="verbous"; break;
00702 case GWEN_LoggerLevel_Unknown:
00703 default:
00704 s="unknown"; break;
00705 }
00706 return s;
00707 }
00708
00709
00710
00711 GWEN_LOGGER_LOGTYPE GWEN_Logger_Name2Logtype(const char *name) {
00712 if (strcasecmp(name, "console")==0)
00713 return GWEN_LoggerType_Console;
00714 else if (strcasecmp(name, "file")==0)
00715 return GWEN_LoggerType_File;
00716 else if (strcasecmp(name, "syslog")==0)
00717 return GWEN_LoggerType_Syslog;
00718 else if (strcasecmp(name, "function")==0)
00719 return GWEN_LoggerType_Function;
00720 else {
00721 return GWEN_LoggerType_Unknown;
00722 }
00723 }
00724
00725
00726
00727 const char *GWEN_Logger_Logtype2Name(GWEN_LOGGER_LOGTYPE lt) {
00728 const char *s;
00729
00730 switch(lt) {
00731 case GWEN_LoggerType_Console:
00732 s="console"; break;
00733 case GWEN_LoggerType_File:
00734 s="file"; break;
00735 case GWEN_LoggerType_Syslog:
00736 s="syslog"; break;
00737 case GWEN_LoggerType_Function:
00738 s="function"; break;
00739 default:
00740 s="unknown"; break;
00741 }
00742 return s;
00743 }
00744
00745
00746
00747 int GWEN_Logger_Exists(const char *logDomain){
00748 assert(logDomain);
00749 return (GWEN_LoggerDomain_Find(logDomain)!=0);
00750 }
00751
00752
00753
00754
00755
00756
00757
00758