~ubuntu-branches/ubuntu/precise/netatalk/precise

« back to all changes in this revision

Viewing changes to libatalk/util/logger.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Rittau
  • Date: 2004-01-19 12:43:49 UTC
  • Revision ID: james.westby@ubuntu.com-20040119124349-es563jbp0hk0ae51
Tags: upstream-1.6.4
ImportĀ upstreamĀ versionĀ 1.6.4

Show diffs side-by-side

added added

removed removed

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