summaryrefslogtreecommitdiff
path: root/lib/libc/gen
diff options
context:
space:
mode:
authorJean-Jacques Bernard-Gundol <jjbg@cvs.openbsd.org>2001-10-24 08:16:43 +0000
committerJean-Jacques Bernard-Gundol <jjbg@cvs.openbsd.org>2001-10-24 08:16:43 +0000
commitdab7fa54300ebdfe67399b7ae0db895888157c2a (patch)
treeca74c2edb5bbd260a106b689c3ae65a42c55bb12 /lib/libc/gen
parentd63faf6dea63e4725598059c282c6c69d1787061 (diff)
syslog_r() implementation. deraadt@ ok.
Diffstat (limited to 'lib/libc/gen')
-rw-r--r--lib/libc/gen/syslog.3113
-rw-r--r--lib/libc/gen/syslog.c263
2 files changed, 275 insertions, 101 deletions
diff --git a/lib/libc/gen/syslog.3 b/lib/libc/gen/syslog.3
index 36f998b8ee2..3f09655a030 100644
--- a/lib/libc/gen/syslog.3
+++ b/lib/libc/gen/syslog.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: syslog.3,v 1.12 2001/07/27 16:41:20 marc Exp $
+.\" $OpenBSD: syslog.3,v 1.13 2001/10/24 08:16:42 jjbg Exp $
.\"
.\" Copyright (c) 1985, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -36,10 +36,15 @@
.Os
.Sh NAME
.Nm syslog ,
+.Nm syslog_r,
.Nm vsyslog ,
+.Nm vsyslog_r,
.Nm openlog ,
+.Nm openlog_r,
.Nm closelog ,
-.Nm setlogmask
+.Nm closelog_r,
+.Nm setlogmask,
+.Nm setlogmask_r
.Nd control system log
.Sh SYNOPSIS
.Fd #include <syslog.h>
@@ -47,13 +52,36 @@
.Ft void
.Fn syslog "int priority" "const char *message" "..."
.Ft void
+.Fn syslog_r "int priority" "struct syslog_data *data" "const char *message" "..."
+.Ft void
.Fn vsyslog "int priority" "const char *message" "va_list args"
.Ft void
+.Fn vsyslog_r "int priority" "struct syslog_data *data" "const char *message" "va_list args"
+.Ft void
.Fn openlog "const char *ident" "int logopt" "int facility"
.Ft void
+.Fn openlog_r "const char *ident" "int logopt" "int facility" "struct syslog_data *data"
+.Ft void
.Fn closelog void
+.Ft void
+.Fn closelog_r "struct syslog_data *data"
.Ft int
.Fn setlogmask "int maskpri"
+.Ft int
+.Fn setlogmask_r "int maskpri" "struct syslog_data *data"
+.Bd -literal
+
+struct syslog_data {
+ int log_file;
+ int connected;
+ int opened;
+ int log_stat;
+ const char *log_tag;
+ int log_fac;
+ int log_mask;
+};
+
+#define SYSLOG_DATA_INIT {-1, 0, 0, 0, NULL, LOG_USER, 0xff}
.Sh DESCRIPTION
The
.Fn syslog
@@ -76,6 +104,39 @@ see
A trailing newline is added if none is present.
.Pp
The
+.Fn syslog_r
+function is a reentrant version of the
+.Xr syslog 3
+function. It takes a pointer to a
+.Fa syslog_data
+structure which is used to store
+information. This parameter must be initialized before
+.Fn syslog_r
+is called. The SYSLOG_DATA_INIT constant is used for this purpose.
+The
+.Fa syslog_data
+structure is composed of the following elements:
+.Bl -tag -width connected
+.It Dv log_file
+contains the file descriptor of the file where the message is logged.
+.It Dv connected
+indicates if connect has been done
+.It Dv opened
+indicates if
+.Xr openlog_r 3
+has been called.
+.It Dv log_stat
+status bits, set by
+.Xr openlog_r 3
+.It Dv log_tag
+string to tag the entry with
+.It Dv log_fac
+facility code
+.It Dv log_mask
+mask of priorities to be logged
+.El
+.Pp
+The
.Fn vsyslog
function is an alternate form in which the arguments have already been captured
using the variable-length argument facilities of
@@ -116,6 +177,16 @@ normally of use only when debugging a program.
.El
.Pp
The
+.Fn vsyslog_r
+is used the same way than
+.Fn vsyslog
+except than it takes an additional pointer on a
+.Fa syslog_data
+structure. It is a reentrant version of the
+.Fn vsyslog
+function described above.
+.Pp
+The
.Fn openlog
function provides for more specialized processing of the messages sent by
.Fn syslog
@@ -210,8 +281,22 @@ through
.El
.Pp
The
+.Fn openlog_r
+function is the reentrant version of the
+.Fn openlog
+function. It takes an additional pointer on a
+.Fa syslog_data
+structure. This function must be used in conjunction with the other
+reentrant functions.
+.Pp
+The
.Fn closelog
-function can be used to close the log file.
+function can be used to close the log file.
+.Fn closelog_r
+do the same thing but in a reentrant way and takes an additional
+pointer on a
+.Fa syslog_data
+structure.
.Pp
The
.Fn setlogmask
@@ -232,18 +317,32 @@ the mask for all priorities up to and including
is given by the macro
.Fn LOG_UPTO toppri ; .
The default allows all priorities to be logged.
+.Pp
+The
+.Fn setlogmask_r
+function is the reentrant version of
+.Fn setlogmask .
+It takes an additional pointer on a
+.Fa syslog_data
+structure.
.Sh RETURN VALUES
The
.Fn closelog ,
+.Fn closelog_r ,
.Fn openlog ,
+.Fn openlog_r ,
.Fn syslog ,
-and
+.Fn syslog_r ,
.Fn vsyslog
+and
+.Fn vsyslog_r
functions return no value.
.Pp
-The routine
+The routines
.Fn setlogmask
-always returns the previous log mask level.
+and
+.Fn setlogmask_r
+always return the previous log mask level.
.Sh EXAMPLES
.Bd -literal -offset indent -compact
syslog(LOG_ALERT, "who: internal error 23");
@@ -263,6 +362,8 @@ syslog(LOG_INFO|LOG_LOCAL2, "foobar error: %m");
These
functions appeared in
.Bx 4.2 .
+The reentrant functions appeared in
+.Ox 3.1 .
.Sh CAVEATS
It is important never to pass a string with user-supplied data as a
format without using
diff --git a/lib/libc/gen/syslog.c b/lib/libc/gen/syslog.c
index fa6b9511921..beabbcce9ba 100644
--- a/lib/libc/gen/syslog.c
+++ b/lib/libc/gen/syslog.c
@@ -32,7 +32,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: syslog.c,v 1.11 2001/08/18 22:56:22 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: syslog.c,v 1.12 2001/10/24 08:16:42 jjbg Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -56,17 +56,15 @@ static char rcsid[] = "$OpenBSD: syslog.c,v 1.11 2001/08/18 22:56:22 deraadt Exp
#include <varargs.h>
#endif
-static int LogFile = -1; /* fd for log */
-static int connected; /* have done connect */
-static int opened; /* have done openlog() */
-static int LogStat = 0; /* status bits, set by openlog() */
-static const char *LogTag = NULL; /* string to tag the entry with */
-static int LogFacility = LOG_USER; /* default facility code */
-static int LogMask = 0xff; /* mask of priorities to be logged */
+static struct syslog_data sdata = SYSLOG_DATA_INIT;
+
extern char *__progname; /* Program name, from crt0. */
static void disconnectlog __P((void)); /* disconnect from syslogd */
static void connectlog __P((void)); /* (re)connect to syslogd */
+static void disconnectlog_r __P((struct syslog_data *));
+static void connectlog_r __P((struct syslog_data *));
+
/*
* syslog, vsyslog --
* print message on log file; output is intended for syslogd(8).
@@ -98,8 +96,76 @@ vsyslog(pri, fmt, ap)
register const char *fmt;
va_list ap;
{
- register int cnt;
- register char ch, *p, *t;
+ vsyslog_r(pri, &sdata, fmt, ap);
+}
+
+static void
+disconnectlog()
+{
+ disconnectlog_r(&sdata);
+}
+
+static void
+connectlog()
+{
+ connectlog_r(&sdata);
+}
+
+void
+openlog(ident, logstat, logfac)
+ const char *ident;
+ int logstat, logfac;
+{
+ openlog_r(ident, logstat, logfac, &sdata);
+}
+
+void
+closelog()
+{
+ closelog_r(&sdata);
+}
+
+/* setlogmask -- set the log mask level */
+int
+setlogmask(pmask)
+ int pmask;
+{
+ return setlogmask_r(pmask, &sdata);
+}
+
+/* Reentrant version of syslog, i.e. syslog_r() */
+
+void
+#ifdef __STDC__
+syslog_r(int pri, struct syslog_data *data, const char *fmt, ...)
+#else
+syslog_r(pri, data, fmt, va_alist)
+ int pri;
+ struct syslog_data *data;
+ char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ vsyslog_r(pri, data, fmt, ap);
+ va_end(ap);
+}
+
+void
+vsyslog_r(pri, data, fmt, ap)
+ int pri;
+ struct syslog_data *data;
+ const char *fmt;
+ va_list ap;
+{
+ int cnt;
+ char ch, *p, *t;
time_t now;
int fd, saved_errno;
#define TBUF_LEN 2048
@@ -110,65 +176,64 @@ vsyslog(pri, fmt, ap)
#define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
/* Check for invalid bits. */
if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
- syslog(INTERNALLOG,
- "syslog: unknown facility/priority: %x", pri);
+ if (data == &sdata) {
+ syslog(INTERNALLOG,
+ "syslog: unknown facility/priority: %x", pri);
+ } else {
+ syslog_r(INTERNALLOG, data,
+ "syslog_r: unknown facility/priority: %x", pri);
+ }
pri &= LOG_PRIMASK|LOG_FACMASK;
}
/* Check priority against setlogmask values. */
- if (!(LOG_MASK(LOG_PRI(pri)) & LogMask))
+ if (!(LOG_MASK(LOG_PRI(pri)) & data->log_mask))
return;
saved_errno = errno;
- /* Set default facility if none specified. */
- if ((pri & LOG_FACMASK) == 0)
- pri |= LogFacility;
+ /* If we have been called through syslog(), no need for reentrancy. */
+ if (data == &sdata)
+ (void)time(&now);
+
+ p = tbuf;
+ tbuf_left = TBUF_LEN;
+
+#define DEC() \
+ do { \
+ if (prlen < 0) \
+ prlen = 0; \
+ if (prlen >= tbuf_left) \
+ prlen = tbuf_left - 1; \
+ p += prlen; \
+ tbuf_left -= prlen; \
+ } while (0)
+
+ prlen = snprintf(p, tbuf_left, "<%d>", pri);
+ DEC();
- /* Build the message. */
-
- /*
- * Although it's tempting, we can't ignore the possibility of
- * overflowing the buffer when assembling the "fixed" portion
- * of the message. Strftime's "%h" directive expands to the
- * locale's abbreviated month name, but if the user has the
- * ability to construct to his own locale files, it may be
- * arbitrarily long.
+ /*
+ * syslogd will expand time automagically for reentrant case, and
+ * for normal case, just do like before
*/
- (void)time(&now);
-
- p = tbuf;
- tbuf_left = TBUF_LEN;
-
-#define DEC() \
- do { \
- if (prlen < 0) \
- prlen = 0; \
- else if (prlen >= tbuf_left) \
- prlen = tbuf_left - 1; \
- p += prlen; \
- tbuf_left -= prlen; \
- } while (0)
-
- prlen = snprintf(p, tbuf_left, "<%d>", pri);
- DEC();
-
- prlen = strftime(p, tbuf_left, "%h %e %T ", localtime(&now));
- DEC();
+ if (data == &sdata) {
+ prlen = strftime(p, tbuf_left, "%h %e %T ", localtime(&now));
+ DEC();
+ }
- if (LogStat & LOG_PERROR)
+ if (data->log_stat & LOG_PERROR)
stdp = p;
- if (LogTag == NULL)
- LogTag = __progname;
- if (LogTag != NULL) {
- prlen = snprintf(p, tbuf_left, "%s", LogTag);
+ if (data->log_tag == NULL)
+ data->log_tag = __progname;
+ if (data->log_tag != NULL) {
+ prlen = snprintf(p, tbuf_left, "%s", data->log_tag);
DEC();
}
- if (LogStat & LOG_PID) {
+ if (data->log_stat & LOG_PID) {
prlen = snprintf(p, tbuf_left, "[%d]", getpid());
DEC();
}
- if (LogTag != NULL) {
+ if (data->log_tag != NULL) {
if (tbuf_left > 1) {
*p++ = ':';
tbuf_left--;
@@ -179,15 +244,18 @@ vsyslog(pri, fmt, ap)
}
}
- /*
- * We wouldn't need this mess if printf handled %m, or if
- * strerror() had been invented before syslog().
- */
+ /* strerror() is not reentrant */
+
for (t = fmt_cpy, fmt_left = FMT_LEN; (ch = *fmt); ++fmt) {
if (ch == '%' && fmt[1] == 'm') {
++fmt;
- prlen = snprintf(t, fmt_left, "%s",
- strerror(saved_errno));
+ if (data == &sdata) {
+ prlen = snprintf(t, fmt_left, "%s",
+ strerror(saved_errno));
+ } else {
+ prlen = snprintf(t, fmt_left, "Error %d",
+ saved_errno);
+ }
if (prlen >= fmt_left)
prlen = fmt_left - 1;
t += prlen;
@@ -206,7 +274,7 @@ vsyslog(pri, fmt, ap)
cnt = p - tbuf;
/* Output to stderr if requested. */
- if (LogStat & LOG_PERROR) {
+ if (data->log_stat & LOG_PERROR) {
struct iovec iov[2];
iov[0].iov_base = stdp;
@@ -217,19 +285,19 @@ vsyslog(pri, fmt, ap)
}
/* Get connected, output the message to the local logger. */
- if (!opened)
- openlog(LogTag, LogStat, 0);
- connectlog();
- if (send(LogFile, tbuf, cnt, 0) >= 0)
+ if (!data->opened)
+ openlog_r(data->log_tag, data->log_stat, 0, data);
+ connectlog_r(data);
+ if (send(data->log_file, tbuf, cnt, 0) >= 0)
return;
/*
* If the send() failed, the odds are syslogd was restarted.
* Make one (only) attempt to reconnect to /dev/log.
*/
- disconnectlog();
- connectlog();
- if (send(LogFile, tbuf, cnt, 0) >= 0)
+ disconnectlog_r(data);
+ connectlog_r(data);
+ if (send(data->log_file, tbuf, cnt, 0) >= 0)
return;
/*
@@ -237,7 +305,7 @@ vsyslog(pri, fmt, ap)
* if console blocks everything will. Make sure the error reported
* is the one from the syslogd failure.
*/
- if (LogStat & LOG_CONS &&
+ if (data->log_stat & LOG_CONS &&
(fd = open(_PATH_CONSOLE, O_WRONLY, 0)) >= 0) {
struct iovec iov[2];
@@ -252,79 +320,84 @@ vsyslog(pri, fmt, ap)
}
static void
-disconnectlog()
+disconnectlog_r(data)
+ struct syslog_data *data;
{
/*
* If the user closed the FD and opened another in the same slot,
* that's their problem. They should close it before calling on
* system services.
*/
- if (LogFile != -1) {
- close(LogFile);
- LogFile = -1;
+ if (data->log_file != -1) {
+ close(data->log_file);
+ data->log_file = -1;
}
- connected = 0; /* retry connect */
+ data->connected = 0; /* retry connect */
}
static void
-connectlog()
+connectlog_r(data)
+ struct syslog_data *data;
{
struct sockaddr_un SyslogAddr; /* AF_UNIX address of local logger */
- if (LogFile == -1) {
- if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
+ if (data->log_file == -1) {
+ if ((data->log_file = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
return;
- (void)fcntl(LogFile, F_SETFD, 1);
+ (void)fcntl(data->log_file, F_SETFD, 1);
}
- if (LogFile != -1 && !connected) {
+ if (data->log_file != -1 && !data->connected) {
memset(&SyslogAddr, '\0', sizeof(SyslogAddr));
SyslogAddr.sun_len = sizeof(SyslogAddr);
SyslogAddr.sun_family = AF_UNIX;
strlcpy(SyslogAddr.sun_path, _PATH_LOG,
sizeof(SyslogAddr.sun_path));
- if (connect(LogFile, (struct sockaddr *)&SyslogAddr,
+ if (connect(data->log_file, (struct sockaddr *)&SyslogAddr,
sizeof(SyslogAddr)) == -1) {
- (void)close(LogFile);
- LogFile = -1;
+ (void)close(data->log_file);
+ data->log_file = -1;
} else
- connected = 1;
+ data->connected = 1;
}
}
void
-openlog(ident, logstat, logfac)
+openlog_r(ident, logstat, logfac, data)
const char *ident;
int logstat, logfac;
+ struct syslog_data *data;
{
if (ident != NULL)
- LogTag = ident;
- LogStat = logstat;
+ data->log_tag = ident;
+ data->log_stat = logstat;
if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
- LogFacility = logfac;
+ data->log_fac = logfac;
- if (LogStat & LOG_NDELAY) /* open immediately */
- connectlog();
+ if (data->log_stat & LOG_NDELAY) /* open immediately */
+ connectlog_r(data);
- opened = 1; /* ident and facility has been set */
+ data->opened = 1; /* ident and facility has been set */
}
void
-closelog()
+closelog_r(data)
+ struct syslog_data *data;
{
- (void)close(LogFile);
- LogFile = -1;
- connected = 0;
+ (void)close(data->log_file);
+ data->log_file = -1;
+ data->connected = 0;
}
/* setlogmask -- set the log mask level */
int
-setlogmask(pmask)
+setlogmask_r(pmask, data)
int pmask;
+ struct syslog_data *data;
{
int omask;
- omask = LogMask;
+ omask = data->log_mask;
if (pmask != 0)
- LogMask = pmask;
+ data->log_mask = pmask;
return (omask);
}