Home | History | Annotate | Line # | Download | only in rpcapd
log.c revision 1.1.1.3
      1 /*
      2  * Copyright (c) 1993, 1994, 1995, 1996, 1998
      3  *	The Regents of the University of California.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that: (1) source code distributions
      7  * retain the above copyright notice and this paragraph in its entirety, (2)
      8  * distributions including binary code include the above copyright notice and
      9  * this paragraph in its entirety in the documentation or other materials
     10  * provided with the distribution, and (3) all advertising materials mentioning
     11  * features or use of this software display the following acknowledgement:
     12  * ``This product includes software developed by the University of California,
     13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
     14  * the University nor the names of its contributors may be used to endorse
     15  * or promote products derived from this software without specific prior
     16  * written permission.
     17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
     18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     20  */
     21 
     22 #include <config.h>
     23 
     24 #include <stdio.h>
     25 #include <stdarg.h>
     26 #include <stdlib.h>
     27 
     28 #ifdef _WIN32
     29 #include <windows.h>
     30 #else
     31 #include <syslog.h>
     32 #endif
     33 
     34 #include "portability.h"
     35 
     36 #include "log.h"
     37 
     38 static int log_to_systemlog;
     39 static int log_debug_messages;
     40 
     41 static void rpcapd_vlog_stderr(log_priority,
     42     PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0);
     43 
     44 static void rpcapd_vlog_stderr(log_priority priority, const char *message, va_list ap)
     45 {
     46 	const char *tag;
     47 
     48 	/*
     49 	 * Squelch warnings from compilers that *don't* assume that
     50 	 * priority always has a valid enum value and therefore don't
     51 	 * assume that we'll always go through one of the case arms.
     52 	 *
     53 	 * If we have a default case, compilers that *do* assume that
     54 	 * will then complain about the default case code being
     55 	 * unreachable.
     56 	 *
     57 	 * Damned if you do, damned if you don't.
     58 	 */
     59 	tag = "";
     60 
     61 	switch (priority) {
     62 
     63 	case LOGPRIO_DEBUG:
     64 		tag = "DEBUG: ";
     65 		break;
     66 
     67 	case LOGPRIO_INFO:
     68 		tag = "";
     69 		break;
     70 
     71 	case LOGPRIO_WARNING:
     72 		tag = "warning: ";
     73 		break;
     74 
     75 	case LOGPRIO_ERROR:
     76 		tag = "error: ";
     77 		break;
     78 	}
     79 
     80 	fprintf(stderr, "rpcapd: %s", tag);
     81 	vfprintf(stderr, message, ap);
     82 	putc('\n', stderr);
     83 }
     84 
     85 static void rpcapd_vlog_systemlog(log_priority,
     86     PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0);
     87 
     88 #ifdef _WIN32
     89 #define MESSAGE_SUBKEY \
     90     "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\rpcapd"
     91 
     92 static void rpcapd_vlog_systemlog(log_priority priority, const char *message,
     93     va_list ap)
     94 {
     95 #if 0
     96 	static int initialized = 0;
     97 	HKEY hey_handle;
     98 	static HANDLE log_handle;
     99 	WORD eventlog_type;
    100 	DWORD event_id;
    101 	char msgbuf[1024];
    102 	char *strings[1];
    103 
    104 	if (!initialized) {
    105 		/*
    106 		 * Register our message stuff in the Registry.
    107 		 *
    108 		 * First, create the registry key for us.  If the key
    109 		 * already exists, this succeeds and returns a handle
    110 		 * for it.
    111 		 */
    112 		if (RegCreateKey(HKEY_LOCAL_MACHINE, MESSAGE_SUBKEY,
    113 		    &key_handle) != ERROR_SUCCESS) {
    114 			/*
    115 			 * Failed - give up and just log this message,
    116 			 * and all subsequent messages, to the
    117 			 * standard error.
    118 			 */
    119 			log_to_systemlog = 0;
    120 			initialized = 1;
    121 			rpcapd_vlog_stderr(priority, message, ap);
    122 			return;
    123 		}
    124 		log_handle = RegisterEventSource(NULL, "rpcapd");
    125 		initialized = 1;
    126 	}
    127 
    128 	switch (priority) {
    129 
    130 	case LOGPRIO_DEBUG:
    131 		//
    132 		// XXX - what *should* we do about debug messages?
    133 		//
    134 		eventlog_type = EVENTLOG_INFORMATION_TYPE;
    135 		event_id = RPCAPD_INFO_ID;
    136 		break;
    137 
    138 	case LOGPRIO_INFO:
    139 		eventlog_type = EVENTLOG_INFORMATION_TYPE;
    140 		event_id = RPCAPD_INFO_ID;
    141 		break;
    142 
    143 	case LOGPRIO_WARNING:
    144 		eventlog_type = EVENTLOG_WARNING_TYPE;
    145 		event_id = RPCAPD_WARNING_ID;
    146 		break;
    147 
    148 	case LOGPRIO_ERROR:
    149 		eventlog_type = EVENTLOG_ERROR_TYPE;
    150 		event_id = RPCAPD_ERROR_ID;
    151 		break;
    152 
    153 	default:
    154 		/* Don't do this. */
    155 		return;
    156 	}
    157 
    158 	vsprintf(msgbuf, message, ap);
    159 
    160 	strings[0] = msgbuf;
    161 	/*
    162 	 * If this fails, how are we going to report it?
    163 	 */
    164 	(void) ReportEvent(log_handle, eventlog_type, 0, event_id, NULL, 1, 0,
    165 	    strings, NULL);
    166 #else
    167 	rpcapd_vlog_stderr(priority, message, ap);
    168 #endif
    169 }
    170 #else
    171 static void rpcapd_vlog_systemlog(log_priority priority, const char *message,
    172     va_list ap)
    173 {
    174 	static int initialized = 0;
    175 	int syslog_priority;
    176 
    177 	if (!initialized) {
    178 		//
    179 		// Open the log.
    180 		//
    181 		openlog("rpcapd", LOG_PID, LOG_DAEMON);
    182 		initialized = 1;
    183 	}
    184 
    185 	switch (priority) {
    186 
    187 	case LOGPRIO_DEBUG:
    188 		syslog_priority = LOG_DEBUG;
    189 		break;
    190 
    191 	case LOGPRIO_INFO:
    192 		syslog_priority = LOG_INFO;
    193 		break;
    194 
    195 	case LOGPRIO_WARNING:
    196 		syslog_priority = LOG_WARNING;
    197 		break;
    198 
    199 	case LOGPRIO_ERROR:
    200 		syslog_priority = LOG_ERR;
    201 		break;
    202 
    203 	default:
    204 		/* Don't do this. */
    205 		return;
    206 	}
    207 
    208 #ifdef HAVE_VSYSLOG
    209 	vsyslog(syslog_priority, message, ap);
    210 #else
    211 	/*
    212 	 * Thanks, IBM, for not providing vsyslog() in AIX!
    213 	 *
    214 	 * They also warn that the syslog functions shouldn't
    215 	 * be used in multithreaded programs, but the only thing
    216 	 * obvious that seems to make the syslog_r functions
    217 	 * better is that they have an additional argument
    218 	 * that points to the information that's static to
    219 	 * the syslog code in non-thread-safe versions.  Most
    220 	 * of that data is set by openlog(); since we already
    221 	 * do an openlog before doing logging, and don't
    222 	 * change that data afterwards, I suspect that, in
    223 	 * practice, the regular syslog routines are OK for
    224 	 * us (especially given that we'd end up having one
    225 	 * static struct syslog_data anyway, which means we'd
    226 	 * just be like the non-thread-safe version).
    227 	 */
    228 	char logbuf[1024+1];
    229 
    230 	vsnprintf(logbuf, sizeof logbuf, message, ap);
    231 	syslog(syslog_priority, "%s", logbuf);
    232 #endif
    233 }
    234 #endif
    235 
    236 void rpcapd_log_set(int log_to_systemlog_arg, int log_debug_messages_arg)
    237 {
    238 	log_debug_messages = log_debug_messages_arg;
    239 	log_to_systemlog = log_to_systemlog_arg;
    240 }
    241 
    242 void rpcapd_log(log_priority priority, const char *message, ...)
    243 {
    244 	va_list ap;
    245 
    246 	if (priority != LOGPRIO_DEBUG || log_debug_messages) {
    247 		va_start(ap, message);
    248 		if (log_to_systemlog)
    249 		{
    250 			rpcapd_vlog_systemlog(priority, message, ap);
    251 		}
    252 		else
    253 		{
    254 			rpcapd_vlog_stderr(priority, message, ap);
    255 		}
    256 		va_end(ap);
    257 	}
    258 }
    259