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