1 /*
2 ** Copyright (C) 2001-2020 by Carnegie Mellon University.
3 **
4 ** @OPENSOURCE_LICENSE_START@
5 ** See license information in ../../LICENSE.txt
6 ** @OPENSOURCE_LICENSE_END@
7 */
8 
9 /*
10 **  sklog.h
11 **
12 **    Function prototypes for writing messages to log files.
13 **
14 */
15 #ifndef _LOG_H
16 #define _LOG_H
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 #include <silk/silk.h>
22 
23 RCSIDENTVAR(rcsID_LOG_H, "$SiLK: sklog.h ef14e54179be 2020-04-14 21:57:45Z mthomas $");
24 
25 #include <syslog.h>
26 
27 /**
28  *  @file
29  *
30  *    Functions to write messages to log files or to the system log
31  *    (syslog).
32  *
33  *    This file is part of libsilk.
34  */
35 
36 
37 /*
38  *    These wrapper functions invoke syslog() or fprintf().  The
39  *    syslog level is implied by the function's name (see syslog(3))
40  *    and are listed here from most severe to least.  This functions
41  *    have the same caveats as sklog().
42  *
43  *    These functions always return 0; they return a value to be
44  *    consistent with printf and sk_msg_fn_t.
45  */
46 #ifdef TEST_PRINTF_FORMATS
47 #  define EMERGMSG printf
48 #  define ALERTMSG printf
49 #  define CRITMSG printf
50 #  define ERRMSG printf
51 #  define WARNINGMSG printf
52 #  define NOTICEMSG printf
53 #  define INFOMSG printf
54 #  define DEBUGMSG printf
55 #else
56 int
57 EMERGMSG(
58     const char         *fmt,
59     ...)
60     SK_CHECK_PRINTF(1, 2);
61 int
62 ALERTMSG(
63     const char         *fmt,
64     ...)
65     SK_CHECK_PRINTF(1, 2);
66 int
67 CRITMSG(
68     const char         *fmt,
69     ...)
70     SK_CHECK_PRINTF(1, 2);
71 int
72 ERRMSG(
73     const char         *fmt,
74     ...)
75     SK_CHECK_PRINTF(1, 2);
76 int
77 WARNINGMSG(
78     const char         *fmt,
79     ...)
80     SK_CHECK_PRINTF(1, 2);
81 int
82 NOTICEMSG(
83     const char         *fmt,
84     ...)
85     SK_CHECK_PRINTF(1, 2);
86 int
87 INFOMSG(
88     const char         *fmt,
89     ...)
90     SK_CHECK_PRINTF(1, 2);
91 int
92 DEBUGMSG(
93     const char         *fmt,
94     ...)
95     SK_CHECK_PRINTF(1, 2);
96 #endif
97 
98 
99 /*
100  *   Available features; pass to sklogSetup().
101  */
102 /** Enable options for use of syslog() */
103 #define SKLOG_FEATURE_SYSLOG  1
104 /** Enable options that mimic the legacy logging */
105 #define SKLOG_FEATURE_LEGACY  2
106 
107 
108 /*
109  *    TRACEMSG() messages should use DEBUGMSG.  See sktracemsg.h.
110  */
111 #ifndef TRACEMSG_FUNCTION
112 #  define TRACEMSG_FUNCTION DEBUGMSG
113 #endif
114 
115 
116 /**
117  *    Signature of function callbacked that will be invoked to lock
118  *    and unlock the log.  These functions are set by
119  *    sklogSetLocking().
120  */
121 typedef int (*sklog_lock_fn_t)(
122     void       *caller_data);
123 
124 
125 /**
126  *    Signature of function that will produce a time/machine stamp on
127  *    each log message.  Function should write the stamp into the
128  *    beginning of the buffer and return the strlen() of the text it
129  *    added.  The text should probably include a trailing ": ".
130  */
131 typedef size_t (*sklog_stamp_fn_t)(
132     char        *buffer,
133     size_t       buffer_size);
134 
135 
136 /**
137  *    Writes a message with the specified 'priority' to the log.
138  *    Requires that sklogSetup() has created the log, that
139  *    sklogSetDestination() has been called, and that sklogOpen() has
140  *    opened the log.  Writing to an unopend log produces no error and
141  *    no message.
142  */
143 #ifdef TEST_PRINTF_FORMATS
144 #define sklog(priority, ...) printf(__VA_ARGS__)
145 #else
146 void
147 sklog(
148     int                 priority,
149     const char         *fmt,
150     ...)
151     SK_CHECK_PRINTF(2, 3);
152 #endif
153 
154 
155 /**
156  *    Return a non-zero value if the current logging level includes
157  *    'level', where 'level' is one of the syslog macros LOG_EMERG,
158  *    LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO,
159  *    or LOG_DEBUG.
160  *
161  *    Return 0 if messages at 'level' are not being written to the log.
162  *
163  *    Since SiLK 3.17.0.
164  */
165 int
166 sklogCheckLevel(
167     int                 level);
168 
169 
170 /**
171  *    Closes the log.  The log can be re-opened by calling
172  *    sklogOpen().
173  */
174 void
175 sklogClose(
176     void);
177 
178 
179 /**
180  *    Creates an internal buffer holding the command line used to
181  *    invoke the application from the specified 'argc' and 'argv' and
182  *    writes it to the log.  If the log is not yet opened, the buffer
183  *    will be written once sklogOpen() is called.
184  */
185 void
186 sklogCommandLine(
187     int                 argc,
188     char * const       *argv);
189 
190 
191 /**
192  *    Disable log rotation once the log has been opened.  Once this
193  *    function has been called, there is no way to re-enable log
194  *    rotation.
195  *
196  *    This function should be called in the child process after a call
197  *    to fork() to avoid having multiple processes attempt to rotate
198  *    the log file.
199  */
200 void
201 sklogDisableRotation(
202     void);
203 
204 
205 /**
206  *    This function is only available when using libsilk-thrd.
207  *
208  *    Configure the log for use in a multithreaded environemnt.  This
209  *    function creates a mutex and calls the sklogSetLocking()
210  *    function with the necessary function pointers.  This function
211  *    returns the value returned by sklogSetLocking(); i.e., it
212  *    returns 0 unless sklogSetup() has not yet been called.
213  *
214  *    If the multithreaded program calls fork(), the child process
215  *    should first call sklogSetLocking() using NULL for all
216  *    parameters.  This ensures that the (single-threaded) child
217  *    process ignores the log-file lock that the parent may have held
218  *    when fork() was called.  Next the child should call
219  *    sklogDisableRotation() to ensure it does not attempt to rotate
220  *    the log-file.
221  */
222 int
223 sklogEnableThreadedLogging(
224     void);
225 
226 
227 /**
228  *    Return the file handle to the log file or rotated log file.
229  *    Return NULL if syslog or no logging is being used, or if the log
230  *    has not yet been opened.
231  */
232 FILE *
233 sklogGetDestination(
234     void);
235 
236 
237 /**
238  *    Fill the character array 'buf' with the name of the logging
239  *    directory as set by sklogSetDirectory() and return a pointer to
240  *    'buf'.  Returns NULL if a log-directory has not been specified,
241  *    or if the logging directory is longer than 'bufsize' characters.
242  */
243 char *
244 sklogGetDirectory(
245     char               *buf,
246     size_t              bufsize);
247 
248 
249 /**
250  *    Return the current level for log messages.  Return NULL before
251  *    sklogSetup() is called and after sklogTeardown() is called.
252  *
253  *    Since SiLK 3.11.0.
254  */
255 const char *
256 sklogGetLevel(
257     void);
258 
259 
260 /**
261  *    Return the current mask for log messages.  Return 0 before
262  *    sklogSetup() is called and after sklogTeardown() is called.
263  *
264  *    Since SiLK 3.11.0.
265  */
266 int
267 sklogGetMask(
268     void);
269 
270 
271 /**
272  *    Similar to sklog(), but returns without logging the message if
273  *    the log is already locked.
274  */
275 void
276 sklogNonBlock(
277     int                 priority,
278     const char         *fmt,
279     ...)
280     SK_CHECK_PRINTF(2, 3);
281 
282 
283 /**
284  *    Opens the log.  This function requires that sklogSetup() and
285  *    sklogSetDestination() be called beforehand.  Return 0 on
286  *    success, or -1 if the log cannot be opened.
287  */
288 int
289 sklogOpen(
290     void);
291 
292 
293 /**
294  *    Verifies that all the required options have been specified and
295  *    that valid values were given.  When an invalid option is found,
296  *    an error message will be printed.  Returns -1 if there is an
297  *    issue with an option; returns 0 on success.
298  */
299 int
300 sklogOptionsVerify(
301     void);
302 
303 
304 /**
305  *    Print the usage of the options defined by this library to the
306  *    specified file handle.
307  */
308 void
309 sklogOptionsUsage(
310     FILE               *fp);
311 
312 
313 /**
314  *    Redirect the standard output and standard error as follows:
315  *
316  *    If log messages are going to a local file, redirect stdout and
317  *    stderr to write to that file.
318  *
319  *    If log messages are going to either stdout or stderr, do not
320  *    redirect anything.  This also includes the case where messages
321  *    are going to both syslog and stderr.
322  *
323  *    If logging is disabled or if the messages are going to syslog
324  *    exclusively, redirect stdout and stderr to /dev/null.
325  *
326  *    This function may only be called after the log has been opened.
327  *
328  *    Return 0 on success.  On failure, write an error message into
329  *    'buf' (when provided) and return -1.
330  */
331 int
332 sklogRedirectStandardStreams(
333     char               *buf,
334     size_t              bufsize);
335 
336 
337 /**
338  *    Set the destination for the log messages.  This should be the
339  *    full path to the log file, or the strings 'none' for no logging,
340  *    'stdout' to log to the standard output, 'stderr' to log to the
341  *    standard error, 'syslog' to log with syslog(3), or 'both' to log
342  *    to both syslog and the standard error.  Note that 'both' is only
343  *    available on systems where LOG_PERROR is defiend.
344  *
345  *    This function must be called after sklogSetup() and prior to
346  *    sklogOpen()ing the log.
347  *
348  *    Returns 0 on success, or -1 on error (not a full path).
349  *
350  *    See also sklogSetDirectory().
351  */
352 int
353 sklogSetDestination(
354     const char         *destination);
355 
356 
357 /**
358  *    This function is provided for backward compatibility.  We
359  *    recommend the use of syslog(3) instead.
360  *
361  *    Set the destination for log messages to multiple files in the
362  *    directory 'dir_name', using 'base_name' as part of the basename
363  *    for the files, and the current date as the remainder of the
364  *    name.  The format of the files will be
365  *
366  *        <dir_name>/<base_name>-YYYYMMDD.log
367  *
368  *    The files will be rotated when they receive the first message
369  *    after midnight local time.  The previous day's log file will be
370  *    compressed.
371  *
372  *    If 'base_name' is NULL, the string returned by skAppName() is
373  *    used.
374  *
375  *    This function must be called after sklogSetup() and prior to
376  *    sklogOpen()ing the log.
377  *
378  *    Return 0 on success, or -1 if 'dir_name' does not exist,
379  *    'base_name' contains a '/', or the combined path is too long.
380  */
381 int
382 sklogSetDirectory(
383     const char         *dir_name,
384     const char         *base_name);
385 
386 
387 /**
388  *    When using syslog(3) for logging, this determines the facility
389  *    to use.  This can only be called prior to sklogOpen().  The
390  *    facility is ignored unless syslog(3) is used.
391  */
392 int
393 sklogSetFacility(
394     int                 facility);
395 
396 
397 /**
398  *    Set the facility for syslog(3) by name or by a C-string that is
399  *    parsable as a number or a recognized name.  Recognized names are
400  *    the values 'user', 'daemon', and 'local0'..'local7'.  Other
401  *    facilities must be set by value.
402  */
403 int
404 sklogSetFacilityByName(
405     const char         *name_or_number);
406 
407 
408 /**
409  *    Sets the log level to all levels up to and including the level
410  *    named by 'level'.  This may be called at any time after
411  *    sklogSetup().  Returns 0 on success, or -1 if 'level' is not a
412  *    valid level.
413  *
414  *    The valid levels are: "emerg", "alert", "crit", "err",
415  *    "warning", "notice", "info", "debug".
416  */
417 int
418 sklogSetLevel(
419     const char         *level);
420 
421 
422 /**
423  *    Set functions that lock and unlock the log when a logging
424  *    mechanism other than syslog(3) is used.  These functions should
425  *    be set in a multi-threaded application so that messages from
426  *    different threads are kept distinct.  The 'locker' function will
427  *    be called to lock the log; the 'unlocker' function to unlock it.
428  *    The value in 'data' will be passed to these functions.
429  *
430  *    The function in 'try_locker' is used when sklogNonBlock() is
431  *    called.  The function should lock the log and return 0 if it is
432  *    currently unlocked, or immediately return a non-zero value.
433  *
434  *    This function must be called after sklogSetup().  The function
435  *    returns 0 unless sklogSetup() has not yet been called, in which
436  *    case -1 is returned.
437  *
438  *    This function can be called multiple times to modify the locking
439  *    mechanism, and it can be called with all arguments set to NULL
440  *    to disable log file locking.  Changing or disabling the locking
441  *    in a multi-threaded environment or when the log file is locked
442  *    is undefined.
443  *
444  *    See also the sklogEnableThreadedLogging() function.
445  */
446 int
447 sklogSetLocking(
448     sklog_lock_fn_t     locker,
449     sklog_lock_fn_t     unlocker,
450     sklog_lock_fn_t     try_locker,
451     void               *data);
452 
453 
454 /**
455  *    Set the mask for log messages.  This may be set at any time
456  *    after calling setup.  Returns the old log mask.  Use the syslog
457  *    macro LOG_UPTO() to specify the mask for this function.
458  */
459 int
460 sklogSetMask(
461     int                 mask);
462 
463 
464 /**
465  *    Specify that 'command' is to run on the newly closed log file
466  *    after log roation.  If 'command' is the empty string, no action
467  *    is taken.  If 'command' is NULL, the default action of
468  *    compressing the log file is taken.
469  *
470  *    Return 0 on success.  If log-rotation is not active, print a
471  *    message and return 0.  On failure, print an error message and
472  *    return -1.
473  *
474  *    The following %-conversions are supported: %s is the full path
475  *    to the closed file, and %% is the character '%'.
476  */
477 int
478 sklogSetPostRotateCommand(
479     const char         *command);
480 
481 
482 /**
483  *    Sets the function that will be used to prefix each log message
484  *    when a logging mechanism other than syslog(3) is used.  If this
485  *    function is not called, a default stamping function is used.
486  *    This function must be called after sklogSetup() and before
487  *    sklogOpen().
488  */
489 int
490 sklogSetStampFunction(
491     sklog_stamp_fn_t    makestamp);
492 
493 
494 /**
495  *    Sets up the sklog module by initializing all memory.  The module
496  *    will register the options appropriate for the 'feature_list'
497  *    requested.  The available features are macros defined above as
498  *    SKLOG_FEATURE_*.  Returns 0 unless there was a problem
499  *    registering the options.
500  */
501 int
502 sklogSetup(
503     int                 feature_list);
504 
505 
506 /**
507  *    Frees and clears all memory associated with the log.  If the log
508  *    is opened it will be closed.
509  */
510 void
511 sklogTeardown(
512     void);
513 
514 
515 /**
516  *    Prototypes that match sk_msg_vargs_fn_t
517  */
518 int
519 EMERGMSG_v(
520     const char         *fmt,
521     va_list             args)
522     SK_CHECK_PRINTF(1, 0);
523 int
524 ALERTMSG_v(
525     const char         *fmt,
526     va_list             args)
527     SK_CHECK_PRINTF(1, 0);
528 int
529 CRITMSG_v(
530     const char         *fmt,
531     va_list             args)
532     SK_CHECK_PRINTF(1, 0);
533 int
534 ERRMSG_v(
535     const char         *fmt,
536     va_list             args)
537     SK_CHECK_PRINTF(1, 0);
538 int
539 WARNINGMSG_v(
540     const char         *fmt,
541     va_list             args)
542     SK_CHECK_PRINTF(1, 0);
543 int
544 NOTICEMSG_v(
545     const char         *fmt,
546     va_list             args)
547     SK_CHECK_PRINTF(1, 0);
548 int
549 INFOMSG_v(
550     const char         *fmt,
551     va_list             args)
552     SK_CHECK_PRINTF(1, 0);
553 int
554 DEBUGMSG_v(
555     const char         *fmt,
556     va_list             args)
557     SK_CHECK_PRINTF(1, 0);
558 
559 
560 /**
561  *    Writes a message with the specified 'priority' to the log.
562  *    Requires that sklogSetup() has created the log, that
563  *    sklogSetDestination() has been called, and that sklogOpen() has
564  *    opened the log.
565  */
566 void
567 sklogv(
568     int                 priority,
569     const char         *fmt,
570     va_list             args)
571     SK_CHECK_PRINTF(2, 0);
572 
573 #ifdef __cplusplus
574 }
575 #endif
576 #endif /*  _LOG_H */
577 
578 /*
579 ** Local Variables:
580 ** mode:c
581 ** indent-tabs-mode:nil
582 ** c-basic-offset:4
583 ** End:
584 */
585