summaryrefslogtreecommitdiff
path: root/libmailutils
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-12-03 19:52:56 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2010-12-03 20:34:19 +0200
commit30bf4d542198abc23b897dd81fc280354903e49f (patch)
tree5e414f29aa6c8a1f720dec837a6c588b89b74d0d /libmailutils
parent554f80a1122f7a931f8c09056f4238b38d5034e8 (diff)
downloadmailutils-30bf4d542198abc23b897dd81fc280354903e49f.tar.gz
mailutils-30bf4d542198abc23b897dd81fc280354903e49f.tar.bz2
Initial implementation of log streams.
* include/mailutils/mailutils.h: Include mailutils/log.h. * include/mailutils/stream.h (MU_IOCTL_LOGSTREAM_GET_SEVERITY) (MU_IOCTL_LOGSTREAM_SET_SEVERITY) (MU_IOCTL_LOGSTREAM_GET_LOCUS,MU_IOCTL_LOGSTREAM_SET_LOCUS) (MU_IOCTL_LOGSTREAM_GET_MODE,MU_IOCTL_LOGSTREAM_SET_MODE): New ioctls. * include/mailutils/sys/logstream.h: New file. * include/mailutils/sys/syslogstream.h: New file. * include/mailutils/sys/Makefile.am (sysinclude_HEADERS): Add logstream.h and syslogstream.h * include/mailutils/types.hin (mu_locus): New struct. * libmailutils/stream/Makefile.am (libstream_la_SOURCES): Add logstream.c and syslogstream.c. * mu/logger.c: New file. * mu/template.c: New file. * mu/Makefile.am (MODULES): Add logger.c (EXTRA_DIST): Add template.c.
Diffstat (limited to 'libmailutils')
-rw-r--r--libmailutils/stream/Makefile.am2
-rw-r--r--libmailutils/stream/dbgstream.c4
-rw-r--r--libmailutils/stream/logstream.c364
-rw-r--r--libmailutils/stream/syslogstream.c90
4 files changed, 458 insertions, 2 deletions
diff --git a/libmailutils/stream/Makefile.am b/libmailutils/stream/Makefile.am
index 82fa573a8..507050dc6 100644
--- a/libmailutils/stream/Makefile.am
+++ b/libmailutils/stream/Makefile.am
@@ -22,6 +22,7 @@ libstream_la_SOURCES = \
file_stream.c\
fltstream.c\
iostream.c\
+ logstream.c\
mapfile_stream.c\
memory_stream.c\
message_stream.c\
@@ -35,6 +36,7 @@ libstream_la_SOURCES = \
stream_vprintf.c\
streamcpy.c\
streamref.c\
+ syslogstream.c\
tcp.c\
temp_file_stream.c\
xscript-stream.c
diff --git a/libmailutils/stream/dbgstream.c b/libmailutils/stream/dbgstream.c
index b7848131a..b1d05696f 100644
--- a/libmailutils/stream/dbgstream.c
+++ b/libmailutils/stream/dbgstream.c
@@ -63,8 +63,8 @@ _dbg_done (struct _mu_stream *str)
}
int
-mu_dbgstream_create(mu_stream_t *pref, mu_debug_t debug, mu_log_level_t level,
- int flags)
+mu_dbgstream_create (mu_stream_t *pref, mu_debug_t debug, mu_log_level_t level,
+ int flags)
{
int rc;
mu_stream_t stream;
diff --git a/libmailutils/stream/logstream.c b/libmailutils/stream/logstream.c
new file mode 100644
index 000000000..5908a27ec
--- /dev/null
+++ b/libmailutils/stream/logstream.c
@@ -0,0 +1,364 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2010 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <mailutils/types.h>
+#include <mailutils/errno.h>
+#include <mailutils/cctype.h>
+#include <mailutils/log.h>
+
+#include <mailutils/nls.h>
+#include <mailutils/stream.h>
+#include <mailutils/sys/logstream.h>
+
+char *_mu_severity_str[] = {
+ N_("DEBUG"),
+ N_("INFO"),
+ N_("NOTICE"),
+ N_("WARNING"),
+ N_("ERROR"),
+ N_("CRIT"),
+ N_("ALERT"),
+ N_("EMERG"),
+};
+int _mu_severity_num = MU_ARRAY_SIZE (_mu_severity_str);
+
+static int
+_locus_set_file (struct mu_locus *loc, const char *file, size_t len)
+{
+ free (loc->mu_file);
+ if (file)
+ {
+ loc->mu_file = malloc (len + 1);
+ if (!loc->mu_file)
+ return ENOMEM;
+ memcpy (loc->mu_file, file, len);
+ loc->mu_file[len] = 0;
+ }
+ else
+ loc->mu_file = NULL;
+ return 0;
+}
+
+#define _locus_set_line(loc, line) ((loc)->mu_line = line)
+#define _locus_set_col(loc, col) ((loc)->mu_col = col)
+
+static int
+_log_write (struct _mu_stream *str, const char *buf, size_t size,
+ size_t *pnwrite)
+{
+ struct _mu_log_stream *sp = (struct _mu_log_stream *)str;
+ unsigned severity = sp->severity;
+ int logmode = sp->logmode;
+ struct mu_locus loc = sp->locus;
+ const char *fname = NULL;
+ unsigned flen = 0;
+ int save_locus = 0;
+ int rc;
+
+#define NEXT do { buf++; size--; if (size == 0) return EINVAL; } while (0)
+#define READNUM(n) do { \
+ unsigned __x = 0; \
+ if (*buf != '<') \
+ return EINVAL; \
+ NEXT; \
+ while (*buf != '>') \
+ { \
+ if (!mu_isdigit (*buf)) \
+ return EINVAL; \
+ __x = __x * 10 + (*buf - '0'); \
+ NEXT; \
+ } \
+ NEXT; \
+ n = __x; \
+} while (0)
+
+ /* Tell them we've consumed everything */
+ *pnwrite = size;
+
+ /* Process escapes */
+ while (*buf == '\033')
+ {
+ int code;
+ unsigned n;
+
+ NEXT;
+ code = *buf;
+ NEXT;
+ switch (code)
+ {
+ case 'S':
+ /* Save locus */
+ save_locus = 1;
+ break;
+
+ case 's':
+ /* Severity code in decimal (single digit) */
+ if (!mu_isdigit (*buf))
+ return EINVAL;
+ severity = *buf - '0';
+ NEXT;
+ break;
+
+ case 'O':
+ /* Flags on. Followed by a bitmask of MU_LOGMODE_*, in decimal */
+ READNUM (n);
+ logmode |= n;
+ break;
+
+ case 'X':
+ /* Flags off. Followed by a bitmask of MU_LOGMODE_*, in decimal */
+ READNUM (n);
+ logmode &= ~n;
+ break;
+
+ case 'l':
+ /* Input line (decimal) */
+ READNUM (n);
+ _locus_set_line (&loc, n);
+ break;
+
+ case 'c':
+ /* Column in input line (decimal) */
+ READNUM (n);
+ _locus_set_col (&loc, n);
+ break;
+
+ case 'f':
+ /* File name. Format: <N>S */
+ READNUM (flen);
+ fname = buf;
+ buf += flen;
+ size -= flen;
+ break;
+
+ default:
+ return EINVAL;
+ }
+ }
+
+ if (severity >= _mu_severity_num)
+ severity = MU_LOG_EMERG;
+
+ if (logmode & MU_LOGMODE_LOCUS)
+ {
+ if (fname)
+ _locus_set_file (&loc, fname, flen);
+
+ if (loc.mu_file)
+ {
+ mu_stream_write (sp->transport, loc.mu_file,
+ strlen (loc.mu_file), NULL);
+ mu_stream_write (sp->transport, ":", 1, NULL);
+ if (loc.mu_line)
+ mu_stream_printf (sp->transport, "%u", loc.mu_line);
+ mu_stream_write (sp->transport, ":", 1, NULL);
+ if (loc.mu_col)
+ mu_stream_printf (sp->transport, "%u:", loc.mu_col);
+ mu_stream_write (sp->transport, " ", 1, NULL);
+ }
+ }
+
+ if (save_locus)
+ {
+ _locus_set_file (&sp->locus, loc.mu_file, strlen (loc.mu_file));
+ _locus_set_line (&sp->locus, loc.mu_line);
+ _locus_set_col (&sp->locus, loc.mu_col);
+ }
+
+ if (fname)
+ free (loc.mu_file);
+
+ if (logmode & MU_LOGMODE_SEVERITY)
+ {
+ char *s = gettext (_mu_severity_str[severity]);
+ rc = mu_stream_write (sp->transport, s, strlen (s), NULL);
+ if (rc)
+ return rc;
+ mu_stream_write (sp->transport, ": ", 2, NULL);
+ }
+ return mu_stream_write (sp->transport, buf, size, NULL);
+}
+
+static int
+_log_flush (struct _mu_stream *str)
+{
+ struct _mu_log_stream *sp = (struct _mu_log_stream *)str;
+ return mu_stream_flush (sp->transport);
+}
+
+static void
+_log_done (struct _mu_stream *str)
+{
+ struct _mu_log_stream *sp = (struct _mu_log_stream *)str;
+ if (str->flags & MU_STREAM_AUTOCLOSE)
+ mu_stream_destroy (&sp->transport);
+}
+
+static int
+_log_close (struct _mu_stream *str)
+{
+ struct _mu_log_stream *sp = (struct _mu_log_stream *)str;
+ if (str->flags & MU_STREAM_AUTOCLOSE)
+ return mu_stream_close (sp->transport);
+ return 0;
+}
+
+static int
+_log_setbuf_hook (mu_stream_t str, enum mu_buffer_type type, size_t size)
+{
+ if (type != mu_buffer_line)
+ return EACCES;
+ return 0;
+}
+
+static int
+_log_ctl (struct _mu_stream *str, int op, void *arg)
+{
+ struct _mu_log_stream *sp = (struct _mu_log_stream *)str;
+ mu_transport_t *ptrans;
+
+ switch (op)
+ {
+ case MU_IOCTL_GET_TRANSPORT:
+ if (!arg)
+ return EINVAL;
+ ptrans = arg;
+ ptrans[0] = (mu_transport_t) sp->transport;
+ ptrans[1] = NULL;
+ break;
+
+ case MU_IOCTL_SET_TRANSPORT:
+ if (!arg)
+ return EINVAL;
+ ptrans = arg;
+ if (ptrans[0])
+ sp->transport = (mu_stream_t) ptrans[0];
+ break;
+
+ case MU_IOCTL_LOGSTREAM_GET_SEVERITY:
+ if (!arg)
+ return EINVAL;
+ *(unsigned*)arg = sp->severity;
+ break;
+
+ case MU_IOCTL_LOGSTREAM_SET_SEVERITY:
+ if (!arg)
+ return EINVAL;
+ if (*(unsigned*)arg >= _mu_severity_num)
+ return EINVAL;
+ sp->severity = *(unsigned*)arg;
+ break;
+
+ case MU_IOCTL_LOGSTREAM_GET_MODE:
+ if (!arg)
+ return EINVAL;
+ *(int*)arg = sp->logmode;
+ break;
+
+ case MU_IOCTL_LOGSTREAM_SET_MODE:
+ if (!arg)
+ return EINVAL;
+ sp->logmode = *(int*)arg;
+ break;
+
+ case MU_IOCTL_LOGSTREAM_GET_LOCUS:
+ {
+ struct mu_locus *ploc = arg;
+ if (!arg)
+ return EINVAL;
+ if (sp->locus.mu_file)
+ {
+ ploc->mu_file = strdup (sp->locus.mu_file);
+ if (!ploc->mu_file)
+ return ENOMEM;
+ }
+ else
+ ploc->mu_file = NULL;
+ ploc->mu_line = sp->locus.mu_line;
+ ploc->mu_col = sp->locus.mu_col;
+ break;
+ }
+
+ case MU_IOCTL_LOGSTREAM_SET_LOCUS:
+ {
+ struct mu_locus *ploc = arg;
+ if (!arg)
+ {
+ free (sp->locus.mu_file);
+ sp->locus.mu_file = NULL;
+ sp->locus.mu_line = 0;
+ sp->locus.mu_col = 0;
+ }
+ else
+ {
+ if (ploc->mu_file)
+ _locus_set_file (&sp->locus, ploc->mu_file,
+ strlen (ploc->mu_file));
+ if (ploc->mu_line)
+ _locus_set_line (&sp->locus, ploc->mu_line);
+ if (ploc->mu_col)
+ _locus_set_col (&sp->locus, ploc->mu_col);
+ }
+ break;
+ }
+
+ default:
+ return ENOSYS;
+ }
+ return 0;
+}
+
+int
+mu_log_stream_create (mu_stream_t *pstr, mu_stream_t transport)
+{
+ struct _mu_log_stream *sp;
+ mu_stream_t stream;
+ int rc;
+
+ sp = (struct _mu_log_stream *)
+ _mu_stream_create (sizeof (*sp), MU_STREAM_WRITE);
+ if (!sp)
+ return ENOMEM;
+ sp->base.write = _log_write;
+ sp->base.flush = _log_flush;
+ sp->base.close = _log_close;
+ sp->base.done = _log_done;
+ sp->base.setbuf_hook = _log_setbuf_hook;
+ sp->base.ctl = _log_ctl;
+ sp->transport = transport;
+ mu_stream_ref (transport);
+ sp->severity = MU_LOG_ERROR;
+ sp->logmode = 0;
+
+ stream = (mu_stream_t) sp;
+ mu_stream_set_buffer (stream, mu_buffer_line, 0);
+ rc = mu_stream_open (stream);
+ if (rc)
+ mu_stream_destroy (&stream);
+ else
+ *pstr = stream;
+
+ return rc;
+}
+
+
diff --git a/libmailutils/stream/syslogstream.c b/libmailutils/stream/syslogstream.c
new file mode 100644
index 000000000..384694e59
--- /dev/null
+++ b/libmailutils/stream/syslogstream.c
@@ -0,0 +1,90 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2010 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+#include <mailutils/stream.h>
+#include <mailutils/sys/syslogstream.h>
+
+static int
+_syslog_stream_write (struct _mu_stream *stream, const char *buf,
+ size_t size, size_t *pret)
+{
+ struct _mu_syslog_stream *lsp = (struct _mu_syslog_stream *)stream;
+
+ *pret = size;
+ if (size > 0 && buf[size-1] == '\n')
+ size--;
+ if (size == 0)
+ return 0;
+ syslog (lsp->prio, "%*.*s", (int) size, (int) size, buf);
+ return 0;
+}
+
+static int
+_syslog_ctl (struct _mu_stream *str, int op, void *arg)
+{
+ struct _mu_syslog_stream *sp = (struct _mu_syslog_stream *)str;
+
+ switch (op)
+ {
+ case MU_IOCTL_LOGSTREAM_GET_SEVERITY:
+ if (!arg)
+ return EINVAL;
+ *(int*)arg = sp->prio;
+ break;
+
+ case MU_IOCTL_LOGSTREAM_SET_SEVERITY:
+ if (!arg)
+ return EINVAL;
+ sp->prio = *(int*)arg;
+ break;
+
+ default:
+ return ENOSYS;
+ }
+ return 0;
+}
+
+int
+_syslog_setbuf_hook (mu_stream_t str, enum mu_buffer_type type, size_t size)
+{
+ if (type != mu_buffer_line)
+ return EACCES;
+ return 0;
+}
+
+int
+mu_syslog_stream_create (mu_stream_t *pstream, int prio)
+{
+ struct _mu_syslog_stream *str =
+ (struct _mu_syslog_stream *) _mu_stream_create (sizeof (*str),
+ MU_STREAM_WRITE);
+ if (!str)
+ return ENOMEM;
+ str->prio = prio;
+ str->base.write = _syslog_stream_write;
+ str->base.ctl = _syslog_ctl;
+ str->base.setbuf_hook = _syslog_setbuf_hook;
+ *pstream = (mu_stream_t) str;
+ mu_stream_set_buffer (*pstream, mu_buffer_line, 0);
+ return 0;
+}

Return to:

Send suggestions and report system problems to the System administrator.