]> arthur.barton.de Git - netatalk.git/blob - libatalk/util/logger.c
146fba4c3dc6925902ecf2cc111ba4966d46e4af
[netatalk.git] / libatalk / util / logger.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 /* =========================================================================
6
7        logger.c is part of the utils section in the libatalk library, 
8         which is part of the netatalk project.  
9
10        logger.c was written by Simon Bazley (sibaz@sibaz.com)
11
12        I believe libatalk is released under the L/GPL licence.  
13
14        Just incase, it is, thats the licence I'm applying to this file.
15
16        Netatalk 2001 (c)
17
18    ==========================================================================
19
20        Logger.c is intended as an alternative to syslog for logging
21
22        ---------------------------------------------------------------
23
24    The initial plan is to create a structure for general information needed
25     to log to a file.  
26
27    Initally I'll hard code the neccesary stuff to start a log, this should
28     probably be moved elsewhere when some code is written to read the log
29     file locations from the config files.  
30
31    As a more longterm idea, I'll code this so that the data struct can be
32     duplicated to allow multiple concurrent log files, although this is 
33     probably a recipe for wasted resources. 
34
35    ========================================================================= */
36
37 #include <stdio.h>
38 #include <limits.h>
39 #include <stdarg.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <syslog.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <unistd.h>
46 #include <time.h>
47
48 #include <atalk/boolean.h>
49 #include <atalk/logger.h>
50
51 #define COUNT_ARRAY(array) (sizeof((array))/sizeof((array)[0]))
52 #define NUMOF COUNT_ARRAY
53 #undef  KEEP_LOGFILES_OPEN
54 #define DO_SYSLOG
55 #define DO_FILELOG
56
57 #undef  DEBUG_OUTPUT_TO_SCREEN
58 #undef  CHECK_STAT_ON_NEW_FILES 
59 #undef  CHECK_ACCESS_ON_NEW_FILES 
60
61 /* =========================================================================
62     External function declarations
63    ========================================================================= */
64
65 /* setup the internal variables used by the logger (called automatically) */
66 void log_init();
67
68 /* Setup the log filename and the loglevel, and the type of log it is. */
69 bool log_setup(char *filename, enum loglevels loglevel, enum logtypes logtype, 
70                int display_options);
71
72 /* Setup the Level and type of log that will be logged to syslog. */
73 void syslog_setup(enum loglevels loglevel, enum logtypes logtype, 
74                   int display_options, int facility);
75
76 /* finish up and close the logs */
77 void log_close();
78
79 /* This function sets up the processname */
80 void set_processname(char *processname);
81
82 /* Log a Message */
83 void make_log(enum loglevels loglevel, enum logtypes logtype, 
84               char *message, ...);
85 #ifndef DISABLE_LOGGER
86 make_log_func set_log_location(char *srcfilename, int srclinenumber);
87
88 /* ========================================================================= 
89     Structure definitions
90    ========================================================================= */
91
92 /* A structure containing object level stuff */
93 struct tag_log_file_data {
94   char log_filename[PATH_MAX];  /* Name of file */
95   FILE *log_file;      /* FILE pointer to file */
96   enum loglevels   log_level;     /* Log Level to put in this file */
97   int  display_options;
98 };
99
100 typedef struct tag_log_file_data log_file_data_pair[2];
101
102 /* A structure containg class level stuff */
103 struct tag_global_log_data {
104   int   struct_size;
105
106   char *temp_src_filename;
107   int   temp_src_linenumber;
108   char  processname[16];
109   
110   int   facility;
111   char *log_file_directory;  /* Path of directory containing log files */
112   log_file_data_pair **logs;
113 };
114
115 struct what_to_print_array {
116   bool print_datetime;
117   bool print_processname;
118   bool print_pid;
119   bool print_srcfile;
120   bool print_srcline;
121   bool print_errlevel;
122   bool print_errtype;
123 };
124
125 /* =========================================================================
126     Internal function declarations
127    ========================================================================= */
128
129 void generate_message_details(char *message_details_buffer,
130                               int message_details_buffer_length,
131                               struct tag_log_file_data *log_struct,
132                               enum loglevels loglevel, enum logtypes logtype);
133
134 int get_syslog_equivalent(enum loglevels loglevel);
135
136 static char *get_command_name(char *commandpath);
137
138 /* =========================================================================
139     Instanciated data
140    ========================================================================= */
141
142 /* A populated instance */
143
144 static log_file_data_pair default_log_file_data_pair = {
145 {
146   log_filename:    "\0\0\0\0\0\0\0\0",
147   log_file:        NULL,
148   log_level:       log_debug,
149   display_options: logoption_pid
150 },
151 {
152   log_filename:     LOGFILEPATH,
153   log_file:         NULL,
154   log_level:        log_debug,
155   display_options:  logoption_pid
156 }};
157
158 static log_file_data_pair logger_log_file_data_pair = {
159 {
160   log_filename:    "\0\0\0\0\0\0\0\0",
161   log_file:        NULL,
162   log_level:       log_warning,
163   display_options: logoption_pid
164 },
165 {
166   log_filename:     LOGFILEPATH,
167   log_file:         NULL,
168   log_level:        log_maxdebug,
169   display_options:  logoption_pid
170 }};
171
172 static log_file_data_pair *log_file_data_array[logtype_end_of_list_marker] = 
173 {&default_log_file_data_pair};
174
175 /* The class (populated) */
176 static struct tag_global_log_data global_log_data = {
177   struct_size:         sizeof(struct tag_global_log_data),
178   temp_src_filename:   NULL,
179   temp_src_linenumber: 0,
180   processname:         "",
181   facility:            logfacility_daemon,
182   log_file_directory:  "",
183   logs:                NULL,
184 };
185
186 /* macro to get access to the array */
187 #define log_file_arr (global_log_data.logs)
188
189 /* Array to store text to list given a log type */
190 static const char * arr_logtype_strings[] =  LOGTYPE_STRING_IDENTIFIERS;
191 static const int num_logtype_strings = COUNT_ARRAY(arr_logtype_strings);
192
193 /* Array for charachters representing log severity in the log file */
194 static const char arr_loglevel_chars[] = {'S', 'E', 'W', 'N', 'I', 'D'};
195 static const int num_loglevel_chars = COUNT_ARRAY(arr_loglevel_chars);
196
197 static const char * arr_loglevel_strings[] = LOGLEVEL_STRING_IDENTIFIERS;
198 static const int num_loglevel_strings = COUNT_ARRAY(arr_loglevel_strings);
199
200 #else /* #ifndef DISABLE_LOGGER */
201   char *disabled_logger_processname=NULL;
202 #endif /* DISABLE_LOGGER */
203 /* =========================================================================
204     Global function definitions
205    ========================================================================= */
206
207 #ifndef DISABLE_LOGGER
208
209 /* remember I'm keeping a copy of the actual char * Filename, so you mustn't
210    delete it, until you've finished with the log.  Also you're responsible
211    for deleting it when you have finished with it. */
212 void log_init()
213 {
214   if (global_log_data.logs==NULL)
215   {
216     /* first check default_log_file_data_pair */
217
218     /* next clear out the log_file_data_array */
219     memset(log_file_data_array, 0, sizeof(log_file_data_array));
220     /* now set default_log_file_data_pairs */
221     log_file_data_array[logtype_default] = &default_log_file_data_pair;
222     log_file_data_array[logtype_logger]  = &logger_log_file_data_pair;
223
224     /* now setup the global_log_data struct */
225     global_log_data.logs = log_file_data_array;
226
227     /* make_log_entry(log_debug, logtype_logger, "log_init ran for the first time"); */
228   }
229 }
230 #endif /* #ifndef DISABLE_LOGGER */
231
232 bool log_setup(char *filename, enum loglevels loglevel, enum logtypes logtype, 
233                int display_options)
234 {
235 #ifndef DISABLE_LOGGER
236
237   struct stat statbuf;
238   int firstattempt;
239   int retval;
240   gid_t gid;
241   uid_t uid;
242   int access;
243   char lastchar[2];
244
245   log_file_data_pair *logs;
246
247   log_init();
248
249   logs = log_file_arr[logtype];
250   
251   LOG(log_info, logtype_logger, "doing log_setup, type %d, level %d, filename \"%s\"", logtype, loglevel, filename);
252
253   /* LOG(log_extradebug+10, logtype_logger, "checking array for logtype is malloc'd"); */
254   /* has the given logtype already been assigned memory? */
255   if (logs==NULL)
256   {
257     logs = (log_file_data_pair *)malloc(sizeof(log_file_data_pair));
258     if (logs==NULL)
259     {
260       LOG(log_severe, logtype_logger, "can't calloc in log_setup");
261     }
262     else
263     {
264     /*
265       memcpy(logs, log_file_arr[logtype_default], sizeof(log_file_data_pair));
266      */
267       log_file_arr[logtype] = logs;
268       (*logs)[1].log_file = NULL;
269     }
270   }
271
272   /* I think this checks if we're logging to stdout or not.  Probably unused */
273   if ( ((*logs)[1].log_file == stdout) && ((*logs)[1].log_file != NULL) )
274   {
275     fclose((*logs)[1].log_file);
276     (*logs)[1].log_file = NULL;
277   }
278
279   /* check if we need to append the given filename to a directory */
280   if (strlen(global_log_data.log_file_directory)>0)
281   {
282     lastchar[0] = global_log_data.
283       log_file_directory[strlen(global_log_data.log_file_directory)-1];
284
285     if (lastchar[0] == '/' || lastchar[0] == '\\' || lastchar[0] == ':')
286       lastchar[0] = 0;
287     else
288       /* this should probably be a platform specific path separator */
289       lastchar[0] = '/';
290
291     lastchar[1] = 0;
292   }
293   else
294     lastchar[0] = 0;
295   
296 #ifdef DEBUG_OUTPUT_TO_SCREEN
297   printf("filename is %s stored at location %p\n", (*logs)[1].log_filename, 
298                                                    (*logs)[1].log_filename);
299 #endif /* DEBUG_OUTPUT_TO_SCREEN */
300   if (filename == NULL)
301   {
302     strncpy((*logs)[1].log_filename, 
303             (*(log_file_arr[0]))[1].log_filename, PATH_MAX);
304   }
305   else
306   {
307     sprintf((*logs)[1].log_filename, "%s%s%s", 
308             global_log_data.log_file_directory,
309             lastchar, filename);
310   }
311   (*logs)[1].log_level    = loglevel;
312   (*logs)[1].display_options = display_options;
313
314 #ifdef DEBUG_OUTPUT_TO_SCREEN
315   printf("filename is %s stored at location %p\n", (*logs)[1].log_filename, 
316                                                    (*logs)[1].log_filename);
317 #endif /* DEBUG_OUTPUT_TO_SCREEN */
318
319 #ifdef CHECK_STAT_ON_NEW_FILES
320   uid = geteuid(); 
321   gid = getegid();
322   
323 #ifdef DEBUG_OUTPUT_TO_SCREEN
324   printf("about to stat file %s\n", (*logs)[1].log_filename);
325 #endif
326   firstattempt = stat((*logs)[1].log_filename, &statbuf);
327
328   if (firstattempt == -1)
329   {
330 #ifdef DEBUG_OUTPUT_TO_SCREEN
331     printf("about to call Log with %d, %d, %s, %s\n", 
332            log_note, logtype_logger, 
333            "can't stat Logfile", 
334            (*logs)[1].log_filename
335            );
336 #endif
337
338     /* syslog(LOG_INFO, "stat failed"); */
339     LOG(log_warning, logtype_logger, "stat fails on file %s",
340                      (*logs)[1].log_filename);
341
342     if (strlen(global_log_data.log_file_directory)>0)
343     {
344       retval = stat(global_log_data.log_file_directory, &statbuf);
345       if (retval == -1)
346       {
347 #ifdef DEBUG_OUTPUT_TO_SCREEN
348         printf("can't stat dir either so I'm giving up\n");
349 #endif
350         LOG(log_severe, logtype_logger, "can't stat directory %s either",
351                          global_log_data.log_file_directory);
352         return false;
353       } 
354     }
355   }
356
357 #ifdef CHECK_ACCESS_ON_NEW_FILES
358   access = ((statbuf.st_uid == uid)?(statbuf.st_mode & S_IWUSR):0) + 
359            ((statbuf.st_gid == gid)?(statbuf.st_mode & S_IWGRP):0) +
360            (statbuf.st_mode & S_IWOTH);
361
362   if (access==0)
363   {
364 #ifdef DEBUG_OUTPUT_TO_SCREEN
365     printf("failing with %d, %d, %s, %s\n", log_note, logtype_logger,
366            "can't access Logfile %s",    (*logs)[1].log_filename);
367 #endif
368
369     LOG(log_note, logtype_logger, "can't access file %s", 
370                      (*logs)[1].log_filename);
371     return false;
372   }
373 #endif /* CHECK_ACCESS_ON_NEW_FILES */
374 #endif /* CHECK_STAT_ON_NEW_FILES */
375 #ifdef KEEP_LOGFILES_OPEN
376   if ((*logs)[1].log_file!=NULL)
377     fclose((*logs)[1].log_file);
378
379   (*logs)[1].log_file     = fopen((*logs)[1].log_filename, "at");
380   if ((*logs)[1].log_file == NULL)
381   {
382     LOG(log_severe, logtype_logger, "can't open Logfile %s", 
383         (*logs)[1].log_filename
384         );
385     return false;
386   }
387 #endif
388
389   LOG(log_debug7, logtype_logger, "log_file_arr[%d] now contains: "
390                                   "{log_filename:%s, log_file:%p, log_level: %d}", logtype,
391                                    (*logs)[1].log_filename, (*logs)[1].log_file, (*logs)[1].log_level);
392   LOG(log_debug, logtype_logger, "log_setup[%d] done", logtype);
393
394 #endif /* DISABLE_LOGGER */
395   return true;
396 }
397
398
399 void syslog_setup(enum loglevels loglevel, enum logtypes logtype, 
400                   int display_options, int facility)
401 {
402 #ifndef DISABLE_LOGGER
403   log_file_data_pair *logs;
404
405   log_init();
406
407   logs = log_file_arr[logtype];
408
409   LOG(log_info, logtype_logger, "doing syslog_setup, type %d, level %d", logtype, loglevel);
410
411   if (logs==NULL)
412   {
413     logs = (log_file_data_pair *)malloc(sizeof(log_file_data_pair));    
414     if (logs==NULL)
415     {
416       LOG(log_severe, logtype_logger, "can't calloc in log_setup");
417     }
418     else
419     {
420       memcpy(logs, log_file_arr[logtype_default], sizeof(log_file_data_pair));
421       log_file_arr[logtype] = logs;
422     }
423   }
424
425   (*logs)[0].log_file        = NULL;
426   (*logs)[0].log_filename[0] = 0;
427   (*logs)[0].log_level       = loglevel;
428   (*logs)[0].display_options = display_options;
429   global_log_data.facility   = facility;
430
431   openlog(global_log_data.processname, (*logs)[0].display_options, 
432           global_log_data.facility);
433
434   LOG(log_debug7, logtype_logger, "log_file_arr[%d] now contains: "
435                                   "{log_filename:%s, log_file:%p, log_level: %d}", logtype,
436                                   (*logs)[0].log_filename, (*logs)[0].log_file, (*logs)[0].log_level);
437   LOG(log_debug, logtype_logger, "syslog_setup[%d] done", logtype);
438 #else /* DISABLE_LOGGER */
439 /* behave like a normal openlog call */
440   openlog(disabled_logger_processname, display_options, facility);
441 #endif /* DISABLE_LOGGER */
442 }
443
444 void log_close()
445 {
446 #ifndef DISABLE_LOGGER
447   log_file_data_pair *logs;
448   int n;
449
450   LOG(log_info, logtype_logger, "log_close called");
451
452   for(n=(sizeof(log_file_arr)-1);n>0;n--)
453   {
454     logs = log_file_arr[n];
455 #ifdef KEEP_LOGFILES_OPEN
456     if ((*logs)[1].log_file!=NULL)
457       fclose((*logs)[1].log_file);
458 #endif /* KEEP_LOGFILES_OPEN */
459     if (logs!=NULL)
460     {
461       LOG(log_debug, logtype_logger, "freeing log entry at %d", n);
462 #ifdef DEBUG_OUTPUT_TO_SCREEN
463       printf("Freeing log_data %d, stored at %p\n", n, logs);
464       printf("\t(filename) %s\t(type) %s\n", (*logs)[1].log_filename, 
465              ((n<num_logtype_strings)?arr_logtype_strings[n]:""));
466 #endif /* DEBUG_OUTPUT_TO_SCREEN */
467       free(logs);
468     }
469     log_file_arr[n] = NULL;
470   }
471 #ifdef DEBUG_OUTPUT_TO_SCREEN
472       printf("Freeing log_data %d, stored at %p\n", n, log_file_arr[n]);
473       printf("\t(filename) %s\t(type) %s\n", 
474              (*(log_file_arr[n]))[1].log_filename, 
475              ((n<num_logtype_strings)?arr_logtype_strings[n]:"")
476              );
477 #endif /* DEBUG_OUTPUT_TO_SCREEN */
478 #endif /* DISABLE_LOGGER */
479
480   LOG(log_debug, logtype_logger, "log_close done");
481
482   closelog();
483 }
484
485 /* This function sets up the processname */
486 void set_processname(char *processname)
487 {
488 #ifndef DISABLE_LOGGER
489   /* strncpy(global_log_data.processname, GetCommandName(processname), 15); */
490   strncpy(global_log_data.processname, processname, 15);
491   global_log_data.processname[15] = 0;
492 #else /* DISABLE_LOGGER */
493   disabled_logger_processname = processname;
494 #endif /* DISABLE_LOGGER */
495 }
496
497 #ifndef DISABLE_LOGGER
498 /* This is called by the macro so set the location of the caller of Log */
499 make_log_func set_log_location(char *srcfilename, int srclinenumber)
500 {
501 #ifdef DEBUG_OUTPUT_TO_SCREEN
502   printf("Setting Log Location\n");
503 #endif
504   global_log_data.temp_src_filename = srcfilename;
505   global_log_data.temp_src_linenumber = srclinenumber;
506
507   return make_log_entry;
508 }
509 #endif /* DISABLE_LOGGER */
510
511 /* -------------------------------------------------------------------------
512     MakeLog has 1 main flaws:
513       The message in its entirity, must fit into the tempbuffer.  
514       So it must be shorter than MAXLOGSIZE
515    ------------------------------------------------------------------------- */
516 void make_log_entry(enum loglevels loglevel, enum logtypes logtype, 
517                     char *message, ...)
518 {
519   va_list args;
520   char log_buffer[MAXLOGSIZE];
521 #ifndef DISABLE_LOGGER
522   char log_details_buffer[MAXLOGSIZE];
523
524   log_file_data_pair *logs;
525
526   log_init();
527
528   logs = log_file_arr[logtype];
529
530   if (logs==NULL)
531   {
532     logs = log_file_arr[logtype_default];
533   }
534 #ifdef DEBUG_OUTPUT_TO_SCREEN
535   printf("Making Log\n");
536 #endif
537   
538 #endif /* DISABLE_LOGGER */
539
540   /* Initialise the Messages */
541   va_start(args, message);
542
543   vsnprintf(log_buffer, sizeof(log_buffer), message, args);
544
545   /* Finished with args for now */
546   va_end(args);
547
548 #ifdef DISABLE_LOGGER
549   syslog(get_syslog_equivalent(loglevel), "%s", log_buffer);
550 #else /* DISABLE_LOGGER */
551
552 #ifdef DO_SYSLOG
553   /* check if sysloglevel is high enough */
554   if ((*logs)[0].log_level>=loglevel)
555   {
556     int sysloglevel = get_syslog_equivalent(loglevel);
557
558     generate_message_details(log_details_buffer, sizeof(log_details_buffer),
559                               &(*logs)[0], loglevel, logtype);
560
561 #ifdef DEBUG_OUTPUT_TO_SCREEN
562     printf("About to log %s %s\n", log_details_buffer, log_buffer);
563     printf("about to do syslog\n");
564     printf("done onw syslog\n");
565 #endif
566     syslog(sysloglevel, "%s: %s", log_details_buffer, log_buffer);
567     /* 
568        syslog(sysloglevel, "%s:%s: %s", log_levelString, 
569               log_typeString, LogBuffer); 
570      */
571   }
572 #endif
573
574 #ifdef DO_FILELOG
575 #ifdef DEBUG_OUTPUT_TO_SCREEN
576   printf("about to do the filelog\n");
577 #endif
578   /* check if log_level is high enough */
579   if ((*logs)[1].log_level>=loglevel) {    
580  
581 #ifdef DEBUG_OUTPUT_TO_SCREEN
582     printf("Open the Log, FILE* is %p\n", (*logs)[1].log_file);
583 #endif
584     /* if log isn't open, open it */
585     if ((*logs)[1].log_file==NULL) {
586 #ifdef DEBUG_OUTPUT_TO_SCREEN
587       printf("Opening the Log, filename is %s\n", (*logs)[1].log_filename);
588 #endif
589       (*logs)[1].log_file     = fopen((*logs)[1].log_filename, "at");
590       if ((*logs)[1].log_file == NULL)
591       {
592         (*logs)[1].log_file = stdout;
593         LOG(log_severe, logtype_logger, "can't open Logfile %s", 
594             (*logs)[1].log_filename
595             );
596         return;
597       }
598     }
599     generate_message_details(log_details_buffer, sizeof(log_details_buffer),
600                              &(*logs)[1], loglevel, logtype);
601
602 #ifdef DEBUG_OUTPUT_TO_SCREEN
603     printf("Files open, lets log\n");
604     printf("FILE* is %p\n", (*logs)[1].log_file);
605     printf("%s: %s\n", log_details_buffer, log_buffer);
606 #endif
607
608     fprintf((*logs)[1].log_file, "%s: %s\n", log_details_buffer, log_buffer);
609
610 #ifndef KEEP_LOGFILES_OPEN
611     if ((*logs)[1].log_file != stdout)
612     {
613 #ifdef DEBUG_OUTPUT_TO_SCREEN
614       printf("Closing %s\n", (*logs)[1].log_filename);
615 #endif
616       fclose((*logs)[1].log_file);
617       (*logs)[1].log_file = NULL;
618 #ifdef DEBUG_OUTPUT_TO_SCREEN
619       printf("Closed\n");
620 #endif
621     }
622 #endif 
623   }
624 #endif
625
626   global_log_data.temp_src_filename = NULL;
627   global_log_data.temp_src_linenumber = 0;
628 #endif /* DISABLE_LOGGER */
629 }
630
631 #ifndef DISABLE_LOGGER
632 void load_proccessname_from_proc()
633 {
634   pid_t pid = getpid();
635   char buffer[PATH_MAX];
636   char procname[16];
637   FILE * statfile;
638   char *ptr;
639
640   sprintf(buffer, "/proc/%d/stat", pid);
641   statfile = fopen(buffer, "rt");
642   fgets(buffer, PATH_MAX-1, statfile);
643   fclose(statfile);
644
645   ptr = (char *)strrchr(buffer, ')');
646   *ptr = '\0';
647   memset(procname, 0, sizeof procname);
648   sscanf(buffer, "%d (%15c", &pid, procname);   /* comm[16] in kernel */
649
650   set_processname(procname);
651 }
652
653 /* =========================================================================
654     Internal function definitions
655    ========================================================================= */
656
657 static char *get_command_name(char *commandpath)
658 {
659   char *ptr;
660 #ifdef DEBUG_OUTPUT_TO_SCREEN
661   printf("getting command name %s\n",commandpath);
662 #endif
663   ptr = (char *)strrchr(commandpath, '/');
664   if (ptr==NULL)
665     ptr = commandpath;
666   else
667     ptr++;
668
669 #ifdef DEBUG_OUTPUT_TO_SCREEN
670   printf("Concluded %s\n", ptr);
671 #endif
672   return ptr;
673 }
674
675 void  workout_what_to_print(struct what_to_print_array *what_to_print, 
676                             struct tag_log_file_data *log_struct)
677 {
678   /* is this a syslog entry? */
679   if (log_struct->log_filename[0]==0)
680   {
681     what_to_print->print_datetime = false;
682     what_to_print->print_processname = false;
683     what_to_print->print_pid = false;
684   }
685   else
686   {
687     what_to_print->print_datetime = true;
688     what_to_print->print_processname = true;
689  
690     /* pid is dealt with at the syslog level if we're syslogging */
691     what_to_print->print_pid = 
692       (((log_struct->display_options & logoption_pid) == 0)?false:true);
693   }
694
695   what_to_print->print_srcfile = 
696     (((log_struct->display_options & logoption_nfile) == 0)?true:false);
697   what_to_print->print_srcline = 
698     (((log_struct->display_options & logoption_nline) == 0)?true:false);
699   
700   what_to_print->print_errlevel = true;
701   what_to_print->print_errtype = true;
702 }
703
704 void generate_message_details(char *message_details_buffer, 
705                               int message_details_buffer_length,
706                               struct tag_log_file_data *log_struct,
707                               enum loglevels loglevel, enum logtypes logtype)
708 {
709   char datebuffer[32];
710   char processinfo[64];
711
712   char *ptr = message_details_buffer;
713   int   templen;
714   int   len = message_details_buffer_length;
715
716   char log_buffer[MAXLOGSIZE];
717   const char *logtype_string;
718
719   char loglevel_string[12]; /* max int size is 2 billion, or 10 digits */
720
721   struct what_to_print_array what_to_print;
722
723   workout_what_to_print(&what_to_print, log_struct);
724
725 #ifdef DEBUG_OUTPUT_TO_SCREEN
726   printf("Making MessageDetails\n");
727 #endif
728
729   *ptr = 0;
730   /*
731   datebuffer[0] = 0;
732   ptr = datebuffer;
733   */
734
735   if (what_to_print.print_datetime)
736   {
737     time_t thetime;
738     time(&thetime);
739
740   /* some people might prefer localtime() to gmtime() */
741     strftime(ptr, len, "%b %d %H:%M:%S", localtime(&thetime));
742 #ifdef DEBUG_OUTPUT_TO_SCREEN
743     printf("date is %s\n", ptr);
744 #endif
745
746     templen = strlen(ptr);
747     len -= templen;
748     if (what_to_print.print_processname || what_to_print.print_pid)
749       strncat(ptr, " ", len);
750     else
751       strncat(ptr, ":", len);
752
753     templen++;
754     len --;
755     ptr += templen;
756   }
757
758   /*
759   processinfo[0] = 0;
760   ptr = processinfo;
761   */
762
763   if (what_to_print.print_processname)
764   {
765     strncpy(ptr, global_log_data.processname, len);
766
767     templen = strlen(ptr);
768     len -= templen;
769     ptr += templen;
770   }
771
772   if (what_to_print.print_pid)
773   {
774     pid_t pid = getpid();
775
776     sprintf(ptr, "[%d]", pid);
777
778     templen = strlen(ptr);
779     len -= templen;
780     ptr += templen;
781   }
782
783   if (what_to_print.print_srcfile || what_to_print.print_srcline)
784   {
785     char sprintf_buffer[8];
786     char *buff_ptr;
787
788     sprintf_buffer[0] = '[';
789     if (what_to_print.print_srcfile)
790     {
791       strcpy(&sprintf_buffer[1], "%s");
792       buff_ptr = &sprintf_buffer[3];
793     }
794     if (what_to_print.print_srcfile && what_to_print.print_srcline)
795     {
796       strcpy(&sprintf_buffer[3], ":");
797       buff_ptr = &sprintf_buffer[4];
798     }
799     if (what_to_print.print_srcline)
800     {
801       strcpy(buff_ptr, "%d");
802       buff_ptr = &buff_ptr[2];
803     }
804     strcpy(buff_ptr, "]");
805
806     /* 
807        ok sprintf string is ready, now is the 1st parameter src or linenumber
808      */
809     if (what_to_print.print_srcfile)
810     {
811       sprintf(ptr, sprintf_buffer, 
812               global_log_data.temp_src_filename, 
813               global_log_data.temp_src_linenumber);
814     }
815     else
816     {
817       sprintf(ptr, sprintf_buffer, global_log_data.temp_src_linenumber);
818     }
819
820 #ifdef DEBUG_OUTPUT_TO_SCREEN
821     printf("Process info is %s\n", ptr);
822 #endif
823
824     templen = strlen(ptr);
825     len -= templen;
826     ptr += templen;
827
828   }
829
830   if (what_to_print.print_processname || what_to_print.print_pid ||
831       what_to_print.print_srcfile || what_to_print.print_srcline)
832   {
833     strncat(ptr, ": ", len);
834     len -= 2;
835     ptr += 2;
836   }
837
838 /*
839   loglevel_string[0] = 0;
840   ptr = loglevel_string;
841 */
842
843   if (what_to_print.print_errlevel)
844   {
845     if ((loglevel/10) >= (num_loglevel_chars-1))
846     {
847       sprintf(ptr, "%c%d", arr_loglevel_chars[num_loglevel_chars-1],
848                                        loglevel/10);
849     }
850     else
851     {
852       sprintf(ptr, "%c", arr_loglevel_chars[loglevel/10]);
853     }
854
855     templen = strlen(ptr);
856     len -= templen;
857     ptr += templen;    
858   }
859
860   if (what_to_print.print_errtype)
861   {
862     const char *logtype_string;
863
864     /* get string represnetation of the Log Type */
865     if (logtype<num_logtype_strings)
866       logtype_string = arr_logtype_strings[logtype];
867     else
868       logtype_string = "";
869
870     if (what_to_print.print_errlevel)
871     {
872       strncat(ptr, ":", len);
873       ptr++;
874     }
875
876     sprintf(ptr, "%s", logtype_string);
877   }
878
879   message_details_buffer[message_details_buffer_length-1] = 0;
880
881 #ifdef DEBUG_OUTPUT_TO_SCREEN
882     printf("Message Details are %s\n", message_details_buffer);
883 #endif
884 }
885 #endif /* DISABLE_LOGGER */
886
887 int get_syslog_equivalent(enum loglevels loglevel)
888 {
889   switch (loglevel/10)
890   {
891     /* The question is we know how bad it is for us,
892                     but how should that translate in the syslogs?  */
893     case 0: /* severe */
894       return LOG_ERR;
895     case 1: /* error */
896       return LOG_ERR;
897     case 2: /* warning */
898       return LOG_WARNING;
899     case 3: /* note */
900       return LOG_NOTICE;
901     case 4: /* information */
902       return LOG_INFO;
903     default: /* debug */
904       return LOG_DEBUG;
905   }
906 }
907
908 /* void setuplog(char *logsource, char *logtype, char *loglevel, char *filename) */
909 void setuplog(char *logtype, char *loglevel, char *filename)
910 {
911 #ifndef DISABLE_LOGGER 
912   /* -[un]setuplog <logtype> <loglevel> [<filename>]*/
913   /*
914     This should be rewritten so that somehow logsource is assumed and everything
915     can be taken from default if needs be.  
916    */
917   /* const char* sources[] = {"syslog", "filelog"}; */
918   const char *null = "";
919   int sourcenum, typenum, levelnum;
920   log_file_data_pair *logs = log_file_arr[logtype_default];
921
922   /*
923   LOG(log_extradebug, logtype_logger, "Attempting setuplog: %s %s %s %s", 
924       logsource, logtype, loglevel, filename);
925   */
926   LOG(log_info, logtype_logger, "setuplog is parsing logtype:%s, loglevel:%s, filename:%s", 
927       logtype, loglevel, filename);
928
929   if (logtype==NULL)
930   {
931     LOG(log_note, logtype_logger, "no logsource given, default is assumed");
932     typenum=0;
933   }
934   else
935   {
936     for(typenum=0;typenum<num_logtype_strings;typenum++)
937     {
938       if (strcasecmp(logtype, arr_logtype_strings[typenum])==0)
939         break;
940     }
941     if (typenum>=num_logtype_strings)
942     {
943       LOG(log_warning, logtype_logger, "%s is not a valid log type", logtype);
944     }
945   }
946
947   if (loglevel==NULL)
948   {
949     LOG(log_note, logtype_logger, "no loglevel given, severe is assumed");
950     levelnum=0;
951   }
952   else
953   {
954     for(levelnum=0;levelnum<num_loglevel_strings;levelnum++)
955     {
956       if (strcasecmp(loglevel, arr_loglevel_strings[levelnum])==0)
957         break;
958     }
959     if (levelnum>=num_loglevel_strings)
960     {
961       LOG(log_warning, logtype_logger, "%s is not a valid log level", loglevel);
962     }
963   }
964
965   /* sanity check */
966   if ((typenum>=num_logtype_strings) || (levelnum>=num_loglevel_strings))
967   {
968     LOG(log_warning, logtype_logger, "sanity check failed: (%s:%d), (%s:%d)", 
969                     logtype, typenum, loglevel, levelnum);
970     return;
971   }
972
973   /* now match the order of the text string with the actual enum value (10 times) */
974   levelnum*=10;
975   
976   /* is this a syslog setup or a filelog setup */
977   if (filename==NULL) /* must be syslog */
978   {
979     LOG(log_debug6, logtype_logger, "calling syslog_setup(%d, %d, ...)", levelnum, typenum);
980     syslog_setup(levelnum, typenum, 
981                  (*logs)[0].display_options,
982                  global_log_data.facility);
983   }
984   else /* this must be a filelog */
985   {
986     LOG(log_debug6, logtype_logger, "calling log_setup(%s, %d, %d, ...)", filename, levelnum, typenum);
987     log_setup(filename, levelnum, typenum, 
988               (*logs)[0].display_options);
989   };  
990   return;
991 #endif /* DISABLE_LOGGER */
992 }
993
994
995
996
997
998
999