chiark / gitweb /
serialmgr: Look for things in /usr, not /usr/local
[sympathy.git] / src / log.c
index 7c04f23772b3c47cab7e2f9a47c3bd7158aff2cf..c7c43c876a8f5a7ed9d497246ada8e45faf9abc0 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -1,15 +1,51 @@
-/*
+/* 
  * log.c:
  *
- * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
+ * Copyright (c) 2008 James McKenzie <sympathy@madingley.org>,
  * All rights reserved.
  *
  */
 
-static char rcsid[] = "$Id$";
+static char rcsid[] = "$Id: log.c,v 1.17 2011/02/04 16:14:16 james Exp $";
 
-/*
- * $Log$
+/* 
+ * $Log: log.c,v $
+ * Revision 1.17  2011/02/04 16:14:16  james
+ * *** empty log message ***
+ *
+ * Revision 1.16  2010/07/27 14:49:35  james
+ * add support for byte logging
+ *
+ * Revision 1.15  2010/07/16 11:04:10  james
+ * ignore tedious return values
+ *
+ * Revision 1.14  2008/03/11 17:56:04  james
+ * *** empty log message ***
+ *
+ * Revision 1.13  2008/03/11 16:56:29  james
+ * *** empty log message ***
+ *
+ * Revision 1.12  2008/03/10 11:49:33  james
+ * *** empty log message ***
+ *
+ * Revision 1.11  2008/03/07 13:16:02  james
+ * *** empty log message ***
+ *
+ * Revision 1.10  2008/03/07 12:37:04  james
+ * *** empty log message ***
+ *
+ * Revision 1.9  2008/03/03 06:20:14  james
+ * *** empty log message ***
+ *
+ * Revision 1.8  2008/03/03 06:04:42  james
+ * *** empty log message ***
+ *
+ * Revision 1.7  2008/03/03 06:04:18  james
+ * *** empty log message ***
+ *
+ * Revision 1.6  2008/03/02 10:37:56  james
+ * *** empty log message ***
+ *
  * Revision 1.5  2008/02/27 01:31:14  james
  * *** empty log message ***
  *
@@ -29,15 +65,93 @@ static char rcsid[] = "$Id$";
 
 #include "project.h"
 
-typedef struct
-{
+typedef struct {
   LOG_SIGNATURE;
   int do_close;
+  int rotate;
   FILE *fp;
+  char *filename;
+  int needs_newline;
 } File_Log;
 
+
+static Log *loggers = NULL;
+
+
 static void
-flog_log (Log * _l, char *buf)
+sighup (int dummy)
+{
+  Log *l;
+
+  for (l = loggers; l; l = l->next) {
+    if (l->sighup)
+      l->sighup (l);
+  }
+}
+
+
+void
+log_register_handlers (void)
+{
+  struct sigaction sa = { 0 };
+
+  sa.sa_handler = sighup;
+  sa.sa_flags = SA_RESTART;
+  sigaction (SIGHUP, &sa, NULL);
+}
+
+
+void
+log_add (Log * l)
+{
+  log_register_handlers ();
+
+  l->next = loggers;
+  loggers = l;
+}
+
+void
+log_remove (Log * l)
+{
+  Log **ptr = &loggers;
+
+  /* Take out of sighup list */
+  while (*ptr && (*ptr != l))
+    ptr = &((*ptr)->next);
+
+  if (*ptr)
+    *ptr = l->next;
+}
+
+static void flog_newline(Log *_l,int force) 
+{
+  File_Log *l = (File_Log *) _l;
+
+  if (force || !l->needs_newline) return;
+
+  l->needs_newline=0;
+
+  fputc ('\n', l->fp);
+  fflush (l->fp);
+}
+
+
+static void
+flog_sighup (Log * _l)
+{
+  File_Log *l = (File_Log *) _l;
+  if (!l->fp)
+    return;
+
+  log_f (_l, "<sighup received - closing log file>");
+  fclose (l->fp);
+
+  l->fp = fopen (l->filename, "a+");
+  log_f (_l, "<sighup received - opening log file>");
+}
+
+static void 
+flog_emit_stamp(Log *_l)
 {
   File_Log *l = (File_Log *) _l;
   struct timeval tv = { 0 };
@@ -54,16 +168,66 @@ flog_log (Log * _l, char *buf)
   if (!l->fp)
     return;
 
+  flog_newline(_l,0);
+
   gettimeofday (&tv, NULL);
   t = tv.tv_sec;
   tm = localtime (&t);
 
   fprintf (l->fp, "%s %2d %02d:%02d:%02d.%06d ", months[tm->tm_mon],
-           tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec);
+           tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,(int) tv.tv_usec);
+}
+
+
+static void flog_check_rotate(Log *_l)
+{
+  File_Log *l = (File_Log *) _l;
+
+  if (l->rotate && rotate_check (l->filename)) {
+    fclose (l->fp);
+    rotate (l->filename);
+    l->fp = fopen (l->filename, "a+");
+  }
+}
+
+
+static void
+flog_log_bytes (Log * _l, void *_buf,int len)
+{
+  File_Log *l = (File_Log *) _l;
+  uint8_t *buf=(uint8_t *) _buf;
+
+  if (!l->fp)
+    return;
+
+  while (len--) {
+       if (*buf=='\n') {
+               flog_newline(_l,1);     
+               flog_check_rotate(_l);
+               flog_emit_stamp(_l);
+       } else { 
+               l->needs_newline++;
+               fputc (*buf, l->fp);
+       }
+       buf++;
+  }
+}
+
+static void
+flog_log (Log * _l, char *buf)
+{
+  File_Log *l = (File_Log *) _l;
+
+  if (!l->fp)
+    return;
+
+  flog_emit_stamp(_l);
 
   fputs (buf, l->fp);
   fputc ('\n', l->fp);
   fflush (l->fp);
+
+  flog_check_rotate(_l);
 }
 
 
@@ -75,36 +239,44 @@ flog_close (Log * _l)
   File_Log *l = (File_Log *) _l;
   if (l->fp && l->do_close)
     fclose (l->fp);
+  if (l->filename)
+    free (l->filename);
   free (l);
 }
 
 Log *
-file_log_new (char *fn)
+file_log_new (char *fn, int rotate)
 {
   File_Log *l;
-  FILE *f;
   int dc = 1;
 
-  if (fn && strcmp (fn, "-"))
-    {
-      f = fopen (fn, "a+");
-      if (!f)
-        return NULL;
-    }
-  else
-    {
-      f = stderr;
-      dc = 0;
+  l = xmalloc (sizeof (File_Log));
+
+  if (fn && strcmp (fn, "-")) {
+    l->fp = fopen (fn, "a+");
+    if (!l->fp) {
+      free (l);
+      return NULL;
     }
+    l->sighup = flog_sighup;
+  } else {
+    l->fp = stderr;
+    dc = 0;
+  }
 
-  l = malloc (sizeof (File_Log));
 
   l->log = flog_log;
+  l->log_bytes = flog_log_bytes;
   l->close = flog_close;
-  l->fp = f;
   l->do_close = dc;
+  l->rotate = rotate;
+  l->filename = strdup (fn);
+
+  l->needs_newline=0;
+
+  fput_cp (l->fp, 0xffef);
 
-  fput_cp (f, 0xffef);
+  log_add ((Log *) l);
 
   return (Log *) l;
 }
@@ -121,35 +293,32 @@ log_f (Log * log, char *fmt, ...)
   if (!log)
     return;
 
-  if (!size)
-    {
-      size = 128;
-      buf = malloc (size);
-    }
+  if (!size) {
+    size = 128;
+    buf = malloc (size);
+  }
 
   if (!buf)
     return;
 
-  while (1)
-    {
-      va_start (ap, fmt);
-      n = vsnprintf (buf, size, fmt, ap);
-      va_end (ap);
+  while (1) {
+    va_start (ap, fmt);
+    n = vsnprintf (buf, size, fmt, ap);
+    va_end (ap);
 
-      if (n > -1 && n < size)
-        {
-          log->log (log, buf);
-          return;
-        }
+    if (n > -1 && n < size) {
+      log->log (log, buf);
+      return;
+    }
 
-      if (n > -1)               /* glibc 2.1 */
-        size = n + 1;
-      else                      /* glibc 2.0 */
-        size *= 2;              /* twice the old size */
+    if (n > -1)                 /* glibc 2.1 */
+      size = n + 1;
+    else                        /* glibc 2.0 */
+      size *= 2;                /* twice the old size */
 
-      buf = realloc (buf, size);
+    buf = xrealloc (buf, size);
 
-      if (!buf)
-        return;
-    }
+    if (!buf)
+      return;
+  }
 }