1 /* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*-
2  *
3  * librsync -- generate and apply network deltas
4  *
5  * Copyright (C) 2000, 2001, 2002, 2003, 2004 by Martin Pool
6  * Copyright 2007 Google Inc.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 /**
25  * @file
26  *
27  * Reusable trace library.
28  *
29  * @todo A function like perror that includes strerror output.  Apache
30  * does this by adding flags as well as the severity level which say
31  * whether such information should be included.
32  *
33  * @todo Also check in configure for the C9X predefined identifier `_function', or
34  * whatever it's called.
35  **/
36 
37 /* Provide simple macro statement wrappers (adapted from glib, and originally from Perl):
38  *  RS_STMT_START { statements; } RS_STMT_END;
39  *  can be used as a single statement, as in
40  *  if (x) RS_STMT_START { ... } RS_STMT_END; else ...
41  *
42  *  For gcc we will wrap the statements within `({' and `})' braces.
43  *  For SunOS they will be wrapped within `if (1)' and `else (void) 0',
44  *  and otherwise within `do' and `while (0)'.
45  */
46 #if !(defined (RS_STMT_START) && defined (RS_STMT_END))
47 #  if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
48 #    define RS_STMT_START    (void)(
49 #    define RS_STMT_END        )
50 #  else
51 #    if (defined (sun) || defined (__sun__))
52 #      define RS_STMT_START    if (1)
53 #      define RS_STMT_END    else (void)0
54 #    else
55 #      define RS_STMT_START    do
56 #      define RS_STMT_END    while (0)
57 #    endif
58 #  endif
59 #endif
60 
61 
62 #include <stdarg.h>
63 
64 /* unconditionally on */
65 #define DO_RS_TRACE
66 
67 /**
68  * Log severity levels.
69  *
70  * These have the same numeric values as the levels for syslog, at
71  * least in glibc.
72  *
73  * Trace may be turned off.
74  *
75  * Error is always on, but you can return and continue in some way.
76  */
77 typedef enum {
78     RS_LOG_EMERG         = 0,   /**< System is unusable */
79     RS_LOG_ALERT         = 1,   /**< Action must be taken immediately */
80     RS_LOG_CRIT          = 2,   /**< Critical conditions */
81     RS_LOG_ERR           = 3,   /**< Error conditions */
82     RS_LOG_WARNING       = 4,   /**< Warning conditions */
83     RS_LOG_NOTICE        = 5,   /**< Normal but significant condition */
84     RS_LOG_INFO          = 6,   /**< Informational */
85     RS_LOG_DEBUG         = 7    /**< Debug-level messages */
86 } rs_loglevel;
87 
88 int rs_loglevel_from_name(const char *name);
89 
90 enum {
91     RS_LOG_PRIMASK       = 7,   /**< Mask to extract priority
92                                    part. \internal */
93 
94     RS_LOG_NONAME        = 8,   /**< \b Don't show function name in
95                                    message. */
96 
97     RS_LOG_NO_PROGRAM   = 16,
98     RS_LOG_NO_PID       = 32
99 };
100 
101 
102 /**
103  * \typedef rs_logger_fn
104  * \brief Callback to write out log messages.
105  * \param level a syslog level.
106  * \param msg message to be logged.
107  *
108  * \param private Opaque data passed in when logger was added.  For
109  * example, pointer to file descriptor.
110  */
111 typedef void    rs_logger_fn(int flags, const char *fn,
112                               char const *msg, va_list,
113                               void *private_ptr, int private_int);
114 
115 void rs_format_msg(char *buf, size_t, int, const char *,
116                    const char *fmt, va_list);
117 
118 void            rs_trace_set_level(rs_loglevel level);
119 
120 void rs_add_logger(rs_logger_fn *, int level, void *, int);
121 void rs_remove_logger(rs_logger_fn *, int level, void *, int);
122 void rs_remove_all_loggers(void);
123 
124 
125 void rs_logger_file(int level, const char *fn, char const *fmt, va_list va,
126                     void *, int);
127 
128 void rs_logger_syslog(int level, const char *fn, char const *fmt, va_list va,
129                       void *, int);
130 
131 /** Check whether the library was compiled with debugging trace support. */
132 int             rs_supports_trace(void);
133 
134 void rs_log0(int level, char const *fn, char const *fmt, ...)
135 #if defined(__GNUC__)
136     __attribute__ ((format(printf, 3, 4)))
137 #endif /* __GNUC__ */
138   ;
139 
140 
141   /* TODO: Check for the __FUNCTION__ thing, rather than gnuc */
142 #if defined(HAVE_VARARG_MACROS)  && defined(__GNUC__)
143 
144 #if 1 || defined(DO_RS_TRACE)
145 #  define rs_trace(fmt, arg...)                            \
146     do { rs_log0(RS_LOG_DEBUG, __FUNCTION__, fmt , ##arg);  \
147     } while (0)
148 #else
149 #  define rs_trace(s, str...)
150 #endif    /* !DO_RS_TRACE */
151 
152 #define rs_log(l, s, str...) do {              \
153      rs_log0((l), __FUNCTION__, (s) , ##str);  \
154      } while (0)
155 
156 
157 #define rs_log_crit(s, str...) do {                         \
158      rs_log0(RS_LOG_CRIT,  __FUNCTION__, (s) , ##str);          \
159      } while (0)
160 
161 #define rs_log_error(s, str...) do {                            \
162      rs_log0(RS_LOG_ERR,  __FUNCTION__, (s) , ##str);           \
163      } while (0)
164 
165 #define rs_log_notice(s, str...) do {                           \
166      rs_log0(RS_LOG_NOTICE,  __FUNCTION__, (s) , ##str);        \
167      } while (0)
168 
169 #define rs_log_warning(s, str...) do {                          \
170      rs_log0(RS_LOG_WARNING,  __FUNCTION__, (s) , ##str);       \
171      } while (0)
172 
173 #define rs_log_info(s, str...) do {                             \
174      rs_log0(RS_LOG_INFO,  __FUNCTION__, (s) , ##str);          \
175      } while (0)
176 
177 #else /* not defined HAVE_VARARG_MACROS */
178 
179 /* If we don't have gcc vararg macros, then we fall back to making the
180  * log routines just plain functions.  On platforms without gcc (boo
181  * hiss!) this means at least you get some messages, but not the nice
182  * function names etc. */
183 #define rs_log rs_log0_nofn
184 
185 #define rs_trace        rs_log_trace_nofn
186 #define rs_log_info     rs_log_info_nofn
187 #define rs_log_notice   rs_log_notice_nofn
188 #define rs_log_warning  rs_log_warning_nofn
189 #define rs_log_error    rs_log_error_nofn
190 #define rs_log_crit     rs_log_critical_nofn
191 #endif /* HAVE_VARARG_MACROS */
192 
193 
194 
195 void rs_log_trace_nofn(char const *s, ...);
196 void rs_log_info_nofn(char const *, ...);
197 void rs_log_notice_nofn(char const *, ...);
198 void rs_log_warning_nofn(char const *s, ...);
199 void rs_log_error_nofn(char const *s, ...);
200 void rs_log_critical_nofn(char const *, ...);
201 
202 void rs_log0_nofn(int level, char const *fmt, ...);
203 
204 
205 
206 /**
207  * \macro rs_trace_enabled()
208  *
209  * Call this before putting too much effort into generating trace
210  * messages.
211  */
212 
213 /* really bool */
214 extern int rs_trace_syslog;
215 extern int rs_trace_level;
216 
217 #ifdef DO_RS_TRACE
218 #  define rs_trace_enabled() ((rs_trace_level & RS_LOG_PRIMASK) >= RS_LOG_DEBUG)
219 #else
220 #  define rs_trace_enabled() 0
221 #endif
222 
223 /**
224  * Name of the program, to be included in log messages.
225  *
226  * @note This must be defined exactly once in each program that links to
227  * trace.c
228  **/
229 extern const char *rs_program_name;
230 
231 void dcc_job_summary_clear(void);
232 void dcc_job_summary(void);
233 void dcc_job_summary_append(const char *s);
234