Commit 0d002309 0d0023093b17fdf1ab62d8872307047a8c96d06b by Sergey Poznyakoff

Assorted changes

* include/mailutils/debug.h (mu_debug_format_spec): New function.

* include/mailutils/stream.h (MU_IOCTL_SYSLOGSTREAM)
(MU_IOCTL_FILTER): New ioctls.
(MU_IOCTL_LOGSTREAM_GET_SEVERITY_MASK)
(MU_IOCTL_LOGSTREAM_SET_SEVERITY_MASK)
(MU_IOCTL_LOGSTREAM_CLONE)
(MU_IOCTL_SYSLOGSTREAM_SET_LOGGER)
(MU_IOCTL_SYSLOGSTREAM_GET_LOGGER)
(MU_IOCTL_FILTER_GET_DISABLED)
(MU_IOCTL_FILTER_SET_DISABLED): And their opcodes.
* include/mailutils/sys/filter.h (_MU_FILTER_DISABLED)
(_MU_FILTER_EOF): New defines.
(_mu_filter_stream) <eof>: Replace with fltflag (a bitmask).
* include/mailutils/sys/logstream.h (_mu_log_stream) <sevmask>: New
member.
* include/mailutils/sys/syslogstream.h (_mu_syslog_stream) <logger>: New
member.
* include/mailutils/util.h (mu_onexit_run): New proto.
* libmailutils/base/onexit.c (_mu_onexit_run): Extra safety check.
(mu_onexit_run): New function.
(mu_debug_level_str): New static.
(mu_debug_format_spec): New function.
* libmailutils/stream/fltstream.c (filter_read, filter_write): Bypass the
xcoder if _MU_FILTER_DISABLED is set.
Use fltflag instead of the removed eof.
(filter_ctl): Handle MU_IOCTL_FILTER.
* libmailutils/stream/logstream.c (_log_write): The sevmask member
masks out severity prefix output for certain severities.
(_log_ctl): Handle new opcodes (see above).
* libmailutils/stream/syslogstream.c (_syslog_stream_write): Use
<logger>, if supplied, instead of the system syslog(3).
(_syslog_ctl): Handle MU_IOCTL_SYSLOGSTREAM.
(mu_syslog_stream_create): Initialize logger to NULL.
* mu/ldflags.c (lib_descr): Protect entries with the
corresponding #ifdef ENABLE_whatever.
1 parent bc526de1
......@@ -63,6 +63,7 @@ void mu_debug_enable_category (const char *catname, size_t catlen, int level);
void mu_debug_disable_category (const char *catname, size_t catlen);
int mu_debug_category_level (const char *catname, size_t catlen, int *plev);
void mu_debug_parse_spec (const char *spec);
int mu_debug_format_spec(mu_stream_t str, const char *names, int showunset);
void mu_debug_set_category_level (int catn, int level);
void mu_debug_clear_all (void);
......
......@@ -71,6 +71,8 @@ enum mu_buffer_type
#define MU_IOCTL_LOGSTREAM 7 /* Log stream (see below) */
#define MU_IOCTL_XSCRIPTSTREAM 8 /* Transcript stream (see below) */
#define MU_IOCTL_FD 9 /* File descriptor manipulation */
#define MU_IOCTL_SYSLOGSTREAM 10 /* Syslog stream (see below) */
#define MU_IOCTL_FILTER 11 /* Filter streams (see below) */
/* Opcodes common for various families */
#define MU_IOCTL_OP_GET 0
......@@ -94,8 +96,8 @@ enum mu_buffer_type
#define MU_IOCTL_NULLSTREAM_CLRSIZE 3
/* Get or set logging severity.
Arg: unsigned *
*/
Arg: unsigned *
*/
#define MU_IOCTL_LOGSTREAM_GET_SEVERITY 0
#define MU_IOCTL_LOGSTREAM_SET_SEVERITY 1
/* Get or set locus.
......@@ -140,6 +142,17 @@ enum mu_buffer_type
*/
#define MU_IOCTL_LOGSTREAM_SUPPRESS_SEVERITY_NAME 11
/* Get or set severity output mask.
Arg: int *
*/
#define MU_IOCTL_LOGSTREAM_GET_SEVERITY_MASK 12
#define MU_IOCTL_LOGSTREAM_SET_SEVERITY_MASK 13
/* Clone the stream.
Arg: mu_stream_t*
*/
#define MU_IOCTL_LOGSTREAM_CLONE 14
/* Opcodes for MU_IOCTL_XSCRIPTSTREAM */
/* Swap transcript levels.
Arg: int *X
......@@ -158,6 +171,23 @@ enum mu_buffer_type
Arg: int *
*/
#define MU_IOCTL_FD_SET_BORROW 1
/* Opcodes for MU_IOCTL_SYSLOGSTREAM */
/* Set logger function.
Arg: void (*) (int, const char *, ...)
*/
#define MU_IOCTL_SYSLOGSTREAM_SET_LOGGER 0
/* Get logger function.
Arg: void (**) (int, const char *, ...)
*/
#define MU_IOCTL_SYSLOGSTREAM_GET_LOGGER 1
/* Filter streams */
/* Get or set disabled state:
Arg: int*
*/
#define MU_IOCTL_FILTER_GET_DISABLED 0
#define MU_IOCTL_FILTER_SET_DISABLED 1
#define MU_TRANSPORT_INPUT 0
#define MU_TRANSPORT_OUTPUT 1
......
......@@ -36,12 +36,15 @@ struct _mu_filter_buffer
size_t pos;
};
#define _MU_FILTER_DISABLED 0x01
#define _MU_FILTER_EOF 0x02
struct _mu_filter_stream
{
struct _mu_stream stream;
mu_stream_t transport;
int mode;
int eof;
int fltflag;
struct _mu_filter_buffer inbuf, outbuf;
mu_filter_xcode_t xcode;
......
......@@ -28,6 +28,8 @@ struct _mu_log_stream
unsigned threshold; /* Suppress the output of severities below
this threshold */
int logmode; /* Mode flags */
int sevmask; /* Mask out the output of severity level for
these severities. */
struct mu_locus locus; /* Location */
};
......
......@@ -24,6 +24,7 @@ struct _mu_syslog_stream
{
struct _mu_stream base;
int prio;
void (*logger) (int, const char *, ...);
};
#endif
......
......@@ -191,6 +191,8 @@ int mu_fd_wait (int fd, int *pflags, struct timeval *tvp);
int mutil_parse_field_map (const char *map, mu_assoc_t *passoc_tab,
int *perr);
/* Run the onexit list */
void mu_onexit_run (void);
/* Reset the onexit list. */
void mu_onexit_reset (void);
/* Register the onexit function and associated data */
......
......@@ -42,7 +42,9 @@ _mu_onexit_run (void)
{
mu_iterator_t itr;
int rc, status = 0;
if (!onexit_list)
return;
rc = mu_list_get_iterator (onexit_list, &itr);
if (rc)
{
......@@ -97,3 +99,9 @@ mu_onexit_reset (void)
{
mu_list_clear (onexit_list);
}
void
mu_onexit_run (void)
{
_mu_onexit_run ();
}
......
......@@ -313,6 +313,97 @@ mu_debug_clear_all ()
cattab[i].isset = 0;
}
#define _LEVEL_ALL MU_DEBUG_LEVEL_UPTO(MU_DEBUG_PROT)
static char *mu_debug_level_str[] = {
"error",
"trace0",
"trace1",
"trace2",
"trace3",
"trace4",
"trace5",
"trace6",
"trace7",
"trace8",
"trace9",
"prot"
};
static int
name_matches (char **names, char *str)
{
int i;
for (i = 0; names[i]; i++)
if (strcmp (names[i], str) == 0)
return 1;
return 0;
}
int
mu_debug_format_spec(mu_stream_t str, const char *names, int showunset)
{
int i;
size_t cnt = 0;
int rc = 0;
struct mu_wordsplit ws;
if (names)
{
ws.ws_delim = ";";
if (mu_wordsplit (names, &ws,
MU_WRDSF_DELIM|MU_WRDSF_WS|
MU_WRDSF_NOVAR|MU_WRDSF_NOCMD))
return errno;
}
for (i = 0; i < catcnt; i++)
{
if (names && !name_matches (ws.ws_wordv, cattab[i].name))
continue;
if (cattab[i].isset && cattab[i].level)
{
if (cnt)
{
rc = mu_stream_printf(str, ";");
if (rc)
break;
}
rc = mu_stream_printf(str, "%s", cattab[i].name);
if (rc)
break;
if (cattab[i].level != _LEVEL_ALL)
{
int j;
int delim = '.';
for (j = MU_DEBUG_ERROR; j <= MU_DEBUG_PROT; j++)
if (cattab[i].level & MU_DEBUG_LEVEL_MASK(j))
{
rc = mu_stream_printf(str, "%c%s", delim,
mu_debug_level_str[j]);
if (rc)
break;
delim = ',';
}
}
cnt++;
}
else if (showunset)
{
rc = mu_stream_printf(str, "!%s", cattab[i].name);
if (rc)
break;
cnt++;
}
}
if (names)
mu_wordsplit_free (&ws);
return rc;
}
void
mu_debug_log (const char *fmt, ...)
......
......@@ -119,6 +119,9 @@ filter_read (mu_stream_t stream, char *buf, size_t size, size_t *pret)
size_t total = 0;
int stop = 0;
int again = 0;
if (fs->fltflag & _MU_FILTER_DISABLED)
return mu_stream_read (fs->transport, buf, size, pret);
do
{
......@@ -129,7 +132,7 @@ filter_read (mu_stream_t stream, char *buf, size_t size, size_t *pret)
enum mu_filter_result res;
int rc;
if (fs->eof)
if (fs->fltflag & _MU_FILTER_EOF)
break;
if (MFB_RDBYTES (fs->inbuf) < min_input_level && !again)
......@@ -178,7 +181,7 @@ filter_read (mu_stream_t stream, char *buf, size_t size, size_t *pret)
again = 0;
if (cmd == mu_filter_lastbuf || iobuf.eof)
{
fs->eof = 1;
fs->fltflag |= _MU_FILTER_EOF;
stop = 1;
}
break;
......@@ -331,6 +334,11 @@ filter_write_internal (mu_stream_t stream, enum mu_filter_command cmd,
static int
filter_write (mu_stream_t stream, const char *buf, size_t size, size_t *pret)
{
struct _mu_filter_stream *fs = (struct _mu_filter_stream *)stream;
if (fs->fltflag & _MU_FILTER_DISABLED)
return mu_stream_write (fs->transport, buf, size, pret);
return filter_write_internal (stream, mu_filter_xcode, buf, size, pret);
}
......@@ -365,6 +373,27 @@ filter_ctl (struct _mu_stream *stream, int code, int opcode, void *ptr)
switch (code)
{
case MU_IOCTL_FILTER:
switch (opcode)
{
case MU_IOCTL_FILTER_SET_DISABLED:
if (ptr && *(int*)ptr)
fs->fltflag |= _MU_FILTER_DISABLED;
else
fs->fltflag &= ~_MU_FILTER_DISABLED;
break;
case MU_IOCTL_FILTER_GET_DISABLED:
if (!ptr)
return EINVAL;
*(int*)ptr = fs->fltflag & _MU_FILTER_DISABLED;
break;
default:
return ENOSYS;
}
break;
case MU_IOCTL_TRANSPORT:
switch (opcode)
{
......@@ -414,7 +443,7 @@ static int
filter_wr_close (mu_stream_t stream)
{
struct _mu_filter_stream *fs = (struct _mu_filter_stream *)stream;
if (!mu_stream_eof (stream) && !fs->eof)
if (!mu_stream_eof (stream) && !(fs->fltflag & _MU_FILTER_EOF))
{
size_t dummy;
int rc = filter_write_internal (stream, mu_filter_lastbuf, NULL, 0,
......@@ -526,7 +555,7 @@ mu_filter_stream_create (mu_stream_t *pflt,
fs->xcode = xcode;
fs->xdata = xdata;
fs->mode = mode;
fs->eof = 0;
fs->fltflag = 0;
mu_stream_set_buffer ((mu_stream_t) fs, mu_buffer_full,
MU_FILTER_BUF_SIZE);
......
......@@ -29,6 +29,7 @@
#include <mailutils/nls.h>
#include <mailutils/stream.h>
#include <mailutils/debug.h>
#include <mailutils/sys/logstream.h>
char *_mu_severity_str[] = {
......@@ -235,7 +236,8 @@ _log_write (struct _mu_stream *str, const char *buf, size_t size,
if (fname)
free (loc.mu_file);
if (logmode & MU_LOGMODE_SEVERITY)
if ((logmode & MU_LOGMODE_SEVERITY) &&
!(sp->sevmask & MU_DEBUG_LEVEL_MASK(severity)))
{
char *s = gettext (_mu_severity_str[severity]);
rc = mu_stream_write (sp->transport, s, strlen (s), NULL);
......@@ -418,11 +420,49 @@ _log_ctl (struct _mu_stream *str, int code, int opcode, void *arg)
else
return mu_severity_from_string ((const char *) arg, &sp->threshold);
case MU_IOCTL_LOGSTREAM_GET_SEVERITY_MASK:
if (!arg)
return EINVAL;
*(int*)arg = sp->sevmask;
break;
case MU_IOCTL_LOGSTREAM_SET_SEVERITY_MASK:
if (!arg)
return EINVAL;
sp->sevmask = *(int*)arg;
break;
case MU_IOCTL_LOGSTREAM_CLONE:
if (!arg)
return EINVAL;
else
{
mu_stream_t str;
struct _mu_log_stream *newp;
int rc = mu_log_stream_create (&str, sp->transport);
if (rc)
return rc;
newp = (struct _mu_log_stream *) str;
newp->severity = sp->severity;
newp->threshold = sp->threshold;
newp->logmode = sp->logmode;
newp->sevmask = sp->sevmask;
if (sp->locus.mu_file)
newp->locus.mu_file = strdup (sp->locus.mu_file);
newp->locus.mu_line = sp->locus.mu_line;
newp->locus.mu_col = sp->locus.mu_col;
*(mu_stream_t*) arg = str;
}
break;
default:
return EINVAL;
}
break;
case MU_IOCTL_FILTER:
return mu_stream_ioctl (sp->transport, code, opcode, arg);
default:
return ENOSYS;
}
......
......@@ -36,7 +36,10 @@ _syslog_stream_write (struct _mu_stream *stream, const char *buf,
size--;
if (size == 0)
return 0;
syslog (lsp->prio, "%*.*s", (int) size, (int) size, buf);
if (lsp->logger)
lsp->logger (lsp->prio, "%*.*s", (int) size, (int) size, buf);
else
syslog (lsp->prio, "%*.*s", (int) size, (int) size, buf);
return 0;
}
......@@ -57,35 +60,53 @@ _syslog_ctl (struct _mu_stream *str, int code, int opcode, void *arg)
struct _mu_syslog_stream *sp = (struct _mu_syslog_stream *)str;
unsigned n;
if (code != MU_IOCTL_LOGSTREAM)
return ENOSYS;
switch (opcode)
if (code == MU_IOCTL_LOGSTREAM)
switch (opcode)
{
case MU_IOCTL_LOGSTREAM_GET_SEVERITY:
if (!arg)
return EINVAL;
for (n = 0; n < MU_ARRAY_SIZE (sev2prio); n++)
if (sev2prio[n] == sp->prio)
{
*(int*)arg = n;
break;
}
return MU_ERR_FAILURE;
case MU_IOCTL_LOGSTREAM_SET_SEVERITY:
if (!arg)
return EINVAL;
n = *(unsigned*)arg;
if (n < MU_ARRAY_SIZE (sev2prio))
sp->prio = sev2prio[n];
else
return EINVAL;
break;
default:
return ENOSYS;
}
else if (code == MU_IOCTL_SYSLOGSTREAM)
{
case MU_IOCTL_LOGSTREAM_GET_SEVERITY:
if (!arg)
return EINVAL;
for (n = 0; n < MU_ARRAY_SIZE (sev2prio); n++)
if (sev2prio[n] == sp->prio)
{
*(int*)arg = n;
break;
}
return MU_ERR_FAILURE;
case MU_IOCTL_LOGSTREAM_SET_SEVERITY:
if (!arg)
return EINVAL;
n = *(unsigned*)arg;
if (n < MU_ARRAY_SIZE (sev2prio))
sp->prio = sev2prio[n];
else
return EINVAL;
break;
switch (opcode)
{
case MU_IOCTL_SYSLOGSTREAM_SET_LOGGER:
sp->logger = arg;
break;
case MU_IOCTL_SYSLOGSTREAM_GET_LOGGER:
*(void (**) (int, const char *, ...))arg = sp->logger;
break;
default:
return ENOSYS;
default:
return ENOSYS;
}
}
else
return ENOSYS;
return 0;
}
......@@ -106,6 +127,7 @@ mu_syslog_stream_create (mu_stream_t *pstream, int prio)
if (!str)
return ENOMEM;
str->prio = prio;
str->logger = NULL;
str->base.write = _syslog_stream_write;
str->base.ctl = _syslog_ctl;
str->base.setbuf_hook = _syslog_setbuf_hook;
......
......@@ -50,11 +50,21 @@ struct lib_descr {
int flags;
} lib_descr[] = {
{ "mbox", "mu_mbox", 0 },
#ifdef ENABLE_MH
{ "mh", "mu_mh", 0 },
#endif
#ifdef ENABLE_MAILDIR
{ "maildir","mu_maildir", 0 },
#endif
#ifdef ENABLE_IMAP
{ "imap", "mu_imap", NEEDAUTH },
#endif
#ifdef ENABLE_POP
{ "pop", "mu_pop", NEEDAUTH },
#endif
#ifdef ENABLE_NNTP
{ "nntp", "mu_nntp", 0 },
#endif
{ "mailer", "mu_mailer", 0 },
{ "sieve", "mu_sieve", NOTALL },
{ "compat", "mu_compat" },
......