1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 1997-2002 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*0Sstevel@tonic-gate /*
8*0Sstevel@tonic-gate  * lib/kadm/logger.c
9*0Sstevel@tonic-gate  *
10*0Sstevel@tonic-gate  * Copyright 1995 by the Massachusetts Institute of Technology.
11*0Sstevel@tonic-gate  * All Rights Reserved.
12*0Sstevel@tonic-gate  *
13*0Sstevel@tonic-gate  * Export of this software from the United States of America may
14*0Sstevel@tonic-gate  *   require a specific license from the United States Government.
15*0Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
16*0Sstevel@tonic-gate  *   export to obtain such a license before exporting.
17*0Sstevel@tonic-gate  *
18*0Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
19*0Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
20*0Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
21*0Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
22*0Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
23*0Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
24*0Sstevel@tonic-gate  * to distribution of the software without specific, written prior
25*0Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
26*0Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
27*0Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
28*0Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
29*0Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
30*0Sstevel@tonic-gate  * or implied warranty.
31*0Sstevel@tonic-gate  *
32*0Sstevel@tonic-gate  */
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate /* KADM5 wants non-syslog log files to contain syslog-like entries */
36*0Sstevel@tonic-gate #define VERBOSE_LOGS
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate /*
39*0Sstevel@tonic-gate  * logger.c	- Handle logging functions for those who want it.
40*0Sstevel@tonic-gate  */
41*0Sstevel@tonic-gate #include "k5-int.h"
42*0Sstevel@tonic-gate #include "adm_proto.h"
43*0Sstevel@tonic-gate #include "com_err.h"
44*0Sstevel@tonic-gate #include <stdio.h>
45*0Sstevel@tonic-gate #include <ctype.h>
46*0Sstevel@tonic-gate #include <ctype.h>
47*0Sstevel@tonic-gate #include <syslog.h>
48*0Sstevel@tonic-gate #include <stdarg.h>
49*0Sstevel@tonic-gate #include <libintl.h>
50*0Sstevel@tonic-gate #include <sys/types.h>
51*0Sstevel@tonic-gate #include <sys/stat.h>
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate #define	KRB5_KLOG_MAX_ERRMSG_SIZE	1024
54*0Sstevel@tonic-gate #ifndef	MAXHOSTNAMELEN
55*0Sstevel@tonic-gate #define	MAXHOSTNAMELEN	256
56*0Sstevel@tonic-gate #endif	/* MAXHOSTNAMELEN */
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate #define LSPEC_PARSE_ERR_1 	1
59*0Sstevel@tonic-gate #define LSPEC_PARSE_ERR_2	2
60*0Sstevel@tonic-gate #define LOG_FILE_ERR		3
61*0Sstevel@tonic-gate #define LOG_DEVICE_ERR		4
62*0Sstevel@tonic-gate #define LOG_UFO_STRING		5
63*0Sstevel@tonic-gate #define LOG_EMERG_STRING	6
64*0Sstevel@tonic-gate #define LOG_ALERT_STRING	7
65*0Sstevel@tonic-gate #define LOG_CRIT_STRING		8
66*0Sstevel@tonic-gate #define LOG_ERR_STRING		9
67*0Sstevel@tonic-gate #define LOG_WARNING_STRING	10
68*0Sstevel@tonic-gate #define LOG_NOTICE_STRING	11
69*0Sstevel@tonic-gate #define LOG_INFO_STRING	12
70*0Sstevel@tonic-gate #define LOG_DEBUG_STRING	13
71*0Sstevel@tonic-gate /* This is to assure that we have at least one match in the syslog stuff */
72*0Sstevel@tonic-gate /*
73*0Sstevel@tonic-gate static const char LSPEC_PARSE_ERR_1[] =	"%s: cannot parse <%s>\n";
74*0Sstevel@tonic-gate static const char LSPEC_PARSE_ERR_2[] =	"%s: warning - logging entry syntax error\n";
75*0Sstevel@tonic-gate static const char LOG_FILE_ERR[] =	"%s: error writing to %s\n";
76*0Sstevel@tonic-gate static const char LOG_DEVICE_ERR[] =	"%s: error writing to %s device\n";
77*0Sstevel@tonic-gate static const char LOG_UFO_STRING[] =	"???";
78*0Sstevel@tonic-gate static const char LOG_EMERG_STRING[] =	"EMERGENCY";
79*0Sstevel@tonic-gate static const char LOG_ALERT_STRING[] =	"ALERT";
80*0Sstevel@tonic-gate static const char LOG_CRIT_STRING[] =	"CRITICAL";
81*0Sstevel@tonic-gate static const char LOG_ERR_STRING[] =	"Error";
82*0Sstevel@tonic-gate static const char LOG_WARNING_STRING[] =	"Warning";
83*0Sstevel@tonic-gate static const char LOG_NOTICE_STRING[] =	"Notice";
84*0Sstevel@tonic-gate static const char LOG_INFO_STRING[] =	"info";
85*0Sstevel@tonic-gate static const char LOG_DEBUG_STRING[] =	"debug";
86*0Sstevel@tonic-gate */
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate const char *
90*0Sstevel@tonic-gate krb5_log_error_table(long errorno) {
91*0Sstevel@tonic-gate switch (errorno) {
92*0Sstevel@tonic-gate 	case LSPEC_PARSE_ERR_1:
93*0Sstevel@tonic-gate 		return(gettext("%s: cannot parse <%s>\n"));
94*0Sstevel@tonic-gate 	case LSPEC_PARSE_ERR_2:
95*0Sstevel@tonic-gate 		return(gettext("%s: warning - logging entry syntax error\n"));
96*0Sstevel@tonic-gate 	case LOG_FILE_ERR:
97*0Sstevel@tonic-gate 		return(gettext("%s: error writing to %s\n"));
98*0Sstevel@tonic-gate 	case LOG_DEVICE_ERR:
99*0Sstevel@tonic-gate 		return(gettext("%s: error writing to %s device\n"));
100*0Sstevel@tonic-gate 	case LOG_UFO_STRING:
101*0Sstevel@tonic-gate 		return(gettext("???"));
102*0Sstevel@tonic-gate 	case LOG_EMERG_STRING:
103*0Sstevel@tonic-gate 		return(gettext("EMERGENCY"));
104*0Sstevel@tonic-gate 	case LOG_ALERT_STRING:
105*0Sstevel@tonic-gate 		return(gettext("ALERT"));
106*0Sstevel@tonic-gate 	case LOG_CRIT_STRING:
107*0Sstevel@tonic-gate 		return(gettext("CRITICAL"));
108*0Sstevel@tonic-gate 	case LOG_ERR_STRING:
109*0Sstevel@tonic-gate 		return(gettext("Error"));
110*0Sstevel@tonic-gate 	case LOG_WARNING_STRING:
111*0Sstevel@tonic-gate 		return(gettext("Warning"));
112*0Sstevel@tonic-gate 	case LOG_NOTICE_STRING:
113*0Sstevel@tonic-gate 		return(gettext("Notice"));
114*0Sstevel@tonic-gate 	case LOG_INFO_STRING:
115*0Sstevel@tonic-gate 		return(gettext("info"));
116*0Sstevel@tonic-gate 	case LOG_DEBUG_STRING:
117*0Sstevel@tonic-gate 		return(gettext("info"));
118*0Sstevel@tonic-gate 	}
119*0Sstevel@tonic-gate }
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate /*
122*0Sstevel@tonic-gate  * Output logging.
123*0Sstevel@tonic-gate  *
124*0Sstevel@tonic-gate  * Output logging is now controlled by the configuration file.  We can specify
125*0Sstevel@tonic-gate  * the following syntaxes under the [logging]->entity specification.
126*0Sstevel@tonic-gate  *	FILE<opentype><pathname>
127*0Sstevel@tonic-gate  *	SYSLOG[=<severity>[:<facility>]]
128*0Sstevel@tonic-gate  *	STDERR
129*0Sstevel@tonic-gate  *	CONSOLE
130*0Sstevel@tonic-gate  *	DEVICE=<device-spec>
131*0Sstevel@tonic-gate  *
132*0Sstevel@tonic-gate  * Where:
133*0Sstevel@tonic-gate  *	<opentype> is ":" for open/append, "=" for open/create.
134*0Sstevel@tonic-gate  *	<pathname> is a valid path name.
135*0Sstevel@tonic-gate  *	<severity> is one of: (default = ERR)
136*0Sstevel@tonic-gate  *		EMERG
137*0Sstevel@tonic-gate  *		ALERT
138*0Sstevel@tonic-gate  *		CRIT
139*0Sstevel@tonic-gate  *		ERR
140*0Sstevel@tonic-gate  *		WARNING
141*0Sstevel@tonic-gate  *		NOTICE
142*0Sstevel@tonic-gate  *		INFO
143*0Sstevel@tonic-gate  *		DEBUG
144*0Sstevel@tonic-gate  *	<facility> is one of: (default = AUTH)
145*0Sstevel@tonic-gate  *		KERN
146*0Sstevel@tonic-gate  *		USER
147*0Sstevel@tonic-gate  *		MAIL
148*0Sstevel@tonic-gate  *		DAEMON
149*0Sstevel@tonic-gate  *		AUTH
150*0Sstevel@tonic-gate  *		LPR
151*0Sstevel@tonic-gate  *		NEWS
152*0Sstevel@tonic-gate  *		UUCP
153*0Sstevel@tonic-gate  *		CRON
154*0Sstevel@tonic-gate  *		LOCAL0..LOCAL7
155*0Sstevel@tonic-gate  *	<device-spec> is a valid device specification.
156*0Sstevel@tonic-gate  */
157*0Sstevel@tonic-gate struct log_entry {
158*0Sstevel@tonic-gate     enum log_type { K_LOG_FILE,
159*0Sstevel@tonic-gate 			K_LOG_SYSLOG,
160*0Sstevel@tonic-gate 			K_LOG_STDERR,
161*0Sstevel@tonic-gate 			K_LOG_CONSOLE,
162*0Sstevel@tonic-gate 			K_LOG_DEVICE,
163*0Sstevel@tonic-gate 			K_LOG_NONE } log_type;
164*0Sstevel@tonic-gate     krb5_pointer log_2free;
165*0Sstevel@tonic-gate     union log_union {
166*0Sstevel@tonic-gate 	struct log_file {
167*0Sstevel@tonic-gate 	    FILE	*lf_filep;
168*0Sstevel@tonic-gate 	    char	*lf_fname;
169*0Sstevel@tonic-gate 	    char	*lf_fopen_mode; /* "a+" or "w" */
170*0Sstevel@tonic-gate #define	K_LOG_DEF_FILE_ROTATE_PERIOD	-1	/* never */
171*0Sstevel@tonic-gate #define	K_LOG_DEF_FILE_ROTATE_VERSIONS	0	/* no versions */
172*0Sstevel@tonic-gate 	    time_t	lf_rotate_period;
173*0Sstevel@tonic-gate 	    time_t	lf_last_rotated;
174*0Sstevel@tonic-gate 	    int		lf_rotate_versions;
175*0Sstevel@tonic-gate 	} log_file;
176*0Sstevel@tonic-gate 	struct log_syslog {
177*0Sstevel@tonic-gate 	    int		ls_facility;
178*0Sstevel@tonic-gate 	    int		ls_severity;
179*0Sstevel@tonic-gate 	} log_syslog;
180*0Sstevel@tonic-gate 	struct log_device {
181*0Sstevel@tonic-gate 	    FILE	*ld_filep;
182*0Sstevel@tonic-gate 	    char	*ld_devname;
183*0Sstevel@tonic-gate 	} log_device;
184*0Sstevel@tonic-gate     } log_union;
185*0Sstevel@tonic-gate };
186*0Sstevel@tonic-gate #define	lfu_filep	log_union.log_file.lf_filep
187*0Sstevel@tonic-gate #define	lfu_fname	log_union.log_file.lf_fname
188*0Sstevel@tonic-gate #define	lfu_fopen_mode	log_union.log_file.lf_fopen_mode
189*0Sstevel@tonic-gate #define	lfu_rotate_period	log_union.log_file.lf_rotate_period
190*0Sstevel@tonic-gate #define	lfu_last_rotated	log_union.log_file.lf_last_rotated
191*0Sstevel@tonic-gate #define	lfu_rotate_versions	log_union.log_file.lf_rotate_versions
192*0Sstevel@tonic-gate #define	lsu_facility	log_union.log_syslog.ls_facility
193*0Sstevel@tonic-gate #define	lsu_severity	log_union.log_syslog.ls_severity
194*0Sstevel@tonic-gate #define	ldu_filep	log_union.log_device.ld_filep
195*0Sstevel@tonic-gate #define	ldu_devname	log_union.log_device.ld_devname
196*0Sstevel@tonic-gate 
197*0Sstevel@tonic-gate struct log_control {
198*0Sstevel@tonic-gate     struct log_entry	*log_entries;
199*0Sstevel@tonic-gate     int			log_nentries;
200*0Sstevel@tonic-gate     char		*log_whoami;
201*0Sstevel@tonic-gate     char		*log_hostname;
202*0Sstevel@tonic-gate     krb5_boolean	log_opened;
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate };
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate static struct log_control log_control = {
207*0Sstevel@tonic-gate     (struct log_entry *) NULL,
208*0Sstevel@tonic-gate     0,
209*0Sstevel@tonic-gate     (char *) NULL,
210*0Sstevel@tonic-gate     (char *) NULL,
211*0Sstevel@tonic-gate     0
212*0Sstevel@tonic-gate };
213*0Sstevel@tonic-gate static struct log_entry	def_log_entry;
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate /*
216*0Sstevel@tonic-gate  * These macros define any special processing that needs to happen for
217*0Sstevel@tonic-gate  * devices.  For unix, of course, this is hardly anything.
218*0Sstevel@tonic-gate  */
219*0Sstevel@tonic-gate #define	DEVICE_OPEN(d, m)	fopen(d, m)
220*0Sstevel@tonic-gate #define	CONSOLE_OPEN(m)		fopen("/dev/console", m)
221*0Sstevel@tonic-gate #define	DEVICE_PRINT(f, m)	((fprintf(f, "%s\r\n", m) >= 0) ? 	\
222*0Sstevel@tonic-gate 				 (fflush(f), 0) :			\
223*0Sstevel@tonic-gate 				 -1)
224*0Sstevel@tonic-gate #define	DEVICE_CLOSE(d)		fclose(d)
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 
227*0Sstevel@tonic-gate /*
228*0Sstevel@tonic-gate  * klog_rotate() - roate a log file if we have specified rotation
229*0Sstevel@tonic-gate  * parameters in krb5.conf.
230*0Sstevel@tonic-gate  */
231*0Sstevel@tonic-gate static void
232*0Sstevel@tonic-gate klog_rotate(struct log_entry *le)
233*0Sstevel@tonic-gate {
234*0Sstevel@tonic-gate 	time_t t;
235*0Sstevel@tonic-gate 	int i;
236*0Sstevel@tonic-gate 	char *name_buf1;
237*0Sstevel@tonic-gate 	char *name_buf2;
238*0Sstevel@tonic-gate 	char *old_name;
239*0Sstevel@tonic-gate 	char *new_name;
240*0Sstevel@tonic-gate 	char *tmp;
241*0Sstevel@tonic-gate 	FILE *fp;
242*0Sstevel@tonic-gate 	int num_vers;
243*0Sstevel@tonic-gate 	mode_t old_umask;
244*0Sstevel@tonic-gate 
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate 	/*
247*0Sstevel@tonic-gate 	 * By default we don't rotate.
248*0Sstevel@tonic-gate 	 */
249*0Sstevel@tonic-gate 	if (le->lfu_rotate_period == K_LOG_DEF_FILE_ROTATE_PERIOD)
250*0Sstevel@tonic-gate 		return;
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate 	t = time(0);
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate 	if (t >= le->lfu_last_rotated + le->lfu_rotate_period) {
255*0Sstevel@tonic-gate 		/*
256*0Sstevel@tonic-gate 		 * The N log file versions will be renamed X.N-1 X.N-2, ... X.0.
257*0Sstevel@tonic-gate 		 * So the allocate file name buffers that can the version
258*0Sstevel@tonic-gate 		 * number extensions.
259*0Sstevel@tonic-gate 		 * 32 extra bytes is plenty.
260*0Sstevel@tonic-gate 		 */
261*0Sstevel@tonic-gate 		name_buf1 = malloc(strlen(le->lfu_fname) + 32);
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 		if (name_buf1 == NULL)
264*0Sstevel@tonic-gate 			return;
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate 		name_buf2 = malloc(strlen(le->lfu_fname) + 32);
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate 		if (name_buf2 == NULL) {
269*0Sstevel@tonic-gate 			free(name_buf1);
270*0Sstevel@tonic-gate 			return;
271*0Sstevel@tonic-gate 		}
272*0Sstevel@tonic-gate 
273*0Sstevel@tonic-gate 		old_name = name_buf1;
274*0Sstevel@tonic-gate 		new_name = name_buf2;
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 		/*
277*0Sstevel@tonic-gate 		 * If there N versions, then the first one has file extension
278*0Sstevel@tonic-gate 		 * of N-1.
279*0Sstevel@tonic-gate 		 */
280*0Sstevel@tonic-gate 		(void) sprintf(new_name, "%s.%d", le->lfu_fname,
281*0Sstevel@tonic-gate 			le->lfu_rotate_versions - 1);
282*0Sstevel@tonic-gate 
283*0Sstevel@tonic-gate 		/*
284*0Sstevel@tonic-gate 		 * Rename file.N-2 to file.N-1, file.N-3 to file.N-2, ...
285*0Sstevel@tonic-gate 		 * file.0 to file.1
286*0Sstevel@tonic-gate 		 */
287*0Sstevel@tonic-gate 		for (i = le->lfu_rotate_versions - 1; i > 0; i--) {
288*0Sstevel@tonic-gate 			(void) sprintf(old_name, "%s.%d", le->lfu_fname, i - 1);
289*0Sstevel@tonic-gate 			(void) rename(old_name, new_name);
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 			/*
292*0Sstevel@tonic-gate 			 * swap old name and new name. This way,
293*0Sstevel@tonic-gate 			 * on the next iteration, new_name.X
294*0Sstevel@tonic-gate 			 * becomes new_name.X-1.
295*0Sstevel@tonic-gate 			 */
296*0Sstevel@tonic-gate 			tmp = old_name;
297*0Sstevel@tonic-gate 			old_name = new_name;
298*0Sstevel@tonic-gate 			new_name = tmp;
299*0Sstevel@tonic-gate 		}
300*0Sstevel@tonic-gate 		old_name = le->lfu_fname;
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 		(void) rename(old_name, new_name);
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate 		/*
305*0Sstevel@tonic-gate 		 * Even though we don't know yet if the fopen()
306*0Sstevel@tonic-gate 		 * of the log file will succeed, we mark the log
307*0Sstevel@tonic-gate 		 * as rotated. This is so we don't repeatably
308*0Sstevel@tonic-gate 		 * rotate file.N-2 to file.N-1 ... etc without
309*0Sstevel@tonic-gate 		 * waiting for the rotate period to elapse.
310*0Sstevel@tonic-gate 		 */
311*0Sstevel@tonic-gate 		le->lfu_last_rotated = t;
312*0Sstevel@tonic-gate 
313*0Sstevel@tonic-gate 		/*
314*0Sstevel@tonic-gate 		 * Default log file creation mode should be read-only
315*0Sstevel@tonic-gate 		 * by owner(root), but the admin can override with
316*0Sstevel@tonic-gate 		 * chmod(1) if desired.
317*0Sstevel@tonic-gate 		 */
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 		old_umask = umask(077);
320*0Sstevel@tonic-gate 		fp = fopen(old_name, le->lfu_fopen_mode);
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 		umask(old_umask);
323*0Sstevel@tonic-gate 
324*0Sstevel@tonic-gate 		if (fp != NULL) {
325*0Sstevel@tonic-gate 
326*0Sstevel@tonic-gate 			(void) fclose(le->lfu_filep);
327*0Sstevel@tonic-gate 			le->lfu_filep = fp;
328*0Sstevel@tonic-gate 
329*0Sstevel@tonic-gate 			/*
330*0Sstevel@tonic-gate 			 * If the version parameter in krb5.conf was
331*0Sstevel@tonic-gate 			 * 0, then we take this to mean that rotating the
332*0Sstevel@tonic-gate 			 * log file will cause us to dispose of the
333*0Sstevel@tonic-gate 			 * old one, and created a new one. We have just
334*0Sstevel@tonic-gate 			 * renamed the old one to file.-1, so remove it.
335*0Sstevel@tonic-gate 			 */
336*0Sstevel@tonic-gate 			if (le->lfu_rotate_versions <= 0)
337*0Sstevel@tonic-gate 				(void) unlink(new_name);
338*0Sstevel@tonic-gate 
339*0Sstevel@tonic-gate 		} else {
340*0Sstevel@tonic-gate 			fprintf(stderr,
341*0Sstevel@tonic-gate 		gettext("During rotate, couldn't open log file %s: %s\n"),
342*0Sstevel@tonic-gate 				old_name, error_message(errno));
343*0Sstevel@tonic-gate 			/*
344*0Sstevel@tonic-gate 			 * Put it back.
345*0Sstevel@tonic-gate 			 */
346*0Sstevel@tonic-gate 			(void) rename(new_name, old_name);
347*0Sstevel@tonic-gate 		}
348*0Sstevel@tonic-gate 		free(name_buf1);
349*0Sstevel@tonic-gate 		free(name_buf2);
350*0Sstevel@tonic-gate 	}
351*0Sstevel@tonic-gate }
352*0Sstevel@tonic-gate 
353*0Sstevel@tonic-gate /*
354*0Sstevel@tonic-gate  * klog_com_err_proc()	- Handle com_err(3) messages as specified by the
355*0Sstevel@tonic-gate  *			  profile.
356*0Sstevel@tonic-gate  */
357*0Sstevel@tonic-gate static void
358*0Sstevel@tonic-gate klog_com_err_proc(whoami, code, format, ap)
359*0Sstevel@tonic-gate     const char	*whoami;
360*0Sstevel@tonic-gate     long	code;
361*0Sstevel@tonic-gate     const char	*format;
362*0Sstevel@tonic-gate     va_list	ap;
363*0Sstevel@tonic-gate {
364*0Sstevel@tonic-gate     char	outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
365*0Sstevel@tonic-gate     int		lindex;
366*0Sstevel@tonic-gate     char	*actual_format;
367*0Sstevel@tonic-gate     int		log_pri = -1;
368*0Sstevel@tonic-gate     char	*cp;
369*0Sstevel@tonic-gate     char	*syslogp;
370*0Sstevel@tonic-gate 
371*0Sstevel@tonic-gate     /* Make the header */
372*0Sstevel@tonic-gate     sprintf(outbuf, "%s: ", whoami);
373*0Sstevel@tonic-gate     /*
374*0Sstevel@tonic-gate      * Squirrel away address after header for syslog since syslog makes
375*0Sstevel@tonic-gate      * a header
376*0Sstevel@tonic-gate      */
377*0Sstevel@tonic-gate     syslogp = &outbuf[strlen(outbuf)];
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate     /* If reporting an error message, separate it. */
380*0Sstevel@tonic-gate     if (code) {
381*0Sstevel@tonic-gate         outbuf[sizeof(outbuf) - 1] = '\0';
382*0Sstevel@tonic-gate 	strncat(outbuf, error_message(code), sizeof(outbuf) - 1 - strlen(outbuf));
383*0Sstevel@tonic-gate 	strncat(outbuf, " - ", sizeof(outbuf) - 1 - strlen(outbuf));
384*0Sstevel@tonic-gate     }
385*0Sstevel@tonic-gate     cp = &outbuf[strlen(outbuf)];
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate     actual_format = (char *) format;
388*0Sstevel@tonic-gate     /*
389*0Sstevel@tonic-gate      * This is an unpleasant hack.  If the first character is less than
390*0Sstevel@tonic-gate      * 8, then we assume that it is a priority.
391*0Sstevel@tonic-gate      *
392*0Sstevel@tonic-gate      * Since it is not guaranteed that there is a direct mapping between
393*0Sstevel@tonic-gate      * syslog priorities (e.g. Ultrix and old BSD), we resort to this
394*0Sstevel@tonic-gate      * intermediate representation.
395*0Sstevel@tonic-gate      */
396*0Sstevel@tonic-gate     if ((((unsigned char) *format) > 0) && (((unsigned char) *format) <= 8)) {
397*0Sstevel@tonic-gate 	actual_format = (char *) (format + 1);
398*0Sstevel@tonic-gate 	switch ((unsigned char) *format) {
399*0Sstevel@tonic-gate 	case 1:
400*0Sstevel@tonic-gate 	    log_pri = LOG_EMERG;
401*0Sstevel@tonic-gate 	    break;
402*0Sstevel@tonic-gate 	case 2:
403*0Sstevel@tonic-gate 	    log_pri = LOG_ALERT;
404*0Sstevel@tonic-gate 	    break;
405*0Sstevel@tonic-gate 	case 3:
406*0Sstevel@tonic-gate 	    log_pri = LOG_CRIT;
407*0Sstevel@tonic-gate 	    break;
408*0Sstevel@tonic-gate 	default:
409*0Sstevel@tonic-gate 	case 4:
410*0Sstevel@tonic-gate 	    log_pri = LOG_ERR;
411*0Sstevel@tonic-gate 	    break;
412*0Sstevel@tonic-gate 	case 5:
413*0Sstevel@tonic-gate 	    log_pri = LOG_WARNING;
414*0Sstevel@tonic-gate 	    break;
415*0Sstevel@tonic-gate 	case 6:
416*0Sstevel@tonic-gate 	    log_pri = LOG_NOTICE;
417*0Sstevel@tonic-gate 	    break;
418*0Sstevel@tonic-gate 	case 7:
419*0Sstevel@tonic-gate 	    log_pri = LOG_INFO;
420*0Sstevel@tonic-gate 	    break;
421*0Sstevel@tonic-gate 	case 8:
422*0Sstevel@tonic-gate 	    log_pri = LOG_DEBUG;
423*0Sstevel@tonic-gate 	    break;
424*0Sstevel@tonic-gate 	}
425*0Sstevel@tonic-gate     }
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate     /* Now format the actual message */
428*0Sstevel@tonic-gate     vsprintf(cp, actual_format, ap);
429*0Sstevel@tonic-gate 
430*0Sstevel@tonic-gate     /*
431*0Sstevel@tonic-gate      * Now that we have the message formatted, perform the output to each
432*0Sstevel@tonic-gate      * logging specification.
433*0Sstevel@tonic-gate      */
434*0Sstevel@tonic-gate     for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
435*0Sstevel@tonic-gate 	switch (log_control.log_entries[lindex].log_type) {
436*0Sstevel@tonic-gate 	case K_LOG_FILE:
437*0Sstevel@tonic-gate 
438*0Sstevel@tonic-gate 	    klog_rotate(&log_control.log_entries[lindex]);
439*0Sstevel@tonic-gate 	    /*FALLTHRU*/
440*0Sstevel@tonic-gate 	case K_LOG_STDERR:
441*0Sstevel@tonic-gate 	    /*
442*0Sstevel@tonic-gate 	     * Files/standard error.
443*0Sstevel@tonic-gate 	     */
444*0Sstevel@tonic-gate 	    if (fprintf(log_control.log_entries[lindex].lfu_filep, "%s\n",
445*0Sstevel@tonic-gate 			outbuf) < 0) {
446*0Sstevel@tonic-gate 		/* Attempt to report error */
447*0Sstevel@tonic-gate 		fprintf(stderr, krb5_log_error_table(LOG_FILE_ERR), whoami,
448*0Sstevel@tonic-gate 			log_control.log_entries[lindex].lfu_fname);
449*0Sstevel@tonic-gate 	    }
450*0Sstevel@tonic-gate 	    else {
451*0Sstevel@tonic-gate 		fflush(log_control.log_entries[lindex].lfu_filep);
452*0Sstevel@tonic-gate 	    }
453*0Sstevel@tonic-gate 	    break;
454*0Sstevel@tonic-gate 	case K_LOG_CONSOLE:
455*0Sstevel@tonic-gate 	case K_LOG_DEVICE:
456*0Sstevel@tonic-gate 	    /*
457*0Sstevel@tonic-gate 	     * Devices (may need special handling)
458*0Sstevel@tonic-gate 	     */
459*0Sstevel@tonic-gate 	    if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep,
460*0Sstevel@tonic-gate 			     outbuf) < 0) {
461*0Sstevel@tonic-gate 		/* Attempt to report error */
462*0Sstevel@tonic-gate 		fprintf(stderr, krb5_log_error_table(LOG_DEVICE_ERR), whoami,
463*0Sstevel@tonic-gate 			log_control.log_entries[lindex].ldu_devname);
464*0Sstevel@tonic-gate 	    }
465*0Sstevel@tonic-gate 	    break;
466*0Sstevel@tonic-gate 	case K_LOG_SYSLOG:
467*0Sstevel@tonic-gate 	    /*
468*0Sstevel@tonic-gate 	     * System log.
469*0Sstevel@tonic-gate 	     */
470*0Sstevel@tonic-gate 	    /*
471*0Sstevel@tonic-gate 	     * If we have specified a priority through our hackery, then
472*0Sstevel@tonic-gate 	     * use it, otherwise use the default.
473*0Sstevel@tonic-gate 	     */
474*0Sstevel@tonic-gate 	    if (log_pri >= 0)
475*0Sstevel@tonic-gate 		log_pri |= log_control.log_entries[lindex].lsu_facility;
476*0Sstevel@tonic-gate 	    else
477*0Sstevel@tonic-gate 		log_pri = log_control.log_entries[lindex].lsu_facility |
478*0Sstevel@tonic-gate 		    log_control.log_entries[lindex].lsu_severity;
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate 	    /* Log the message with our header trimmed off */
481*0Sstevel@tonic-gate 	    syslog(log_pri, "%s", syslogp);
482*0Sstevel@tonic-gate 	    break;
483*0Sstevel@tonic-gate 	default:
484*0Sstevel@tonic-gate 	    break;
485*0Sstevel@tonic-gate 	}
486*0Sstevel@tonic-gate     }
487*0Sstevel@tonic-gate }
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate /*
490*0Sstevel@tonic-gate  * krb5_klog_init()	- Initialize logging.
491*0Sstevel@tonic-gate  *
492*0Sstevel@tonic-gate  * This routine parses the syntax described above to specify destinations for
493*0Sstevel@tonic-gate  * com_err(3) or krb5_klog_syslog() messages generated by the caller.
494*0Sstevel@tonic-gate  *
495*0Sstevel@tonic-gate  * Parameters:
496*0Sstevel@tonic-gate  *	kcontext	- Kerberos context.
497*0Sstevel@tonic-gate  *	ename		- Entity name as it is to appear in the profile.
498*0Sstevel@tonic-gate  *	whoami		- Entity name as it is to appear in error output.
499*0Sstevel@tonic-gate  *	do_com_err	- Take over com_err(3) processing.
500*0Sstevel@tonic-gate  *
501*0Sstevel@tonic-gate  * Implicit inputs:
502*0Sstevel@tonic-gate  *	stderr		- This is where STDERR output goes.
503*0Sstevel@tonic-gate  *
504*0Sstevel@tonic-gate  * Implicit outputs:
505*0Sstevel@tonic-gate  *	log_nentries	- Number of log entries, both valid and invalid.
506*0Sstevel@tonic-gate  *	log_control	- List of entries (log_nentries long) which contains
507*0Sstevel@tonic-gate  *			  data for klog_com_err_proc() to use to determine
508*0Sstevel@tonic-gate  *			  where/how to send output.
509*0Sstevel@tonic-gate  */
510*0Sstevel@tonic-gate krb5_error_code
511*0Sstevel@tonic-gate krb5_klog_init(kcontext, ename, whoami, do_com_err)
512*0Sstevel@tonic-gate     krb5_context	kcontext;
513*0Sstevel@tonic-gate     char		*ename;
514*0Sstevel@tonic-gate     char		*whoami;
515*0Sstevel@tonic-gate     krb5_boolean	do_com_err;
516*0Sstevel@tonic-gate {
517*0Sstevel@tonic-gate     const char	*logging_profent[3];
518*0Sstevel@tonic-gate     const char	*logging_defent[3];
519*0Sstevel@tonic-gate     char	**logging_specs;
520*0Sstevel@tonic-gate     int		i, ngood;
521*0Sstevel@tonic-gate     char	*cp, *cp2;
522*0Sstevel@tonic-gate     char	savec;
523*0Sstevel@tonic-gate     int		error;
524*0Sstevel@tonic-gate     int		do_openlog, log_facility;
525*0Sstevel@tonic-gate     FILE	*f;
526*0Sstevel@tonic-gate     mode_t      old_umask;
527*0Sstevel@tonic-gate 
528*0Sstevel@tonic-gate     /* Initialize */
529*0Sstevel@tonic-gate     do_openlog = 0;
530*0Sstevel@tonic-gate     log_facility = 0;
531*0Sstevel@tonic-gate 
532*0Sstevel@tonic-gate     /*
533*0Sstevel@tonic-gate      * Look up [logging]-><ename> in the profile.  If that doesn't
534*0Sstevel@tonic-gate      * succeed, then look for [logging]->default.
535*0Sstevel@tonic-gate      */
536*0Sstevel@tonic-gate     logging_profent[0] = "logging";
537*0Sstevel@tonic-gate     logging_profent[1] = ename;
538*0Sstevel@tonic-gate     logging_profent[2] = (char *) NULL;
539*0Sstevel@tonic-gate     logging_defent[0] = "logging";
540*0Sstevel@tonic-gate     logging_defent[1] = "default";
541*0Sstevel@tonic-gate     logging_defent[2] = (char *) NULL;
542*0Sstevel@tonic-gate     logging_specs = (char **) NULL;
543*0Sstevel@tonic-gate     ngood = 0;
544*0Sstevel@tonic-gate     log_control.log_nentries = 0;
545*0Sstevel@tonic-gate     if (!profile_get_values(kcontext->profile,
546*0Sstevel@tonic-gate 			    logging_profent,
547*0Sstevel@tonic-gate 			    &logging_specs) ||
548*0Sstevel@tonic-gate 	!profile_get_values(kcontext->profile,
549*0Sstevel@tonic-gate 			    logging_defent,
550*0Sstevel@tonic-gate 			    &logging_specs)) {
551*0Sstevel@tonic-gate 	/*
552*0Sstevel@tonic-gate 	 * We have a match, so we first count the number of elements
553*0Sstevel@tonic-gate 	 */
554*0Sstevel@tonic-gate 	for (log_control.log_nentries = 0;
555*0Sstevel@tonic-gate 	     logging_specs[log_control.log_nentries];
556*0Sstevel@tonic-gate 	     log_control.log_nentries++);
557*0Sstevel@tonic-gate 
558*0Sstevel@tonic-gate 	/*
559*0Sstevel@tonic-gate 	 * Now allocate our structure.
560*0Sstevel@tonic-gate 	 */
561*0Sstevel@tonic-gate 	log_control.log_entries = (struct log_entry *)
562*0Sstevel@tonic-gate 	    malloc(log_control.log_nentries * sizeof(struct log_entry));
563*0Sstevel@tonic-gate 	if (log_control.log_entries) {
564*0Sstevel@tonic-gate 	    /*
565*0Sstevel@tonic-gate 	     * Scan through the list.
566*0Sstevel@tonic-gate 	     */
567*0Sstevel@tonic-gate 	    for (i=0; i<log_control.log_nentries; i++) {
568*0Sstevel@tonic-gate 		log_control.log_entries[i].log_type = K_LOG_NONE;
569*0Sstevel@tonic-gate 		log_control.log_entries[i].log_2free = logging_specs[i];
570*0Sstevel@tonic-gate 		/*
571*0Sstevel@tonic-gate 		 * The format is:
572*0Sstevel@tonic-gate 		 *	<whitespace><data><whitespace>
573*0Sstevel@tonic-gate 		 * so, trim off the leading and trailing whitespace here.
574*0Sstevel@tonic-gate 		 */
575*0Sstevel@tonic-gate 		for (cp = logging_specs[i]; isspace(*cp); cp++);
576*0Sstevel@tonic-gate 		for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1];
577*0Sstevel@tonic-gate 		     isspace(*cp2); cp2--);
578*0Sstevel@tonic-gate 		cp2++;
579*0Sstevel@tonic-gate 		*cp2 = '\0';
580*0Sstevel@tonic-gate 		/*
581*0Sstevel@tonic-gate 		 * Is this a file?
582*0Sstevel@tonic-gate 		 */
583*0Sstevel@tonic-gate 		if (!strncasecmp(cp, "FILE", 4)) {
584*0Sstevel@tonic-gate 		    /*
585*0Sstevel@tonic-gate 		     * Check for append/overwrite, then open the file.
586*0Sstevel@tonic-gate 		     */
587*0Sstevel@tonic-gate 		    if (cp[4] == ':' || cp[4] == '=') {
588*0Sstevel@tonic-gate 			log_control.log_entries[i].lfu_fopen_mode =
589*0Sstevel@tonic-gate 				(cp[4] == ':') ? "a+" : "w";
590*0Sstevel@tonic-gate 			old_umask = umask(077);
591*0Sstevel@tonic-gate 			f = fopen(&cp[5],
592*0Sstevel@tonic-gate 				log_control.log_entries[i].lfu_fopen_mode);
593*0Sstevel@tonic-gate 			umask(old_umask);
594*0Sstevel@tonic-gate 			if (f) {
595*0Sstevel@tonic-gate                             char rotate_kw[128];
596*0Sstevel@tonic-gate 
597*0Sstevel@tonic-gate 			    log_control.log_entries[i].lfu_filep = f;
598*0Sstevel@tonic-gate 			    log_control.log_entries[i].log_type = K_LOG_FILE;
599*0Sstevel@tonic-gate 			    log_control.log_entries[i].lfu_fname = &cp[5];
600*0Sstevel@tonic-gate 			    log_control.log_entries[i].lfu_rotate_period =
601*0Sstevel@tonic-gate 				K_LOG_DEF_FILE_ROTATE_PERIOD;
602*0Sstevel@tonic-gate 			    log_control.log_entries[i].lfu_rotate_versions =
603*0Sstevel@tonic-gate 				K_LOG_DEF_FILE_ROTATE_VERSIONS;
604*0Sstevel@tonic-gate 			    log_control.log_entries[i].lfu_last_rotated =
605*0Sstevel@tonic-gate 				time(0);
606*0Sstevel@tonic-gate 
607*0Sstevel@tonic-gate 			/*
608*0Sstevel@tonic-gate 			 * Now parse for ename_"rotate" = {
609*0Sstevel@tonic-gate 			 *	period = XXX
610*0Sstevel@tonic-gate 			 * 	versions = 10
611*0Sstevel@tonic-gate 			 * }
612*0Sstevel@tonic-gate 			 */
613*0Sstevel@tonic-gate 			    if (strlen(ename) + strlen("_rotate") <
614*0Sstevel@tonic-gate 				sizeof (rotate_kw)) {
615*0Sstevel@tonic-gate 
616*0Sstevel@tonic-gate 				    char *time;
617*0Sstevel@tonic-gate 				    krb5_deltat	dt;
618*0Sstevel@tonic-gate 				    int vers;
619*0Sstevel@tonic-gate 
620*0Sstevel@tonic-gate 				    strcpy(rotate_kw, ename);
621*0Sstevel@tonic-gate 				    strcat(rotate_kw, "_rotate");
622*0Sstevel@tonic-gate 
623*0Sstevel@tonic-gate 				    if (!profile_get_string(kcontext->profile,
624*0Sstevel@tonic-gate 				        "logging", rotate_kw, "period",
625*0Sstevel@tonic-gate 					NULL, &time)) {
626*0Sstevel@tonic-gate 
627*0Sstevel@tonic-gate 					if (time != NULL) {
628*0Sstevel@tonic-gate 					    if (!krb5_string_to_deltat(time,
629*0Sstevel@tonic-gate 						&dt)) {
630*0Sstevel@tonic-gate 			log_control.log_entries[i].lfu_rotate_period =
631*0Sstevel@tonic-gate 							(time_t) dt;
632*0Sstevel@tonic-gate 					    }
633*0Sstevel@tonic-gate 					    free(time);
634*0Sstevel@tonic-gate 					}
635*0Sstevel@tonic-gate 				    }
636*0Sstevel@tonic-gate 
637*0Sstevel@tonic-gate 				    if (!profile_get_integer(
638*0Sstevel@tonic-gate 					kcontext->profile, "logging",
639*0Sstevel@tonic-gate 					rotate_kw, "versions",
640*0Sstevel@tonic-gate 					K_LOG_DEF_FILE_ROTATE_VERSIONS,
641*0Sstevel@tonic-gate 					&vers)) {
642*0Sstevel@tonic-gate 			log_control.log_entries[i].lfu_rotate_versions = vers;
643*0Sstevel@tonic-gate 				    }
644*0Sstevel@tonic-gate 
645*0Sstevel@tonic-gate 			   }
646*0Sstevel@tonic-gate 			} else {
647*0Sstevel@tonic-gate 			    fprintf(stderr,gettext("Couldn't open log file %s: %s\n"),
648*0Sstevel@tonic-gate 				    &cp[5], error_message(errno));
649*0Sstevel@tonic-gate 			    continue;
650*0Sstevel@tonic-gate 			}
651*0Sstevel@tonic-gate 		    }
652*0Sstevel@tonic-gate 		}
653*0Sstevel@tonic-gate 		/*
654*0Sstevel@tonic-gate 		 * Is this a syslog?
655*0Sstevel@tonic-gate 		 */
656*0Sstevel@tonic-gate 		else if (!strncasecmp(cp, "SYSLOG", 6)) {
657*0Sstevel@tonic-gate 		    error = 0;
658*0Sstevel@tonic-gate 		    log_control.log_entries[i].lsu_facility = LOG_AUTH;
659*0Sstevel@tonic-gate 		    log_control.log_entries[i].lsu_severity = LOG_ERR;
660*0Sstevel@tonic-gate 		    /*
661*0Sstevel@tonic-gate 		     * Is there a severify specified?
662*0Sstevel@tonic-gate 		     */
663*0Sstevel@tonic-gate 		    if (cp[6] == ':') {
664*0Sstevel@tonic-gate 			/*
665*0Sstevel@tonic-gate 			 * Find the end of the severity.
666*0Sstevel@tonic-gate 			 */
667*0Sstevel@tonic-gate 			if (cp2 = strchr(&cp[7], ':')) {
668*0Sstevel@tonic-gate 			    savec = *cp2;
669*0Sstevel@tonic-gate 			    *cp2 = '\0';
670*0Sstevel@tonic-gate 			    cp2++;
671*0Sstevel@tonic-gate 			}
672*0Sstevel@tonic-gate 
673*0Sstevel@tonic-gate 			/*
674*0Sstevel@tonic-gate 			 * Match a severity.
675*0Sstevel@tonic-gate 			 */
676*0Sstevel@tonic-gate 			if (!strcasecmp(&cp[7], "ERR")) {
677*0Sstevel@tonic-gate 			    log_control.log_entries[i].lsu_severity = LOG_ERR;
678*0Sstevel@tonic-gate 			}
679*0Sstevel@tonic-gate 			else if (!strcasecmp(&cp[7], "EMERG")) {
680*0Sstevel@tonic-gate 			    log_control.log_entries[i].lsu_severity =
681*0Sstevel@tonic-gate 				LOG_EMERG;
682*0Sstevel@tonic-gate 			}
683*0Sstevel@tonic-gate 			else if (!strcasecmp(&cp[7], "ALERT")) {
684*0Sstevel@tonic-gate 			    log_control.log_entries[i].lsu_severity =
685*0Sstevel@tonic-gate 				LOG_ALERT;
686*0Sstevel@tonic-gate 			}
687*0Sstevel@tonic-gate 			else if (!strcasecmp(&cp[7], "CRIT")) {
688*0Sstevel@tonic-gate 			    log_control.log_entries[i].lsu_severity = LOG_CRIT;
689*0Sstevel@tonic-gate 			}
690*0Sstevel@tonic-gate 			else if (!strcasecmp(&cp[7], "WARNING")) {
691*0Sstevel@tonic-gate 			    log_control.log_entries[i].lsu_severity =
692*0Sstevel@tonic-gate 				LOG_WARNING;
693*0Sstevel@tonic-gate 			}
694*0Sstevel@tonic-gate 			else if (!strcasecmp(&cp[7], "NOTICE")) {
695*0Sstevel@tonic-gate 			    log_control.log_entries[i].lsu_severity =
696*0Sstevel@tonic-gate 				LOG_NOTICE;
697*0Sstevel@tonic-gate 			}
698*0Sstevel@tonic-gate 			else if (!strcasecmp(&cp[7], "INFO")) {
699*0Sstevel@tonic-gate 			    log_control.log_entries[i].lsu_severity = LOG_INFO;
700*0Sstevel@tonic-gate 			}
701*0Sstevel@tonic-gate 			else if (!strcasecmp(&cp[7], "DEBUG")) {
702*0Sstevel@tonic-gate 			    log_control.log_entries[i].lsu_severity =
703*0Sstevel@tonic-gate 				LOG_DEBUG;
704*0Sstevel@tonic-gate 			}
705*0Sstevel@tonic-gate 			else
706*0Sstevel@tonic-gate 			    error = 1;
707*0Sstevel@tonic-gate 
708*0Sstevel@tonic-gate 			/*
709*0Sstevel@tonic-gate 			 * If there is a facility present, then parse that.
710*0Sstevel@tonic-gate 			 */
711*0Sstevel@tonic-gate 			if (cp2) {
712*0Sstevel@tonic-gate 			    if (!strcasecmp(cp2, "AUTH")) {
713*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_AUTH;
714*0Sstevel@tonic-gate 			    }
715*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "KERN")) {
716*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_KERN;
717*0Sstevel@tonic-gate 			    }
718*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "USER")) {
719*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_USER;
720*0Sstevel@tonic-gate 			    }
721*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "MAIL")) {
722*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_MAIL;
723*0Sstevel@tonic-gate 			    }
724*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "DAEMON")) {
725*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_DAEMON;
726*0Sstevel@tonic-gate 			    }
727*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "LPR")) {
728*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_LPR;
729*0Sstevel@tonic-gate 			    }
730*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "NEWS")) {
731*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_NEWS;
732*0Sstevel@tonic-gate 			    }
733*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "UUCP")) {
734*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_UUCP;
735*0Sstevel@tonic-gate 			    }
736*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "CRON")) {
737*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_CRON;
738*0Sstevel@tonic-gate 			    }
739*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "LOCAL0")) {
740*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_LOCAL0;
741*0Sstevel@tonic-gate 			    }
742*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "LOCAL1")) {
743*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_LOCAL1;
744*0Sstevel@tonic-gate 			    }
745*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "LOCAL2")) {
746*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_LOCAL2;
747*0Sstevel@tonic-gate 			    }
748*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "LOCAL3")) {
749*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_LOCAL3;
750*0Sstevel@tonic-gate 			    }
751*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "LOCAL4")) {
752*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_LOCAL4;
753*0Sstevel@tonic-gate 			    }
754*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "LOCAL5")) {
755*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_LOCAL5;
756*0Sstevel@tonic-gate 			    }
757*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "LOCAL6")) {
758*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_LOCAL6;
759*0Sstevel@tonic-gate 			    }
760*0Sstevel@tonic-gate 			    else if (!strcasecmp(cp2, "LOCAL7")) {
761*0Sstevel@tonic-gate 				log_control.log_entries[i].lsu_facility = LOG_LOCAL7;
762*0Sstevel@tonic-gate 			    }
763*0Sstevel@tonic-gate 			    cp2--;
764*0Sstevel@tonic-gate 			    *cp2 = savec;
765*0Sstevel@tonic-gate 			}
766*0Sstevel@tonic-gate 		    }
767*0Sstevel@tonic-gate 		    if (!error) {
768*0Sstevel@tonic-gate 			log_control.log_entries[i].log_type = K_LOG_SYSLOG;
769*0Sstevel@tonic-gate 			do_openlog = 1;
770*0Sstevel@tonic-gate 			log_facility = log_control.log_entries[i].lsu_facility;
771*0Sstevel@tonic-gate 		    }
772*0Sstevel@tonic-gate 		}
773*0Sstevel@tonic-gate 		/*
774*0Sstevel@tonic-gate 		 * Is this a standard error specification?
775*0Sstevel@tonic-gate 		 */
776*0Sstevel@tonic-gate 		else if (!strcasecmp(cp, "STDERR")) {
777*0Sstevel@tonic-gate 		    if (log_control.log_entries[i].lfu_filep =
778*0Sstevel@tonic-gate 			fdopen(fileno(stderr), "a+")) {
779*0Sstevel@tonic-gate 			log_control.log_entries[i].log_type = K_LOG_STDERR;
780*0Sstevel@tonic-gate 			log_control.log_entries[i].lfu_fname =
781*0Sstevel@tonic-gate 			    "standard error";
782*0Sstevel@tonic-gate 		    }
783*0Sstevel@tonic-gate 		}
784*0Sstevel@tonic-gate 		/*
785*0Sstevel@tonic-gate 		 * Is this a specification of the console?
786*0Sstevel@tonic-gate 		 */
787*0Sstevel@tonic-gate 		else if (!strcasecmp(cp, "CONSOLE")) {
788*0Sstevel@tonic-gate 		    if (log_control.log_entries[i].ldu_filep =
789*0Sstevel@tonic-gate 			CONSOLE_OPEN("a+")) {
790*0Sstevel@tonic-gate 			log_control.log_entries[i].log_type = K_LOG_CONSOLE;
791*0Sstevel@tonic-gate 			log_control.log_entries[i].ldu_devname = "console";
792*0Sstevel@tonic-gate 		    }
793*0Sstevel@tonic-gate 		}
794*0Sstevel@tonic-gate 		/*
795*0Sstevel@tonic-gate 		 * Is this a specification of a device?
796*0Sstevel@tonic-gate 		 */
797*0Sstevel@tonic-gate 		else if (!strncasecmp(cp, "DEVICE", 6)) {
798*0Sstevel@tonic-gate 		    /*
799*0Sstevel@tonic-gate 		     * We handle devices very similarly to files.
800*0Sstevel@tonic-gate 		     */
801*0Sstevel@tonic-gate 		    if (cp[6] == '=') {
802*0Sstevel@tonic-gate 			if (log_control.log_entries[i].ldu_filep =
803*0Sstevel@tonic-gate 			    DEVICE_OPEN(&cp[7], "w")) {
804*0Sstevel@tonic-gate 			    log_control.log_entries[i].log_type = K_LOG_DEVICE;
805*0Sstevel@tonic-gate 			    log_control.log_entries[i].ldu_devname = &cp[7];
806*0Sstevel@tonic-gate 			}
807*0Sstevel@tonic-gate 		    }
808*0Sstevel@tonic-gate 		}
809*0Sstevel@tonic-gate 		/*
810*0Sstevel@tonic-gate 		 * See if we successfully parsed this specification.
811*0Sstevel@tonic-gate 		 */
812*0Sstevel@tonic-gate 		if (log_control.log_entries[i].log_type == K_LOG_NONE) {
813*0Sstevel@tonic-gate 		    fprintf(stderr, krb5_log_error_table(LSPEC_PARSE_ERR_1), whoami, cp);
814*0Sstevel@tonic-gate 		    fprintf(stderr, krb5_log_error_table(LSPEC_PARSE_ERR_2), whoami);
815*0Sstevel@tonic-gate 		}
816*0Sstevel@tonic-gate 		else
817*0Sstevel@tonic-gate 		    ngood++;
818*0Sstevel@tonic-gate 	    }
819*0Sstevel@tonic-gate 	}
820*0Sstevel@tonic-gate 	/*
821*0Sstevel@tonic-gate 	 * If we didn't find anything, then free our lists.
822*0Sstevel@tonic-gate 	 */
823*0Sstevel@tonic-gate 	if (ngood == 0) {
824*0Sstevel@tonic-gate 	    for (i=0; i<log_control.log_nentries; i++)
825*0Sstevel@tonic-gate 		free(logging_specs[i]);
826*0Sstevel@tonic-gate 	}
827*0Sstevel@tonic-gate 	free(logging_specs);
828*0Sstevel@tonic-gate     }
829*0Sstevel@tonic-gate     /*
830*0Sstevel@tonic-gate      * If we didn't find anything, go for the default which is to log to
831*0Sstevel@tonic-gate      * the system log.
832*0Sstevel@tonic-gate      */
833*0Sstevel@tonic-gate     if (ngood == 0) {
834*0Sstevel@tonic-gate 	if (log_control.log_entries)
835*0Sstevel@tonic-gate 	    free(log_control.log_entries);
836*0Sstevel@tonic-gate 	log_control.log_entries = &def_log_entry;
837*0Sstevel@tonic-gate 	log_control.log_entries->log_type = K_LOG_SYSLOG;
838*0Sstevel@tonic-gate 	log_control.log_entries->log_2free = (krb5_pointer) NULL;
839*0Sstevel@tonic-gate 	log_facility = log_control.log_entries->lsu_facility = LOG_AUTH;
840*0Sstevel@tonic-gate 	log_control.log_entries->lsu_severity = LOG_ERR;
841*0Sstevel@tonic-gate 	do_openlog = 1;
842*0Sstevel@tonic-gate 	log_control.log_nentries = 1;
843*0Sstevel@tonic-gate     }
844*0Sstevel@tonic-gate     if (log_control.log_nentries) {
845*0Sstevel@tonic-gate 	if (log_control.log_whoami = (char *) malloc(strlen(whoami)+1))
846*0Sstevel@tonic-gate 	    strcpy(log_control.log_whoami, whoami);
847*0Sstevel@tonic-gate 	if (log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN))
848*0Sstevel@tonic-gate 	    gethostname(log_control.log_hostname, MAXHOSTNAMELEN);
849*0Sstevel@tonic-gate 	if (do_openlog) {
850*0Sstevel@tonic-gate 	    openlog(whoami, LOG_NDELAY|LOG_PID, log_facility);
851*0Sstevel@tonic-gate 	    log_control.log_opened = 1;
852*0Sstevel@tonic-gate 	}
853*0Sstevel@tonic-gate 	if (do_com_err)
854*0Sstevel@tonic-gate 	    (void) set_com_err_hook(klog_com_err_proc);
855*0Sstevel@tonic-gate     }
856*0Sstevel@tonic-gate     return((log_control.log_nentries) ? 0 : ENOENT);
857*0Sstevel@tonic-gate }
858*0Sstevel@tonic-gate 
859*0Sstevel@tonic-gate /*
860*0Sstevel@tonic-gate  * krb5_klog_close()	- Close the logging context and free all data.
861*0Sstevel@tonic-gate  */
862*0Sstevel@tonic-gate void
863*0Sstevel@tonic-gate krb5_klog_close(kcontext)
864*0Sstevel@tonic-gate     krb5_context	kcontext;
865*0Sstevel@tonic-gate {
866*0Sstevel@tonic-gate     int lindex;
867*0Sstevel@tonic-gate     (void) reset_com_err_hook();
868*0Sstevel@tonic-gate     for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
869*0Sstevel@tonic-gate 	switch (log_control.log_entries[lindex].log_type) {
870*0Sstevel@tonic-gate 	case K_LOG_FILE:
871*0Sstevel@tonic-gate 	case K_LOG_STDERR:
872*0Sstevel@tonic-gate 	    /*
873*0Sstevel@tonic-gate 	     * Files/standard error.
874*0Sstevel@tonic-gate 	     */
875*0Sstevel@tonic-gate 	    fclose(log_control.log_entries[lindex].lfu_filep);
876*0Sstevel@tonic-gate 	    break;
877*0Sstevel@tonic-gate 	case K_LOG_CONSOLE:
878*0Sstevel@tonic-gate 	case K_LOG_DEVICE:
879*0Sstevel@tonic-gate 	    /*
880*0Sstevel@tonic-gate 	     * Devices (may need special handling)
881*0Sstevel@tonic-gate 	     */
882*0Sstevel@tonic-gate 	    DEVICE_CLOSE(log_control.log_entries[lindex].ldu_filep);
883*0Sstevel@tonic-gate 	    break;
884*0Sstevel@tonic-gate 	case K_LOG_SYSLOG:
885*0Sstevel@tonic-gate 	    /*
886*0Sstevel@tonic-gate 	     * System log.
887*0Sstevel@tonic-gate 	     */
888*0Sstevel@tonic-gate 	    break;
889*0Sstevel@tonic-gate 	default:
890*0Sstevel@tonic-gate 	    break;
891*0Sstevel@tonic-gate 	}
892*0Sstevel@tonic-gate 	if (log_control.log_entries[lindex].log_2free)
893*0Sstevel@tonic-gate 	    free(log_control.log_entries[lindex].log_2free);
894*0Sstevel@tonic-gate     }
895*0Sstevel@tonic-gate     if (log_control.log_entries != &def_log_entry)
896*0Sstevel@tonic-gate 	free(log_control.log_entries);
897*0Sstevel@tonic-gate     log_control.log_entries = (struct log_entry *) NULL;
898*0Sstevel@tonic-gate     log_control.log_nentries = 0;
899*0Sstevel@tonic-gate     if (log_control.log_whoami)
900*0Sstevel@tonic-gate 	free(log_control.log_whoami);
901*0Sstevel@tonic-gate     log_control.log_whoami = (char *) NULL;
902*0Sstevel@tonic-gate     if (log_control.log_hostname)
903*0Sstevel@tonic-gate 	free(log_control.log_hostname);
904*0Sstevel@tonic-gate     log_control.log_hostname = (char *) NULL;
905*0Sstevel@tonic-gate     if (log_control.log_opened)
906*0Sstevel@tonic-gate 	closelog();
907*0Sstevel@tonic-gate }
908*0Sstevel@tonic-gate 
909*0Sstevel@tonic-gate /*
910*0Sstevel@tonic-gate  * severity2string()	- Convert a severity to a string.
911*0Sstevel@tonic-gate  */
912*0Sstevel@tonic-gate static char *
913*0Sstevel@tonic-gate severity2string(severity)
914*0Sstevel@tonic-gate     int	severity;
915*0Sstevel@tonic-gate {
916*0Sstevel@tonic-gate     int s;
917*0Sstevel@tonic-gate     const char *ss;
918*0Sstevel@tonic-gate 
919*0Sstevel@tonic-gate     s = severity & LOG_PRIMASK;
920*0Sstevel@tonic-gate     ss = krb5_log_error_table(LOG_UFO_STRING);
921*0Sstevel@tonic-gate     switch (s) {
922*0Sstevel@tonic-gate     case LOG_EMERG:
923*0Sstevel@tonic-gate 	ss = krb5_log_error_table(LOG_EMERG_STRING);
924*0Sstevel@tonic-gate 	break;
925*0Sstevel@tonic-gate     case LOG_ALERT:
926*0Sstevel@tonic-gate 	ss = krb5_log_error_table(LOG_ALERT_STRING);
927*0Sstevel@tonic-gate 	break;
928*0Sstevel@tonic-gate     case LOG_CRIT:
929*0Sstevel@tonic-gate 	ss = krb5_log_error_table(LOG_CRIT_STRING);
930*0Sstevel@tonic-gate 	break;
931*0Sstevel@tonic-gate     case LOG_ERR:
932*0Sstevel@tonic-gate 	ss = krb5_log_error_table(LOG_ERR_STRING);
933*0Sstevel@tonic-gate 	break;
934*0Sstevel@tonic-gate     case LOG_WARNING:
935*0Sstevel@tonic-gate 	ss = krb5_log_error_table(LOG_WARNING_STRING);
936*0Sstevel@tonic-gate 	break;
937*0Sstevel@tonic-gate     case LOG_NOTICE:
938*0Sstevel@tonic-gate 	ss = krb5_log_error_table(LOG_NOTICE_STRING);
939*0Sstevel@tonic-gate 	break;
940*0Sstevel@tonic-gate     case LOG_INFO:
941*0Sstevel@tonic-gate 	ss = krb5_log_error_table(LOG_INFO_STRING);
942*0Sstevel@tonic-gate 	break;
943*0Sstevel@tonic-gate     case LOG_DEBUG:
944*0Sstevel@tonic-gate 	ss = krb5_log_error_table(LOG_DEBUG_STRING);
945*0Sstevel@tonic-gate 	break;
946*0Sstevel@tonic-gate     }
947*0Sstevel@tonic-gate     return((char *) ss);
948*0Sstevel@tonic-gate }
949*0Sstevel@tonic-gate 
950*0Sstevel@tonic-gate /*
951*0Sstevel@tonic-gate  * krb5_klog_syslog()	- Simulate the calling sequence of syslog(3), while
952*0Sstevel@tonic-gate  *			  also performing the logging redirection as specified
953*0Sstevel@tonic-gate  *			  by krb5_klog_init().
954*0Sstevel@tonic-gate  */
955*0Sstevel@tonic-gate static int
956*0Sstevel@tonic-gate klog_vsyslog(priority, format, arglist)
957*0Sstevel@tonic-gate     int		priority;
958*0Sstevel@tonic-gate     const char	*format;
959*0Sstevel@tonic-gate     va_list	arglist;
960*0Sstevel@tonic-gate {
961*0Sstevel@tonic-gate     char	outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
962*0Sstevel@tonic-gate     int		lindex;
963*0Sstevel@tonic-gate     char	*syslogp;
964*0Sstevel@tonic-gate     char	*cp;
965*0Sstevel@tonic-gate     time_t	now;
966*0Sstevel@tonic-gate     size_t	soff;
967*0Sstevel@tonic-gate 
968*0Sstevel@tonic-gate     /*
969*0Sstevel@tonic-gate      * Format a syslog-esque message of the format:
970*0Sstevel@tonic-gate      *
971*0Sstevel@tonic-gate      * (verbose form)
972*0Sstevel@tonic-gate      * 		<date> <hostname> <id>[<pid>](<priority>): <message>
973*0Sstevel@tonic-gate      *
974*0Sstevel@tonic-gate      * (short form)
975*0Sstevel@tonic-gate      *		<date> <message>
976*0Sstevel@tonic-gate      */
977*0Sstevel@tonic-gate     cp = outbuf;
978*0Sstevel@tonic-gate     (void) time(&now);
979*0Sstevel@tonic-gate     /*
980*0Sstevel@tonic-gate      * Format the date: mon dd hh:mm:ss
981*0Sstevel@tonic-gate      */
982*0Sstevel@tonic-gate     soff = strftime(outbuf, sizeof(outbuf), "%b %d %H:%M:%S", localtime(&now));
983*0Sstevel@tonic-gate     if (soff > 0)
984*0Sstevel@tonic-gate 	cp += soff;
985*0Sstevel@tonic-gate     else
986*0Sstevel@tonic-gate 	return(-1);
987*0Sstevel@tonic-gate #ifdef VERBOSE_LOGS
988*0Sstevel@tonic-gate     sprintf(cp, " %s %s[%ld](%s): ",
989*0Sstevel@tonic-gate 	    log_control.log_hostname, log_control.log_whoami, (long) getpid(),
990*0Sstevel@tonic-gate 	    severity2string(priority));
991*0Sstevel@tonic-gate #else
992*0Sstevel@tonic-gate     sprintf(cp, " ");
993*0Sstevel@tonic-gate #endif
994*0Sstevel@tonic-gate     syslogp = &outbuf[strlen(outbuf)];
995*0Sstevel@tonic-gate 
996*0Sstevel@tonic-gate     /* Now format the actual message */
997*0Sstevel@tonic-gate     vsprintf(syslogp, format, arglist);
998*0Sstevel@tonic-gate 
999*0Sstevel@tonic-gate     /*
1000*0Sstevel@tonic-gate      * Now that we have the message formatted, perform the output to each
1001*0Sstevel@tonic-gate      * logging specification.
1002*0Sstevel@tonic-gate      */
1003*0Sstevel@tonic-gate     for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
1004*0Sstevel@tonic-gate 	switch (log_control.log_entries[lindex].log_type) {
1005*0Sstevel@tonic-gate 	case K_LOG_FILE:
1006*0Sstevel@tonic-gate 
1007*0Sstevel@tonic-gate 	    klog_rotate(&log_control.log_entries[lindex]);
1008*0Sstevel@tonic-gate 	    /*FALLTHRU*/
1009*0Sstevel@tonic-gate 	case K_LOG_STDERR:
1010*0Sstevel@tonic-gate 	    /*
1011*0Sstevel@tonic-gate 	     * Files/standard error.
1012*0Sstevel@tonic-gate 	     */
1013*0Sstevel@tonic-gate 	    if (fprintf(log_control.log_entries[lindex].lfu_filep, "%s\n",
1014*0Sstevel@tonic-gate 			outbuf) < 0) {
1015*0Sstevel@tonic-gate 		/* Attempt to report error */
1016*0Sstevel@tonic-gate 		fprintf(stderr, krb5_log_error_table(LOG_FILE_ERR),
1017*0Sstevel@tonic-gate 			log_control.log_whoami,
1018*0Sstevel@tonic-gate 			log_control.log_entries[lindex].lfu_fname);
1019*0Sstevel@tonic-gate 	    }
1020*0Sstevel@tonic-gate 	    else {
1021*0Sstevel@tonic-gate 		fflush(log_control.log_entries[lindex].lfu_filep);
1022*0Sstevel@tonic-gate 	    }
1023*0Sstevel@tonic-gate 	    break;
1024*0Sstevel@tonic-gate 	case K_LOG_CONSOLE:
1025*0Sstevel@tonic-gate 	case K_LOG_DEVICE:
1026*0Sstevel@tonic-gate 	    /*
1027*0Sstevel@tonic-gate 	     * Devices (may need special handling)
1028*0Sstevel@tonic-gate 	     */
1029*0Sstevel@tonic-gate 	    if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep,
1030*0Sstevel@tonic-gate 			     outbuf) < 0) {
1031*0Sstevel@tonic-gate 		/* Attempt to report error */
1032*0Sstevel@tonic-gate 		fprintf(stderr, krb5_log_error_table(LOG_DEVICE_ERR),
1033*0Sstevel@tonic-gate 			log_control.log_whoami,
1034*0Sstevel@tonic-gate 			log_control.log_entries[lindex].ldu_devname);
1035*0Sstevel@tonic-gate 	    }
1036*0Sstevel@tonic-gate 	    break;
1037*0Sstevel@tonic-gate 	case K_LOG_SYSLOG:
1038*0Sstevel@tonic-gate 	    /*
1039*0Sstevel@tonic-gate 	     * System log.
1040*0Sstevel@tonic-gate 	     */
1041*0Sstevel@tonic-gate 
1042*0Sstevel@tonic-gate 	    /* Log the message with our header trimmed off */
1043*0Sstevel@tonic-gate 	    syslog(priority, "%s", syslogp);
1044*0Sstevel@tonic-gate 	    break;
1045*0Sstevel@tonic-gate 	default:
1046*0Sstevel@tonic-gate 	    break;
1047*0Sstevel@tonic-gate 	}
1048*0Sstevel@tonic-gate     }
1049*0Sstevel@tonic-gate     return(0);
1050*0Sstevel@tonic-gate }
1051*0Sstevel@tonic-gate 
1052*0Sstevel@tonic-gate int
1053*0Sstevel@tonic-gate krb5_klog_syslog(int priority, const char *format, ...)
1054*0Sstevel@tonic-gate {
1055*0Sstevel@tonic-gate     int		retval;
1056*0Sstevel@tonic-gate     va_list	pvar;
1057*0Sstevel@tonic-gate 
1058*0Sstevel@tonic-gate     va_start(pvar, format);
1059*0Sstevel@tonic-gate     retval = klog_vsyslog(priority, format, pvar);
1060*0Sstevel@tonic-gate     va_end(pvar);
1061*0Sstevel@tonic-gate     return(retval);
1062*0Sstevel@tonic-gate }
1063*0Sstevel@tonic-gate 
1064*0Sstevel@tonic-gate /*
1065*0Sstevel@tonic-gate  * krb5_klog_reopen() - Close and reopen any open (non-syslog) log files.
1066*0Sstevel@tonic-gate  *                      This function is called when a SIGHUP is received
1067*0Sstevel@tonic-gate  *                      so that external log-archival utilities may
1068*0Sstevel@tonic-gate  *                      alert the Kerberos daemons that they should get
1069*0Sstevel@tonic-gate  *                      a new file descriptor for the give filename.
1070*0Sstevel@tonic-gate  */
1071*0Sstevel@tonic-gate void
1072*0Sstevel@tonic-gate krb5_klog_reopen(kcontext)
1073*0Sstevel@tonic-gate krb5_context kcontext;
1074*0Sstevel@tonic-gate {
1075*0Sstevel@tonic-gate     int lindex;
1076*0Sstevel@tonic-gate     FILE *f;
1077*0Sstevel@tonic-gate 
1078*0Sstevel@tonic-gate     /*
1079*0Sstevel@tonic-gate      * Only logs which are actually files need to be closed
1080*0Sstevel@tonic-gate      * and reopened in response to a SIGHUP
1081*0Sstevel@tonic-gate      */
1082*0Sstevel@tonic-gate     for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
1083*0Sstevel@tonic-gate 	if (log_control.log_entries[lindex].log_type == K_LOG_FILE) {
1084*0Sstevel@tonic-gate 	    fclose(log_control.log_entries[lindex].lfu_filep);
1085*0Sstevel@tonic-gate 	    /*
1086*0Sstevel@tonic-gate 	     * In case the old logfile did not get moved out of the
1087*0Sstevel@tonic-gate 	     * way, open for append to prevent squashing the old logs.
1088*0Sstevel@tonic-gate 	     */
1089*0Sstevel@tonic-gate 	    f = fopen(log_control.log_entries[lindex].lfu_fname, "a+");
1090*0Sstevel@tonic-gate 	    if (f) {
1091*0Sstevel@tonic-gate 		log_control.log_entries[lindex].lfu_filep = f;
1092*0Sstevel@tonic-gate 	    } else {
1093*0Sstevel@tonic-gate 		fprintf(stderr, "Couldn't open log file %s: %s\n",
1094*0Sstevel@tonic-gate 			log_control.log_entries[lindex].lfu_fname,
1095*0Sstevel@tonic-gate 			error_message(errno));
1096*0Sstevel@tonic-gate 	    }
1097*0Sstevel@tonic-gate 	}
1098*0Sstevel@tonic-gate     }
1099*0Sstevel@tonic-gate }
1100