| /* |
| * Copyright (c) 1993, 1994, 1995, 1996, 1998 |
| * The Regents of the University of California. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that: (1) source code distributions |
| * retain the above copyright notice and this paragraph in its entirety, (2) |
| * distributions including binary code include the above copyright notice and |
| * this paragraph in its entirety in the documentation or other materials |
| * provided with the distribution, and (3) all advertising materials mentioning |
| * features or use of this software display the following acknowledgement: |
| * ``This product includes software developed by the University of California, |
| * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of |
| * the University nor the names of its contributors may be used to endorse |
| * or promote products derived from this software without specific prior |
| * written permission. |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #endif |
| |
| #include <stdio.h> |
| #include <stdarg.h> |
| #include <stdlib.h> |
| |
| #ifdef _WIN32 |
| #include <windows.h> |
| #else |
| #include <syslog.h> |
| #endif |
| |
| #include "portability.h" |
| |
| #include "log.h" |
| |
| static int log_to_systemlog; |
| static int log_debug_messages; |
| |
| static void rpcapd_vlog_stderr(log_priority, |
| PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0); |
| |
| static void rpcapd_vlog_stderr(log_priority priority, const char *message, va_list ap) |
| { |
| const char *tag; |
| |
| /* |
| * Squelch warnings from compilers that *don't* assume that |
| * priority always has a valid enum value and therefore don't |
| * assume that we'll always go through one of the case arms. |
| * |
| * If we have a default case, compilers that *do* assume that |
| * will then complain about the default case code being |
| * unreachable. |
| * |
| * Damned if you do, damned if you don't. |
| */ |
| tag = ""; |
| |
| switch (priority) { |
| |
| case LOGPRIO_DEBUG: |
| tag = "DEBUG: "; |
| break; |
| |
| case LOGPRIO_INFO: |
| tag = ""; |
| break; |
| |
| case LOGPRIO_WARNING: |
| tag = "warning: "; |
| break; |
| |
| case LOGPRIO_ERROR: |
| tag = "error: "; |
| break; |
| } |
| |
| fprintf(stderr, "rpcapd: %s", tag); |
| vfprintf(stderr, message, ap); |
| putc('\n', stderr); |
| } |
| |
| static void rpcapd_vlog_systemlog(log_priority, |
| PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0); |
| |
| #ifdef _WIN32 |
| #define MESSAGE_SUBKEY \ |
| "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\rpcapd" |
| |
| static void rpcapd_vlog_systemlog(log_priority priority, const char *message, |
| va_list ap) |
| { |
| #if 0 |
| static int initialized = 0; |
| HKEY hey_handle; |
| static HANDLE log_handle; |
| WORD eventlog_type; |
| DWORD event_id; |
| char msgbuf[1024]; |
| char *strings[1]; |
| |
| if (!initialized) { |
| /* |
| * Register our message stuff in the Registry. |
| * |
| * First, create the registry key for us. If the key |
| * already exists, this succeeds and returns a handle |
| * for it. |
| */ |
| if (RegCreateKey(HKEY_LOCAL_MACHINE, MESSAGE_SUBKEY, |
| &key_handle) != ERROR_SUCCESS) { |
| /* |
| * Failed - give up and just log this message, |
| * and all subsequent messages, to the |
| * standard error. |
| */ |
| log_to_systemlog = 0; |
| initialized = 1; |
| rpcapd_vlog_stderr(priority, message, ap); |
| return; |
| } |
| log_handle = RegisterEventSource(NULL, "rpcapd"); |
| initialized = 1; |
| } |
| |
| switch (priority) { |
| |
| case LOGPRIO_DEBUG: |
| // |
| // XXX - what *should* we do about debug messages? |
| // |
| eventlog_type = EVENTLOG_INFORMATION_TYPE; |
| event_id = RPCAPD_INFO_ID; |
| break; |
| |
| case LOGPRIO_INFO: |
| eventlog_type = EVENTLOG_INFORMATION_TYPE; |
| event_id = RPCAPD_INFO_ID; |
| break; |
| |
| case LOGPRIO_WARNING: |
| eventlog_type = EVENTLOG_WARNING_TYPE; |
| event_id = RPCAPD_WARNING_ID; |
| break; |
| |
| case LOGPRIO_ERROR: |
| eventlog_type = EVENTLOG_ERROR_TYPE; |
| event_id = RPCAPD_ERROR_ID; |
| break; |
| |
| default: |
| /* Don't do this. */ |
| return; |
| } |
| |
| vsprintf(msgbuf, message, ap); |
| |
| strings[0] = msgbuf; |
| /* |
| * If this fails, how are we going to report it? |
| */ |
| (void) ReportEvent(log_handle, eventlog_type, 0, event_id, NULL, 1, 0, |
| strings, NULL); |
| #else |
| rpcapd_vlog_stderr(priority, message, ap); |
| #endif |
| } |
| #else |
| static void rpcapd_vlog_systemlog(log_priority priority, const char *message, |
| va_list ap) |
| { |
| static int initialized = 0; |
| int syslog_priority; |
| |
| if (!initialized) { |
| // |
| // Open the log. |
| // |
| openlog("rpcapd", LOG_PID, LOG_DAEMON); |
| initialized = 1; |
| } |
| |
| switch (priority) { |
| |
| case LOGPRIO_DEBUG: |
| syslog_priority = LOG_DEBUG; |
| break; |
| |
| case LOGPRIO_INFO: |
| syslog_priority = LOG_INFO; |
| break; |
| |
| case LOGPRIO_WARNING: |
| syslog_priority = LOG_WARNING; |
| break; |
| |
| case LOGPRIO_ERROR: |
| syslog_priority = LOG_ERR; |
| break; |
| |
| default: |
| /* Don't do this. */ |
| return; |
| } |
| |
| #ifdef HAVE_VSYSLOG |
| vsyslog(syslog_priority, message, ap); |
| #else |
| /* |
| * Thanks, IBM, for not providing vsyslog() in AIX! |
| * |
| * They also warn that the syslog functions shouldn't |
| * be used in multithreaded programs, but the only thing |
| * obvious that seems to make the syslog_r functions |
| * better is that they have an additional argument |
| * that points to the information that's static to |
| * the syslog code in non-thread-safe versions. Most |
| * of that data is set by openlog(); since we already |
| * do an openlog before doing logging, and don't |
| * change that data afterwards, I suspect that, in |
| * practice, the regular syslog routines are OK for |
| * us (especially given that we'd end up having one |
| * static struct syslog_data anyway, which means we'd |
| * just be like the non-thread-safe version). |
| */ |
| char logbuf[1024+1]; |
| |
| vsnprintf(logbuf, sizeof logbuf, message, ap); |
| syslog(syslog_priority, "%s", logbuf); |
| #endif |
| } |
| #endif |
| |
| void rpcapd_log_set(int log_to_systemlog_arg, int log_debug_messages_arg) |
| { |
| log_debug_messages = log_debug_messages_arg; |
| log_to_systemlog = log_to_systemlog_arg; |
| } |
| |
| void rpcapd_log(log_priority priority, const char *message, ...) |
| { |
| va_list ap; |
| |
| if (priority != LOGPRIO_DEBUG || log_debug_messages) { |
| va_start(ap, message); |
| if (log_to_systemlog) |
| { |
| rpcapd_vlog_systemlog(priority, message, ap); |
| } |
| else |
| { |
| rpcapd_vlog_stderr(priority, message, ap); |
| } |
| va_end(ap); |
| } |
| } |