5 /* =========================================================================
7 logger.c is part of the utils section in the libatalk library,
8 which is part of the netatalk project.
10 logger.c was written by Simon Bazley (sibaz@sibaz.com)
12 I believe libatalk is released under the L/GPL licence.
14 Just incase, it is, thats the licence I'm applying to this file.
18 ==========================================================================
20 Logger.c is intended as an alternative to syslog for logging
22 ---------------------------------------------------------------
24 The initial plan is to create a structure for general information needed
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.
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.
35 ========================================================================= */
43 #include <sys/types.h>
48 #include <atalk/boolean.h>
49 #include <atalk/logger.h>
51 #define COUNT_ARRAY(array) (sizeof((array))/sizeof((array)[0]))
52 #define NUMOF COUNT_ARRAY
53 #undef KEEP_LOGFILES_OPEN
57 #undef DEBUG_OUTPUT_TO_SCREEN
58 #undef CHECK_STAT_ON_NEW_FILES
59 #undef CHECK_ACCESS_ON_NEW_FILES
61 /* =========================================================================
62 External function declarations
63 ========================================================================= */
65 /* setup the internal variables used by the logger (called automatically) */
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,
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);
76 /* finish up and close the logs */
79 /* This function sets up the processname */
80 void set_processname(char *processname);
83 void make_log(enum loglevels loglevel, enum logtypes logtype,
85 #ifndef DISABLE_LOGGER
86 make_log_func set_log_location(char *srcfilename, int srclinenumber);
88 /* =========================================================================
90 ========================================================================= */
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 */
100 typedef struct tag_log_file_data log_file_data_pair[2];
102 /* A structure containg class level stuff */
103 struct tag_global_log_data {
106 char *temp_src_filename;
107 int temp_src_linenumber;
108 char processname[16];
110 char *log_file_directory; /* Path of directory containing log files */
111 log_file_data_pair **logs;
114 struct what_to_print_array {
116 bool print_processname;
124 /* =========================================================================
125 Internal function declarations
126 ========================================================================= */
128 void generate_message_details(char *message_details_buffer,
129 int message_details_buffer_length,
130 struct tag_log_file_data *log_struct,
131 enum loglevels loglevel, enum logtypes logtype);
133 int get_syslog_equivalent(enum loglevels loglevel);
135 static char *get_command_name(char *commandpath);
137 /* =========================================================================
139 ========================================================================= */
141 /* A populated instance */
143 static log_file_data_pair default_log_file_data_pair = {
145 /* log_filename */ "\0\0\0\0\0\0\0\0",
147 /* log_level */ log_debug,
148 /* display_options */ logoption_pid
151 /* log_filename */ LOGFILEPATH,
153 /* log_level */ log_debug,
154 /* display_options */ logoption_pid
157 static log_file_data_pair *log_file_data_array[logtype_end_of_list_marker] =
158 {&default_log_file_data_pair};
160 /* The class (populated) */
161 static struct tag_global_log_data global_log_data = {
162 /* struct_size */ sizeof(struct tag_global_log_data),
163 /* temp_src_filename */ NULL,
164 /* temp_src_linenumber */ 0,
165 /* processname */ "",
166 /* log_file_directory */ "",
170 /* macro to get access to the array */
171 #define log_file_arr (global_log_data.logs)
173 /* Array to store text to list given a log type */
174 static const char * arr_logtype_strings[] = LOGTYPE_STRING_IDENTIFIERS;
175 static const int num_logtype_strings = COUNT_ARRAY(arr_logtype_strings);
177 /* Array for charachters representing log severity in the log file */
178 static const char arr_loglevel_chars[] = {'S', 'E', 'W', 'N', 'I', 'D'};
179 static const int num_loglevel_chars = COUNT_ARRAY(arr_loglevel_chars);
181 static const char * arr_loglevel_strings[] = LOGLEVEL_STRING_IDENTIFIERS;
182 static const int num_loglevel_strings = COUNT_ARRAY(arr_loglevel_strings);
184 #else /* #ifndef DISABLE_LOGGER */
185 char *disabled_logger_processname=NULL;
186 #endif /* DISABLE_LOGGER */
187 /* =========================================================================
188 Global function definitions
189 ========================================================================= */
191 #ifndef DISABLE_LOGGER
193 /* remember I'm keeping a copy of the actual char * Filename, so you mustn't
194 delete it, until you've finished with the log. Also you're responsible
195 for deleting it when you have finished with it. */
198 if (global_log_data.logs==NULL)
200 /* first check default_log_file_data_pair */
202 /* next clear out the log_file_data_array */
203 memset(log_file_data_array, 0, sizeof(log_file_data_array));
204 /* now set default_log_file_data_pairs */
205 log_file_data_array[0] = &default_log_file_data_pair;
207 /* now setup the global_log_data struct */
208 global_log_data.logs = log_file_data_array;
211 #endif /* #ifndef DISABLE_LOGGER */
213 bool log_setup(char *filename, enum loglevels loglevel, enum logtypes logtype,
216 #ifndef DISABLE_LOGGER
226 log_file_data_pair *logs;
230 logs = log_file_arr[logtype];
234 logs = (log_file_data_pair *)malloc(sizeof(log_file_data_pair));
237 LOG(log_severe, logtype_logger, "can't calloc in log_setup");
242 memcpy(logs, log_file_arr[logtype_default], sizeof(log_file_data_pair));
244 log_file_arr[logtype] = logs;
245 (*logs)[1].log_file = NULL;
249 if ( ((*logs)[1].log_file == stdout) && ((*logs)[1].log_file != NULL) )
251 fclose((*logs)[1].log_file);
252 (*logs)[1].log_file = NULL;
255 if (strlen(global_log_data.log_file_directory)>0)
257 lastchar[0] = global_log_data.
258 log_file_directory[strlen(global_log_data.log_file_directory)-1];
260 if (lastchar[0] == '/' || lastchar[0] == '\\' || lastchar[0] == ':')
263 /* this should probably be a platform specific path separator */
271 #ifdef DEBUG_OUTPUT_TO_SCREEN
272 printf("filename is %s stored at location %p\n", (*logs)[1].log_filename,
273 (*logs)[1].log_filename);
274 #endif /* DEBUG_OUTPUT_TO_SCREEN */
275 if (filename == NULL)
277 strncpy((*logs)[1].log_filename,
278 (*(log_file_arr[0]))[1].log_filename, PATH_MAX);
282 sprintf((*logs)[1].log_filename, "%s%s%s",
283 global_log_data.log_file_directory,
286 (*logs)[1].log_level = loglevel;
287 (*logs)[1].display_options = display_options;
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 */
294 #ifdef CHECK_STAT_ON_NEW_FILES
298 #ifdef DEBUG_OUTPUT_TO_SCREEN
299 printf("about to stat file %s\n", (*logs)[1].log_filename);
301 firstattempt = stat((*logs)[1].log_filename, &statbuf);
303 if (firstattempt == -1)
305 #ifdef DEBUG_OUTPUT_TO_SCREEN
306 printf("about to call Log with %d, %d, %s, %s\n",
307 log_note, logtype_logger,
308 "can't stat Logfile",
309 (*logs)[1].log_filename
313 /* syslog(LOG_INFO, "stat failed"); */
314 LOG(log_warning, logtype_logger, "stat fails on file %s",
315 (*logs)[1].log_filename);
317 if (strlen(global_log_data.log_file_directory)>0)
319 retval = stat(global_log_data.log_file_directory, &statbuf);
322 #ifdef DEBUG_OUTPUT_TO_SCREEN
323 printf("can't stat dir either so I'm giving up\n");
325 LOG(log_severe, logtype_logger, "can't stat directory %s either",
326 global_log_data.log_file_directory);
332 #ifdef CHECK_ACCESS_ON_NEW_FILES
333 access = ((statbuf.st_uid == uid)?(statbuf.st_mode & S_IWUSR):0) +
334 ((statbuf.st_gid == gid)?(statbuf.st_mode & S_IWGRP):0) +
335 (statbuf.st_mode & S_IWOTH);
339 #ifdef DEBUG_OUTPUT_TO_SCREEN
340 printf("failing with %d, %d, %s, %s\n", log_note, logtype_logger,
341 "can't access Logfile %s", (*logs)[1].log_filename);
344 LOG(log_note, logtype_logger, "can't access file %s",
345 (*logs)[1].log_filename);
348 #endif /* CHECK_ACCESS_ON_NEW_FILES */
349 #endif /* CHECK_STAT_ON_NEW_FILES */
350 #ifdef KEEP_LOGFILES_OPEN
351 if ((*logs)[1].log_file!=NULL)
352 fclose((*logs)[1].log_file);
354 (*logs)[1].log_file = fopen((*logs)[1].log_filename, "at");
355 if ((*logs)[1].log_file == NULL)
357 LOG(log_severe, logtype_logger, "can't open Logfile %s",
358 (*logs)[1].log_filename
364 LOG(log_info, logtype_logger, "Log setup complete");
366 #endif /* DISABLE_LOGGER */
371 void syslog_setup(enum loglevels loglevel, enum logtypes logtype,
372 int display_options, int facility)
374 #ifndef DISABLE_LOGGER
375 log_file_data_pair *logs;
379 logs = log_file_arr[logtype];
383 logs = (log_file_data_pair *)malloc(sizeof(log_file_data_pair));
386 LOG(log_severe, logtype_logger, "can't calloc in log_setup");
390 memcpy(logs, log_file_arr[logtype_default], sizeof(log_file_data_pair));
391 log_file_arr[logtype] = logs;
395 (*logs)[0].log_file = NULL;
396 (*logs)[0].log_filename[0] = 0;
397 (*logs)[0].log_level = loglevel;
398 (*logs)[0].display_options = display_options;
400 openlog(global_log_data.processname, (*logs)[0].display_options, facility);
402 LOG(log_info, logtype_logger, "SysLog setup complete");
403 #else /* DISABLE_LOGGER */
404 /* behave like a normal openlog call */
405 openlog(disabled_logger_processname, display_options, facility);
406 #endif /* DISABLE_LOGGER */
411 #ifndef DISABLE_LOGGER
412 log_file_data_pair *logs;
415 LOG(log_info, logtype_logger, "Closing logs");
417 for(n=(sizeof(log_file_arr)-1);n>0;n--)
419 logs = log_file_arr[n];
420 #ifdef KEEP_LOGFILES_OPEN
421 if ((*logs)[1].log_file!=NULL)
422 fclose((*logs)[1].log_file);
423 #endif /* KEEP_LOGFILES_OPEN */
426 #ifdef DEBUG_OUTPUT_TO_SCREEN
427 printf("Freeing log_data %d, stored at %p\n", n, logs);
428 printf("\t(filename) %s\t(type) %s\n", (*logs)[1].log_filename,
429 ((n<num_logtype_strings)?arr_logtype_strings[n]:""));
430 #endif /* DEBUG_OUTPUT_TO_SCREEN */
433 log_file_arr[n] = NULL;
435 #ifdef DEBUG_OUTPUT_TO_SCREEN
436 printf("Freeing log_data %d, stored at %p\n", n, log_file_arr[n]);
437 printf("\t(filename) %s\t(type) %s\n",
438 (*(log_file_arr[n]))[1].log_filename,
439 ((n<num_logtype_strings)?arr_logtype_strings[n]:"")
441 #endif /* DEBUG_OUTPUT_TO_SCREEN */
442 #endif /* DISABLE_LOGGER */
447 /* This function sets up the processname */
448 void set_processname(char *processname)
450 #ifndef DISABLE_LOGGER
451 /* strncpy(global_log_data.processname, GetCommandName(processname), 15); */
452 strncpy(global_log_data.processname, processname, 15);
453 global_log_data.processname[15] = 0;
454 #else /* DISABLE_LOGGER */
455 disabled_logger_processname = processname;
456 #endif /* DISABLE_LOGGER */
459 #ifndef DISABLE_LOGGER
460 /* This is called by the macro so set the location of the caller of Log */
461 make_log_func set_log_location(char *srcfilename, int srclinenumber)
463 #ifdef DEBUG_OUTPUT_TO_SCREEN
464 printf("Setting Log Location\n");
466 global_log_data.temp_src_filename = srcfilename;
467 global_log_data.temp_src_linenumber = srclinenumber;
469 return make_log_entry;
471 #endif /* DISABLE_LOGGER */
473 /* -------------------------------------------------------------------------
474 MakeLog has 1 main flaws:
475 The message in its entirity, must fit into the tempbuffer.
476 So it must be shorter than MAXLOGSIZE
477 ------------------------------------------------------------------------- */
478 void make_log_entry(enum loglevels loglevel, enum logtypes logtype,
482 char log_buffer[MAXLOGSIZE];
483 #ifndef DISABLE_LOGGER
484 char log_details_buffer[MAXLOGSIZE];
486 log_file_data_pair *logs;
490 logs = log_file_arr[logtype];
494 logs = log_file_arr[logtype_default];
496 #ifdef DEBUG_OUTPUT_TO_SCREEN
497 printf("Making Log\n");
500 #endif /* DISABLE_LOGGER */
502 /* Initialise the Messages */
503 va_start(args, message);
505 vsnprintf(log_buffer, sizeof(log_buffer), message, args);
507 /* Finished with args for now */
510 #ifdef DISABLE_LOGGER
511 syslog(get_syslog_equivalent(loglevel), "%s", log_buffer);
512 #else /* DISABLE_LOGGER */
515 /* check if sysloglevel is high enough */
516 if ((*logs)[0].log_level>=loglevel)
518 int sysloglevel = get_syslog_equivalent(loglevel);
520 generate_message_details(log_details_buffer, sizeof(log_details_buffer),
521 &(*logs)[0], loglevel, logtype);
523 #ifdef DEBUG_OUTPUT_TO_SCREEN
524 printf("About to log %s %s\n", log_details_buffer, log_buffer);
525 printf("about to do syslog\n");
526 printf("done onw syslog\n");
528 syslog(sysloglevel, "%s: %s", log_details_buffer, log_buffer);
530 syslog(sysloglevel, "%s:%s: %s", log_levelString,
531 log_typeString, LogBuffer);
537 #ifdef DEBUG_OUTPUT_TO_SCREEN
538 printf("about to do the filelog\n");
540 /* check if log_level is high enough */
541 if ((*logs)[1].log_level>=loglevel) {
543 #ifdef DEBUG_OUTPUT_TO_SCREEN
544 printf("Open the Log, FILE* is %p\n", (*logs)[1].log_file);
546 /* if log isn't open, open it */
547 if ((*logs)[1].log_file==NULL) {
548 #ifdef DEBUG_OUTPUT_TO_SCREEN
549 printf("Opening the Log, filename is %s\n", (*logs)[1].log_filename);
551 (*logs)[1].log_file = fopen((*logs)[1].log_filename, "at");
552 if ((*logs)[1].log_file == NULL)
554 (*logs)[1].log_file = stdout;
555 LOG(log_severe, logtype_logger, "can't open Logfile %s",
556 (*logs)[1].log_filename
561 generate_message_details(log_details_buffer, sizeof(log_details_buffer),
562 &(*logs)[1], loglevel, logtype);
564 #ifdef DEBUG_OUTPUT_TO_SCREEN
565 printf("Files open, lets log\n");
566 printf("FILE* is %p\n", (*logs)[1].log_file);
567 printf("%s: %s\n", log_details_buffer, log_buffer);
570 fprintf((*logs)[1].log_file, "%s: %s\n", log_details_buffer, log_buffer);
572 #ifndef KEEP_LOGFILES_OPEN
573 if ((*logs)[1].log_file != stdout)
575 #ifdef DEBUG_OUTPUT_TO_SCREEN
576 printf("Closing %s\n", (*logs)[1].log_filename);
578 fclose((*logs)[1].log_file);
579 (*logs)[1].log_file = NULL;
580 #ifdef DEBUG_OUTPUT_TO_SCREEN
588 global_log_data.temp_src_filename = NULL;
589 global_log_data.temp_src_linenumber = 0;
590 #endif /* DISABLE_LOGGER */
593 #ifndef DISABLE_LOGGER
594 void load_proccessname_from_proc()
596 pid_t pid = getpid();
597 char buffer[PATH_MAX];
602 sprintf(buffer, "/proc/%d/stat", pid);
603 statfile = fopen(buffer, "rt");
604 fgets(buffer, PATH_MAX-1, statfile);
607 ptr = (char *)strrchr(buffer, ')');
609 memset(procname, 0, sizeof procname);
610 sscanf(buffer, "%d (%15c", &pid, procname); /* comm[16] in kernel */
612 set_processname(procname);
615 /* =========================================================================
616 Internal function definitions
617 ========================================================================= */
619 static char *get_command_name(char *commandpath)
622 #ifdef DEBUG_OUTPUT_TO_SCREEN
623 printf("getting command name %s\n",commandpath);
625 ptr = (char *)strrchr(commandpath, '/');
631 #ifdef DEBUG_OUTPUT_TO_SCREEN
632 printf("Concluded %s\n", ptr);
637 void workout_what_to_print(struct what_to_print_array *what_to_print,
638 struct tag_log_file_data *log_struct)
640 /* is this a syslog entry? */
641 if (log_struct->log_filename[0]==0)
643 what_to_print->print_datetime = false;
644 what_to_print->print_processname = false;
645 what_to_print->print_pid = false;
649 what_to_print->print_datetime = true;
650 what_to_print->print_processname = true;
652 /* pid is dealt with at the syslog level if we're syslogging */
653 what_to_print->print_pid =
654 (((log_struct->display_options & logoption_pid) == 0)?false:true);
657 what_to_print->print_srcfile =
658 (((log_struct->display_options & logoption_nfile) == 0)?true:false);
659 what_to_print->print_srcline =
660 (((log_struct->display_options & logoption_nline) == 0)?true:false);
662 what_to_print->print_errlevel = true;
663 what_to_print->print_errtype = true;
666 void generate_message_details(char *message_details_buffer,
667 int message_details_buffer_length,
668 struct tag_log_file_data *log_struct,
669 enum loglevels loglevel, enum logtypes logtype)
672 char processinfo[64];
674 char *ptr = message_details_buffer;
676 int len = message_details_buffer_length;
678 char log_buffer[MAXLOGSIZE];
679 const char *logtype_string;
681 char loglevel_string[12]; /* max int size is 2 billion, or 10 digits */
683 struct what_to_print_array what_to_print;
685 workout_what_to_print(&what_to_print, log_struct);
687 #ifdef DEBUG_OUTPUT_TO_SCREEN
688 printf("Making MessageDetails\n");
697 if (what_to_print.print_datetime)
702 /* some people might prefer localtime() to gmtime() */
703 strftime(ptr, len, "%b %d %H:%M:%S", gmtime(&thetime));
704 #ifdef DEBUG_OUTPUT_TO_SCREEN
705 printf("date is %s\n", ptr);
708 templen = strlen(ptr);
710 if (what_to_print.print_processname || what_to_print.print_pid)
711 strncat(ptr, " ", len);
713 strncat(ptr, ":", len);
725 if (what_to_print.print_processname)
727 strncpy(ptr, global_log_data.processname, len);
729 templen = strlen(ptr);
734 if (what_to_print.print_pid)
736 pid_t pid = getpid();
738 sprintf(ptr, "[%d]", pid);
740 templen = strlen(ptr);
745 if (what_to_print.print_srcfile || what_to_print.print_srcline)
747 char sprintf_buffer[8];
750 sprintf_buffer[0] = '[';
751 if (what_to_print.print_srcfile)
753 strcpy(&sprintf_buffer[1], "%s");
754 buff_ptr = &sprintf_buffer[3];
756 if (what_to_print.print_srcfile && what_to_print.print_srcline)
758 strcpy(&sprintf_buffer[3], ":");
759 buff_ptr = &sprintf_buffer[4];
761 if (what_to_print.print_srcline)
763 strcpy(buff_ptr, "%d");
764 buff_ptr = &buff_ptr[2];
766 strcpy(buff_ptr, "]");
769 ok sprintf string is ready, now is the 1st parameter src or linenumber
771 if (what_to_print.print_srcfile)
773 sprintf(ptr, sprintf_buffer,
774 global_log_data.temp_src_filename,
775 global_log_data.temp_src_linenumber);
779 sprintf(ptr, sprintf_buffer, global_log_data.temp_src_linenumber);
782 #ifdef DEBUG_OUTPUT_TO_SCREEN
783 printf("Process info is %s\n", ptr);
786 templen = strlen(ptr);
792 if (what_to_print.print_processname || what_to_print.print_pid ||
793 what_to_print.print_srcfile || what_to_print.print_srcline)
795 strncat(ptr, ": ", len);
801 loglevel_string[0] = 0;
802 ptr = loglevel_string;
805 if (what_to_print.print_errlevel)
807 if ((loglevel/10) >= (num_loglevel_chars-1))
809 sprintf(ptr, "%c%d", arr_loglevel_chars[num_loglevel_chars-1],
814 sprintf(ptr, "%c", arr_loglevel_chars[loglevel/10]);
817 templen = strlen(ptr);
822 if (what_to_print.print_errtype)
824 const char *logtype_string;
826 /* get string represnetation of the Log Type */
827 if (logtype<num_logtype_strings)
828 logtype_string = arr_logtype_strings[logtype];
832 if (what_to_print.print_errlevel)
834 strncat(ptr, ":", len);
838 sprintf(ptr, "%s", logtype_string);
841 message_details_buffer[message_details_buffer_length-1] = 0;
843 #ifdef DEBUG_OUTPUT_TO_SCREEN
844 printf("Message Details are %s\n", message_details_buffer);
847 #endif /* DISABLE_LOGGER */
849 int get_syslog_equivalent(enum loglevels loglevel)
853 /* The question is we know how bad it is for us,
854 but how should that translate in the syslogs? */
859 case 2: /* warning */
863 case 4: /* information */
870 void setuplog(char *logsource, char *logtype, char *loglevel, char *filename)
872 /* -setuplogtype <syslog|filelog> <logtype> <loglevel>*/
873 const char* sources[] = {"syslog", "filelog"};
874 char sourcebuf[64], typebuf[64], levelbuf[32], *ptr;
875 int sourcenum, typenum, levelnum;
877 ptr = strpbrk(logsource, " \t");
878 strncpy(sourcebuf, logsource, ptr-logsource);
879 sourcebuf[ptr-logsource]=0;
881 ptr = strpbrk(logtype, " \t");
882 strncpy(typebuf, logtype, ptr-logtype);
883 typebuf[ptr-logtype]=0;
885 ptr = strpbrk(loglevel, " \t");
886 strncpy(levelbuf, loglevel, ptr-loglevel);
887 levelbuf[ptr-loglevel]=0;
889 for(sourcenum=0;sourcenum<NUMOF(sources);sourcenum++)
891 if (strcasecmp(sourcebuf, sources[sourcenum])==0)
895 for(typenum=0;typenum<num_logtype_strings;typenum++)
897 if (strcasecmp(typebuf, arr_logtype_strings[typenum])==0)
901 for(levelnum=0;levelnum<num_loglevel_strings;levelnum++)
903 if (strcasecmp(levelbuf, arr_loglevel_strings[levelnum])==0)
908 for(logtype=logtype_default;logtype<logtype_end_of_list_marker;logtype++)
910 if (strcasecmp(buffer,
916 if ((c = getoption(buf, "-setuplogtype")))
918 int logsource, logtype;
919 char buffer[64], *ptr;
921 ptr = strpbrk(c, " \t");
922 strncpy(buffer, c, ptr-c);
925 if (strcasecmp(buffer, "syslog")==0)
927 else if (strcasecmp(buffer, "filelog")==0)
934 opt = strpbrk(c, " \t");
935 while (opt ** isspace(*opt))
938 ptr = strpbrk(opt, " \t");
939 strncpy(buffer, opt, ptr-opt);
942 for(logtype=logtype_default;
943 logtype<logtype_end_of_list_marker;
946 if (strcasecmp(buffer,
949 buf = strpbrk(buf, " \t");
951 while (buf && isspace(*buf))
954 if (opt = getoption(c, "syslog"))
957 else if (opt = getoption(c, "filelog"))