No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / heimdal / lib / krb5 / log.c
blob83b57e5ceb6de2443f50ea12e590cf44bf010342
1 /*
2 * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "krb5_locl.h"
36 __RCSID("$Heimdal: log.c 19088 2006-11-21 08:08:46Z lha $"
37 "$NetBSD$");
39 struct facility {
40 int min;
41 int max;
42 krb5_log_log_func_t log_func;
43 krb5_log_close_func_t close_func;
44 void *data;
47 static struct facility*
48 log_realloc(krb5_log_facility *f)
50 struct facility *fp;
51 fp = realloc(f->val, (f->len + 1) * sizeof(*f->val));
52 if(fp == NULL)
53 return NULL;
54 f->len++;
55 f->val = fp;
56 fp += f->len - 1;
57 return fp;
60 struct s2i {
61 const char *s;
62 int val;
65 #define L(X) { #X, LOG_ ## X }
67 static struct s2i syslogvals[] = {
68 L(EMERG),
69 L(ALERT),
70 L(CRIT),
71 L(ERR),
72 L(WARNING),
73 L(NOTICE),
74 L(INFO),
75 L(DEBUG),
77 L(AUTH),
78 #ifdef LOG_AUTHPRIV
79 L(AUTHPRIV),
80 #endif
81 #ifdef LOG_CRON
82 L(CRON),
83 #endif
84 L(DAEMON),
85 #ifdef LOG_FTP
86 L(FTP),
87 #endif
88 L(KERN),
89 L(LPR),
90 L(MAIL),
91 #ifdef LOG_NEWS
92 L(NEWS),
93 #endif
94 L(SYSLOG),
95 L(USER),
96 #ifdef LOG_UUCP
97 L(UUCP),
98 #endif
99 L(LOCAL0),
100 L(LOCAL1),
101 L(LOCAL2),
102 L(LOCAL3),
103 L(LOCAL4),
104 L(LOCAL5),
105 L(LOCAL6),
106 L(LOCAL7),
107 { NULL, -1 }
110 static int
111 find_value(const char *s, struct s2i *table)
113 while(table->s && strcasecmp(table->s, s))
114 table++;
115 return table->val;
118 krb5_error_code KRB5_LIB_FUNCTION
119 krb5_initlog(krb5_context context,
120 const char *program,
121 krb5_log_facility **fac)
123 krb5_log_facility *f = calloc(1, sizeof(*f));
124 if(f == NULL) {
125 krb5_set_error_string (context, "malloc: out of memory");
126 return ENOMEM;
128 f->program = strdup(program);
129 if(f->program == NULL){
130 free(f);
131 krb5_set_error_string (context, "malloc: out of memory");
132 return ENOMEM;
134 *fac = f;
135 return 0;
138 krb5_error_code KRB5_LIB_FUNCTION
139 krb5_addlog_func(krb5_context context,
140 krb5_log_facility *fac,
141 int min,
142 int max,
143 krb5_log_log_func_t log_func,
144 krb5_log_close_func_t close_func,
145 void *data)
147 struct facility *fp = log_realloc(fac);
148 if(fp == NULL) {
149 krb5_set_error_string (context, "malloc: out of memory");
150 return ENOMEM;
152 fp->min = min;
153 fp->max = max;
154 fp->log_func = log_func;
155 fp->close_func = close_func;
156 fp->data = data;
157 return 0;
161 struct _heimdal_syslog_data{
162 int priority;
165 static void
166 log_syslog(const char *timestr,
167 const char *msg,
168 void *data)
171 struct _heimdal_syslog_data *s = data;
172 syslog(s->priority, "%s", msg);
175 static void
176 close_syslog(void *data)
178 free(data);
179 closelog();
182 static krb5_error_code
183 open_syslog(krb5_context context,
184 krb5_log_facility *facility, int min, int max,
185 const char *sev, const char *fac)
187 struct _heimdal_syslog_data *sd = malloc(sizeof(*sd));
188 int i;
190 if(sd == NULL) {
191 krb5_set_error_string (context, "malloc: out of memory");
192 return ENOMEM;
194 i = find_value(sev, syslogvals);
195 if(i == -1)
196 i = LOG_ERR;
197 sd->priority = i;
198 i = find_value(fac, syslogvals);
199 if(i == -1)
200 i = LOG_AUTH;
201 sd->priority |= i;
202 roken_openlog(facility->program, LOG_PID | LOG_NDELAY, i);
203 return krb5_addlog_func(context, facility, min, max,
204 log_syslog, close_syslog, sd);
207 struct file_data{
208 const char *filename;
209 const char *mode;
210 FILE *fd;
211 int keep_open;
214 static void
215 log_file(const char *timestr,
216 const char *msg,
217 void *data)
219 struct file_data *f = data;
220 if(f->keep_open == 0)
221 f->fd = fopen(f->filename, f->mode);
222 if(f->fd == NULL)
223 return;
224 fprintf(f->fd, "%s %s\n", timestr, msg);
225 if(f->keep_open == 0) {
226 fclose(f->fd);
227 f->fd = NULL;
231 static void
232 close_file(void *data)
234 struct file_data *f = data;
235 if(f->keep_open && f->filename)
236 fclose(f->fd);
237 free(data);
240 static krb5_error_code
241 open_file(krb5_context context, krb5_log_facility *fac, int min, int max,
242 const char *filename, const char *mode, FILE *f, int keep_open)
244 struct file_data *fd = malloc(sizeof(*fd));
245 if(fd == NULL) {
246 krb5_set_error_string (context, "malloc: out of memory");
247 return ENOMEM;
249 fd->filename = filename;
250 fd->mode = mode;
251 fd->fd = f;
252 fd->keep_open = keep_open;
254 return krb5_addlog_func(context, fac, min, max, log_file, close_file, fd);
259 krb5_error_code KRB5_LIB_FUNCTION
260 krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig)
262 krb5_error_code ret = 0;
263 int min = 0, max = -1, n;
264 char c;
265 const char *p = orig;
267 n = sscanf(p, "%d%c%d/", &min, &c, &max);
268 if(n == 2){
269 if(c == '/') {
270 if(min < 0){
271 max = -min;
272 min = 0;
273 }else{
274 max = min;
278 if(n){
279 p = strchr(p, '/');
280 if(p == NULL) {
281 krb5_set_error_string (context, "failed to parse \"%s\"", orig);
282 return HEIM_ERR_LOG_PARSE;
284 p++;
286 if(strcmp(p, "STDERR") == 0){
287 ret = open_file(context, f, min, max, NULL, NULL, stderr, 1);
288 }else if(strcmp(p, "CONSOLE") == 0){
289 ret = open_file(context, f, min, max, "/dev/console", "w", NULL, 0);
290 }else if(strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')){
291 char *fn;
292 FILE *file = NULL;
293 int keep_open = 0;
294 fn = strdup(p + 5);
295 if(fn == NULL) {
296 krb5_set_error_string (context, "malloc: out of memory");
297 return ENOMEM;
299 if(p[4] == '='){
300 int i = open(fn, O_WRONLY | O_CREAT |
301 O_TRUNC | O_APPEND, 0666);
302 if(i < 0) {
303 ret = errno;
304 krb5_set_error_string (context, "open(%s): %s", fn,
305 strerror(ret));
306 free(fn);
307 return ret;
309 file = fdopen(i, "a");
310 if(file == NULL){
311 ret = errno;
312 close(i);
313 krb5_set_error_string (context, "fdopen(%s): %s", fn,
314 strerror(ret));
315 free(fn);
316 return ret;
318 keep_open = 1;
320 ret = open_file(context, f, min, max, fn, "a", file, keep_open);
321 }else if(strncmp(p, "DEVICE", 6) == 0 && (p[6] == ':' || p[6] == '=')){
322 ret = open_file(context, f, min, max, strdup(p + 7), "w", NULL, 0);
323 }else if(strncmp(p, "SYSLOG", 6) == 0 && (p[6] == '\0' || p[6] == ':')){
324 char severity[128] = "";
325 char facility[128] = "";
326 p += 6;
327 if(*p != '\0')
328 p++;
329 if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1)
330 strsep_copy(&p, ":", facility, sizeof(facility));
331 if(*severity == '\0')
332 strlcpy(severity, "ERR", sizeof(severity));
333 if(*facility == '\0')
334 strlcpy(facility, "AUTH", sizeof(facility));
335 ret = open_syslog(context, f, min, max, severity, facility);
336 }else{
337 krb5_set_error_string (context, "unknown log type: %s", p);
338 ret = HEIM_ERR_LOG_PARSE; /* XXX */
340 return ret;
344 krb5_error_code KRB5_LIB_FUNCTION
345 krb5_openlog(krb5_context context,
346 const char *program,
347 krb5_log_facility **fac)
349 krb5_error_code ret;
350 char **p, **q;
352 ret = krb5_initlog(context, program, fac);
353 if(ret)
354 return ret;
356 p = krb5_config_get_strings(context, NULL, "logging", program, NULL);
357 if(p == NULL)
358 p = krb5_config_get_strings(context, NULL, "logging", "default", NULL);
359 if(p){
360 for(q = p; *q; q++)
361 ret = krb5_addlog_dest(context, *fac, *q);
362 krb5_config_free_strings(p);
363 }else
364 ret = krb5_addlog_dest(context, *fac, "SYSLOG");
365 return 0;
368 krb5_error_code KRB5_LIB_FUNCTION
369 krb5_closelog(krb5_context context,
370 krb5_log_facility *fac)
372 int i;
373 for(i = 0; i < fac->len; i++)
374 (*fac->val[i].close_func)(fac->val[i].data);
375 free(fac->val);
376 free(fac->program);
377 fac->val = NULL;
378 fac->len = 0;
379 fac->program = NULL;
380 free(fac);
381 return 0;
384 #undef __attribute__
385 #define __attribute__(X)
387 krb5_error_code KRB5_LIB_FUNCTION
388 krb5_vlog_msg(krb5_context context,
389 krb5_log_facility *fac,
390 char **reply,
391 int level,
392 const char *fmt,
393 va_list ap)
394 __attribute__((format (printf, 5, 0)))
397 char *msg = NULL;
398 const char *actual = NULL;
399 char buf[64];
400 time_t t = 0;
401 int i;
403 for(i = 0; fac && i < fac->len; i++)
404 if(fac->val[i].min <= level &&
405 (fac->val[i].max < 0 || fac->val[i].max >= level)) {
406 if(t == 0) {
407 t = time(NULL);
408 krb5_format_time(context, t, buf, sizeof(buf), TRUE);
410 if(actual == NULL) {
411 vasprintf(&msg, fmt, ap);
412 if(msg == NULL)
413 actual = fmt;
414 else
415 actual = msg;
417 (*fac->val[i].log_func)(buf, actual, fac->val[i].data);
419 if(reply == NULL)
420 free(msg);
421 else
422 *reply = msg;
423 return 0;
426 krb5_error_code KRB5_LIB_FUNCTION
427 krb5_vlog(krb5_context context,
428 krb5_log_facility *fac,
429 int level,
430 const char *fmt,
431 va_list ap)
432 __attribute__((format (printf, 4, 0)))
434 return krb5_vlog_msg(context, fac, NULL, level, fmt, ap);
437 krb5_error_code KRB5_LIB_FUNCTION
438 krb5_log_msg(krb5_context context,
439 krb5_log_facility *fac,
440 int level,
441 char **reply,
442 const char *fmt,
443 ...)
444 __attribute__((format (printf, 5, 6)))
446 va_list ap;
447 krb5_error_code ret;
449 va_start(ap, fmt);
450 ret = krb5_vlog_msg(context, fac, reply, level, fmt, ap);
451 va_end(ap);
452 return ret;
456 krb5_error_code KRB5_LIB_FUNCTION
457 krb5_log(krb5_context context,
458 krb5_log_facility *fac,
459 int level,
460 const char *fmt,
461 ...)
462 __attribute__((format (printf, 4, 5)))
464 va_list ap;
465 krb5_error_code ret;
467 va_start(ap, fmt);
468 ret = krb5_vlog(context, fac, level, fmt, ap);
469 va_end(ap);
470 return ret;