fixed pluto/scepclient out-of-tree builds
[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
33 #include <constants.h>
34 #include <defs.h>
35 #include <log.h>
36 #include <whack.h>
37
38 bool
39 log_to_stderr = FALSE, /* should log go to stderr? */
40 log_to_syslog = TRUE; /* should log go to syslog? */
41
42 void
43 init_log(const char *program)
44 {
45 if (log_to_stderr)
46 setbuf(stderr, NULL);
47 if (log_to_syslog)
48 openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
49 }
50
51 void
52 close_log(void)
53 {
54 if (log_to_syslog)
55 closelog();
56 }
57
58 void
59 plog(const char *message, ...)
60 {
61 va_list args;
62 char m[LOG_WIDTH]; /* longer messages will be truncated */
63
64 va_start(args, message);
65 vsnprintf(m, sizeof(m), message, args);
66 va_end(args);
67
68 if (log_to_stderr)
69 fprintf(stderr, "%s\n", m);
70 if (log_to_syslog)
71 syslog(LOG_WARNING, "%s", m);
72 }
73
74 void
75 loglog(int mess_no, const char *message, ...)
76 {
77 va_list args;
78 char m[LOG_WIDTH]; /* longer messages will be truncated */
79
80 va_start(args, message);
81 vsnprintf(m, sizeof(m), message, args);
82 va_end(args);
83
84 if (log_to_stderr)
85 fprintf(stderr, "%s\n", m);
86 if (log_to_syslog)
87 syslog(LOG_WARNING, "%s", m);
88 }
89
90 void
91 log_errno_routine(int e, const char *message, ...)
92 {
93 va_list args;
94 char m[LOG_WIDTH]; /* longer messages will be truncated */
95
96 va_start(args, message);
97 vsnprintf(m, sizeof(m), message, args);
98 va_end(args);
99
100 if (log_to_stderr)
101 fprintf(stderr, "ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
102 if (log_to_syslog)
103 syslog(LOG_ERR, "ERROR: %s. Errno %d: %s", m, e, strerror(e));
104 }
105
106 void
107 exit_log(const char *message, ...)
108 {
109 va_list args;
110 char m[LOG_WIDTH]; /* longer messages will be truncated */
111
112 va_start(args, message);
113 vsnprintf(m, sizeof(m), message, args);
114 va_end(args);
115
116 if (log_to_stderr)
117 fprintf(stderr, "FATAL ERROR: %s\n", m);
118 if (log_to_syslog)
119 syslog(LOG_ERR, "FATAL ERROR: %s", m);
120 exit(1);
121 }
122
123 void
124 exit_log_errno_routine(int e, const char *message, ...)
125 {
126 va_list args;
127 char m[LOG_WIDTH]; /* longer messages will be truncated */
128
129 va_start(args, message);
130 vsnprintf(m, sizeof(m), message, args);
131 va_end(args);
132
133 if (log_to_stderr)
134 fprintf(stderr, "FATAL ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
135 if (log_to_syslog)
136 syslog(LOG_ERR, "FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
137 exit(1);
138 }
139
140 void
141 whack_log(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 fprintf(stderr, "%s\n", m);
151 }
152
153 /* Build up a diagnostic in a static buffer.
154 * Although this would be a generally useful function, it is very
155 * hard to come up with a discipline that prevents different uses
156 * from interfering. It is intended that by limiting it to building
157 * diagnostics, we will avoid this problem.
158 * Juggling is performed to allow an argument to be a previous
159 * result: the new string may safely depend on the old one. This
160 * restriction is not checked in any way: violators will produce
161 * confusing results (without crashing!).
162 */
163 char diag_space[sizeof(diag_space)];
164
165 err_t
166 builddiag(const char *fmt, ...)
167 {
168 static char diag_space[LOG_WIDTH]; /* longer messages will be truncated */
169 char t[sizeof(diag_space)]; /* build result here first */
170 va_list args;
171
172 va_start(args, fmt);
173 t[0] = '\0'; /* in case nothing terminates string */
174 vsnprintf(t, sizeof(t), fmt, args);
175 va_end(args);
176 strcpy(diag_space, t);
177 return diag_space;
178 }
179
180 /* Debugging message support */
181
182 #ifdef DEBUG
183
184 void
185 switch_fail(int n, const char *file_str, unsigned long line_no)
186 {
187 char buf[30];
188
189 snprintf(buf, sizeof(buf), "case %d unexpected", n);
190 passert_fail(buf, file_str, line_no);
191 }
192
193 void
194 passert_fail(const char *pred_str, const char *file_str, unsigned long line_no)
195 {
196 /* we will get a possibly unplanned prefix. Hope it works */
197 loglog(RC_LOG_SERIOUS, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
198 abort(); /* exiting correctly doesn't always work */
199 }
200
201 lset_t
202 base_debugging = DBG_NONE, /* default to reporting nothing */
203 cur_debugging = DBG_NONE;
204
205 void
206 pexpect_log(const char *pred_str, const char *file_str, unsigned long line_no)
207 {
208 /* we will get a possibly unplanned prefix. Hope it works */
209 loglog(RC_LOG_SERIOUS, "EXPECTATION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
210 }
211
212 /* log a debugging message (prefixed by "| ") */
213
214 void
215 DBG_log(const char *message, ...)
216 {
217 va_list args;
218 char m[LOG_WIDTH]; /* longer messages will be truncated */
219
220 va_start(args, message);
221 vsnprintf(m, sizeof(m), message, args);
222 va_end(args);
223
224 if (log_to_stderr)
225 fprintf(stderr, "| %s\n", m);
226 if (log_to_syslog)
227 syslog(LOG_DEBUG, "| %s", m);
228 }
229
230 /* dump raw bytes in hex to stderr (for lack of any better destination) */
231
232 void
233 DBG_dump(const char *label, const void *p, size_t len)
234 {
235 # define DUMP_LABEL_WIDTH 20 /* arbitrary modest boundary */
236 # define DUMP_WIDTH (4 * (1 + 4 * 3) + 1)
237 char buf[DUMP_LABEL_WIDTH + DUMP_WIDTH];
238 char *bp;
239 const unsigned char *cp = p;
240
241 bp = buf;
242
243 if (label != NULL && label[0] != '\0')
244 {
245 /* Handle the label. Care must be taken to avoid buffer overrun. */
246 size_t llen = strlen(label);
247
248 if (llen + 1 > sizeof(buf))
249 {
250 DBG_log("%s", label);
251 }
252 else
253 {
254 strcpy(buf, label);
255 if (buf[llen-1] == '\n')
256 {
257 buf[llen-1] = '\0'; /* get rid of newline */
258 DBG_log("%s", buf);
259 }
260 else if (llen < DUMP_LABEL_WIDTH)
261 {
262 bp = buf + llen;
263 }
264 else
265 {
266 DBG_log("%s", buf);
267 }
268 }
269 }
270
271 do {
272 int i, j;
273
274 for (i = 0; len!=0 && i!=4; i++)
275 {
276 *bp++ = ' ';
277 for (j = 0; len!=0 && j!=4; len--, j++)
278 {
279 static const char hexdig[] = "0123456789abcdef";
280
281 *bp++ = ' ';
282 *bp++ = hexdig[(*cp >> 4) & 0xF];
283 *bp++ = hexdig[*cp & 0xF];
284 cp++;
285 }
286 }
287 *bp = '\0';
288 DBG_log("%s", buf);
289 bp = buf;
290 } while (len != 0);
291 # undef DUMP_LABEL_WIDTH
292 # undef DUMP_WIDTH
293 }
294
295 #endif /* DEBUG */