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