gwenhywfar  4.8.0beta
logger.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Sun Dec 05 2003
3  copyright : (C) 2003 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #include <gwenhywfar/gwenhywfarapi.h>
31 #include <gwenhywfar/misc.h>
32 #include <gwenhywfar/buffer.h>
33 #include <gwenhywfar/gui.h>
34 
35 #include "logger_p.h"
36 
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <errno.h>
40 #ifdef HAVE_SYSLOG_H
41 # include <syslog.h>
42 #endif
43 #include <string.h>
44 #ifdef HAVE_STRINGS_H
45 # include <strings.h>
46 #endif
47 #ifdef HAVE_TIME_H
48 # include <time.h>
49 #endif
50 #ifdef HAVE_UNISTD_H
51 # include <unistd.h>
52 #endif
53 
54 
55 static GWEN_LOGGER_DOMAIN *gwen_loggerdomains=0;
56 
57 
58 
60  const char *s;
62 
64  "gwen",
65  0,
68  s=getenv("GWEN_LOGLEVEL");
69  if (s) {
73  }
75  return 0;
76 }
77 
78 
79 
81  GWEN_LOGGER_DOMAIN *ld;
82 
83  while((ld=gwen_loggerdomains)) {
86  }
87  return 0;
88 }
89 
90 
91 
92 GWEN_LOGGER_DOMAIN *GWEN_LoggerDomain_new(const char *name){
93  GWEN_LOGGER_DOMAIN *ld;
94 
95  assert(name);
96  GWEN_NEW_OBJECT(GWEN_LOGGER_DOMAIN, ld);
97  ld->name=strdup(name);
98  return ld;
99 }
100 
101 
102 
103 void GWEN_LoggerDomain_free(GWEN_LOGGER_DOMAIN *ld){
104  if (ld) {
105  free(ld->name);
106  GWEN_Logger_free(ld->logger);
107  GWEN_FREE_OBJECT(ld);
108  }
109 }
110 
111 
112 GWEN_LOGGER_DOMAIN *GWEN_LoggerDomain_Find(const char *name) {
113  GWEN_LOGGER_DOMAIN *ld;
114 
115  assert(name);
117  while(ld) {
118  if (strcasecmp(ld->name, name)==0)
119  break;
120  ld=ld->next;
121  }
122 
123  return ld;
124 }
125 
126 
127 
128 void GWEN_LoggerDomain_Add(GWEN_LOGGER_DOMAIN *ld){
129  assert(ld);
130  GWEN_LIST_INSERT(GWEN_LOGGER_DOMAIN, ld, &gwen_loggerdomains);
131 }
132 
133 
134 
135 void GWEN_LoggerDomain_Del(GWEN_LOGGER_DOMAIN *ld){
136  assert(ld);
137  GWEN_LIST_DEL(GWEN_LOGGER_DOMAIN, ld, &gwen_loggerdomains);
138 }
139 
140 
141 
142 GWEN_LOGGER *GWEN_LoggerDomain_GetLogger(const char *name) {
143  GWEN_LOGGER_DOMAIN *ld;
144 
145  if (!name)
146  name="default";
147 
148  ld=GWEN_LoggerDomain_Find(name);
149  if (ld) {
150  return ld->logger;
151  }
152  ld=GWEN_LoggerDomain_new(name);
153  ld->logger=GWEN_Logger_new(ld);
154 
156  return ld->logger;
157 }
158 
159 
160 
161 GWEN_LOGGER *GWEN_Logger_new(GWEN_LOGGER_DOMAIN *domain){
162  GWEN_LOGGER *lg;
163 
164  GWEN_NEW_OBJECT(GWEN_LOGGER, lg);
165  lg->usage=1;
166  lg->enabled=1;
167  lg->logType=GWEN_LoggerType_Console;
168  lg->logLevel=GWEN_LoggerLevel_Error;
169  lg->domain=domain;
170  return lg;
171 }
172 
173 
174 
175 void GWEN_Logger_free(GWEN_LOGGER *lg){
176  if (lg) {
177  assert(lg->usage);
178  if (--(lg->usage)==0) {
179  free(lg->logFile);
180  free(lg->logIdent);
181  GWEN_FREE_OBJECT(lg);
182  }
183  }
184 }
185 
186 
187 
188 void GWEN_Logger_Attach(GWEN_LOGGER *lg){
189  assert(lg);
190  lg->usage++;
191 }
192 
193 
194 
195 void GWEN_Logger_AddLogger(GWEN_LOGGER *oldLogger, GWEN_LOGGER *newLogger){
196  assert(newLogger);
197 
198  assert(oldLogger);
199  GWEN_LIST_ADD(GWEN_LOGGER, newLogger, &(oldLogger->next));
200 }
201 
202 
203 
205  fprintf(stderr, "GWEN_Logger_SetDefaultLogger: Deprecated function\n");
206 }
207 
208 
209 
210 int GWEN_Logger_Open(const char *logDomain,
211  const char *ident,
212  const char *file,
213  GWEN_LOGGER_LOGTYPE logtype,
214  GWEN_LOGGER_FACILITY facility){
215  GWEN_LOGGER *lg;
216 
217  lg=GWEN_LoggerDomain_GetLogger(logDomain);
218  assert(lg);
219  lg->logType=logtype;
220 
221  GWEN_Logger_SetIdent(logDomain, ident);
222  GWEN_Logger_SetFilename(logDomain, file);
223 
224  if (logtype==GWEN_LoggerType_File) {
225  /* logging to a file */
226  if (file==0) {
227  lg->logType=GWEN_LoggerType_Console;
228  lg->enabled=1;
229  fprintf(stderr,"LOGGER: No filename given, will log to console.\n");
230  }
231  else {
232  lg->logType=GWEN_LoggerType_File;
233  lg->enabled=1;
234  }
235  }
236 #ifdef HAVE_SYSLOG_H
237  else if (logtype==GWEN_LoggerType_Syslog) {
238  /* caller wants to log via syslog */
239  int fac;
240 
241  switch(facility) {
243  fac=LOG_AUTH;
244  break;
246  fac=LOG_DAEMON;
247  break;
249  fac=LOG_MAIL;
250  break;
252  fac=LOG_NEWS;
253  break;
256  default:
257  fac=LOG_USER;
258  break;
259  }
260 
261  openlog(ident,
262  LOG_CONS |
263  LOG_PID,
264  fac);
265  lg->enabled=1;
266  } /* if syslog */
267 #endif /* ifdef HAVE_SYSLOG_H */
268 
269  else {
270  /* console or function */
271  lg->enabled=1;
272  }
273 
274  lg->open=1;
275 
276  return GWEN_Logger_Log(logDomain, GWEN_LoggerLevel_Debug, "started");
277 }
278 
279 
280 
281 void GWEN_Logger_Close(const char *logDomain){
282  GWEN_LOGGER *lg;
283 
284  lg=GWEN_LoggerDomain_GetLogger(logDomain);
285  assert(lg);
286  GWEN_Logger_Log(logDomain, GWEN_LoggerLevel_Debug, "stopped");
287  lg->logType=GWEN_LoggerType_Console;
288  lg->enabled=0;
289 #ifdef HAVE_SYSLOG_H
290  closelog();
291 #endif
292  lg->open=0;
293  /* remove logdomain after it has been closed */
294  GWEN_LoggerDomain_Del(lg->domain);
295  GWEN_LoggerDomain_free(lg->domain);
296 }
297 
298 
299 
300 int GWEN_Logger_IsOpen(const char *logDomain){
301  GWEN_LOGGER_DOMAIN *ld;
302 
303  if (!logDomain)
304  logDomain="default";
305  ld=GWEN_LoggerDomain_Find(logDomain);
306  if (ld)
307  return ld->logger->open;
308  return 0;
309 }
310 
311 
312 int GWEN_Logger__CreateMessage(GWEN_LOGGER *lg,
313  GWEN_LOGGER_LEVEL priority, const char *s,
314  GWEN_BUFFER *mbuf) {
315 #ifdef HAVE_SNPRINTF
316  unsigned int i;
317 #endif /* HAVE_SNPRINTF */
318 #ifdef HAVE_TIME_H
319  struct tm *t;
320  time_t tt;
321 #endif /* HAVE_TIME_H */
322  char buffer[256];
323 
324  assert(lg);
325  if (lg->logIdent) {
326  if (strlen(lg->logIdent)+32>=sizeof(buffer)) {
327  fprintf(stderr," LOGGER: Logbuffer too small (1).\n");
328  return 1;
329  }
330  }
331 
332 #ifdef HAVE_TIME_H
333  tt=time(0);
334  t=localtime(&tt);
335 
336 # ifdef HAVE_SNPRINTF
337 # ifdef HAVE_GETPID
338  i=snprintf(buffer, sizeof(buffer)-1,
339  "%d:%04d/%02d/%02d %02d-%02d-%02d:%s(%d):",priority,
340  t->tm_year+1900, t->tm_mon+1, t->tm_mday,
341  t->tm_hour, t->tm_min, t->tm_sec,
342  lg->logIdent, (int)getpid());
343 # else
344  i=snprintf(buffer, sizeof(buffer)-1,
345  "%d:%04d/%02d/%02d %02d-%02d-%02d:%s:",priority,
346  t->tm_year+1900, t->tm_mon+1, t->tm_mday,
347  t->tm_hour, t->tm_min, t->tm_sec,
348  lg->logIdent);
349 # endif /* HAVE_GETPID */
350  if (i>=sizeof(buffer)) {
351  fprintf(stderr," LOGGER: Logbuffer too small (2).\n");
352  return 1;
353  }
354 # else /* HAVE_SNPRINTF */
355 # ifdef HAVE_GETPID
356  sprintf(buffer,"%d:%04d/%02d/%02d %02d-%02d-%02d:%s(%d):",priority,
357  t->tm_year+1900, t->tm_mon+1, t->tm_mday,
358  t->tm_hour, t->tm_min, t->tm_sec,
359  lg->logIdent, (int)getpid());
360 # else
361  sprintf(buffer,"%d:%04d/%02d/%02d %02d-%02d-%02d:%s:",priority,
362  t->tm_year+1900, t->tm_mon+1, t->tm_mday,
363  t->tm_hour, t->tm_min, t->tm_sec,
364  lg->logIdent);
365 # endif /* HAVE_GETPID */
366 # endif /* HAVE_SNPRINTF */
367 #else /* HAVE_TIME_H */
368 # ifdef HAVE_SNPRINTF
369  buffer[sizeof(buffer)-1]=0;
370  i=snprintf(buffer, sizeof(buffer)-1,
371  "%d:%s:",priority,
372  lg->logIdent);
373  if (i>=sizeof(buffer)) {
374  fprintf(stderr," LOGGER: Logbuffer too small (3).\n");
375  return 1;
376  }
377 # else /* HAVE_SNPRINTF */
378  sprintf(buffer,"%d:%s:",priority,
379  lg->logIdent);
380 # endif /* HAVE_SNPRINTF */
381 #endif /* HAVE_TIME_H */
382  GWEN_Buffer_AppendString(mbuf, buffer);
383  GWEN_Buffer_AppendString(mbuf, s);
384  GWEN_Buffer_AppendByte(mbuf, '\n');
385  return 0;
386 }
387 
388 
389 
390 int GWEN_Logger_CreateLogMessage(const char *logDomain,
391  GWEN_LOGGER_LEVEL priority, const char *s,
392  GWEN_BUFFER *mbuf){
393  GWEN_LOGGER *lg;
394 
395  lg=GWEN_LoggerDomain_GetLogger(logDomain);
396  assert(lg);
397 
398  return GWEN_Logger__CreateMessage(lg, priority, s, mbuf);
399 }
400 
401 
402 
403 int GWEN_Logger__Log(GWEN_LOGGER *lg,
404  GWEN_LOGGER_LEVEL priority, const char *s){
405  while(lg) {
406  FILE *f;
407 #ifdef HAVE_SYSLOG_H
408  int pri;
409 #endif /* HAVE_SYSLOG_H */
410  GWEN_BUFFER *mbuf;
411  int rv;
412 
413  assert(lg);
414  if (priority>lg->logLevel)
415  /* priority too low, don't log */
416  return 0;
417 
418  mbuf=GWEN_Buffer_new(0, 256, 0, 1);
419  switch(lg->logType) {
421  rv=GWEN_Logger__CreateMessage(lg, priority, s, mbuf);
422  if (rv) {
423  GWEN_Buffer_free(mbuf);
424  return rv;
425  }
426 
427  f=fopen(lg->logFile,"a+");
428  if (f==0) {
429  fprintf(stderr,
430  "LOGGER: Unable to open file \"%s\" (%s)\n",
431  lg->logFile,
432  strerror(errno));
433  lg->logType=GWEN_LoggerType_Console;
434  GWEN_Buffer_free(mbuf);
435  return 1;
436  }
437 
438  if (fwrite(GWEN_Buffer_GetStart(mbuf),
439  GWEN_Buffer_GetUsedBytes(mbuf), 1, f)!=1) {
440  fprintf(stderr,
441  "LOGGER: Unable to write to file \"%s\" (%s)\n",
442  lg->logFile,
443  strerror(errno));
444  fclose(f);
445  lg->logType=GWEN_LoggerType_Console;
446  GWEN_Buffer_free(mbuf);
447  return 1;
448  }
449  if (fclose(f)) {
450  fprintf(stderr,
451  "LOGGER: Unable to close file \"%s\" (%s)\n",
452  lg->logFile,
453  strerror(errno));
454  lg->logType=GWEN_LoggerType_Console;
455  GWEN_Buffer_free(mbuf);
456  return 1;
457  }
458  break;
459 
460 #ifdef HAVE_SYSLOG_H
462  switch(priority) {
464  pri=LOG_EMERG;
465  break;
467  pri=LOG_ALERT;
468  break;
470  pri=LOG_CRIT;
471  break;
473  pri=LOG_ERR;
474  break;
476  pri=LOG_WARNING;
477  break;
479  pri=LOG_NOTICE;
480  break;
482  pri=LOG_NOTICE;
483  break;
484 
488  default:
489  pri=LOG_DEBUG;
490  break;
491  } /* switch */
492  syslog(pri,"%s",s);
493  break;
494 #endif /* HAVE_SYSLOG_H */
495 
497  if (lg->logFunction==0) {
498  fprintf(stderr,
499  "LOGGER: Logtype is \"Function\", but no function is set.\n");
500  GWEN_Buffer_free(mbuf);
501  return 1;
502  }
503  rv=GWEN_Logger__CreateMessage(lg, priority, s, mbuf);
504  if (rv) {
505  GWEN_Buffer_free(mbuf);
506  return rv;
507  }
508  (lg->logFunction)(GWEN_Buffer_GetStart(mbuf));
509  break;
510 
513  default:
514  rv=GWEN_Logger__CreateMessage(lg, priority, s, mbuf);
515  if (rv) {
516  GWEN_Buffer_free(mbuf);
517  return rv;
518  }
519 
520  fprintf(stderr, "%s", GWEN_Buffer_GetStart(mbuf));
521  break;
522  } /* switch */
523  lg=lg->next;
524  GWEN_Buffer_free(mbuf);
525  } /* while lg */
526  return 0;
527 }
528 
529 
530 
531 int GWEN_Logger_Log(const char *logDomain,
532  GWEN_LOGGER_LEVEL priority, const char *s){
533  if (!GWEN_Gui_LogHook(logDomain, priority, s)) {
534  const char *p;
535  int rv;
536  unsigned int i;
537  GWEN_BUFFER *mbuf;
538  GWEN_LOGGER *lg;
539 
540  lg=GWEN_LoggerDomain_GetLogger(logDomain);
541  assert(lg);
542 
543  if (!lg->enabled)
544  return 1;
545 
546  if (priority>lg->logLevel)
547  /* priority too low, don't log */
548  return 0;
549 
550  /* temporarily disable logging to avoid endless loops */
551  lg->enabled=0;
552  /* copy buffer, exchange all newlines by 0 */
553  mbuf=GWEN_Buffer_new(0, strlen(s)+1, 0, 1);
554  for (i=0; i<strlen(s)+1; i++) {
555  if (s[i]=='\n') {
556  GWEN_Buffer_AppendByte(mbuf, 0);
557  }
558  else
559  GWEN_Buffer_AppendByte(mbuf, s[i]);
560  }
561 
562  /* now log each line */
563  rv=0;
564  p=GWEN_Buffer_GetStart(mbuf);
565  while (*p) {
566  rv|=GWEN_Logger__Log(lg, priority, p);
567  while(*p)
568  p++;
569  p++;
570  }
571  GWEN_Buffer_free(mbuf);
572  /* reenable logging */
573  lg->enabled=1;
574  return rv;
575  }
576  else
577  return 0;
578 }
579 
580 
581 
582 void GWEN_Logger_Enable(const char *logDomain, int f){
583  GWEN_LOGGER *lg;
584 
585  lg=GWEN_LoggerDomain_GetLogger(logDomain);
586  assert(lg);
587  lg->enabled=f;
588 }
589 
590 
591 
592 int GWEN_Logger_IsEnabled(const char *logDomain){
593  GWEN_LOGGER *lg;
594 
595  lg=GWEN_LoggerDomain_GetLogger(logDomain);
596  assert(lg);
597  return lg->enabled;
598 }
599 
600 
601 
602 void GWEN_Logger_SetLevel(const char *logDomain, GWEN_LOGGER_LEVEL l){
603  GWEN_LOGGER *lg;
604 
605  lg=GWEN_LoggerDomain_GetLogger(logDomain);
606  assert(lg);
607  lg->logLevel=l;
608 }
609 
610 
611 
612 int GWEN_Logger_GetLevel(const char *logDomain) {
613  GWEN_LOGGER *lg;
614 
615  lg=GWEN_LoggerDomain_GetLogger(logDomain);
616  assert(lg);
617 
618  return lg->logLevel;
619 }
620 
621 
622 
623 void GWEN_Logger_SetIdent(const char *logDomain, const char *id){
624  GWEN_LOGGER *lg;
625 
626  lg=GWEN_LoggerDomain_GetLogger(logDomain);
627  assert(lg);
628 
629  free(lg->logIdent);
630  if (id)
631  lg->logIdent=strdup(id);
632  else
633  lg->logIdent=strdup("No ident, please adjust your program");
634 }
635 
636 
637 
638 void GWEN_Logger_SetFilename(const char *logDomain, const char *name){
639  GWEN_LOGGER *lg;
640 
641  lg=GWEN_LoggerDomain_GetLogger(logDomain);
642  assert(lg);
643 
644  free(lg->logFile);
645  if (name)
646  lg->logFile=strdup(name);
647  else
648  lg->logFile=strdup("");
649 }
650 
651 
652 
655  GWEN_LOGGER *lg;
657 
658  lg=GWEN_LoggerDomain_GetLogger(logDomain);
659  assert(lg);
660  oldFn=lg->logFunction;
661  lg->logFunction=fn;
662  return oldFn;
663 }
664 
665 
666 
668  if (strcasecmp(name, "emergency")==0)
670  else if (strcasecmp(name, "alert")==0)
671  return GWEN_LoggerLevel_Alert;
672  else if (strcasecmp(name, "critical")==0)
674  else if (strcasecmp(name, "error")==0)
675  return GWEN_LoggerLevel_Error;
676  else if (strcasecmp(name, "warning")==0)
678  else if (strcasecmp(name, "notice")==0)
680  else if (strcasecmp(name, "info")==0)
681  return GWEN_LoggerLevel_Info;
682  else if (strcasecmp(name, "debug")==0)
683  return GWEN_LoggerLevel_Debug;
684  else if (strcasecmp(name, "verbous")==0)
686  else {
688  }
689 }
690 
691 
692 
694  const char *s;
695 
696  switch(level) {
698  s="emergency"; break;
700  s="alert"; break;
702  s="critical"; break;
704  s="error"; break;
706  s="warning"; break;
708  s="notice"; break;
710  s="info"; break;
712  s="debug"; break;
714  s="verbous"; break;
716  default:
717  s="unknown"; break;
718  } /* switch */
719  return s;
720 }
721 
722 
723 
725  if (strcasecmp(name, "console")==0)
727  else if (strcasecmp(name, "file")==0)
728  return GWEN_LoggerType_File;
729  else if (strcasecmp(name, "syslog")==0)
730  return GWEN_LoggerType_Syslog;
731  else if (strcasecmp(name, "function")==0)
733  else {
735  }
736 }
737 
738 
739 
741  const char *s;
742 
743  switch(lt) {
745  s="console"; break;
747  s="file"; break;
749  s="syslog"; break;
751  s="function"; break;
753  default:
754  s="unknown"; break;
755  } /* switch */
756  return s;
757 }
758 
759 
760 
761 int GWEN_Logger_Exists(const char *logDomain){
762  assert(logDomain);
763  return (GWEN_LoggerDomain_Find(logDomain)!=0);
764 }
765 
766 
767 
768 
769 
770 
771 
772