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