xref: /freebsd-src/crypto/heimdal/lib/krb5/log.c (revision 0cadf2f4d7b9f212800448d915003abd40c2e40d)
1b528cefcSMark Murray /*
28373020dSJacques Vidrine  * Copyright (c) 1997-2002 Kungliga Tekniska H�gskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34b528cefcSMark Murray #include "krb5_locl.h"
35b528cefcSMark Murray 
36*0cadf2f4SJacques Vidrine RCSID("$Id: log.c,v 1.31 2002/09/05 14:59:14 joda Exp $");
37b528cefcSMark Murray 
38b528cefcSMark Murray struct facility {
39b528cefcSMark Murray     int min;
40b528cefcSMark Murray     int max;
41b528cefcSMark Murray     krb5_log_log_func_t log;
42b528cefcSMark Murray     krb5_log_close_func_t close;
43b528cefcSMark Murray     void *data;
44b528cefcSMark Murray };
45b528cefcSMark Murray 
46b528cefcSMark Murray static struct facility*
47b528cefcSMark Murray log_realloc(krb5_log_facility *f)
48b528cefcSMark Murray {
49b528cefcSMark Murray     struct facility *fp;
50b528cefcSMark Murray     f->len++;
51b528cefcSMark Murray     fp = realloc(f->val, f->len * sizeof(*f->val));
52b528cefcSMark Murray     if(fp == NULL)
53b528cefcSMark Murray 	return NULL;
54b528cefcSMark Murray     f->val = fp;
55b528cefcSMark Murray     fp += f->len - 1;
56b528cefcSMark Murray     return fp;
57b528cefcSMark Murray }
58b528cefcSMark Murray 
59b528cefcSMark Murray struct s2i {
608373020dSJacques Vidrine     const char *s;
61b528cefcSMark Murray     int val;
62b528cefcSMark Murray };
63b528cefcSMark Murray 
64b528cefcSMark Murray #define L(X) { #X, LOG_ ## X }
65b528cefcSMark Murray 
665e9cd1aeSAssar Westerlund static struct s2i syslogvals[] = {
67b528cefcSMark Murray     L(EMERG),
68b528cefcSMark Murray     L(ALERT),
69b528cefcSMark Murray     L(CRIT),
70b528cefcSMark Murray     L(ERR),
71b528cefcSMark Murray     L(WARNING),
72b528cefcSMark Murray     L(NOTICE),
73b528cefcSMark Murray     L(INFO),
74b528cefcSMark Murray     L(DEBUG),
75b528cefcSMark Murray 
76b528cefcSMark Murray     L(AUTH),
77b528cefcSMark Murray #ifdef LOG_AUTHPRIV
78b528cefcSMark Murray     L(AUTHPRIV),
79b528cefcSMark Murray #endif
80b528cefcSMark Murray #ifdef LOG_CRON
81b528cefcSMark Murray     L(CRON),
82b528cefcSMark Murray #endif
83b528cefcSMark Murray     L(DAEMON),
84b528cefcSMark Murray #ifdef LOG_FTP
85b528cefcSMark Murray     L(FTP),
86b528cefcSMark Murray #endif
87b528cefcSMark Murray     L(KERN),
88b528cefcSMark Murray     L(LPR),
89b528cefcSMark Murray     L(MAIL),
90b528cefcSMark Murray #ifdef LOG_NEWS
91b528cefcSMark Murray     L(NEWS),
92b528cefcSMark Murray #endif
93b528cefcSMark Murray     L(SYSLOG),
94b528cefcSMark Murray     L(USER),
95b528cefcSMark Murray #ifdef LOG_UUCP
96b528cefcSMark Murray     L(UUCP),
97b528cefcSMark Murray #endif
98b528cefcSMark Murray     L(LOCAL0),
99b528cefcSMark Murray     L(LOCAL1),
100b528cefcSMark Murray     L(LOCAL2),
101b528cefcSMark Murray     L(LOCAL3),
102b528cefcSMark Murray     L(LOCAL4),
103b528cefcSMark Murray     L(LOCAL5),
104b528cefcSMark Murray     L(LOCAL6),
105b528cefcSMark Murray     L(LOCAL7),
106b528cefcSMark Murray     { NULL, -1 }
107b528cefcSMark Murray };
108b528cefcSMark Murray 
109b528cefcSMark Murray static int
110b528cefcSMark Murray find_value(const char *s, struct s2i *table)
111b528cefcSMark Murray {
112b528cefcSMark Murray     while(table->s && strcasecmp(table->s, s))
113b528cefcSMark Murray 	table++;
114b528cefcSMark Murray     return table->val;
115b528cefcSMark Murray }
116b528cefcSMark Murray 
117b528cefcSMark Murray krb5_error_code
118b528cefcSMark Murray krb5_initlog(krb5_context context,
119b528cefcSMark Murray 	     const char *program,
120b528cefcSMark Murray 	     krb5_log_facility **fac)
121b528cefcSMark Murray {
122b528cefcSMark Murray     krb5_log_facility *f = calloc(1, sizeof(*f));
123adb0ddaeSAssar Westerlund     if(f == NULL) {
124adb0ddaeSAssar Westerlund 	krb5_set_error_string (context, "malloc: out of memory");
125b528cefcSMark Murray 	return ENOMEM;
126adb0ddaeSAssar Westerlund     }
127b528cefcSMark Murray     f->program = strdup(program);
128b528cefcSMark Murray     if(f->program == NULL){
129b528cefcSMark Murray 	free(f);
130adb0ddaeSAssar Westerlund 	krb5_set_error_string (context, "malloc: out of memory");
131b528cefcSMark Murray 	return ENOMEM;
132b528cefcSMark Murray     }
133b528cefcSMark Murray     *fac = f;
134b528cefcSMark Murray     return 0;
135b528cefcSMark Murray }
136b528cefcSMark Murray 
137b528cefcSMark Murray krb5_error_code
138b528cefcSMark Murray krb5_addlog_func(krb5_context context,
139b528cefcSMark Murray 		 krb5_log_facility *fac,
140b528cefcSMark Murray 		 int min,
141b528cefcSMark Murray 		 int max,
142b528cefcSMark Murray 		 krb5_log_log_func_t log,
143b528cefcSMark Murray 		 krb5_log_close_func_t close,
144b528cefcSMark Murray 		 void *data)
145b528cefcSMark Murray {
146b528cefcSMark Murray     struct facility *fp = log_realloc(fac);
147adb0ddaeSAssar Westerlund     if(fp == NULL) {
148adb0ddaeSAssar Westerlund 	krb5_set_error_string (context, "malloc: out of memory");
149b528cefcSMark Murray 	return ENOMEM;
150adb0ddaeSAssar Westerlund     }
151b528cefcSMark Murray     fp->min = min;
152b528cefcSMark Murray     fp->max = max;
153b528cefcSMark Murray     fp->log = log;
154b528cefcSMark Murray     fp->close = close;
155b528cefcSMark Murray     fp->data = data;
156b528cefcSMark Murray     return 0;
157b528cefcSMark Murray }
158b528cefcSMark Murray 
159b528cefcSMark Murray 
1608373020dSJacques Vidrine struct _heimdal_syslog_data{
161b528cefcSMark Murray     int priority;
162b528cefcSMark Murray };
163b528cefcSMark Murray 
164b528cefcSMark Murray static void
165b528cefcSMark Murray log_syslog(const char *time,
166b528cefcSMark Murray 	   const char *msg,
167b528cefcSMark Murray 	   void *data)
168b528cefcSMark Murray 
169b528cefcSMark Murray {
1708373020dSJacques Vidrine     struct _heimdal_syslog_data *s = data;
171b528cefcSMark Murray     syslog(s->priority, "%s", msg);
172b528cefcSMark Murray }
173b528cefcSMark Murray 
174b528cefcSMark Murray static void
175b528cefcSMark Murray close_syslog(void *data)
176b528cefcSMark Murray {
177b528cefcSMark Murray     free(data);
178b528cefcSMark Murray     closelog();
179b528cefcSMark Murray }
180b528cefcSMark Murray 
181b528cefcSMark Murray static krb5_error_code
182b528cefcSMark Murray open_syslog(krb5_context context,
183b528cefcSMark Murray 	    krb5_log_facility *facility, int min, int max,
184b528cefcSMark Murray 	    const char *sev, const char *fac)
185b528cefcSMark Murray {
1868373020dSJacques Vidrine     struct _heimdal_syslog_data *sd = malloc(sizeof(*sd));
187b528cefcSMark Murray     int i;
188b528cefcSMark Murray 
189adb0ddaeSAssar Westerlund     if(sd == NULL) {
190adb0ddaeSAssar Westerlund 	krb5_set_error_string (context, "malloc: out of memory");
191b528cefcSMark Murray 	return ENOMEM;
192adb0ddaeSAssar Westerlund     }
193b528cefcSMark Murray     i = find_value(sev, syslogvals);
194b528cefcSMark Murray     if(i == -1)
195b528cefcSMark Murray 	i = LOG_ERR;
196b528cefcSMark Murray     sd->priority = i;
197b528cefcSMark Murray     i = find_value(fac, syslogvals);
198b528cefcSMark Murray     if(i == -1)
199b528cefcSMark Murray 	i = LOG_AUTH;
200b528cefcSMark Murray     sd->priority |= i;
201b528cefcSMark Murray     roken_openlog(facility->program, LOG_PID | LOG_NDELAY, i);
202b528cefcSMark Murray     return krb5_addlog_func(context, facility, min, max,
203b528cefcSMark Murray 			    log_syslog, close_syslog, sd);
204b528cefcSMark Murray }
205b528cefcSMark Murray 
206b528cefcSMark Murray struct file_data{
2078373020dSJacques Vidrine     const char *filename;
2088373020dSJacques Vidrine     const char *mode;
209b528cefcSMark Murray     FILE *fd;
210b528cefcSMark Murray     int keep_open;
211b528cefcSMark Murray };
212b528cefcSMark Murray 
213b528cefcSMark Murray static void
214b528cefcSMark Murray log_file(const char *time,
215b528cefcSMark Murray 	 const char *msg,
216b528cefcSMark Murray 	 void *data)
217b528cefcSMark Murray {
218b528cefcSMark Murray     struct file_data *f = data;
219b528cefcSMark Murray     if(f->keep_open == 0)
220b528cefcSMark Murray 	f->fd = fopen(f->filename, f->mode);
221b528cefcSMark Murray     if(f->fd == NULL)
222b528cefcSMark Murray 	return;
223b528cefcSMark Murray     fprintf(f->fd, "%s %s\n", time, msg);
224b528cefcSMark Murray     if(f->keep_open == 0)
225b528cefcSMark Murray 	fclose(f->fd);
226b528cefcSMark Murray }
227b528cefcSMark Murray 
228b528cefcSMark Murray static void
229b528cefcSMark Murray close_file(void *data)
230b528cefcSMark Murray {
231b528cefcSMark Murray     struct file_data *f = data;
232b528cefcSMark Murray     if(f->keep_open && f->filename)
233b528cefcSMark Murray 	fclose(f->fd);
234b528cefcSMark Murray     free(data);
235b528cefcSMark Murray }
236b528cefcSMark Murray 
237b528cefcSMark Murray static krb5_error_code
238b528cefcSMark Murray open_file(krb5_context context, krb5_log_facility *fac, int min, int max,
2398373020dSJacques Vidrine 	  const char *filename, const char *mode, FILE *f, int keep_open)
240b528cefcSMark Murray {
241b528cefcSMark Murray     struct file_data *fd = malloc(sizeof(*fd));
242adb0ddaeSAssar Westerlund     if(fd == NULL) {
243adb0ddaeSAssar Westerlund 	krb5_set_error_string (context, "malloc: out of memory");
244b528cefcSMark Murray 	return ENOMEM;
245adb0ddaeSAssar Westerlund     }
246b528cefcSMark Murray     fd->filename = filename;
247b528cefcSMark Murray     fd->mode = mode;
248b528cefcSMark Murray     fd->fd = f;
249b528cefcSMark Murray     fd->keep_open = keep_open;
250b528cefcSMark Murray 
251b528cefcSMark Murray     return krb5_addlog_func(context, fac, min, max, log_file, close_file, fd);
252b528cefcSMark Murray }
253b528cefcSMark Murray 
254b528cefcSMark Murray 
255b528cefcSMark Murray 
256b528cefcSMark Murray krb5_error_code
257adb0ddaeSAssar Westerlund krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig)
258b528cefcSMark Murray {
259b528cefcSMark Murray     krb5_error_code ret = 0;
260b528cefcSMark Murray     int min = 0, max = -1, n;
261b528cefcSMark Murray     char c;
262adb0ddaeSAssar Westerlund     const char *p = orig;
263adb0ddaeSAssar Westerlund 
264b528cefcSMark Murray     n = sscanf(p, "%d%c%d/", &min, &c, &max);
265b528cefcSMark Murray     if(n == 2){
266b528cefcSMark Murray 	if(c == '/') {
267b528cefcSMark Murray 	    if(min < 0){
268b528cefcSMark Murray 		max = -min;
269b528cefcSMark Murray 		min = 0;
270b528cefcSMark Murray 	    }else{
271b528cefcSMark Murray 		max = min;
272b528cefcSMark Murray 	    }
273b528cefcSMark Murray 	}
274b528cefcSMark Murray     }
275b528cefcSMark Murray     if(n){
276b528cefcSMark Murray 	p = strchr(p, '/');
277adb0ddaeSAssar Westerlund 	if(p == NULL) {
278adb0ddaeSAssar Westerlund 	    krb5_set_error_string (context, "failed to parse \"%s\"", orig);
279adb0ddaeSAssar Westerlund 	    return HEIM_ERR_LOG_PARSE;
280adb0ddaeSAssar Westerlund 	}
281b528cefcSMark Murray 	p++;
282b528cefcSMark Murray     }
283b528cefcSMark Murray     if(strcmp(p, "STDERR") == 0){
284b528cefcSMark Murray 	ret = open_file(context, f, min, max, NULL, NULL, stderr, 1);
285b528cefcSMark Murray     }else if(strcmp(p, "CONSOLE") == 0){
286b528cefcSMark Murray 	ret = open_file(context, f, min, max, "/dev/console", "w", NULL, 0);
287b528cefcSMark Murray     }else if(strncmp(p, "FILE:", 4) == 0 && (p[4] == ':' || p[4] == '=')){
288b528cefcSMark Murray 	char *fn;
289b528cefcSMark Murray 	FILE *file = NULL;
290b528cefcSMark Murray 	int keep_open = 0;
291b528cefcSMark Murray 	fn = strdup(p + 5);
292adb0ddaeSAssar Westerlund 	if(fn == NULL) {
293adb0ddaeSAssar Westerlund 	    krb5_set_error_string (context, "malloc: out of memory");
294b528cefcSMark Murray 	    return ENOMEM;
295adb0ddaeSAssar Westerlund 	}
296b528cefcSMark Murray 	if(p[4] == '='){
297b528cefcSMark Murray 	    int i = open(fn, O_WRONLY | O_CREAT |
298b528cefcSMark Murray 			 O_TRUNC | O_APPEND, 0666);
299adb0ddaeSAssar Westerlund 	    if(i < 0) {
300adb0ddaeSAssar Westerlund 		ret = errno;
301adb0ddaeSAssar Westerlund 		krb5_set_error_string (context, "open(%s): %s", fn,
302adb0ddaeSAssar Westerlund 				       strerror(ret));
303adb0ddaeSAssar Westerlund 		return ret;
304adb0ddaeSAssar Westerlund 	    }
305b528cefcSMark Murray 	    file = fdopen(i, "a");
306b528cefcSMark Murray 	    if(file == NULL){
307adb0ddaeSAssar Westerlund 		ret = errno;
308b528cefcSMark Murray 		close(i);
309adb0ddaeSAssar Westerlund 		krb5_set_error_string (context, "fdopen(%s): %s", fn,
310adb0ddaeSAssar Westerlund 				       strerror(ret));
311adb0ddaeSAssar Westerlund 		return ret;
312b528cefcSMark Murray 	    }
313b528cefcSMark Murray 	    keep_open = 1;
314b528cefcSMark Murray 	}
315b528cefcSMark Murray 	ret = open_file(context, f, min, max, fn, "a", file, keep_open);
316b528cefcSMark Murray     }else if(strncmp(p, "DEVICE=", 6) == 0){
317b528cefcSMark Murray 	ret = open_file(context, f, min, max, strdup(p + 7), "w", NULL, 0);
3188373020dSJacques Vidrine     }else if(strncmp(p, "SYSLOG", 6) == 0 && (p[6] == '\0' || p[6] == ':')){
3198373020dSJacques Vidrine 	char severity[128] = "";
3208373020dSJacques Vidrine 	char facility[128] = "";
3218373020dSJacques Vidrine 	p += 6;
3228373020dSJacques Vidrine 	if(*p != '\0')
3238373020dSJacques Vidrine 	    p++;
3248373020dSJacques Vidrine 	if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1)
3258373020dSJacques Vidrine 	    strsep_copy(&p, ":", facility, sizeof(facility));
3268373020dSJacques Vidrine 	if(*severity == '\0')
3278373020dSJacques Vidrine 	    strlcpy(severity, "ERR", sizeof(severity));
3288373020dSJacques Vidrine  	if(*facility == '\0')
3298373020dSJacques Vidrine 	    strlcpy(facility, "AUTH", sizeof(facility));
330b528cefcSMark Murray 	ret = open_syslog(context, f, min, max, severity, facility);
331b528cefcSMark Murray     }else{
332adb0ddaeSAssar Westerlund 	krb5_set_error_string (context, "unknown log type: %s", p);
333b528cefcSMark Murray 	ret = HEIM_ERR_LOG_PARSE; /* XXX */
334b528cefcSMark Murray     }
335b528cefcSMark Murray     return ret;
336b528cefcSMark Murray }
337b528cefcSMark Murray 
338b528cefcSMark Murray 
339b528cefcSMark Murray krb5_error_code
340b528cefcSMark Murray krb5_openlog(krb5_context context,
341b528cefcSMark Murray 	     const char *program,
342b528cefcSMark Murray 	     krb5_log_facility **fac)
343b528cefcSMark Murray {
344b528cefcSMark Murray     krb5_error_code ret;
345b528cefcSMark Murray     char **p, **q;
346b528cefcSMark Murray 
347b528cefcSMark Murray     ret = krb5_initlog(context, program, fac);
348b528cefcSMark Murray     if(ret)
349b528cefcSMark Murray 	return ret;
350b528cefcSMark Murray 
351b528cefcSMark Murray     p = krb5_config_get_strings(context, NULL, "logging", program, NULL);
352b528cefcSMark Murray     if(p == NULL)
353b528cefcSMark Murray 	p = krb5_config_get_strings(context, NULL, "logging", "default", NULL);
354b528cefcSMark Murray     if(p){
355b528cefcSMark Murray 	for(q = p; *q; q++)
356b528cefcSMark Murray 	    ret = krb5_addlog_dest(context, *fac, *q);
357b528cefcSMark Murray 	krb5_config_free_strings(p);
358b528cefcSMark Murray     }else
359b528cefcSMark Murray 	ret = krb5_addlog_dest(context, *fac, "SYSLOG");
360b528cefcSMark Murray     return 0;
361b528cefcSMark Murray }
362b528cefcSMark Murray 
363b528cefcSMark Murray krb5_error_code
364b528cefcSMark Murray krb5_closelog(krb5_context context,
365b528cefcSMark Murray 	      krb5_log_facility *fac)
366b528cefcSMark Murray {
367b528cefcSMark Murray     int i;
368b528cefcSMark Murray     for(i = 0; i < fac->len; i++)
3694137ff4cSJacques Vidrine 	(*fac->val[i].close)(fac->val[i].data);
370b528cefcSMark Murray     return 0;
371b528cefcSMark Murray }
372b528cefcSMark Murray 
373b528cefcSMark Murray #undef __attribute__
374b528cefcSMark Murray #define __attribute__(X)
375b528cefcSMark Murray 
376b528cefcSMark Murray krb5_error_code
377b528cefcSMark Murray krb5_vlog_msg(krb5_context context,
378b528cefcSMark Murray 	      krb5_log_facility *fac,
379b528cefcSMark Murray 	      char **reply,
380b528cefcSMark Murray 	      int level,
381b528cefcSMark Murray 	      const char *fmt,
382b528cefcSMark Murray 	      va_list ap)
383b528cefcSMark Murray      __attribute__((format (printf, 5, 0)))
384b528cefcSMark Murray {
385*0cadf2f4SJacques Vidrine 
386*0cadf2f4SJacques Vidrine     char *msg = NULL;
387*0cadf2f4SJacques Vidrine     const char *actual = NULL;
388b528cefcSMark Murray     char buf[64];
389*0cadf2f4SJacques Vidrine     time_t t = 0;
390b528cefcSMark Murray     int i;
391b528cefcSMark Murray 
392*0cadf2f4SJacques Vidrine     for(i = 0; fac && i < fac->len; i++)
393*0cadf2f4SJacques Vidrine 	if(fac->val[i].min <= level &&
394*0cadf2f4SJacques Vidrine 	   (fac->val[i].max < 0 || fac->val[i].max >= level)) {
395*0cadf2f4SJacques Vidrine 	    if(t == 0) {
396b528cefcSMark Murray 		t = time(NULL);
3975e9cd1aeSAssar Westerlund 		krb5_format_time(context, t, buf, sizeof(buf), TRUE);
398*0cadf2f4SJacques Vidrine 	    }
399*0cadf2f4SJacques Vidrine 	    if(actual == NULL) {
400*0cadf2f4SJacques Vidrine 		vasprintf(&msg, fmt, ap);
401*0cadf2f4SJacques Vidrine 		if(msg == NULL)
402*0cadf2f4SJacques Vidrine 		    actual = fmt;
403*0cadf2f4SJacques Vidrine 		else
404*0cadf2f4SJacques Vidrine 		    actual = msg;
405*0cadf2f4SJacques Vidrine 	    }
4065e9cd1aeSAssar Westerlund 	    (*fac->val[i].log)(buf, actual, fac->val[i].data);
407*0cadf2f4SJacques Vidrine 	}
408*0cadf2f4SJacques Vidrine     if(reply == NULL)
409*0cadf2f4SJacques Vidrine 	free(msg);
410*0cadf2f4SJacques Vidrine     else
411b528cefcSMark Murray 	*reply = msg;
412b528cefcSMark Murray     return 0;
413b528cefcSMark Murray }
414b528cefcSMark Murray 
415b528cefcSMark Murray krb5_error_code
416b528cefcSMark Murray krb5_vlog(krb5_context context,
417b528cefcSMark Murray 	  krb5_log_facility *fac,
418b528cefcSMark Murray 	  int level,
419b528cefcSMark Murray 	  const char *fmt,
420b528cefcSMark Murray 	  va_list ap)
421b528cefcSMark Murray      __attribute__((format (printf, 4, 0)))
422b528cefcSMark Murray {
423*0cadf2f4SJacques Vidrine     return krb5_vlog_msg(context, fac, NULL, level, fmt, ap);
424b528cefcSMark Murray }
425b528cefcSMark Murray 
426b528cefcSMark Murray krb5_error_code
427b528cefcSMark Murray krb5_log_msg(krb5_context context,
428b528cefcSMark Murray 	     krb5_log_facility *fac,
429b528cefcSMark Murray 	     int level,
430b528cefcSMark Murray 	     char **reply,
431b528cefcSMark Murray 	     const char *fmt,
432b528cefcSMark Murray 	     ...)
433b528cefcSMark Murray      __attribute__((format (printf, 5, 6)))
434b528cefcSMark Murray {
435b528cefcSMark Murray     va_list ap;
436b528cefcSMark Murray     krb5_error_code ret;
437b528cefcSMark Murray 
438b528cefcSMark Murray     va_start(ap, fmt);
439b528cefcSMark Murray     ret = krb5_vlog_msg(context, fac, reply, level, fmt, ap);
440b528cefcSMark Murray     va_end(ap);
441b528cefcSMark Murray     return ret;
442b528cefcSMark Murray }
443b528cefcSMark Murray 
444b528cefcSMark Murray 
445b528cefcSMark Murray krb5_error_code
446b528cefcSMark Murray krb5_log(krb5_context context,
447b528cefcSMark Murray 	 krb5_log_facility *fac,
448b528cefcSMark Murray 	 int level,
449b528cefcSMark Murray 	 const char *fmt,
450b528cefcSMark Murray 	 ...)
451b528cefcSMark Murray      __attribute__((format (printf, 4, 5)))
452b528cefcSMark Murray {
453b528cefcSMark Murray     va_list ap;
454b528cefcSMark Murray     krb5_error_code ret;
455b528cefcSMark Murray 
456b528cefcSMark Murray     va_start(ap, fmt);
457b528cefcSMark Murray     ret = krb5_vlog(context, fac, level, fmt, ap);
458b528cefcSMark Murray     va_end(ap);
459b528cefcSMark Murray     return ret;
460b528cefcSMark Murray }
461b528cefcSMark Murray 
462