core: exported dprint_term_color() function
[sip-router] / dprint.h
1 /*
2  * Copyright (C) 2001-2003 FhG Fokus
3  *
4  * This file is part of ser, a free SIP server.
5  *
6  * ser is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * ser is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License 
17  * along with this program; if not, write to the Free Software 
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 /**
22  * @file
23  * @brief SIP-router core :: debug printing
24  * @ingroup core
25  * Module: @ref core
26  */
27
28 #ifndef dprint_h
29 #define dprint_h
30
31 #include <assert.h>
32 #include <syslog.h>
33 #include <stdio.h> /* stderr, fprintf() */
34
35 #include "compiler_opt.h"
36 #include "cfg_core.h"
37
38
39 /** if defined the function name will also be logged. */
40 #ifdef NO_LOG_FUNC_NAME
41 #       undef LOG_FUNC_NAME
42 #else
43 /* by default log the function name */
44 #       define LOG_FUNC_NAME
45 #endif /* NO_LOG_FUNC_NAME */
46
47 /* C >= 99 has __func__, older gcc versions have __FUNCTION__ */
48 #if __STDC_VERSION__ < 199901L
49 #       if __GNUC__ >= 2 && defined __FUNCTION__
50 #               define _FUNC_NAME_ __FUNCTION__
51 #       else
52 #               define _FUNC_NAME_ ""
53 #               undef LOG_FUNC_NAME
54 #       endif
55 #else
56 #       define _FUNC_NAME_ __func__
57 #endif
58
59 #ifdef NO_DEBUG
60 #       ifdef MOD_NAME
61 #               define LOC_INFO         MOD_NAME ": "
62 #       else
63 #               define LOC_INFO         "<core>: "
64 #       endif
65 #else
66 #       define XCT2STR(i) #i
67 #       define CT2STR(l)  XCT2STR(l)
68 #
69 #       ifdef MOD_NAME
70 #               define LOC_INFO         MOD_NAME " [" __FILE__ ":" CT2STR(__LINE__) "]: "
71 #       else
72 #               define LOC_INFO         "<core> [" __FILE__ ":" CT2STR(__LINE__) "]: "
73 #       endif
74 #
75 #       ifdef NO_LOG
76 #               undef NO_LOG
77 #       endif
78 #endif /* NO_DEBUG */
79
80
81 /*
82  * Log levels
83  */
84 #define L_MIN           -5
85 #define L_ALERT         -5
86 #define L_BUG           -4
87 #define L_CRIT2         -3  /* like L_CRIT, but adds prefix */
88 #define L_CRIT          -2  /* no prefix added */
89 #define L_ERR           -1
90 #define L_WARN          0
91 #define L_NOTICE        1
92 #define L_INFO          2
93 #define L_DBG           3
94 #define L_MAX           3
95
96 /** @brief This is the facility value used to indicate that the caller of the macro
97  * did not override the facility. Value 0 (the defaul) is LOG_KERN on Linux
98  */
99 #define DEFAULT_FACILITY 0
100
101 #define LOG_LEVEL2NAME(level)   (log_level_info[(level) - (L_ALERT)].name)
102 #define LOG2SYSLOG_LEVEL(level) \
103         (log_level_info[(level) - (L_ALERT)].syslog_level)
104
105
106 /** @brief my_pid(), process_no are from pt.h but we cannot \#include it here
107    because of circular dependencies */
108 extern int process_no;
109 extern int my_pid(void);
110
111 /** @brief non-zero if logging to stderr instead to the syslog */
112 extern int log_stderr;
113
114 extern int log_color;
115
116 /** @brief maps log levels to their string name and corresponding syslog level */
117
118 struct log_level_info {
119         char *name;
120         int syslog_level;
121 };
122
123 /** @brief per process debug level handling */
124 int get_debug_level(void);
125 void set_local_debug_level(int level);
126 void reset_local_debug_level(void);
127
128 #define is_printable(level) (get_debug_level()>=(level))
129 extern struct log_level_info log_level_info[];
130 extern char *log_name;
131
132 #ifndef NO_SIG_DEBUG
133 /** @brief protection against "simultaneous" printing from signal handlers */
134 extern volatile int dprint_crit; 
135 #endif
136
137 int str2facility(char *s);
138 int log_facility_fixup(void *handle, str *gname, str *name, void **val);
139
140 void dprint_color(int level);
141 void dprint_color_reset(void);
142 void dprint_color_update(int level, char f, char b);
143 void dprint_init_colors(void);
144 void dprint_term_color(char f, char b, str *obuf);
145
146 /** @brief
147  * General logging macros
148  *
149  * LOG_(level, prefix, fmt, ...) prints "printf"-formatted log message to
150  * stderr (if `log_stderr' is non-zero) or to syslog.  Note that `fmt' must
151  * be constant. `prefix' is added to the beginning of the message.
152  *
153  * LOG(level, fmt, ...) is same as LOG_() with LOC_INFO prefix.
154  */
155 #ifdef NO_LOG
156
157 #       ifdef __SUNPRO_C
158 #               define LOG_(facility, level, prefix, fmt, ...)
159 #               define LOG(level, fmt, ...)
160 #               define LOG_FC(facility, level, fmt, ...)
161 #       else
162 #               define LOG_(facility, level, prefix, fmt, args...)
163 #               define LOG(level, fmt, args...)
164 #               define LOG_FC(facility, level, fmt, args...)
165 #       endif
166
167 #else
168
169 #       ifdef NO_SIG_DEBUG
170 #               define DPRINT_NON_CRIT          (1)
171 #               define DPRINT_CRIT_ENTER
172 #               define DPRINT_CRIT_EXIT
173 #       else
174 #               define DPRINT_NON_CRIT          (dprint_crit==0)
175 #               define DPRINT_CRIT_ENTER        (dprint_crit++)
176 #               define DPRINT_CRIT_EXIT         (dprint_crit--)
177 #       endif
178
179 #       ifdef __SUNPRO_C
180 #               define LOG_(facility, level, prefix, fmt, ...) \
181                         do { \
182                                 if (unlikely(get_debuglevel() >= (level) && \
183                                                 DPRINT_NON_CRIT)) { \
184                                         DPRINT_CRIT_ENTER; \
185                                         if (likely(((level) >= L_ALERT) && ((level) <= L_DBG))){ \
186                                                 if (unlikely(log_stderr)) { \
187                                                         if (unlikely(log_color)) dprint_color(level); \
188                                                         fprintf(stderr, "%2d(%d) %s: %s" fmt, \
189                                                                         process_no, my_pid(), \
190                                                                         LOG_LEVEL2NAME(level), (prefix), \
191                                                                         __VA_ARGS__); \
192                                                         if (unlikely(log_color)) dprint_color_reset(); \
193                                                 } else { \
194                                                         syslog(LOG2SYSLOG_LEVEL(level) | \
195                                                                    (((facility) != DEFAULT_FACILITY) ? \
196                                                                         (facility) : \
197                                                                         cfg_get(core, core_cfg, log_facility)), \
198                                                                         "%s: %s" fmt, LOG_LEVEL2NAME(level),\
199                                                                         (prefix), __VA_ARGS__); \
200                                                 } \
201                                         } else { \
202                                                 if (log_stderr) { \
203                                                         if (unlikely(log_color)) dprint_color(level); \
204                                                         fprintf(stderr, "%2d(%d) %s" fmt, \
205                                                                         process_no, my_pid(), \
206                                                                         (prefix),  __VA_ARGS__); \
207                                                         if (unlikely(log_color)) dprint_color_reset(); \
208                                                 } else { \
209                                                         if ((level)<L_ALERT) \
210                                                                 syslog(LOG2SYSLOG_LEVEL(L_ALERT) | \
211                                                                            (((facility) != DEFAULT_FACILITY) ? \
212                                                                                 (facility) : \
213                                                                                 cfg_get(core, core_cfg, log_facility)),\
214                                                                            "%s" fmt, (prefix), __VA_ARGS__); \
215                                                         else \
216                                                                 syslog(LOG2SYSLOG_LEVEL(L_DBG) | \
217                                                                            (((facility) != DEFAULT_FACILITY) ? \
218                                                                                 (facility) : \
219                                                                                 cfg_get(core, core_cfg, log_facility)),\
220                                                                            "%s" fmt, (prefix), __VA_ARGS__); \
221                                                 } \
222                                         } \
223                                         DPRINT_CRIT_EXIT; \
224                                 } \
225                         } while(0)
226                         
227 #               ifdef LOG_FUNC_NAME
228 #                       define LOG(level, fmt, ...) \
229         LOG_(DEFAULT_FACILITY, (level), LOC_INFO, "%s(): " fmt,\
230                                 _FUNC_NAME_, __VA_ARGS__)
231
232 #                       define LOG_FC(facility, level, fmt, ...) \
233         LOG_((facility), (level), LOC_INFO, "%s(): " fmt,\
234                                 _FUNC_NAME_, __VA_ARGS__)
235 #               else /* LOG_FUNC_NAME */
236
237 #                       define LOG(level, fmt, ...) \
238         LOG_(DEFAULT_FACILITY, (level), LOC_INFO, fmt, __VA_ARGS__)
239
240 #                       define LOG_FC(facility, level, fmt, ...) \
241         LOG_((facility), (level), LOC_INFO, fmt, __VA_ARGS__)
242
243 #               endif /* LOG_FUNC_NAME */
244
245 #       else /* ! __SUNPRO_C */
246 #               define LOG_(facility, level, prefix, fmt, args...) \
247                         do { \
248                                 if (get_debug_level() >= (level) && \
249                                                 DPRINT_NON_CRIT) { \
250                                         DPRINT_CRIT_ENTER; \
251                                         if (likely(((level) >= L_ALERT) && ((level) <= L_DBG))){ \
252                                                 if (unlikely(log_stderr)) { \
253                                                         if (unlikely(log_color)) dprint_color(level); \
254                                                         fprintf(stderr, "%2d(%d) %s: %s" fmt, \
255                                                                         process_no, my_pid(), \
256                                                                         LOG_LEVEL2NAME(level), \
257                                                                         (prefix) , ## args);\
258                                                         if (unlikely(log_color)) dprint_color_reset(); \
259                                                 } else { \
260                                                         syslog(LOG2SYSLOG_LEVEL(level) |\
261                                                                    (((facility) != DEFAULT_FACILITY) ? \
262                                                                         (facility) : \
263                                                                         cfg_get(core, core_cfg, log_facility)), \
264                                                                         "%s: %s" fmt, LOG_LEVEL2NAME(level),\
265                                                                         (prefix) , ## args); \
266                                                 } \
267                                         } else { \
268                                                 if (log_stderr) { \
269                                                         if (unlikely(log_color)) dprint_color(level); \
270                                                         fprintf(stderr, "%2d(%d) %s" fmt, \
271                                                                                 process_no, my_pid(), \
272                                                                                 (prefix) , ## args); \
273                                                         if (unlikely(log_color)) dprint_color_reset(); \
274                                                 } else { \
275                                                         if ((level)<L_ALERT) \
276                                                                 syslog(LOG2SYSLOG_LEVEL(L_ALERT) | \
277                                                                            (((facility) != DEFAULT_FACILITY) ? \
278                                                                                 (facility) : \
279                                                                                 cfg_get(core, core_cfg, log_facility)),\
280                                                                                 "%s" fmt, (prefix) , ## args); \
281                                                         else \
282                                                                 syslog(LOG2SYSLOG_LEVEL(L_DBG) | \
283                                                                            (((facility) != DEFAULT_FACILITY) ? \
284                                                                                 (facility) : \
285                                                                                 cfg_get(core, core_cfg, log_facility)),\
286                                                                                 "%s" fmt, (prefix) , ## args); \
287                                                 } \
288                                         } \
289                                         DPRINT_CRIT_EXIT; \
290                                 } \
291                         } while(0)
292                         
293 #               ifdef LOG_FUNC_NAME
294 #                       define LOG(level, fmt, args...) \
295         LOG_(DEFAULT_FACILITY, (level), LOC_INFO, "%s(): " fmt ,\
296                         _FUNC_NAME_, ## args)
297
298 #                       define LOG_FC(facility, level, fmt, args...) \
299         LOG_((facility), (level), LOC_INFO, "%s(): " fmt , _FUNC_NAME_, ## args)
300
301 #               else /* LOG_FUNC_NAME */
302 #                       define LOG(level, fmt, args...) \
303         LOG_(DEFAULT_FACILITY, (level), LOC_INFO, fmt , ## args)
304 #                       define LOG_FC(facility, level, fmt, args...) \
305         LOG_((facility), (level), LOC_INFO, fmt , ## args)
306
307 #               endif /* LOG_FUNC_NAME */
308 #       endif /* __SUNPRO_C */
309 #endif /* NO_LOG */
310
311
312 /** @name SimpleLog
313  * Simplier, prefered logging macros for constant log level
314  */
315 /*@ { */
316 #ifdef __SUNPRO_C
317 #       define ALERT(...)  LOG(L_ALERT,  __VA_ARGS__)
318 #       define BUG(...)    LOG(L_BUG,   __VA_ARGS__)
319 #       define ERR(...)    LOG(L_ERR,    __VA_ARGS__)
320 #       define WARN(...)   LOG(L_WARN,   __VA_ARGS__)
321 #       define NOTICE(...) LOG(L_NOTICE, __VA_ARGS__)
322 #       define INFO(...)   LOG(L_INFO,   __VA_ARGS__)
323 #       define CRIT(...)    LOG(L_CRIT2,   __VA_ARGS__)
324
325 #       ifdef NO_DEBUG
326 #               define DBG(...)
327 #       else
328 #               define DBG(...)    LOG(L_DBG, __VA_ARGS__)
329 #       endif           
330 /*@ } */
331
332 /* obsolete, do not use */
333 #       define DEBUG(...) DBG(__VA_ARGS__)
334
335 #else /* ! __SUNPRO_C */
336 #       define ALERT(fmt, args...)  LOG(L_ALERT,  fmt , ## args)
337 #       define BUG(fmt, args...)    LOG(L_BUG,   fmt , ## args)
338 #       define ERR(fmt, args...)    LOG(L_ERR,    fmt , ## args)
339 #       define WARN(fmt, args...)   LOG(L_WARN,   fmt , ## args)
340 #       define NOTICE(fmt, args...) LOG(L_NOTICE, fmt , ## args)
341 #       define INFO(fmt, args...)   LOG(L_INFO,   fmt , ## args)
342 #       define CRIT(fmt, args...)   LOG(L_CRIT2,   fmt , ## args)
343
344 #       ifdef NO_DEBUG
345 #               define DBG(fmt, args...)
346 #       else
347 #               define DBG(fmt, args...)    LOG(L_DBG, fmt , ## args)
348 #       endif           
349
350 /* obsolete, do not use */
351 #       define DEBUG(fmt, args...) DBG(fmt , ## args)
352                 
353 #endif /* __SUNPRO_C */
354
355
356 /* kamailio/openser compatibility */
357
358 #define LM_GEN1 LOG
359 #define LM_GEN2 LOG_FC
360 #define LM_ALERT ALERT
361 #define LM_CRIT  CRIT
362 #define LM_ERR ERR
363 #define LM_WARN WARN
364 #define LM_NOTICE NOTICE
365 #define LM_INFO INFO
366 #define LM_DBG DEBUG
367
368 #endif /* !dprint_h */