From db7c242983986fbb69d7c292b81057d07ad043fa Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Wed, 21 Jun 2017 06:02:20 -0600 Subject: [PATCH] rktio: add syslog --- racket/src/racket/src/error.c | 101 ++------------ racket/src/rktio/Makefile.in | 4 + racket/src/rktio/rktio.h | 19 +++ racket/src/rktio/rktio_main.c | 3 + racket/src/rktio/rktio_private.h | 7 + racket/src/rktio/rktio_syslog.c | 142 ++++++++++++++++++++ racket/src/rktio/rktio_wide.c | 1 + racket/src/worksp/librktio/librktio.vcproj | 4 + racket/src/worksp/librktio/librktio.vcxproj | 1 + 9 files changed, 192 insertions(+), 90 deletions(-) create mode 100644 racket/src/rktio/rktio_syslog.c diff --git a/racket/src/racket/src/error.c b/racket/src/racket/src/error.c index eddfb10e40..7cbf1e707e 100644 --- a/racket/src/racket/src/error.c +++ b/racket/src/racket/src/error.c @@ -34,10 +34,6 @@ #else # include #endif -#ifdef USE_C_SYSLOG -# include -# include -#endif #define mzVA_ARG(x, y) HIDE_FROM_XFORM(va_arg(x, y)) #define TMP_CMARK_VALUE scheme_parameterization_key @@ -3820,16 +3816,6 @@ Scheme_Object *extract_all_levels(Scheme_Logger *logger) return result; } -#ifdef USE_WINDOWS_EVENT_LOG -static int event_procs_ready; -typedef HANDLE (WINAPI *mzRegisterEventSourceProc)(LPCTSTR lpUNCServerName, LPCTSTR lpSourceName); -typedef BOOL (WINAPI *mzReportEventProc)(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, - PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, LPCTSTR* lpStrings, - LPVOID lpRawData); -static mzRegisterEventSourceProc mzRegisterEventSource; -static mzReportEventProc mzReportEvent; -#endif - static Scheme_Object *make_log_message(int level, Scheme_Object *name, int prefix_msg, char *buffer, intptr_t len, Scheme_Object *data) { Scheme_Object *msg; @@ -3892,97 +3878,32 @@ void scheme_log_name_pfx_message(Scheme_Logger *logger, int level, Scheme_Object while (logger) { if (extract_spec_level(logger->syslog_level, name) >= level) { -#ifdef USE_C_SYSLOG int pri; + Scheme_Object *cmd; switch (level) { case SCHEME_LOG_FATAL: - pri = LOG_CRIT; + pri = RKTIO_LOG_FATAL; break; case SCHEME_LOG_ERROR: - pri = LOG_ERR; + pri = RKTIO_LOG_ERROR; break; case SCHEME_LOG_WARNING: - pri = LOG_WARNING; + pri = RKTIO_LOG_WARNING; break; case SCHEME_LOG_INFO: - pri = LOG_INFO; + pri = RKTIO_LOG_INFO; break; case SCHEME_LOG_DEBUG: default: - pri = LOG_DEBUG; + pri = RKTIO_LOG_DEBUG; break; } - if (name) - syslog(pri, "%s: %s", SCHEME_SYM_VAL(name), buffer); - else - syslog(pri, "%s", buffer); -#endif -#ifdef USE_WINDOWS_EVENT_LOG - if (!event_procs_ready) { - HMODULE hm; - hm = LoadLibrary("advapi32.dll"); - if (hm) { - mzRegisterEventSource = (mzRegisterEventSourceProc)GetProcAddress(hm, "RegisterEventSourceA"); - mzReportEvent = (mzReportEventProc)GetProcAddress(hm, "ReportEventA"); - } - event_procs_ready = 1; - } - if (mzRegisterEventSource) { - static HANDLE hEventLog; - WORD ty; - unsigned long sev; - LPCTSTR a[1]; - - if (!hEventLog) { - Scheme_Object *cmd; - cmd = scheme_get_run_cmd(); - hEventLog = mzRegisterEventSource(NULL, SCHEME_PATH_VAL(cmd)); - } - - switch (level) { - case SCHEME_LOG_FATAL: - ty = EVENTLOG_ERROR_TYPE; - sev = 3; - break; - case SCHEME_LOG_ERROR: - ty = EVENTLOG_ERROR_TYPE; - sev = 3; - break; - case SCHEME_LOG_WARNING: - ty = EVENTLOG_WARNING_TYPE; - sev = 2; - break; - case SCHEME_LOG_INFO: - ty = EVENTLOG_INFORMATION_TYPE; - sev = 1; - break; - case SCHEME_LOG_DEBUG: - default: - ty = EVENTLOG_AUDIT_SUCCESS; - sev = 0; - break; - } - if (name) { - char *naya; - intptr_t slen; - slen = SCHEME_SYM_LEN(name); - naya = (char *)scheme_malloc_atomic(slen + 2 + len + 1); - memcpy(naya, SCHEME_SYM_VAL(name), slen); - memcpy(naya + slen, ": ", 2); - memcpy(naya + slen + 2, buffer, len); - naya[slen + 2 + len] = 0; - buffer = naya; - len += slen + 2; - } - a[0] = buffer; - mzReportEvent(hEventLog, ty, 1 /* category */, - (sev << 30) | 2 /* message */, - NULL, - 1, 0, - a, NULL); - } -#endif + cmd = scheme_get_run_cmd(); + rktio_syslog(scheme_rktio, pri, + (name ? SCHEME_SYM_VAL(name) : NULL), + buffer, SCHEME_PATH_VAL(cmd)); } + if (extract_spec_level(logger->stderr_level, name) >= level) { if (name) { intptr_t slen; diff --git a/racket/src/rktio/Makefile.in b/racket/src/rktio/Makefile.in index 2125044233..ec40f7aaf0 100644 --- a/racket/src/rktio/Makefile.in +++ b/racket/src/rktio/Makefile.in @@ -27,6 +27,7 @@ OBJS = rktio_fs.@LTO@ \ rktio_flock.@LTO@ \ rktio_shellex.@LTO@ \ rktio_time.@LTO@ \ + rktio_syslog.@LTO@ \ rktio_error.@LTO@ \ rktio_hash.@LTO@ \ rktio_wide.@LTO@ \ @@ -81,6 +82,9 @@ rktio_shellex.@LTO@: $(srcdir)/rktio_shellex.c $(RKTIO_HEADERS) rktio_time.@LTO@: $(srcdir)/rktio_time.c $(RKTIO_HEADERS) $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_time.@LTO@ -c $(srcdir)/rktio_time.c +rktio_syslog.@LTO@: $(srcdir)/rktio_syslog.c $(RKTIO_HEADERS) + $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_syslog.@LTO@ -c $(srcdir)/rktio_syslog.c + rktio_error.@LTO@: $(srcdir)/rktio_error.c $(RKTIO_HEADERS) $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_error.@LTO@ -c $(srcdir)/rktio_error.c diff --git a/racket/src/rktio/rktio.h b/racket/src/rktio/rktio.h index 56fca913ce..d9bba5edaf 100644 --- a/racket/src/rktio/rktio.h +++ b/racket/src/rktio/rktio.h @@ -885,6 +885,25 @@ char *rktio_wide_path_to_path(rktio_t *rktio, const void *wp); is actually a `wchar_t*`. The `rktio_path_to_wide_path` function can fail and report `RKTIO_ERROR_INVALID_PATH`. */ +/*************************************************/ +/* Logging */ + +rktio_ok_t rktio_syslog(rktio_t *rktio, int level, const char *name, const char *msg, + const char *exec_name); +/* Adds a message to the system log. The `name` argument can be NULL, + and it is added to the front of the message with a separating ": " + if non_NULL. The `exec_name` is the current executable name; it's + currently, used only on Windows, and the value may matter only the + first time that `rktio_syslog` is called. */ +/* `level` values: */ +enum { + RKTIO_LOG_FATAL = 1, + RKTIO_LOG_ERROR, + RKTIO_LOG_WARNING, + RKTIO_LOG_INFO, + RKTIO_LOG_DEBUG +}; + /*************************************************/ /* Errors */ diff --git a/racket/src/rktio/rktio_main.c b/racket/src/rktio/rktio_main.c index 980302af82..833bfff905 100644 --- a/racket/src/rktio/rktio_main.c +++ b/racket/src/rktio/rktio_main.c @@ -31,11 +31,14 @@ rktio_t *rktio_init(void) rktio_init_time(rktio); rktio_init_wide(rktio); + rktio_syslog_init(rktio); + return rktio; } void rktio_destroy(rktio_t *rktio) { + rktio_syslog_clean(rktio); rktio_error_clean(rktio); rktio_process_deinit(rktio); rktio_free_ghbn(rktio); diff --git a/racket/src/rktio/rktio_private.h b/racket/src/rktio/rktio_private.h index 893ad825f5..a4da11158c 100644 --- a/racket/src/rktio/rktio_private.h +++ b/racket/src/rktio/rktio_private.h @@ -91,6 +91,10 @@ struct rktio_t { wchar_t *wide_buffer; #endif +#ifdef RKTIO_SYSTEM_WINDOWS + HANDLE hEventLog; +#endif + #ifdef RKTIO_USE_FCNTL_AND_FORK_FOR_FILE_LOCKS struct rktio_hash_t *locked_fd_process_map; #endif @@ -311,6 +315,9 @@ int rktio_make_os_pipe(rktio_t *rktio, intptr_t *a, int flags); char **rktio_get_environ_array(void); #endif +void rktio_syslog_init(rktio_t* rktio); +void rktio_syslog_clean(rktio_t* rktio); + #ifdef USE_TRANSITIONAL_64_FILE_OPS # define BIG_OFF_T_IZE(n) n ## 64 #else diff --git a/racket/src/rktio/rktio_syslog.c b/racket/src/rktio/rktio_syslog.c new file mode 100644 index 0000000000..28782a108a --- /dev/null +++ b/racket/src/rktio/rktio_syslog.c @@ -0,0 +1,142 @@ +#include "rktio.h" +#include "rktio_private.h" + +#ifdef RKTIO_SYSTEM_UNIX +# include +#endif + +#ifdef RKTIO_SYSTEM_WINDOWS +# include +# include +static int event_procs_ready; +typedef HANDLE (WINAPI *do_RegisterEventSourceProc)(wchar_t *lpUNCServerName, wchar_t *lpSourceName); +typedef BOOL (WINAPI *do_ReportEventProc)(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, + PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, const wchar_t** lpStrings, + LPVOID lpRawData); +static do_RegisterEventSourceProc do_RegisterEventSource; +static do_ReportEventProc do_ReportEvent; +#endif + +void rktio_syslog_init(rktio_t *rktio) +{ +#ifdef RKTIO_SYSTEM_WINDOWS + if (!event_procs_ready) { + HMODULE hm; + hm = LoadLibraryW(L"advapi32.dll"); + if (hm) { + do_RegisterEventSource = (do_RegisterEventSourceProc)GetProcAddress(hm, "RegisterEventSourceW"); + do_ReportEvent = (do_ReportEventProc)GetProcAddress(hm, "ReportEventW"); + } + event_procs_ready = 1; + } + + rktio->hEventLog = INVALID_HANDLE_VALUE; +#endif +} + +void rktio_syslog_clean(rktio_t *rktio) +{ +#ifdef RKTIO_SYSTEM_WINDOWS + if (rktio->hEventLog != INVALID_HANDLE_VALUE) + CloseHandle(rktio->hEventLog); +#endif +} + +rktio_ok_t rktio_syslog(rktio_t *rktio, int level, const char *name, const char *msg, const char *exec_name) +{ +#ifdef RKTIO_SYSTEM_UNIX + int pri; + switch (level) { + case RKTIO_LOG_FATAL: + pri = LOG_CRIT; + break; + case RKTIO_LOG_ERROR: + pri = LOG_ERR; + break; + case RKTIO_LOG_WARNING: + pri = LOG_WARNING; + break; + case RKTIO_LOG_INFO: + pri = LOG_INFO; + break; + case RKTIO_LOG_DEBUG: + default: + pri = LOG_DEBUG; + break; + } + if (name) + syslog(pri, "%s: %s", name, msg); + else + syslog(pri, "%s", msg); + return 1; +#endif +#ifdef RKTIO_SYSTEM_WINDOWS + if (do_RegisterEventSource) { + WORD ty; + unsigned long sev; + const wchar_t *a[1]; + char *naya = NULL; + int ok; + + if (rktio->hEventLog == INVALID_HANDLE_VALUE) { + rktio->hEventLog = do_RegisterEventSource(NULL, WIDE_PATH_temp(exec_name)); + if (rktio->hEventLog == INVALID_HANDLE_VALUE) { + get_windows_error(); + return 0; + } + } + + switch (level) { + case RKTIO_LOG_FATAL: + ty = EVENTLOG_ERROR_TYPE; + sev = 3; + break; + case RKTIO_LOG_ERROR: + ty = EVENTLOG_ERROR_TYPE; + sev = 3; + break; + case RKTIO_LOG_WARNING: + ty = EVENTLOG_WARNING_TYPE; + sev = 2; + break; + case RKTIO_LOG_INFO: + ty = EVENTLOG_INFORMATION_TYPE; + sev = 1; + break; + case RKTIO_LOG_DEBUG: + default: + ty = EVENTLOG_AUDIT_SUCCESS; + sev = 0; + break; + } + if (name) { + intptr_t len, slen; + slen = strlen(name); + len = strlen(msg); + naya = malloc(slen + 2 + len + 1); + memcpy(naya, name, slen); + memcpy(naya + slen, ": ", 2); + memcpy(naya + slen + 2, msg, len); + naya[slen + 2 + len] = 0; + msg = naya; + } + a[0] = WIDE_PATH_temp(msg); + + ok = do_ReportEvent(rktio->hEventLog, ty, 1 /* category */, + (sev << 30) | 2 /* message */, + NULL, + 1, 0, + a, NULL); + if (!ok) + get_windows_error(); + + if (naya) + free(naya); + + return ok; + } else { + set_racket_error(RKTIO_ERROR_UNSUPPORTED); + return 0; + } +#endif +} diff --git a/racket/src/rktio/rktio_wide.c b/racket/src/rktio/rktio_wide.c index fb72092d55..6350280d9e 100644 --- a/racket/src/rktio/rktio_wide.c +++ b/racket/src/rktio/rktio_wide.c @@ -1,5 +1,6 @@ #include "rktio.h" #include "rktio_private.h" +#include /* For converting byte strings to and from "wide" strings on Windows. */ diff --git a/racket/src/worksp/librktio/librktio.vcproj b/racket/src/worksp/librktio/librktio.vcproj index 0c7ae2555a..109f62b7b8 100644 --- a/racket/src/worksp/librktio/librktio.vcproj +++ b/racket/src/worksp/librktio/librktio.vcproj @@ -162,6 +162,10 @@ RelativePath="..\..\rktio\rktio_time.c" > + + diff --git a/racket/src/worksp/librktio/librktio.vcxproj b/racket/src/worksp/librktio/librktio.vcxproj index a5b9a58a86..8a8a7612fa 100644 --- a/racket/src/worksp/librktio/librktio.vcxproj +++ b/racket/src/worksp/librktio/librktio.vcxproj @@ -129,6 +129,7 @@ +