]> arthur.barton.de Git - netatalk.git/blob - libatalk/util/logger.c
Warning fixes.
[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 #define 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 #define OPEN_LOGS_AS_UID 0
61
62 /* =========================================================================
63     External function declarations
64    ========================================================================= */
65
66 /* setup the internal variables used by the logger (called automatically) */
67 void log_init();
68
69 /* Setup the log filename and the loglevel, and the type of log it is. */
70 bool log_setup(char *filename, enum loglevels loglevel, enum logtypes logtype, 
71                int display_options);
72
73 /* Setup the Level and type of log that will be logged to syslog. */
74 void syslog_setup(enum loglevels loglevel, enum logtypes logtype, 
75                   int display_options, int facility);
76
77 /* finish up and close the logs */
78 void log_close();
79
80 /* This function sets up the processname */
81 void set_processname(char *processname);
82
83 /* Log a Message */
84 void make_log(enum loglevels loglevel, enum logtypes logtype, 
85               char *message, ...);
86 #ifndef DISABLE_LOGGER
87 make_log_func set_log_location(char *srcfilename, int srclinenumber);
88
89 /* ========================================================================= 
90     Structure definitions
91    ========================================================================= */
92
93 /* A structure containing object level stuff */
94 struct tag_log_file_data {
95   char log_filename[PATH_MAX];  /* Name of file */
96   FILE *log_file;      /* FILE pointer to file */
97   enum loglevels   log_level;     /* Log Level to put in this file */
98   int  display_options;
99 };
100
101 typedef struct tag_log_file_data log_file_data_pair[2];
102
103 /* A structure containg class level stuff */
104 struct tag_global_log_data {
105   int   struct_size;
106
107   char *temp_src_filename;
108   int   temp_src_linenumber;
109   char  processname[16];
110   
111   int   facility;
112   char *log_file_directory;  /* Path of directory containing log files */
113   log_file_data_pair **logs;
114 };
115
116 struct what_to_print_array {
117   bool print_datetime;
118   bool print_processname;
119   bool print_pid;
120   bool print_srcfile;
121   bool print_srcline;
122   bool print_errlevel;
123   bool print_errtype;
124 };
125
126 /* =========================================================================
127     Internal function declarations
128    ========================================================================= */
129
130 void generate_message_details(char *message_details_buffer,
131                               int message_details_buffer_length,
132                               struct tag_log_file_data *log_struct,
133                               enum loglevels loglevel, enum logtypes logtype);
134
135 int get_syslog_equivalent(enum loglevels loglevel);
136
137 /* =========================================================================
138     Instanciated data
139    ========================================================================= */
140
141 /* A populated instance */
142
143 static log_file_data_pair default_log_file_data_pair = {
144 {
145   /*log_filename:*/    "\0\0\0\0\0\0\0\0",
146   /*log_file:*/        NULL,
147   /*log_level:*/       log_debug,
148   /*display_options:*/ logoption_pid
149 },
150 {
151   /*log_filename:*/     LOGFILEPATH,
152   /*log_file:*/         NULL,
153   /*log_level:*/        log_debug,
154   /*display_options:*/  logoption_pid
155 }};
156
157 static log_file_data_pair logger_log_file_data_pair = {
158 {
159   /*log_filename:*/    "\0\0\0\0\0\0\0\0",
160   /*log_file:*/        NULL,
161   /*log_level:*/       log_warning,
162   /*display_options:*/ logoption_pid
163 },
164 {
165   /*log_filename:*/     LOGFILEPATH,
166   /*log_file:*/         NULL,
167   /*log_level:*/        log_maxdebug,
168   /*display_options:*/  logoption_pid
169 }};
170
171 static log_file_data_pair *log_file_data_array[logtype_end_of_list_marker] = 
172 {&default_log_file_data_pair};
173
174 /* The class (populated) */
175 static struct tag_global_log_data global_log_data = {
176   /*struct_size:*/         sizeof(struct tag_global_log_data),
177   /*temp_src_filename:*/   NULL,
178   /*temp_src_linenumber:*/ 0,
179   /*processname:*/         "",
180   /*facility:*/            logfacility_daemon,
181   /*log_file_directory:*/  "",
182   /*logs:*/                NULL,
183 };
184
185 /* macro to get access to the array */
186 #define log_file_arr (global_log_data.logs)
187
188 /* Array to store text to list given a log type */
189 static const char * arr_logtype_strings[] =  LOGTYPE_STRING_IDENTIFIERS;
190 static const int num_logtype_strings = COUNT_ARRAY(arr_logtype_strings);
191
192 /* Array for charachters representing log severity in the log file */
193 static const char arr_loglevel_chars[] = {'S', 'E', 'W', 'N', 'I', 'D'};
194 static const int num_loglevel_chars = COUNT_ARRAY(arr_loglevel_chars);
195
196 static const char * arr_loglevel_strings[] = LOGLEVEL_STRING_IDENTIFIERS;
197 static const int num_loglevel_strings = COUNT_ARRAY(arr_loglevel_strings);
198
199 #else /* #ifndef DISABLE_LOGGER */
200   char *disabled_logger_processname=NULL;
201 #endif /* DISABLE_LOGGER */
202 /* =========================================================================
203     Global function definitions
204    ========================================================================= */
205
206 #ifndef DISABLE_LOGGER
207
208 /* remember I'm keeping a copy of the actual char * Filename, so you mustn't
209    delete it, until you've finished with the log.  Also you're responsible
210    for deleting it when you have finished with it. */
211 void log_init()
212 {
213   if (global_log_data.logs==NULL)
214   {
215     /* first check default_log_file_data_pair */
216
217     /* next clear out the log_file_data_array */
218     memset(log_file_data_array, 0, sizeof(log_file_data_array));
219     /* now set default_log_file_data_pairs */
220     log_file_data_array[logtype_default] = &default_log_file_data_pair;
221     log_file_data_array[logtype_logger]  = &logger_log_file_data_pair;
222
223     /* now setup the global_log_data struct */
224     global_log_data.logs = log_file_data_array;
225
226     /* make_log_entry(log_debug, logtype_logger, "log_init ran for the first time"); */
227   }
228 }
229 #endif /* #ifndef DISABLE_LOGGER */
230
231 bool log_setup(char *filename, enum loglevels loglevel, enum logtypes logtype, 
232                int display_options)
233 {
234 #ifndef DISABLE_LOGGER
235
236   char lastchar[2];
237
238   log_file_data_pair *logs;
239
240   log_init();
241
242   logs = log_file_arr[logtype];
243   
244   LOG(log_info, logtype_logger, "doing log_setup, type %d, level %d, filename \"%s\"", logtype, loglevel, filename);
245
246   /* LOG(log_extradebug+10, logtype_logger, "checking array for logtype is malloc'd"); */
247   /* has the given logtype already been assigned memory? */
248   if (logs==NULL)
249   {
250     logs = (log_file_data_pair *)malloc(sizeof(log_file_data_pair));
251     if (logs==NULL)
252     {
253       LOG(log_severe, logtype_logger, "can't calloc in log_setup");
254     }
255     else
256     {
257     /*
258       memcpy(logs, log_file_arr[logtype_default], sizeof(log_file_data_pair));
259      */
260       log_file_arr[logtype] = logs;
261       (*logs)[1].log_file = NULL;
262     }
263   }
264
265   /* I think this checks if we're logging to stdout or not.  Probably unused */
266   if ( ((*logs)[1].log_file == stdout) && ((*logs)[1].log_file != NULL) )
267   {
268     fclose((*logs)[1].log_file);
269     (*logs)[1].log_file = NULL;
270   }
271
272   /* check if we need to append the given filename to a directory */
273   if (strlen(global_log_data.log_file_directory)>0)
274   {
275     lastchar[0] = global_log_data.
276       log_file_directory[strlen(global_log_data.log_file_directory)-1];
277
278     if (lastchar[0] == '/' || lastchar[0] == '\\' || lastchar[0] == ':')
279       lastchar[0] = 0;
280     else
281       /* this should probably be a platform specific path separator */
282       lastchar[0] = '/';
283
284     lastchar[1] = 0;
285   }
286   else
287     lastchar[0] = 0;
288   
289 #ifdef DEBUG_OUTPUT_TO_SCREEN
290   printf("filename is %s stored at location %p\n", (*logs)[1].log_filename, 
291                                                    (*logs)[1].log_filename);
292 #endif /* DEBUG_OUTPUT_TO_SCREEN */
293   if (filename == NULL)
294   {
295     strncpy((*logs)[1].log_filename, 
296             (*(log_file_arr[0]))[1].log_filename, PATH_MAX);
297   }
298   else
299   {
300     sprintf((*logs)[1].log_filename, "%s%s%s", 
301             global_log_data.log_file_directory,
302             lastchar, filename);
303   }
304   (*logs)[1].log_level    = loglevel;
305   (*logs)[1].display_options = display_options;
306
307 #ifdef DEBUG_OUTPUT_TO_SCREEN
308   printf("filename is %s stored at location %p\n", (*logs)[1].log_filename, 
309                                                    (*logs)[1].log_filename);
310 #endif /* DEBUG_OUTPUT_TO_SCREEN */
311
312 #ifdef CHECK_STAT_ON_NEW_FILES
313   uid = geteuid(); 
314   gid = getegid();
315   
316 #ifdef DEBUG_OUTPUT_TO_SCREEN
317   printf("about to stat file %s\n", (*logs)[1].log_filename);
318 #endif
319   firstattempt = stat((*logs)[1].log_filename, &statbuf);
320
321   if (firstattempt == -1)
322   {
323 #ifdef DEBUG_OUTPUT_TO_SCREEN
324     printf("about to call Log with %d, %d, %s, %s\n", 
325            log_note, logtype_logger, 
326            "can't stat Logfile", 
327            (*logs)[1].log_filename
328            );
329 #endif
330
331     /* syslog(LOG_INFO, "stat failed"); */
332     LOG(log_warning, logtype_logger, "stat fails on file %s",
333                      (*logs)[1].log_filename);
334
335     if (strlen(global_log_data.log_file_directory)>0)
336     {
337       retval = stat(global_log_data.log_file_directory, &statbuf);
338       if (retval == -1)
339       {
340 #ifdef DEBUG_OUTPUT_TO_SCREEN
341         printf("can't stat dir either so I'm giving up\n");
342 #endif
343         LOG(log_severe, logtype_logger, "can't stat directory %s either",
344                          global_log_data.log_file_directory);
345         return false;
346       } 
347     }
348   }
349
350 #ifdef CHECK_ACCESS_ON_NEW_FILES
351   access = ((statbuf.st_uid == uid)?(statbuf.st_mode & S_IWUSR):0) + 
352            ((statbuf.st_gid == gid)?(statbuf.st_mode & S_IWGRP):0) +
353            (statbuf.st_mode & S_IWOTH);
354
355   if (access==0)
356   {
357 #ifdef DEBUG_OUTPUT_TO_SCREEN
358     printf("failing with %d, %d, %s, %s\n", log_note, logtype_logger,
359            "can't access Logfile %s",    (*logs)[1].log_filename);
360 #endif
361
362     LOG(log_note, logtype_logger, "can't access file %s", 
363                      (*logs)[1].log_filename);
364     return false;
365   }
366 #endif /* CHECK_ACCESS_ON_NEW_FILES */
367 #endif /* CHECK_STAT_ON_NEW_FILES */
368 /*
369 #ifdef KEEP_LOGFILES_OPEN
370   if ((*logs)[1].log_file!=NULL)
371     fclose((*logs)[1].log_file);
372
373   (*logs)[1].log_file     = fopen((*logs)[1].log_filename, "at");
374   if ((*logs)[1].log_file == NULL)
375   {
376     LOG(log_severe, logtype_logger, "can't open Logfile %s", 
377         (*logs)[1].log_filename
378         );
379     return false;
380   }
381 #endif
382 */
383
384   LOG(log_debug7, logtype_logger, "log_file_arr[%d] now contains: "
385                                   "{log_filename:%s, log_file:%p, log_level: %d}", logtype,
386                                    (*logs)[1].log_filename, (*logs)[1].log_file, (*logs)[1].log_level);
387   LOG(log_debug, logtype_logger, "log_setup[%d] done", logtype);
388
389 #endif /* DISABLE_LOGGER */
390   return true;
391 }
392
393
394 void syslog_setup(enum loglevels loglevel, enum logtypes logtype, 
395                   int display_options, int facility)
396 {
397 #ifndef DISABLE_LOGGER
398   log_file_data_pair *logs;
399
400   log_init();
401
402   logs = log_file_arr[logtype];
403
404   LOG(log_info, logtype_logger, "doing syslog_setup, type %d, level %d", logtype, loglevel);
405
406   if (logs==NULL)
407   {
408     logs = (log_file_data_pair *)malloc(sizeof(log_file_data_pair));    
409     if (logs==NULL)
410     {
411       LOG(log_severe, logtype_logger, "can't calloc in log_setup");
412     }
413     else
414     {
415       memcpy(logs, log_file_arr[logtype_default], sizeof(log_file_data_pair));
416       log_file_arr[logtype] = logs;
417     }
418   }
419
420   (*logs)[0].log_file        = NULL;
421   (*logs)[0].log_filename[0] = 0;
422   (*logs)[0].log_level       = loglevel;
423   (*logs)[0].display_options = display_options;
424   global_log_data.facility   = facility;
425
426   openlog(global_log_data.processname, (*logs)[0].display_options, 
427           global_log_data.facility);
428
429   LOG(log_debug7, logtype_logger, "log_file_arr[%d] now contains: "
430                                   "{log_filename:%s, log_file:%p, log_level: %d}", logtype,
431                                   (*logs)[0].log_filename, (*logs)[0].log_file, (*logs)[0].log_level);
432   LOG(log_debug, logtype_logger, "syslog_setup[%d] done", logtype);
433 #else /* DISABLE_LOGGER */
434 /* behave like a normal openlog call */
435   openlog(disabled_logger_processname, display_options, facility);
436 #endif /* DISABLE_LOGGER */
437 }
438
439 void log_close()
440 {
441 #ifndef DISABLE_LOGGER
442   log_file_data_pair *logs;
443   int n;
444
445   LOG(log_info, logtype_logger, "log_close called");
446
447   for(n=(sizeof(log_file_arr)-1);n>0;n--)
448   {
449     logs = log_file_arr[n];
450 #ifdef KEEP_LOGFILES_OPEN
451     if ((*logs)[1].log_file!=NULL)
452       fclose((*logs)[1].log_file);
453 #endif /* KEEP_LOGFILES_OPEN */
454     if (logs!=NULL)
455     {
456       LOG(log_debug, logtype_logger, "freeing log entry at %d", n);
457 #ifdef DEBUG_OUTPUT_TO_SCREEN
458       printf("Freeing log_data %d, stored at %p\n", n, logs);
459       printf("\t(filename) %s\t(type) %s\n", (*logs)[1].log_filename, 
460              ((n<num_logtype_strings)?arr_logtype_strings[n]:""));
461 #endif /* DEBUG_OUTPUT_TO_SCREEN */
462       free(logs);
463     }
464     log_file_arr[n] = NULL;
465   }
466 #ifdef DEBUG_OUTPUT_TO_SCREEN
467       printf("Freeing log_data %d, stored at %p\n", n, log_file_arr[n]);
468       printf("\t(filename) %s\t(type) %s\n", 
469              (*(log_file_arr[n]))[1].log_filename, 
470              ((n<num_logtype_strings)?arr_logtype_strings[n]:"")
471              );
472 #endif /* DEBUG_OUTPUT_TO_SCREEN */
473 #endif /* DISABLE_LOGGER */
474
475   LOG(log_debug, logtype_logger, "log_close done");
476
477   closelog();
478 }
479
480 /* This function sets up the processname */
481 void set_processname(char *processname)
482 {
483 #ifndef DISABLE_LOGGER
484   /* strncpy(global_log_data.processname, GetCommandName(processname), 15); */
485   strncpy(global_log_data.processname, processname, 15);
486   global_log_data.processname[15] = 0;
487 #else /* DISABLE_LOGGER */
488   disabled_logger_processname = processname;
489 #endif /* DISABLE_LOGGER */
490 }
491
492 #ifndef DISABLE_LOGGER
493 /* This is called by the macro so set the location of the caller of Log */
494 make_log_func set_log_location(char *srcfilename, int srclinenumber)
495 {
496 #ifdef DEBUG_OUTPUT_TO_SCREEN
497   printf("Setting Log Location\n");
498 #endif
499   global_log_data.temp_src_filename = srcfilename;
500   global_log_data.temp_src_linenumber = srclinenumber;
501
502   return make_log_entry;
503 }
504 #endif /* DISABLE_LOGGER */
505
506 /* -------------------------------------------------------------------------
507     MakeLog has 1 main flaws:
508       The message in its entirity, must fit into the tempbuffer.  
509       So it must be shorter than MAXLOGSIZE
510    ------------------------------------------------------------------------- */
511 void make_log_entry(enum loglevels loglevel, enum logtypes logtype, 
512                     char *message, ...)
513 {
514   va_list args;
515   char log_buffer[MAXLOGSIZE];
516 #ifndef DISABLE_LOGGER
517   char log_details_buffer[MAXLOGSIZE];
518 #ifdef OPEN_LOGS_AS_UID
519   uid_t process_uid;
520 #endif
521   log_file_data_pair *logs;
522
523   log_init();
524
525   logs = log_file_arr[logtype];
526
527   if (logs==NULL)
528   {
529     logs = log_file_arr[logtype_default];
530   }
531 #ifdef DEBUG_OUTPUT_TO_SCREEN
532   printf("Making Log\n");
533 #endif
534   
535 #endif /* DISABLE_LOGGER */
536
537   /* Initialise the Messages */
538   va_start(args, message);
539
540   vsnprintf(log_buffer, sizeof(log_buffer), message, args);
541
542   /* Finished with args for now */
543   va_end(args);
544
545 #ifdef DISABLE_LOGGER
546   syslog(get_syslog_equivalent(loglevel), "%s", log_buffer);
547 #else /* DISABLE_LOGGER */
548
549 #ifdef DO_SYSLOG
550   /* check if sysloglevel is high enough */
551   if ((*logs)[0].log_level>=loglevel)
552   {
553     int sysloglevel = get_syslog_equivalent(loglevel);
554
555     generate_message_details(log_details_buffer, sizeof(log_details_buffer),
556                               &(*logs)[0], loglevel, logtype);
557
558 #ifdef DEBUG_OUTPUT_TO_SCREEN
559     printf("About to log %s %s\n", log_details_buffer, log_buffer);
560     printf("about to do syslog\n");
561     printf("done onw syslog\n");
562 #endif
563     syslog(sysloglevel, "%s: %s", log_details_buffer, log_buffer);
564     /* 
565        syslog(sysloglevel, "%s:%s: %s", log_levelString, 
566               log_typeString, LogBuffer); 
567      */
568   }
569 #endif
570
571 #ifdef DO_FILELOG
572 #ifdef DEBUG_OUTPUT_TO_SCREEN
573   printf("about to do the filelog\n");
574 #endif
575   /* check if log_level is high enough */
576   if ((*logs)[1].log_level>=loglevel) {    
577  
578 #ifdef DEBUG_OUTPUT_TO_SCREEN
579     printf("Open the Log, FILE* is %p\n", (*logs)[1].log_file);
580 #endif
581     /* if log isn't open, open it */
582     if ((*logs)[1].log_file==NULL) {
583 #ifdef DEBUG_OUTPUT_TO_SCREEN
584       printf("Opening the Log, filename is %s\n", (*logs)[1].log_filename);
585 #endif
586 #ifdef OPEN_LOGS_AS_UID
587    process_uid = getuid();
588    setuid(OPEN_LOGS_AS_UID);
589 #endif
590       (*logs)[1].log_file     = fopen((*logs)[1].log_filename, "at");
591 #ifdef OPEN_LOGS_AS_UID
592    setuid(process_uid);
593 #endif
594       if ((*logs)[1].log_file == NULL)
595       {
596         (*logs)[1].log_file = stdout;
597         LOG(log_severe, logtype_logger, "can't open Logfile %s", 
598             (*logs)[1].log_filename
599             );
600         return;
601       }
602     }
603     generate_message_details(log_details_buffer, sizeof(log_details_buffer),
604                              &(*logs)[1], loglevel, logtype);
605
606 #ifdef DEBUG_OUTPUT_TO_SCREEN
607     printf("Files open, lets log\n");
608     printf("FILE* is %p\n", (*logs)[1].log_file);
609     printf("%s: %s\n", log_details_buffer, log_buffer);
610 #endif
611
612     fprintf((*logs)[1].log_file, "%s: %s\n", log_details_buffer, log_buffer);
613
614 #ifndef KEEP_LOGFILES_OPEN
615     if ((*logs)[1].log_file != stdout)
616     {
617 #ifdef DEBUG_OUTPUT_TO_SCREEN
618       printf("Closing %s\n", (*logs)[1].log_filename);
619 #endif
620       fclose((*logs)[1].log_file);
621       (*logs)[1].log_file = NULL;
622 #ifdef DEBUG_OUTPUT_TO_SCREEN
623       printf("Closed\n");
624 #endif
625     }
626 #else // KEEP_LOGFILES_OPEN
627     fflush((*logs)[1].log_file);
628 #endif // KEEP_LOGFILES_OPEN
629   }
630 #endif
631
632   global_log_data.temp_src_filename = NULL;
633   global_log_data.temp_src_linenumber = 0;
634 #endif /* DISABLE_LOGGER */
635 }
636
637 #ifndef DISABLE_LOGGER
638 void load_proccessname_from_proc()
639 {
640   pid_t pid = getpid();
641   char buffer[PATH_MAX];
642   char procname[16];
643   FILE * statfile;
644   char *ptr;
645
646   sprintf(buffer, "/proc/%d/stat", pid);
647   statfile = fopen(buffer, "rt");
648   fgets(buffer, PATH_MAX-1, statfile);
649   fclose(statfile);
650
651   ptr = (char *)strrchr(buffer, ')');
652   *ptr = '\0';
653   memset(procname, 0, sizeof procname);
654   sscanf(buffer, "%d (%15c", &pid, procname);   /* comm[16] in kernel */
655
656   set_processname(procname);
657 }
658
659 /* =========================================================================
660     Internal function definitions
661    ========================================================================= */
662
663 #if 0
664 static char *get_command_name(char *commandpath)
665 {
666   char *ptr;
667 #ifdef DEBUG_OUTPUT_TO_SCREEN
668   printf("getting command name %s\n",commandpath);
669 #endif
670   ptr = (char *)strrchr(commandpath, '/');
671   if (ptr==NULL)
672     ptr = commandpath;
673   else
674     ptr++;
675                                                                                 
676 #ifdef DEBUG_OUTPUT_TO_SCREEN
677   printf("Concluded %s\n", ptr);
678 #endif
679   return ptr;
680 }
681 #endif
682
683 void  workout_what_to_print(struct what_to_print_array *what_to_print, 
684                             struct tag_log_file_data *log_struct)
685 {
686   /* is this a syslog entry? */
687   if (log_struct->log_filename[0]==0)
688   {
689     what_to_print->print_datetime = false;
690     what_to_print->print_processname = false;
691     what_to_print->print_pid = false;
692   }
693   else
694   {
695     what_to_print->print_datetime = true;
696     what_to_print->print_processname = true;
697  
698     /* pid is dealt with at the syslog level if we're syslogging */
699     what_to_print->print_pid = 
700       (((log_struct->display_options & logoption_pid) == 0)?false:true);
701   }
702
703   what_to_print->print_srcfile = 
704     (((log_struct->display_options & logoption_nfile) == 0)?true:false);
705   what_to_print->print_srcline = 
706     (((log_struct->display_options & logoption_nline) == 0)?true:false);
707   
708   what_to_print->print_errlevel = true;
709   what_to_print->print_errtype = true;
710 }
711
712 void generate_message_details(char *message_details_buffer, 
713                               int message_details_buffer_length,
714                               struct tag_log_file_data *log_struct,
715                               enum loglevels loglevel, enum logtypes logtype)
716 {
717   char *ptr = message_details_buffer;
718   int   templen;
719   int   len = message_details_buffer_length;
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   int typenum, levelnum;
919   log_file_data_pair *logs = log_file_arr[logtype_default];
920
921   /*
922   LOG(log_extradebug, logtype_logger, "Attempting setuplog: %s %s %s %s", 
923       logsource, logtype, loglevel, filename);
924   */
925   LOG(log_info, logtype_logger, "setuplog is parsing logtype:%s, loglevel:%s, filename:%s", 
926       logtype, loglevel, filename);
927
928   if (logtype==NULL)
929   {
930     LOG(log_note, logtype_logger, "no logsource given, default is assumed");
931     typenum=0;
932   }
933   else
934   {
935     for(typenum=0;typenum<num_logtype_strings;typenum++)
936     {
937       if (strcasecmp(logtype, arr_logtype_strings[typenum])==0)
938         break;
939     }
940     if (typenum>=num_logtype_strings)
941     {
942       LOG(log_warning, logtype_logger, "%s is not a valid log type", logtype);
943     }
944   }
945
946   if (loglevel==NULL)
947   {
948     LOG(log_note, logtype_logger, "no loglevel given, severe is assumed");
949     levelnum=0;
950   }
951   else
952   {
953     for(levelnum=0;levelnum<num_loglevel_strings;levelnum++)
954     {
955       if (strcasecmp(loglevel, arr_loglevel_strings[levelnum])==0)
956         break;
957     }
958     if (levelnum>=num_loglevel_strings)
959     {
960       LOG(log_warning, logtype_logger, "%s is not a valid log level", loglevel);
961     }
962   }
963
964   /* sanity check */
965   if ((typenum>=num_logtype_strings) || (levelnum>=num_loglevel_strings))
966   {
967     LOG(log_warning, logtype_logger, "sanity check failed: (%s:%d), (%s:%d)", 
968                     logtype, typenum, loglevel, levelnum);
969     return;
970   }
971
972   /* now match the order of the text string with the actual enum value (10 times) */
973   levelnum*=10;
974   
975   /* is this a syslog setup or a filelog setup */
976   if (filename==NULL) /* must be syslog */
977   {
978     LOG(log_debug6, logtype_logger, "calling syslog_setup(%d, %d, ...)", levelnum, typenum);
979     syslog_setup(levelnum, typenum, 
980                  (*logs)[0].display_options,
981                  global_log_data.facility);
982   }
983   else /* this must be a filelog */
984   {
985     LOG(log_debug6, logtype_logger, "calling log_setup(%s, %d, %d, ...)", filename, levelnum, typenum);
986     log_setup(filename, levelnum, typenum, 
987               (*logs)[0].display_options);
988   };  
989   return;
990 #endif /* DISABLE_LOGGER */
991 }
992
993
994
995
996
997
998