aboutsummaryrefslogtreecommitdiff
path: root/jim-syslog.c
diff options
context:
space:
mode:
Diffstat (limited to 'jim-syslog.c')
-rw-r--r--jim-syslog.c199
1 files changed, 199 insertions, 0 deletions
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 <vitus@ice.ru> at
+ * http://www.ice.ru/~vitus/works/tcl.html#syslog
+ *
+ * Slightly modified by Steve Bennett <steveb@snapgear.com>
+ * Ported to Jim by Steve Bennett <steveb@workware.net.au>
+ */
+#include <jim.h>
+#include <syslog.h>
+#include <string.h>
+
+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 (i<argc-1) {
+ priority = find_by_name(Jim_GetString(argv[i], NULL), priorities, sizeof(priorities) / sizeof(*priorities));
+ if (priority < 0) {
+ Jim_SetResultString(interp, "Unknown priority", -1);
+ return JIM_ERR;
+ }
+ i++;
+ }
+
+ if (i != argc - 1) {
+ goto wrongargs;
+ }
+ if (!info->logOpened) {
+ 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;
+}