Initial revision
[egate.git] / res+log / gw-log.c
diff --git a/res+log/gw-log.c b/res+log/gw-log.c
new file mode 100644 (file)
index 0000000..bfeccf4
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+   gw-log.c: Implementation of logging facilities.
+
+   Europagate, 1994-1995.
+
+   $Log: gw-log.c,v $
+   Revision 1.1  1995/02/09 17:27:11  adam
+   Initial revision
+
+
+   Initial:       Dec  7, 94 (Adam Dickmeiss)
+   Last update:   Dec 13, 94 (Adam Dickmeiss)
+
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <gw-log.h>
+
+static char *app_name = NULL;
+static unsigned level = GW_LOG_DEFAULT;
+static int session = 0;
+
+struct file_mask {
+    unsigned mask;           /* level mask for this file entry */
+    int fd;                  /* file descriptor for this file */
+    char *fname;             /* name of file ("" if stdout) */
+    struct file_mask *next;  /* next file in chain */
+};
+
+struct file_mask *file_mask_list = NULL;
+
+char *gw_strdup (const char *s)
+{
+    char *n = malloc (strlen(s)+1);
+    if (n)
+        strcpy (n, s);
+    return n;
+}
+
+void gw_log_init (const char *app_name_a)
+{
+    struct file_mask *list, *list1;
+
+    app_name = gw_strdup (app_name_a);
+    level = GW_LOG_DEFAULT;
+    session = 0;
+
+    /* clean up all output file masks... */
+    for (list = file_mask_list; list; list = list1)
+    {
+        if (list->fd > 2)                  /* avoid closing stdout/stderr */
+            close (list->fd);              
+        free (list->fname);
+        list1 = list->next;
+        free (list);
+    }
+    file_mask_list = NULL;
+}
+
+void gw_log_level (unsigned level_a)
+{
+    level = level_a;
+}
+
+void gw_log_session (int session_a)
+{
+    session = session_a;
+}
+
+int gw_log_file (unsigned level_a, const char *fname_a)
+{
+    struct file_mask **listp, *new_file_mask;
+    listp = &file_mask_list;
+
+    /* go through file mask list and close files already associated */
+    /* on new level */
+    while (*listp)
+    {
+        if (!((*listp)->mask &= ~level_a)) /* any levels left on this one? */
+        {
+            if ((*listp)->fd > 2)          /* close if not stdout/stderr */
+                close ((*listp)->fd);      
+            free ((*listp)->fname);
+            *listp = (*listp)->next;
+        }
+        listp = &(*listp)->next;
+    }
+    if (!fname_a)                          /* stderr? */
+        return 0;                          /* stderr doesn't appear on list */
+    new_file_mask = malloc (sizeof(*new_file_mask));
+    if (!new_file_mask)
+        return -1;
+    new_file_mask->mask = level_a;
+    new_file_mask->next = file_mask_list;
+    file_mask_list = new_file_mask;
+    if (!(file_mask_list->fname = gw_strdup (fname_a)))
+        return -1;
+    if (*fname_a == '\0')                  /* stdout? */
+        new_file_mask->fd = 1;            
+    else                                   /* no, open as usual */
+    {
+        new_file_mask->fd = open (fname_a, O_WRONLY|O_CREAT|O_APPEND, 0666);
+        if (new_file_mask->fd == -1)
+            return -1;
+    }
+    return 0;
+}
+
+int gw_log (unsigned level_a, const char *event_type, const char *format, ...)
+{
+    static char emit_str[2048];
+    struct file_mask *list;
+    va_list ap;
+    unsigned e_level = level_a & level;
+    int count;
+    int err = 0;
+    time_t time_now;
+    char *cp;
+
+    if (!e_level)                          /* any effective level(s)? */      
+        return 0;
+
+    va_start (ap, format);
+    time (&time_now);
+    sprintf (emit_str, "%s %d %s %d %s ", app_name, session,
+             ctime (&time_now), e_level, event_type);
+    if ((cp = strchr (emit_str, '\n')))    /* remove \n from ctime-str */
+        *cp = ' ';
+    count = strlen (emit_str);
+    vsprintf (emit_str+count, format, ap);
+    strcat (emit_str, "\n");
+    count = strlen (emit_str);
+
+    /* go through file mask list... */
+    for (list = file_mask_list; list; list = list->next)
+        if (list->mask & e_level)          /* output this one? */
+        {
+            e_level &= ~list->mask;        /* remove from effective level */
+            if (write (list->fd, emit_str, count) != count)
+                err = 1;
+        }
+    if (e_level)                           /* bits left on effective level? */
+        write (2, emit_str, count);
+    va_end (ap);
+    return err;
+}