1#ifndef _ATALK_LOGGER_H
2#define _ATALK_LOGGER_H 1
3
4/*
5 * logger LOG Macro Usage
6 * ======================
7 *
8 * LOG(<logtype>, <loglevel>, "<string>"[, args]);
9 *
10 *
11 * logger API Setup
12 * ================
13 *
14 * Standard interface:
15 * -------------------
16 *
17 *    setuplog(char *confstring)
18 *    confstring = "<logtype> <loglevel> [<filename>]"
19 *
20 * Calling without <filename> configures basic logging to syslog. Specifying <filename>
21 * configures extended logging to <filename>.
22 *
23 * You can later disable logging by calling
24 *
25 *    unsetuplog(char *confstring)
26 *    confstring = "<logtype> [<any_string>]"
27 *
28 * Calling without <any_string> disables syslog logging, calling with <any_string>
29 * disables file logging.
30 *
31 * <logtype>:
32 * you can setup a default with "Default". Any other logtype used in LOG will then
33 * use the default if not setup itself. This is probabyl the only thing you may
34 * want to use.
35 *
36 * Example:
37 * setuplog("default log_debug /var/log/debug.log");
38 * See also libatalk/util/test/logger_test.c
39 *
40 * "Legacy" interface:
41 * -------------------
42 *
43 * Some netatalk daemons (31.3.2009.: e.g. atalkd, papd) may not be converted to
44 * use the new API and might still call
45 *
46 *    syslog_setup(int loglevel, enum logtypes logtype, int display_options, int facility);
47 *
48 * directly. These daemons are therefore limited to syslog logging. Also their
49 * loglevel can't be changed at runtime.
50 *
51 *
52 * Note:
53 * dont get confused by log_init(). It only gets called if your app
54 * forgets to setup logging before calling LOG.
55 */
56
57
58#include <limits.h>
59#include <stdio.h>
60
61#include <atalk/boolean.h>
62
63#ifdef HAVE_CONFIG_H
64#include "config.h"
65#endif
66
67/* logger is used by pam modules */
68#ifndef UAM_MODULE_EXPORT
69#define UAM_MODULE_EXPORT
70#endif
71
72enum loglevels {
73    log_none,
74    log_severe,
75    log_error,
76    log_warning,
77    log_note,
78    log_info,
79    log_debug,
80    log_debug6,
81    log_debug7,
82    log_debug8,
83    log_debug9,
84    log_maxdebug
85};
86
87/* this is the enum specifying all availiable logtypes */
88enum logtypes {
89  logtype_default,
90  logtype_logger,
91  logtype_cnid,
92  logtype_afpd,
93  logtype_dsi,
94  logtype_atalkd,
95  logtype_papd,
96  logtype_uams,
97  logtype_end_of_list_marker  /* don't put any logtypes after this */
98};
99
100
101/* Display Option flags. */
102/* redefine these so they can don't interfeer with syslog */
103/* these can be used in standard logging too */
104#define logoption_nsrcinfo    0x04   /* don't log source info */
105/* the following do not work anymore, they're only provided in order to not
106 * break existing source code */
107#define logoption_pid         0x01   /* log the pid with each message */
108#define logoption_cons        0x02   /* log on the console if error logging */
109#define logoption_ndelay      0x08   /* don't delay open */
110#define logoption_perror      0x20   /* log to stderr as well */
111#define logoption_nfile       0x40   /* ignore the file that called the log */
112#define logoption_nline       0x80   /* ignore the line that called the log*/
113
114/* facility codes */
115/* redefine these so they can don't interfeer with syslog */
116#define logfacility_user        (1<<3)  /* random user-level messages */
117#define logfacility_mail        (2<<3)  /* mail system */
118#define logfacility_daemon      (3<<3)  /* system daemons */
119#define logfacility_auth        (4<<3)  /* security/authorization messages */
120#define logfacility_syslog      (5<<3)  /* messages generated by syslogd */
121#define logfacility_lpr         (6<<3)  /* line printer subsystem */
122#define logfacility_authpriv    (10<<3) /* security/auth messages (private) */
123#define logfacility_ftp         (11<<3) /* ftp daemon */
124
125/* =========================================================================
126    Structure definitions
127   ========================================================================= */
128
129/* Main log config */
130typedef struct {
131    bool           inited;                 /* file log config initialized ? */
132    bool           syslog_opened;          /* syslog opened ? */
133    bool           console;                /* if logging to console from a cli util */
134    char           processname[16];
135    int            syslog_facility;
136    int            syslog_display_options;
137} log_config_t;
138
139/* This stores the config and options for one filelog type (e.g. logger, afpd etc.) */
140typedef struct {
141    bool           set;           /* set individually ? yes: changing default
142			                       * doesnt change it. no: it changes it.*/
143    bool           syslog;        /* This type logs to syslog */
144    int            fd;            /* logfiles fd */
145    enum loglevels level;         /* Log Level to put in this file */
146    int            display_options;
147} logtype_conf_t;
148
149
150/* =========================================================================
151    Global variables
152    ========================================================================= */
153
154/* Make config accessible for LOG macro */
155extern log_config_t log_config;
156
157extern UAM_MODULE_EXPORT logtype_conf_t type_configs[logtype_end_of_list_marker];
158
159/* =========================================================================
160    Global function decarations
161   ========================================================================= */
162
163/*  */
164void log_init(void);
165
166/* Setup the level and type of log that will be logged for file loggging */
167void log_setup(const char *filename, enum loglevels loglevel, enum logtypes logtype);
168
169/* Setup the level and type of log that will be logged to syslog. */
170void syslog_setup(int loglevel, enum logtypes logtype,
171		  int display_options, int facility);
172
173/* This gets called e.g. from afpd.conf parsing code with a string like: */
174/* "default log_maxdebug /var/log/afpd.log" */
175void setuplog(const char *logstr);
176
177/* This gets called e.g. from afpd.conf parsing code with a string like: */
178/* "default dummyname" */
179void unsetuplog(const char *logstr);
180
181/* finish up and close the logs */
182void log_close(void);
183
184/* This function sets up the ProcessName */
185void set_processname(const char *processname);
186
187/* LOG macro func no.1: log the message to file */
188UAM_MODULE_EXPORT  void make_log_entry(enum loglevels loglevel, enum logtypes logtype, const char *file, int line, char *message, ...);
189
190/*
191 * How to write a LOG macro:
192 * http://c-faq.com/cpp/debugmacs.html
193 *
194 * We choose the verbose form in favor of the obfuscated ones, its easier
195 * to parse for human beings and facilitates expanding the macro for
196 * inline checks for debug levels.
197 *
198 * How to properly enclose multistatement macros:
199 * http://en.wikipedia.org/wiki/C_macro#Multiple_statements
200 */
201
202#define LOG_MAX log_info
203
204#ifdef NO_DEBUG
205
206#define LOG(log_level, type, ...)                                       \
207    do {                                                                \
208        if (log_level <= LOG_MAX)                                       \
209            if (log_level <= type_configs[type].level)                  \
210                make_log_entry((log_level), (type), __FILE__, __LINE__,  __VA_ARGS__); \
211    } while(0)
212
213#else  /* ! NO_DEBUG */
214
215#define LOG(log_level, type, ...)               \
216    do {                                                                \
217        if (log_level <= type_configs[type].level)                      \
218            make_log_entry((log_level), (type), __FILE__, __LINE__,  __VA_ARGS__); \
219    } while(0)
220
221#endif  /* NO_DEBUG */
222
223#endif /* _ATALK_LOGGER_H */
224