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