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, int display_options);
71 /* Setup the Level and type of log that will be logged to syslog. */
72 void syslog_setup(enum loglevels loglevel, enum logtypes logtype, int display_options, int facility);
74 /* finish up and close the logs */
77 /* This function sets up the processname */
78 void set_processname(char *processname);
81 void make_log(enum loglevels loglevel, enum logtypes logtype, char *message, ...);
82 #ifndef DISABLE_LOGGER
83 make_log_func set_log_location(char *srcfilename, int srclinenumber);
85 /* ==========================================================================
87 ========================================================================== */
89 /* A structure containing object level stuff */
90 struct tag_log_file_data {
91 char log_filename[PATH_MAX]; /* Name of file */
92 FILE *log_file; /* FILE pointer to file */
93 enum loglevels log_level; /* Log Level to put in this file */
97 typedef struct tag_log_file_data log_file_data_pair[2];
99 /* A structure containg class level stuff */
100 struct tag_global_log_data {
103 char *temp_src_filename;
104 int temp_src_linenumber;
105 char processname[16];
107 char *log_file_directory; /* Path of directory containing log files */
108 log_file_data_pair **logs;
111 struct what_to_print_array {
113 bool print_processname;
121 /* ==========================================================================
122 Internal function declarations
123 ========================================================================== */
125 void generate_message_details(char *message_details_buffer,
126 int message_details_buffer_length,
127 struct tag_log_file_data *log_struct,
128 enum loglevels loglevel, enum logtypes logtype);
130 int get_syslog_equivalent(enum loglevels loglevel);
132 static char *get_command_name(char *commandpath);
134 /* ==========================================================================
136 ========================================================================== */
138 /* A populated instance */
140 static log_file_data_pair default_log_file_data_pair = {
142 /* log_filename */ "\0\0\0\0\0\0\0\0",
144 /* log_level */ log_debug,
145 /* display_options */ logoption_pid
148 /* log_filename */ LOGFILEPATH,
150 /* log_level */ log_debug,
151 /* display_options */ logoption_pid
154 static log_file_data_pair *log_file_data_array[logtype_end_of_list_marker] =
155 {&default_log_file_data_pair};
157 /* The class (populated) */
158 static struct tag_global_log_data global_log_data = {
159 /* struct_size */ sizeof(struct tag_global_log_data),
160 /* temp_src_filename */ NULL,
161 /* temp_src_linenumber */ 0,
162 /* processname */ "",
163 /* log_file_directory */ "",
167 /* macro to get access to the array */
168 #define log_file_arr (global_log_data.logs)
170 /* Array to store text to list given a log type */
171 static const char * arr_logtype_strings[] = LOGTYPE_STRING_IDENTIFIERS;
172 static const int num_logtype_strings = COUNT_ARRAY(arr_logtype_strings);
174 /* Array for charachters representing log severity in the log file */
175 static const char arr_loglevel_chars[] = {'S', 'E', 'W', 'N', 'I', 'D'};
176 static const int num_loglevel_chars = COUNT_ARRAY(arr_loglevel_chars);
178 static const char * arr_loglevel_strings[] = LOGLEVEL_STRING_IDENTIFIERS;
179 static const int num_loglevel_strings = COUNT_ARRAY(arr_loglevel_strings);
181 #else /* #ifndef DISABLE_LOGGER */
182 char *disabled_logger_processname=NULL;
183 #endif /* DISABLE_LOGGER */
184 /* ==========================================================================
185 Global function definitions
186 ========================================================================== */
188 #ifndef DISABLE_LOGGER
190 /* remember I'm keeping a copy of the actual char * Filename, so you mustn't
191 delete it, until you've finished with the log. Also you're responsible
192 for deleting it when you have finished with it. */
195 if (global_log_data.logs==NULL)
197 /* first check default_log_file_data_pair */
199 /* next clear out the log_file_data_array */
200 memset(log_file_data_array, 0, sizeof(log_file_data_array));
201 /* now set default_log_file_data_pairs */
202 log_file_data_array[0] = &default_log_file_data_pair;
204 /* now setup the global_log_data struct */
205 global_log_data.logs = log_file_data_array;
208 #endif /* #ifndef DISABLE_LOGGER */
210 bool log_setup(char *filename, enum loglevels loglevel, enum logtypes logtype, int display_options)
212 #ifndef DISABLE_LOGGER
222 log_file_data_pair *logs;
226 logs = log_file_arr[logtype];
230 logs = (log_file_data_pair *)malloc(sizeof(log_file_data_pair));
233 LOG(log_severe, logtype_logger, "can't calloc in log_setup");
237 /* memcpy(logs, log_file_arr[logtype_default], sizeof(log_file_data_pair)); */
238 log_file_arr[logtype] = logs;
239 (*logs)[1].log_file = NULL;
243 if ( ((*logs)[1].log_file == stdout) && ((*logs)[1].log_file != NULL) )
245 fclose((*logs)[1].log_file);
246 (*logs)[1].log_file = NULL;
249 if (strlen(global_log_data.log_file_directory)>0)
251 lastchar[0] = global_log_data.log_file_directory[strlen(global_log_data.log_file_directory)-1];
253 if (lastchar[0] == '/' || lastchar[0] == '\\' || lastchar[0] == ':')
256 /* this should probably be a platform specific path separator */
264 #ifdef DEBUG_OUTPUT_TO_SCREEN
265 printf("filename is %s stored at location %p\n", (*logs)[1].log_filename,
266 (*logs)[1].log_filename);
267 #endif /* DEBUG_OUTPUT_TO_SCREEN */
268 if (filename == NULL)
270 strncpy((*logs)[1].log_filename, (*(log_file_arr[0]))[1].log_filename, PATH_MAX);
274 sprintf((*logs)[1].log_filename, "%s%s%s", global_log_data.log_file_directory,
277 (*logs)[1].log_level = loglevel;
278 (*logs)[1].display_options = display_options;
280 #ifdef DEBUG_OUTPUT_TO_SCREEN
281 printf("filename is %s stored at location %p\n", (*logs)[1].log_filename,
282 (*logs)[1].log_filename);
283 #endif /* DEBUG_OUTPUT_TO_SCREEN */
285 #ifdef CHECK_STAT_ON_NEW_FILES
289 #ifdef DEBUG_OUTPUT_TO_SCREEN
290 printf("about to stat file %s\n", (*logs)[1].log_filename);
292 firstattempt = stat((*logs)[1].log_filename, &statbuf);
294 if (firstattempt == -1)
296 #ifdef DEBUG_OUTPUT_TO_SCREEN
297 printf("about to call Log with %d, %d, %s, %s\n", log_note, logtype_logger,
298 "can't stat Logfile", (*logs)[1].log_filename);
301 /* syslog(LOG_INFO, "stat failed"); */
302 LOG(log_warning, logtype_logger, "stat fails on file %s",
303 (*logs)[1].log_filename);
305 if (strlen(global_log_data.log_file_directory)>0)
307 retval = stat(global_log_data.log_file_directory, &statbuf);
310 #ifdef DEBUG_OUTPUT_TO_SCREEN
311 printf("can't stat dir either so I'm giving up\n");
313 LOG(log_severe, logtype_logger, "can't stat directory %s either",
314 global_log_data.log_file_directory);
320 #ifdef CHECK_ACCESS_ON_NEW_FILES
321 access = ((statbuf.st_uid == uid)?(statbuf.st_mode & S_IWUSR):0) +
322 ((statbuf.st_gid == gid)?(statbuf.st_mode & S_IWGRP):0) +
323 (statbuf.st_mode & S_IWOTH);
327 #ifdef DEBUG_OUTPUT_TO_SCREEN
328 printf("failing with %d, %d, %s, %s\n", log_note, logtype_logger,
329 "can't access Logfile %s", (*logs)[1].log_filename);
332 LOG(log_note, logtype_logger, "can't access file %s",
333 (*logs)[1].log_filename);
336 #endif /* CHECK_ACCESS_ON_NEW_FILES */
337 #endif /* CHECK_STAT_ON_NEW_FILES */
338 #ifdef KEEP_LOGFILES_OPEN
339 if ((*logs)[1].log_file!=NULL)
340 fclose((*logs)[1].log_file);
342 (*logs)[1].log_file = fopen((*logs)[1].log_filename, "at");
343 if ((*logs)[1].log_file == NULL)
345 LOG(log_severe, logtype_logger, "can't open Logfile %s", (*logs)[1].log_filename);
350 LOG(log_info, logtype_logger, "Log setup complete");
352 #endif /* DISABLE_LOGGER */
357 void syslog_setup(enum loglevels loglevel, enum logtypes logtype, int display_options, int facility)
359 #ifndef DISABLE_LOGGER
360 log_file_data_pair *logs;
364 logs = log_file_arr[logtype];
368 logs = (log_file_data_pair *)malloc(sizeof(log_file_data_pair));
371 LOG(log_severe, logtype_logger, "can't calloc in log_setup");
375 memcpy(logs, log_file_arr[logtype_default], sizeof(log_file_data_pair));
376 log_file_arr[logtype] = logs;
380 (*logs)[0].log_file = NULL;
381 (*logs)[0].log_filename[0] = 0;
382 (*logs)[0].log_level = loglevel;
383 (*logs)[0].display_options = display_options;
385 openlog(global_log_data.processname, (*logs)[0].display_options, facility);
387 LOG(log_info, logtype_logger, "SysLog setup complete");
388 #else /* DISABLE_LOGGER */
389 /* behave like a normal openlog call */
390 openlog(disabled_logger_processname, display_options, facility);
391 #endif /* DISABLE_LOGGER */
396 #ifndef DISABLE_LOGGER
397 log_file_data_pair *logs;
400 LOG(log_info, logtype_logger, "Closing logs");
402 for(n=(sizeof(log_file_arr)-1);n>0;n--)
404 logs = log_file_arr[n];
405 #ifdef KEEP_LOGFILES_OPEN
406 if ((*logs)[1].log_file!=NULL)
407 fclose((*logs)[1].log_file);
408 #endif /* KEEP_LOGFILES_OPEN */
411 #ifdef DEBUG_OUTPUT_TO_SCREEN
412 printf("Freeing log_data %d, stored at %p\n", n, logs);
413 printf("\t(filename) %s\t(type) %s\n", (*logs)[1].log_filename,
414 ((n<num_logtype_strings)?arr_logtype_strings[n]:""));
415 #endif /* DEBUG_OUTPUT_TO_SCREEN */
418 log_file_arr[n] = NULL;
420 #ifdef DEBUG_OUTPUT_TO_SCREEN
421 printf("Freeing log_data %d, stored at %p\n", n, log_file_arr[n]);
422 printf("\t(filename) %s\t(type) %s\n", (*(log_file_arr[n]))[1].log_filename,
423 ((n<num_logtype_strings)?arr_logtype_strings[n]:""));
424 #endif /* DEBUG_OUTPUT_TO_SCREEN */
425 #endif /* DISABLE_LOGGER */
430 /* This function sets up the processname */
431 void set_processname(char *processname)
433 #ifndef DISABLE_LOGGER
434 /* strncpy(global_log_data.processname, GetCommandName(processname), 15); */
435 strncpy(global_log_data.processname, processname, 15);
436 global_log_data.processname[15] = 0;
437 #else /* DISABLE_LOGGER */
438 disabled_logger_processname = processname;
439 #endif /* DISABLE_LOGGER */
442 #ifndef DISABLE_LOGGER
443 /* This is called by the macro so set the location of the caller of Log */
444 make_log_func set_log_location(char *srcfilename, int srclinenumber)
446 #ifdef DEBUG_OUTPUT_TO_SCREEN
447 printf("Setting Log Location\n");
449 global_log_data.temp_src_filename = srcfilename;
450 global_log_data.temp_src_linenumber = srclinenumber;
452 return make_log_entry;
454 #endif /* DISABLE_LOGGER */
456 /* --------------------------------------------------------------------------
457 MakeLog has 1 main flaws:
458 The message in its entirity, must fit into the tempbuffer.
459 So it must be shorter than MAXLOGSIZE
460 -------------------------------------------------------------------------- */
461 void make_log_entry(enum loglevels loglevel, enum logtypes logtype, char *message, ...)
464 char log_buffer[MAXLOGSIZE];
465 #ifndef DISABLE_LOGGER
466 char log_details_buffer[MAXLOGSIZE];
468 log_file_data_pair *logs;
472 logs = log_file_arr[logtype];
476 logs = log_file_arr[logtype_default];
478 #ifdef DEBUG_OUTPUT_TO_SCREEN
479 printf("Making Log\n");
482 #endif /* DISABLE_LOGGER */
484 /* Initialise the Messages */
485 va_start(args, message);
487 vsnprintf(log_buffer, sizeof(log_buffer), message, args);
489 /* Finished with args for now */
492 #ifdef DISABLE_LOGGER
493 syslog(get_syslog_equivalent(loglevel), "%s", log_buffer);
494 #else /* DISABLE_LOGGER */
497 /* check if sysloglevel is high enough */
498 if ((*logs)[0].log_level>=loglevel)
500 int sysloglevel = get_syslog_equivalent(loglevel);
502 generate_message_details(log_details_buffer, sizeof(log_details_buffer),
503 &(*logs)[0], loglevel, logtype);
505 #ifdef DEBUG_OUTPUT_TO_SCREEN
506 printf("About to log %s %s\n", log_details_buffer, log_buffer);
507 printf("about to do syslog\n");
508 printf("done onw syslog\n");
510 syslog(sysloglevel, "%s: %s", log_details_buffer, log_buffer);
511 /* syslog(sysloglevel, "%s:%s: %s", log_levelString, log_typeString, LogBuffer); */
516 #ifdef DEBUG_OUTPUT_TO_SCREEN
517 printf("about to do the filelog\n");
519 /* check if log_level is high enough */
520 if ((*logs)[1].log_level>=loglevel) {
522 #ifdef DEBUG_OUTPUT_TO_SCREEN
523 printf("Open the Log, FILE* is %p\n", (*logs)[1].log_file);
525 /* if log isn't open, open it */
526 if ((*logs)[1].log_file==NULL) {
527 #ifdef DEBUG_OUTPUT_TO_SCREEN
528 printf("Opening the Log, filename is %s\n", (*logs)[1].log_filename);
530 (*logs)[1].log_file = fopen((*logs)[1].log_filename, "at");
531 if ((*logs)[1].log_file == NULL)
533 (*logs)[1].log_file = stdout;
534 LOG(log_severe, logtype_logger, "can't open Logfile %s", (*logs)[1].log_filename);
538 generate_message_details(log_details_buffer, sizeof(log_details_buffer),
539 &(*logs)[1], loglevel, logtype);
541 #ifdef DEBUG_OUTPUT_TO_SCREEN
542 printf("Files open, lets log\n");
543 printf("FILE* is %p\n", (*logs)[1].log_file);
544 printf("%s: %s\n", log_details_buffer, log_buffer);
547 fprintf((*logs)[1].log_file, "%s: %s\n", log_details_buffer, log_buffer);
549 #ifndef KEEP_LOGFILES_OPEN
550 if ((*logs)[1].log_file != stdout)
552 #ifdef DEBUG_OUTPUT_TO_SCREEN
553 printf("Closing %s\n", (*logs)[1].log_filename);
555 fclose((*logs)[1].log_file);
556 (*logs)[1].log_file = NULL;
557 #ifdef DEBUG_OUTPUT_TO_SCREEN
565 global_log_data.temp_src_filename = NULL;
566 global_log_data.temp_src_linenumber = 0;
567 #endif /* DISABLE_LOGGER */
570 #ifndef DISABLE_LOGGER
571 void load_proccessname_from_proc()
573 pid_t pid = getpid();
574 char buffer[PATH_MAX];
579 sprintf(buffer, "/proc/%d/stat", pid);
580 statfile = fopen(buffer, "rt");
581 fgets(buffer, PATH_MAX-1, statfile);
584 ptr = (char *)strrchr(buffer, ')');
586 memset(procname, 0, sizeof procname);
587 sscanf(buffer, "%d (%15c", &pid, procname); /* comm[16] in kernel */
589 set_processname(procname);
592 /* ==========================================================================
593 Internal function definitions
594 ========================================================================== */
596 static char *get_command_name(char *commandpath)
599 #ifdef DEBUG_OUTPUT_TO_SCREEN
600 printf("getting command name %s\n",commandpath);
602 ptr = (char *)strrchr(commandpath, '/');
608 #ifdef DEBUG_OUTPUT_TO_SCREEN
609 printf("Concluded %s\n", ptr);
614 void workout_what_to_print(struct what_to_print_array *what_to_print, struct tag_log_file_data *log_struct)
616 /* is this a syslog entry? */
617 if (log_struct->log_filename[0]==0)
619 what_to_print->print_datetime = false;
620 what_to_print->print_processname = false;
621 what_to_print->print_pid = false;
625 what_to_print->print_datetime = true;
626 what_to_print->print_processname = true;
628 /* pid is dealt with at the syslog level if we're syslogging */
629 what_to_print->print_pid = (((log_struct->display_options & logoption_pid) == 0)?false:true);
632 what_to_print->print_srcfile = (((log_struct->display_options & logoption_nfile) == 0)?true:false);
633 what_to_print->print_srcline = (((log_struct->display_options & logoption_nline) == 0)?true:false);
635 what_to_print->print_errlevel = true;
636 what_to_print->print_errtype = true;
639 void generate_message_details(char *message_details_buffer,
640 int message_details_buffer_length,
641 struct tag_log_file_data *log_struct,
642 enum loglevels loglevel, enum logtypes logtype)
645 char processinfo[64];
647 char *ptr = message_details_buffer;
649 int len = message_details_buffer_length;
651 char log_buffer[MAXLOGSIZE];
652 const char *logtype_string;
654 char loglevel_string[12]; /* max int size is 2 billion, or 10 digits */
656 struct what_to_print_array what_to_print;
658 workout_what_to_print(&what_to_print, log_struct);
660 #ifdef DEBUG_OUTPUT_TO_SCREEN
661 printf("Making MessageDetails\n");
670 if (what_to_print.print_datetime)
675 /* some people might prefer localtime() to gmtime() */
676 strftime(ptr, len, "%b %d %H:%M:%S", gmtime(&thetime));
677 #ifdef DEBUG_OUTPUT_TO_SCREEN
678 printf("date is %s\n", ptr);
681 templen = strlen(ptr);
683 if (what_to_print.print_processname || what_to_print.print_pid)
684 strncat(ptr, " ", len);
686 strncat(ptr, ":", len);
698 if (what_to_print.print_processname)
700 strncpy(ptr, global_log_data.processname, len);
702 templen = strlen(ptr);
707 if (what_to_print.print_pid)
709 pid_t pid = getpid();
711 sprintf(ptr, "[%d]", pid);
713 templen = strlen(ptr);
718 if (what_to_print.print_srcfile || what_to_print.print_srcline)
720 char sprintf_buffer[8];
723 sprintf_buffer[0] = '[';
724 if (what_to_print.print_srcfile)
726 strcpy(&sprintf_buffer[1], "%s");
727 buff_ptr = &sprintf_buffer[3];
729 if (what_to_print.print_srcfile && what_to_print.print_srcline)
731 strcpy(&sprintf_buffer[3], ":");
732 buff_ptr = &sprintf_buffer[4];
734 if (what_to_print.print_srcline)
736 strcpy(buff_ptr, "%d");
737 buff_ptr = &buff_ptr[2];
739 strcpy(buff_ptr, "]");
741 /* ok sprintf string is ready, now is the 1st parameter src or linenumber */
742 if (what_to_print.print_srcfile)
744 sprintf(ptr, sprintf_buffer,
745 global_log_data.temp_src_filename, global_log_data.temp_src_linenumber);
749 sprintf(ptr, sprintf_buffer, global_log_data.temp_src_linenumber);
752 #ifdef DEBUG_OUTPUT_TO_SCREEN
753 printf("Process info is %s\n", ptr);
756 templen = strlen(ptr);
762 if (what_to_print.print_processname || what_to_print.print_pid ||
763 what_to_print.print_srcfile || what_to_print.print_srcline)
765 strncat(ptr, ": ", len);
771 loglevel_string[0] = 0;
772 ptr = loglevel_string;
775 if (what_to_print.print_errlevel)
777 if ((loglevel/10) >= (num_loglevel_chars-1))
779 sprintf(ptr, "%c%d", arr_loglevel_chars[num_loglevel_chars-1],
784 sprintf(ptr, "%c", arr_loglevel_chars[loglevel/10]);
787 templen = strlen(ptr);
792 if (what_to_print.print_errtype)
794 const char *logtype_string;
796 /* get string represnetation of the Log Type */
797 if (logtype<num_logtype_strings)
798 logtype_string = arr_logtype_strings[logtype];
802 if (what_to_print.print_errlevel)
804 strncat(ptr, ":", len);
808 sprintf(ptr, "%s", logtype_string);
811 message_details_buffer[message_details_buffer_length-1] = 0;
813 #ifdef DEBUG_OUTPUT_TO_SCREEN
814 printf("Message Details are %s\n", message_details_buffer);
817 #endif /* DISABLE_LOGGER */
819 int get_syslog_equivalent(enum loglevels loglevel)
823 /* The question is we know how bad it is for us,
824 but how should that translate in the syslogs? */
829 case 2: /* warning */
833 case 4: /* information */
840 void setuplog(char *logsource, char *logtype, char *loglevel, char *filename)
842 /* -setuplogtype <syslog|filelog> <logtype> <loglevel>*/
843 const char* sources[] = {"syslog", "filelog"};
844 char sourcebuf[64], typebuf[64], levelbuf[32], *ptr;
845 int sourcenum, typenum, levelnum;
847 ptr = strpbrk(logsource, " \t");
848 strncpy(sourcebuf, logsource, ptr-logsource);
849 sourcebuf[ptr-logsource]=0;
851 ptr = strpbrk(logtype, " \t");
852 strncpy(typebuf, logtype, ptr-logtype);
853 typebuf[ptr-logtype]=0;
855 ptr = strpbrk(loglevel, " \t");
856 strncpy(levelbuf, loglevel, ptr-loglevel);
857 levelbuf[ptr-loglevel]=0;
859 for(sourcenum=0;sourcenum<NUMOF(sources);sourcenum++)
861 if (strcasecmp(sourcebuf, sources[sourcenum])==0)
865 for(typenum=0;typenum<num_logtype_strings;typenum++)
867 if (strcasecmp(typebuf, arr_logtype_strings[typenum])==0)
871 for(levelnum=0;levelnum<num_loglevel_strings;levelnum++)
873 if (strcasecmp(levelbuf, arr_loglevel_strings[levelnum])==0)
878 for(logtype=logtype_default;logtype<logtype_end_of_list_marker;logtype++)
880 if (strcasecmp(buffer,
886 if ((c = getoption(buf, "-setuplogtype")))
888 int logsource, logtype;
889 char buffer[64], *ptr;
891 ptr = strpbrk(c, " \t");
892 strncpy(buffer, c, ptr-c);
895 if (strcasecmp(buffer, "syslog")==0)
897 else if (strcasecmp(buffer, "filelog")==0)
904 opt = strpbrk(c, " \t");
905 while (opt ** isspace(*opt))
908 ptr = strpbrk(opt, " \t");
909 strncpy(buffer, opt, ptr-opt);
912 for(logtype=logtype_default;logtype<logtype_end_of_list_marker;logtype++)
914 if (strcasecmp(buffer,
917 buf = strpbrk(buf, " \t");
919 while (buf && isspace(*buf))
922 if (opt = getoption(c, "syslog"))
925 else if (opt = getoption(c, "filelog"))