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