/* 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] = "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; } } 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; }