-/*
+/*
* log.c:
*
* Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
*
*/
-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 ***
+ *
+ * Revision 1.4 2008/02/27 00:54:16 james
+ * *** empty log message ***
+ *
+ * Revision 1.3 2008/02/23 11:48:37 james
+ * *** empty log message ***
+ *
+ * Revision 1.2 2008/02/22 14:51:54 james
+ * *** empty log message ***
+ *
* Revision 1.1 2008/02/14 12:14:50 james
* *** empty log message ***
*
#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 };
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);
}
+
+
+
static void
flog_close (Log * _l)
{
File_Log *l = (File_Log *) _l;
- if (l->fp)
+ 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;
- f = fopen (fn, "a+");
- if (!f)
- return NULL;
+ 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);
+
+ log_add ((Log *) l);
return (Log *) l;
}
+
+void
+log_f (Log * log, char *fmt, ...)
+{
+
+ int n;
+ static char *buf;
+ va_list ap;
+ static int size;
+
+ if (!log)
+ return;
+
+ 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);
+
+ 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 */
+
+ buf = xrealloc (buf, size);
+
+ if (!buf)
+ return;
+ }
+}