From 1df9b19429212012b245a88b08ab37caef564d1c Mon Sep 17 00:00:00 2001 From: Steve Bennett Date: Sun, 24 Jan 2010 10:26:24 +1000 Subject: Implement some new features Implement 'lreplace' Implement 'string last' Implement 'pid' Implement 'info procs' Implement 'info script' Implement 'info patchlevel' as an alias for 'info version' Implement syslog extensions for jim Fix return code display in jim-interactive.c Make jim more compatible if JIM_TCL_COMPAT is set *: Use tcl_interactive rather than jim_interactive *: Use auto_path rather than jim_libpath Add "." to the lib search path, not "./" Fix a couple of files with CRLF line endings --- jim-syslog.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 jim-syslog.c (limited to 'jim-syslog.c') diff --git a/jim-syslog.c b/jim-syslog.c new file mode 100644 index 0000000..4a039ef --- /dev/null +++ b/jim-syslog.c @@ -0,0 +1,199 @@ +/* Syslog interface for tcl + * Copyright Victor Wagner at + * http://www.ice.ru/~vitus/works/tcl.html#syslog + * + * Slightly modified by Steve Bennett + * Ported to Jim by Steve Bennett + */ +#include +#include +#include + +typedef struct { + int logOpened; + int facility; + int options; + char ident[32]; +} SyslogInfo; + +#ifndef LOG_AUTHPRIV +# define LOG_AUTHPRIV LOG_AUTH +#endif + +static const char *facilities[] = { + [LOG_AUTHPRIV] = "authpriv", + [LOG_CRON] = "cron", + [LOG_DAEMON] = "daemon", + [LOG_KERN] = "kernel", + [LOG_LPR] = "lpr", + [LOG_MAIL] = "mail", + [LOG_NEWS] = "news", + [LOG_SYSLOG] = "syslog", + [LOG_USER] = "user", + [LOG_UUCP] = "uucp", + [LOG_LOCAL0] = "local0", + [LOG_LOCAL1] = "local1", + [LOG_LOCAL2] = "local2", + [LOG_LOCAL3] = "local3", + [LOG_LOCAL4] = "local4", + [LOG_LOCAL5] = "local5", + [LOG_LOCAL6] = "local6", + [LOG_LOCAL7] = "local7", +}; + +static const char *priorities[] = { + [LOG_EMERG] = "emerg", + [LOG_ALERT] = "alert", + [LOG_CRIT] = "crit", + [LOG_ERR] = "err", + [LOG_ERR] = "error", + [LOG_WARNING] = "warning", + [LOG_NOTICE] = "notice", + [LOG_INFO] = "info", + [LOG_DEBUG] = "debug", +}; + +/** + * Find a matching name in the array of the given length. + * + * NULL entries are ignored. + * + * Returns the matching index if found, or -1 if not. + */ +static int find_by_name(const char *name, const char *array[], size_t len) +{ + int i; + for (i = 0; i < len; i++) { + if (array[i] && strcmp(array[i], name) == 0) { + return i; + } + } + return -1; +} + +/** + * Deletes the syslog command. + */ +static void Jim_SyslogCmdDelete(Jim_Interp *interp, void *privData) +{ + SyslogInfo *info=(SyslogInfo *)privData; + if (info->logOpened) { + closelog(); + } + Jim_Free(info); +} + +/* Syslog_Log - + * implements syslog tcl command. General format: syslog ?options? level text + * options -facility -ident -options + * + * syslog ?-facility cron|daemon|...? ?-ident string? ?-options int? ?debug|info|...? text + */ +int +Jim_SyslogCmd (Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int priority = LOG_INFO; + int i=1; + SyslogInfo *info = Jim_CmdPrivData(interp); + + if (argc <= 1) { +wrongargs: + Jim_WrongNumArgs(interp, 1, argv, "?-facility cron|daemon|...? ?-ident string? ?-options int? ?debug|info|...? message"); + return JIM_ERR; + } + while (i < argc-1) { + if (Jim_CompareStringImmediate(interp, argv[i], "-facility")) { + int entry = find_by_name(Jim_GetString(argv[i + 1], NULL), facilities, sizeof(facilities) / sizeof(*facilities)); + if (entry < 0) { + Jim_SetResultString(interp, "Unknown facility", -1); + return JIM_ERR; + } + if (info->facility != entry) { + info->facility = entry; + if (info->logOpened) { + closelog(); + info->logOpened=0; + } + } + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-options")) { + long tmp; + if (Jim_GetLong(interp, argv[i+1], &tmp) == JIM_ERR) { + return JIM_ERR; + } + info->options = tmp; + if (info->logOpened) { + closelog(); + info->logOpened=0; + } + continue; + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-ident")) { + strncpy(info->ident, Jim_GetString(argv[i+1], NULL), sizeof(info->ident)); + info->ident[sizeof(info->ident) - 1] = 0; + if (info->logOpened) { + closelog(); + info->logOpened=0; + } + } + else { + break; + } + i += 2; + } + + /* There should be either 0, 1 or 2 args left */ + if (i == argc) { + /* No args, but they have set some options, so OK */ + return JIM_OK; + } + + if (ilogOpened) { + if (!info->ident[0]) { + Jim_Obj *argv0 = Jim_GetGlobalVariableStr(interp, "argv0", JIM_NONE); + if (argv0) { + strncpy(info->ident, Jim_GetString(argv0, NULL), sizeof(info->ident)); + } else { + strcpy(info->ident,"Tcl script"); + } + info->ident[sizeof(info->ident) - 1] = 0; + } + openlog(info->ident, info->options, info->facility); + info->logOpened=1; + } + syslog(priority, "%s", Jim_GetString(argv[i], NULL)); + + return JIM_OK; +} + +int Jim_syslogInit(Jim_Interp *interp) +{ + SyslogInfo *info; + + if (Jim_PackageProvide(interp, "syslog", "1.0", JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + info = Jim_Alloc(sizeof(*info)); + + info->logOpened=0; + info->options=0; + info->facility=LOG_USER; + info->ident[0] = 0; + + Jim_CreateCommand(interp, "syslog", Jim_SyslogCmd, info, Jim_SyslogCmdDelete); + + return JIM_OK; +} -- cgit v1.1