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