added plugin load mechanism to pluto and scepclient and improved debug output
[strongswan.git] / src / scepclient / loglite.c
1 /* error logging functions
2 * Copyright (C) 1997 Angelos D. Keromytis.
3 * Copyright (C) 1998-2001 D. Hugh Redelmeier.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * RCSID $Id: loglite.c,v 1.2 2005/07/11 18:38:16 as Exp $
16 */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <ctype.h>
21 #include <stdarg.h>
22 #include <syslog.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <signal.h> /* used only if MSG_NOSIGNAL not defined */
27 #include <libgen.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30
31 #include <freeswan.h>
32 #include <debug.h>
33
34 #include <constants.h>
35 #include <defs.h>
36 #include <log.h>
37 #include <whack.h>
38
39 bool
40 log_to_stderr = FALSE, /* should log go to stderr? */
41 log_to_syslog = TRUE; /* should log go to syslog? */
42
43 /**
44 * @brief scepclient dbg function
45 */
46 static void scepclient_dbg(int level, char *fmt, ...)
47 {
48 int priority = LOG_INFO;
49 int debug_level;
50 char buffer[8192];
51 char *current = buffer, *next;
52 va_list args;
53
54 if (cur_debugging & DBG_PRIVATE)
55 {
56 debug_level = 4;
57 }
58 else if (cur_debugging & DBG_RAW)
59 {
60 debug_level = 3;
61 }
62 else if (cur_debugging & DBG_PARSING)
63 {
64 debug_level = 2;
65 }
66 else
67 {
68 debug_level = 1;
69 }
70
71 if (level <= debug_level)
72 {
73 va_start(args, fmt);
74
75 if (log_to_stderr)
76 {
77 if (level > 1)
78 {
79 fprintf(stderr, "| ");
80 }
81 vfprintf(stderr, fmt, args);
82 fprintf(stderr, "\n");
83 }
84 if (log_to_syslog)
85 {
86 /* write in memory buffer first */
87 vsnprintf(buffer, sizeof(buffer), fmt, args);
88
89 /* do a syslog with every line */
90 while (current)
91 {
92 next = strchr(current, '\n');
93 if (next)
94 {
95 *(next++) = '\0';
96 }
97 syslog(priority, "%s%s\n", (level > 1)? "| ":"", current);
98 current = next;
99 }
100 }
101 va_end(args);
102 }
103 }
104
105 void init_log(const char *program)
106 {
107 /* enable scepclient bugging hook */
108 dbg = scepclient_dbg;
109
110 if (log_to_stderr)
111 {
112 setbuf(stderr, NULL);
113 }
114 if (log_to_syslog)
115 {
116 openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
117 }
118 }
119
120 void close_log(void)
121 {
122 if (log_to_syslog)
123 closelog();
124 }
125
126 void plog(const char *message, ...)
127 {
128 va_list args;
129 char m[LOG_WIDTH]; /* longer messages will be truncated */
130
131 va_start(args, message);
132 vsnprintf(m, sizeof(m), message, args);
133 va_end(args);
134
135 if (log_to_stderr)
136 fprintf(stderr, "%s\n", m);
137 if (log_to_syslog)
138 syslog(LOG_WARNING, "%s", m);
139 }
140
141 void loglog(int mess_no, const char *message, ...)
142 {
143 va_list args;
144 char m[LOG_WIDTH]; /* longer messages will be truncated */
145
146 va_start(args, message);
147 vsnprintf(m, sizeof(m), message, args);
148 va_end(args);
149
150 if (log_to_stderr)
151 fprintf(stderr, "%s\n", m);
152 if (log_to_syslog)
153 syslog(LOG_WARNING, "%s", m);
154 }
155
156 void log_errno_routine(int e, const char *message, ...)
157 {
158 va_list args;
159 char m[LOG_WIDTH]; /* longer messages will be truncated */
160
161 va_start(args, message);
162 vsnprintf(m, sizeof(m), message, args);
163 va_end(args);
164
165 if (log_to_stderr)
166 fprintf(stderr, "ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
167 if (log_to_syslog)
168 syslog(LOG_ERR, "ERROR: %s. Errno %d: %s", m, e, strerror(e));
169 }
170
171 void exit_log(const char *message, ...)
172 {
173 va_list args;
174 char m[LOG_WIDTH]; /* longer messages will be truncated */
175
176 va_start(args, message);
177 vsnprintf(m, sizeof(m), message, args);
178 va_end(args);
179
180 if (log_to_stderr)
181 fprintf(stderr, "FATAL ERROR: %s\n", m);
182 if (log_to_syslog)
183 syslog(LOG_ERR, "FATAL ERROR: %s", m);
184 exit(1);
185 }
186
187 void exit_log_errno_routine(int e, const char *message, ...)
188 {
189 va_list args;
190 char m[LOG_WIDTH]; /* longer messages will be truncated */
191
192 va_start(args, message);
193 vsnprintf(m, sizeof(m), message, args);
194 va_end(args);
195
196 if (log_to_stderr)
197 fprintf(stderr, "FATAL ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
198 if (log_to_syslog)
199 syslog(LOG_ERR, "FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
200 exit(1);
201 }
202
203 void whack_log(int mess_no, const char *message, ...)
204 {
205 va_list args;
206 char m[LOG_WIDTH]; /* longer messages will be truncated */
207
208 va_start(args, message);
209 vsnprintf(m, sizeof(m), message, args);
210 va_end(args);
211
212 fprintf(stderr, "%s\n", m);
213 }
214
215 /* Build up a diagnostic in a static buffer.
216 * Although this would be a generally useful function, it is very
217 * hard to come up with a discipline that prevents different uses
218 * from interfering. It is intended that by limiting it to building
219 * diagnostics, we will avoid this problem.
220 * Juggling is performed to allow an argument to be a previous
221 * result: the new string may safely depend on the old one. This
222 * restriction is not checked in any way: violators will produce
223 * confusing results (without crashing!).
224 */
225 char diag_space[sizeof(diag_space)];
226
227 err_t builddiag(const char *fmt, ...)
228 {
229 static char diag_space[LOG_WIDTH]; /* longer messages will be truncated */
230 char t[sizeof(diag_space)]; /* build result here first */
231 va_list args;
232
233 va_start(args, fmt);
234 t[0] = '\0'; /* in case nothing terminates string */
235 vsnprintf(t, sizeof(t), fmt, args);
236 va_end(args);
237 strcpy(diag_space, t);
238 return diag_space;
239 }
240
241 /* Debugging message support */
242
243 #ifdef DEBUG
244
245 void switch_fail(int n, const char *file_str, unsigned long line_no)
246 {
247 char buf[30];
248
249 snprintf(buf, sizeof(buf), "case %d unexpected", n);
250 passert_fail(buf, file_str, line_no);
251 }
252
253 void passert_fail(const char *pred_str, const char *file_str, unsigned long line_no)
254 {
255 /* we will get a possibly unplanned prefix. Hope it works */
256 loglog(RC_LOG_SERIOUS, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
257 abort(); /* exiting correctly doesn't always work */
258 }
259
260 lset_t
261 base_debugging = DBG_NONE, /* default to reporting nothing */
262 cur_debugging = DBG_NONE;
263
264 void pexpect_log(const char *pred_str, const char *file_str, unsigned long line_no)
265 {
266 /* we will get a possibly unplanned prefix. Hope it works */
267 loglog(RC_LOG_SERIOUS, "EXPECTATION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
268 }
269
270 /* log a debugging message (prefixed by "| ") */
271
272 void DBG_log(const char *message, ...)
273 {
274 va_list args;
275 char m[LOG_WIDTH]; /* longer messages will be truncated */
276
277 va_start(args, message);
278 vsnprintf(m, sizeof(m), message, args);
279 va_end(args);
280
281 if (log_to_stderr)
282 fprintf(stderr, "| %s\n", m);
283 if (log_to_syslog)
284 syslog(LOG_DEBUG, "| %s", m);
285 }
286
287 /* dump raw bytes in hex to stderr (for lack of any better destination) */
288
289 void DBG_dump(const char *label, const void *p, size_t len)
290 {
291 # define DUMP_LABEL_WIDTH 20 /* arbitrary modest boundary */
292 # define DUMP_WIDTH (4 * (1 + 4 * 3) + 1)
293 char buf[DUMP_LABEL_WIDTH + DUMP_WIDTH];
294 char *bp;
295 const unsigned char *cp = p;
296
297 bp = buf;
298
299 if (label != NULL && label[0] != '\0')
300 {
301 /* Handle the label. Care must be taken to avoid buffer overrun. */
302 size_t llen = strlen(label);
303
304 if (llen + 1 > sizeof(buf))
305 {
306 DBG_log("%s", label);
307 }
308 else
309 {
310 strcpy(buf, label);
311 if (buf[llen-1] == '\n')
312 {
313 buf[llen-1] = '\0'; /* get rid of newline */
314 DBG_log("%s", buf);
315 }
316 else if (llen < DUMP_LABEL_WIDTH)
317 {
318 bp = buf + llen;
319 }
320 else
321 {
322 DBG_log("%s", buf);
323 }
324 }
325 }
326
327 do {
328 int i, j;
329
330 for (i = 0; len!=0 && i!=4; i++)
331 {
332 *bp++ = ' ';
333 for (j = 0; len!=0 && j!=4; len--, j++)
334 {
335 static const char hexdig[] = "0123456789abcdef";
336
337 *bp++ = ' ';
338 *bp++ = hexdig[(*cp >> 4) & 0xF];
339 *bp++ = hexdig[*cp & 0xF];
340 cp++;
341 }
342 }
343 *bp = '\0';
344 DBG_log("%s", buf);
345 bp = buf;
346 } while (len != 0);
347 # undef DUMP_LABEL_WIDTH
348 # undef DUMP_WIDTH
349 }
350
351 #endif /* DEBUG */