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