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