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