1 /*
2  *      $Id: ErrLogSyslog.c 191 2007-03-30 23:26:38Z boote $
3  */
4 /************************************************************************
5 *									*
6 *			     Copyright (C)  2002			*
7 *				Internet2				*
8 *			     All Rights Reserved			*
9 *									*
10 ************************************************************************/
11 /*
12  *	File:		ErrLogSyslog.c
13  *
14  *	Author:		Jeff Boote
15  *			Internet2
16  *
17  *	Date:		Tue Apr 23 11:05:18  2002
18  *
19  *	Description:	This file defines a "syslog-mode" logging
20  *			function to be used as the `log_func' argument
21  *			to the I2OpenErr() function.
22  *
23  *			Modified from code writen by John Clyne at UCAR...
24  *
25  *
26  *		Based on code from UCAR DCS tools. Copyright information
27  *		from UCAR follows:
28  *
29  *		Copyright 1997 University Corporation for Atmospheric Research,
30  *		Scientific Computing Division.  All rights reserved.
31  *
32  *
33  *		Permission to use, copy, modify and distribute this software
34  *		and its	documentation for any academic, educational and
35  *		scientific research purpose is hereby granted without fee,
36  *		provided that the above copyright notice and this permission
37  *		notice appear in all copies of this software and its
38  *		documentation, and that the software is not sold and/or made
39  *		the subject of any commercial activity.  Parties interested
40  *		in commercial licensing should contact the copyright holder.
41  */
42 #include <I2util/utilP.h>
43 
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <time.h>
48 #ifdef  HAVE_SYSLOG_NAMES
49 #define SYSLOG_NAMES
50 #endif
51 #include <syslog.h>
52 
53 /*
54  * I prefer to get these arrays from syslog.h... But, they doesn't exist on
55  * all systems. I do what I can.
56  *
57  * If it isn't in the system's syslog.h - I have taken the portion I need
58  * from freebsd.
59  */
60 #ifndef	HAVE_SYSLOG_NAMES
61 /*
62  * Copyright (c) 1982, 1986, 1988, 1993
63  *	The Regents of the University of California.  All rights reserved.
64  *
65  * Redistribution and use in source and binary forms, with or without
66  * modification, are permitted provided that the following conditions
67  * are met:
68  * 1. Redistributions of source code must retain the above copyright
69  *    notice, this list of conditions and the following disclaimer.
70  * 2. Redistributions in binary form must reproduce the above copyright
71  *    notice, this list of conditions and the following disclaimer in the
72  *    documentation and/or other materials provided with the distribution.
73  * 3. All advertising materials mentioning features or use of this software
74  *    must display the following acknowledgement:
75  *	This product includes software developed by the University of
76  *	California, Berkeley and its contributors.
77  * 4. Neither the name of the University nor the names of its contributors
78  *    may be used to endorse or promote products derived from this software
79  *    without specific prior written permission.
80  *
81  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
82  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
84  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
85  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
86  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
87  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
88  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
89  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
90  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
91  * SUCH DAMAGE.
92  *
93  *	@(#)syslog.h	8.1 (Berkeley) 6/2/93
94  */
95 typedef struct _code {
96 	const char	*c_name;
97 	int		c_val;
98 } CODE;
99 
100 static CODE prioritynames[] = {
101 	{ "alert",	LOG_ALERT,	},
102 	{ "crit",	LOG_CRIT,	},
103 	{ "debug",	LOG_DEBUG,	},
104 	{ "emerg",	LOG_EMERG,	},
105 	{ "err",	LOG_ERR,	},
106 	{ "error",	LOG_ERR,	},	/* DEPRECATED */
107 	{ "info",	LOG_INFO,	},
108 	{ "notice",	LOG_NOTICE,	},
109 	{ "panic", 	LOG_EMERG,	},	/* DEPRECATED */
110 	{ "warn",	LOG_WARNING,	},	/* DEPRECATED */
111 	{ "warning",	LOG_WARNING,	},
112 	{ NULL,		-1,		}
113 };
114 
115 #ifndef LOG_AUTHPRIV
116 #define LOG_AUTHPRIV LOG_AUTH
117 #endif
118 #ifndef LOG_FTP
119 #define LOG_FTP LOG_DAEMON
120 #endif
121 
122 static CODE facilitynames[] = {
123 	{ "auth",	LOG_AUTH,	},
124 	{ "authpriv",	LOG_AUTHPRIV,	},
125 	{ "cron", 	LOG_CRON,	},
126 	{ "daemon",	LOG_DAEMON,	},
127 	{ "ftp",	LOG_FTP,	},
128 	{ "kern",	LOG_KERN,	},
129 	{ "lpr",	LOG_LPR,	},
130 	{ "mail",	LOG_MAIL,	},
131 	{ "news",	LOG_NEWS,	},
132 	{ "syslog",	LOG_SYSLOG,	},
133 	{ "user",	LOG_USER,	},
134 	{ "uucp",	LOG_UUCP,	},
135 	{ "local0",	LOG_LOCAL0,	},
136 	{ "local1",	LOG_LOCAL1,	},
137 	{ "local2",	LOG_LOCAL2,	},
138 	{ "local3",	LOG_LOCAL3,	},
139 	{ "local4",	LOG_LOCAL4,	},
140 	{ "local5",	LOG_LOCAL5,	},
141 	{ "local6",	LOG_LOCAL6,	},
142 	{ "local7",	LOG_LOCAL7,	},
143 	{ NULL,		-1,		}
144 };
145 #endif
146 
147 /*
148  * Function:	I2ErrLogSyslogFacility
149  *
150  * Description:	Given a string name, looks for the integer id that matches.
151  *
152  * In Args:
153  *
154  * Out Args:
155  *
156  * Scope:
157  * Returns:	integer id : -1 on error.
158  * Side Effect:
159  */
160 int
I2ErrLogSyslogFacility(const char * name)161 I2ErrLogSyslogFacility(
162 	const char	*name
163 	)
164 {
165 	CODE	*ptr = facilitynames;
166 	int	val=-1;
167 
168 	while(ptr->c_name){
169 		if(strncasecmp(ptr->c_name,name,strlen(ptr->c_name)) == 0){
170 			val = ptr->c_val;
171 			break;
172 		}
173 		ptr++;
174 	}
175 
176 	return val;
177 }
178 
179 /*
180  * Function:	I2ErrLogSyslogFacilityName
181  *
182  * Description:	Given an integer, return a "name" for the facility that
183  * 		matches that integer.
184  *
185  * In Args:
186  *
187  * Out Args:
188  *
189  * Scope:
190  * Returns:	const char * (static memory) or NULL
191  * Side Effect:
192  */
193 const char
I2ErrLogSyslogFacilityName(int fac)194 *I2ErrLogSyslogFacilityName(
195 	int	fac
196 		)
197 {
198 	CODE	*ptr = facilitynames;
199 
200 	while(ptr->c_name){
201 		if(ptr->c_val == fac)
202 			return ptr->c_name;
203 		ptr++;
204 	}
205 
206 	return NULL;
207 }
208 
209 /*
210  * Function:	I2ErrLogSyslogPriority
211  *
212  * Description:	Given a string name, looks for the integer id that matches.
213  *
214  * In Args:
215  *
216  * Out Args:
217  *
218  * Scope:
219  * Returns:	integer id : -1 on error.
220  * Side Effect:
221  */
222 int
I2ErrLogSyslogPriority(const char * name)223 I2ErrLogSyslogPriority(
224 	const char	*name
225 	)
226 {
227 	CODE	*ptr = prioritynames;
228 	int	val=-1;
229 
230         if(strncasecmp(name,"none",5) == 0){
231             val = I2LOG_NONE;
232         }
233         else{
234 	    while(ptr->c_name){
235 		if(strncasecmp(ptr->c_name,name,strlen(ptr->c_name)) == 0){
236 			val = ptr->c_val;
237                         break;
238 		}
239 		ptr++;
240 	    }
241         }
242 
243 	return val;
244 }
245 
246 /*
247  * Function:	I2ErrLogSyslogPriorityName
248  *
249  * Description:	Given an integer, return a "name" for the "priority" that
250  * 		matches that integer.
251  *
252  * In Args:
253  *
254  * Out Args:
255  *
256  * Scope:
257  * Returns:	const char * (static memory) or NULL
258  * Side Effect:
259  */
260 const char
I2ErrLogSyslogPriorityName(int fac)261 *I2ErrLogSyslogPriorityName(
262 	int	fac
263 		)
264 {
265 	CODE	*ptr = prioritynames;
266         static char *none = "none";
267 
268         if(fac == I2LOG_NONE){
269             return none;
270         }
271 
272 	while(ptr->c_name){
273 		if(ptr->c_val == fac)
274 			return ptr->c_name;
275 		ptr++;
276 	}
277 
278 	return NULL;
279 }
280 
281 
282 /*
283  * Function:	I2ErrLogSyslog()
284  *
285  * Description:	The I2ErrLogSyslog() function is a client logging function
286  *		that may be passed to DPOpenErr() as the `log_func' argument.
287  *
288  *		Upon invocation, I2ErrLogSyslog() writes a logging message
289  *		to the system log via  a call to syslog(). The behavior of
290  *		I2ErrLogSyslog()
291  *		may be controlled by the structure pointed to by `arg'. The
292  *		members of the structure pointed to by `arg' that may be
293  *		set include:
294  *
295  *
296  *			*ident		A string passed as the first parameter
297  *					to openlog() the first time
298  *					I2ErrLogSys() is called iff ident
299  *					is not NULL.
300  *
301  *			logopt		An integer passed as the second
302  *					parameter to openlog iff ident
303  *					is not NULL.
304  *
305  *			facility	An integer passed as the third
306  *					parameter to openlog iff ident is
307  *					not NULL.
308  *
309  *			priority	An integer log priority passed to
310  *					syslog as its first argument.
311  *
312  *			line_info	A bit mask indicating how each output
313  *					line should be formatted. The mask
314  *					is a bitwise inclusive OR of the
315  *					valid attribute bits. If line_info
316  *					is zero nothing is printed.
317  *
318  *		Valid attribute mask bits include:
319  *
320  *			I2NAME
321  *			I2FILE
322  *			I2LINE
323  *			I2DATE
324  *			I2RTIME
325  *			I2MSG
326  *
327  *		If I2NAME is set `program_name', followed by a ":" is
328  *		copied to `arg->fp'.
329  *
330  *		If I2FILE is set the string "FILE=", followed by
331  *		`file', followed by ",", followed by a space is copied
332  *		to `arg->fp'.
333  *
334  *		If I2LINE is set the string "LINE=", followed by the ascii
335  *		representation of `line', followed by ",", followed by
336  *		a space is copied to `arg->fp'.
337  *
338  *		If I2DATE is set the string "DATE=", followed by
339  *		`date', followed by ",", followed by a space is copied
340  *		to `arg->fp'.
341  *
342  *		If I2RTIME is set the string "RTIME=", followed by
343  *		`time', followed by ",", followed by a space is copied
344  *		to `arg->fp', where `time' is string formatted by
345  *		arg->tformat.
346  *
347  *		If I2MSG is set `msg' is copied to `arg->fp.
348  *
349  *
350  * In Args:
351  *
352  *	*arg	A pointer to a I2ErrLogSyslogAttr structure.
353  *
354  * Out Args:
355  *
356  * Return Values:
357  *
358  * Side Effects:
359  */
I2ErrLogSyslog(struct I2ErrLogEvent * ev,void * arg,void ** data)360 void	I2ErrLogSyslog(
361 	struct I2ErrLogEvent	*ev,
362 	void			*arg,
363 	void			**data
364 )
365 {
366 	I2ErrLogSyslogAttr	*sa = (I2ErrLogSyslogAttr *) arg;
367 	char			buf[4096], *bufptr;
368 	size_t			size=sizeof(buf);
369 	int			rc;
370         int                     prio;
371 
372 	bufptr = buf;
373 
374 	if(*data == NULL && sa->ident){
375 		openlog((char *) sa->ident, sa->logopt, sa->facility);
376 		*data = (void *) 1;
377 	}
378 
379 	if(ev->mask & sa->line_info & I2NAME) {
380 		rc = snprintf(bufptr,size,"%s: ", ev->name);
381 		bufptr += rc;
382 		size -= rc;
383 	}
384 
385 	if(ev->mask & sa->line_info & I2FILE){
386 		rc = snprintf(bufptr,size,"FILE=%s, ", ev->file);
387 		bufptr += rc;
388 		size -= rc;
389 	}
390 
391 	if(ev->mask & sa->line_info & I2LINE){
392 		rc = snprintf(bufptr,size,"LINE=%d, ", ev->line);
393 		bufptr += rc;
394 		size -= rc;
395 	}
396 
397 	if(ev->mask & sa->line_info & I2DATE){
398 		rc = snprintf(bufptr,size,"DATE=%s, ", ev->date);
399 		bufptr += rc;
400 		size -= rc;
401 	}
402 
403 	if(sa->line_info & I2RTIME){
404 		time_t		clock;
405 		struct tm	*tm;
406 		char		ftime[64];
407 
408 		time(&clock);
409 		tm = localtime(&clock);
410 		if( strftime(ftime,sizeof(ftime),sa->tformat,tm)){
411 			rc = snprintf(bufptr,size,"RTIME=%s, ",ftime);
412 			bufptr += rc;
413 			size -= rc;
414 		}
415 	}
416 
417 	if(ev->mask & sa->line_info & I2MSG){
418 		rc = sprintf(bufptr, "%s", ev->msg);
419 		bufptr += rc;
420 	}
421 
422 	if(bufptr == buf)
423 		return;
424 
425 	if(ev->mask & I2LEVEL)
426             prio = ev->level;
427 	else
428             prio = sa->priority;
429 
430         if(prio != I2LOG_NONE)
431 	    syslog(prio, "%s", buf);
432 
433 #ifndef HAVE_SYSLOG_PERROR
434         if(sa->logopt | LOG_PERROR){
435             fprintf(stderr,"%s\n", buf);
436         }
437 #endif
438 
439         return;
440 }
441 
442 /*
443  * Function:	I2ErrResetSyslog
444  *
445  * Description:
446  * 		Used to reset syslog error logging. Useful in case of
447  * 		forking etc...
448  *
449  * In Args:
450  *
451  * Out Args:
452  *
453  * Scope:
454  * Returns:
455  * Side Effect:
456  */
I2ErrLogSyslogReset(void * arg,void ** data)457 I2Boolean	I2ErrLogSyslogReset(
458 		void	*arg __attribute__((unused)),
459 		void	**data
460 		)
461 {
462 	closelog();
463 	*data = NULL;
464 
465 	return True;
466 }
467 
468