Module Name: src
Committed By: christos
Date: Thu Jan 12 00:38:01 UTC 2017
Modified Files:
src/lib/libc/gen: Makefile.inc syslog.c
Added Files:
src/lib/libc/gen: syslog_private.h syslog_ss.c xsyslog.c
Log Message:
Split syslog.c to:
- syslog_ss.c *_ss api functions (don't use stdio, time)
- syslog.c: *syslog* non _ss api functions (use stdio, time)
- xsyslog.c> common guts.
The motivation for this is not to drag in stdio/locale/floating point/time
for every binary, since syslog_ss() is used in __stack_check_fail() for SSP.
To generate a diff of this commit:
cvs rdiff -u -r1.196 -r1.197 src/lib/libc/gen/Makefile.inc
cvs rdiff -u -r1.55 -r1.56 src/lib/libc/gen/syslog.c
cvs rdiff -u -r0 -r1.1 src/lib/libc/gen/syslog_private.h \
src/lib/libc/gen/syslog_ss.c src/lib/libc/gen/xsyslog.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libc/gen/Makefile.inc
diff -u src/lib/libc/gen/Makefile.inc:1.196 src/lib/libc/gen/Makefile.inc:1.197
--- src/lib/libc/gen/Makefile.inc:1.196 Tue Oct 4 05:41:41 2016
+++ src/lib/libc/gen/Makefile.inc Wed Jan 11 19:38:01 2017
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.inc,v 1.196 2016/10/04 09:41:41 kamil Exp $
+# $NetBSD: Makefile.inc,v 1.197 2017/01/12 00:38:01 christos Exp $
# from: @(#)Makefile.inc 8.6 (Berkeley) 5/4/95
# gen sources
@@ -32,12 +32,12 @@ SRCS+= alarm.c alphasort.c arc4random.c
siglist.c signal.c signame.c sigrelse.c \
sigset.c sigsetops.c sleep.c \
stringlist.c sysconf.c sysctl.c sysctlbyname.c sysctlgetmibinfo.c \
- sysctlnametomib.c syslog.c telldir.c time.c timespec_get.c \
+ sysctlnametomib.c syslog.c syslog_ss.c telldir.c time.c timespec_get.c \
times.c toascii.c tolower_.c ttyname.c ttyslot.c toupper_.c ualarm.c \
ulimit.c uname.c unvis.c usleep.c utime.c utimens.c utmp.c \
utmpx.c valloc.c vis.c wait.c wait3.c waitid.c waitpid.c warn.c \
- warnx.c warnc.c vwarn.c vwarnx.c vwarnc.c verr.c verrx.c verrc.c \
- wordexp.c
+ warnx.c warnc.c wordexp.c xsyslog.c \
+ vwarn.c vwarnx.c vwarnc.c verr.c verrx.c verrc.c
# uses alloca
COPTS.execvp.c = -Wno-stack-protector
Index: src/lib/libc/gen/syslog.c
diff -u src/lib/libc/gen/syslog.c:1.55 src/lib/libc/gen/syslog.c:1.56
--- src/lib/libc/gen/syslog.c:1.55 Mon Oct 26 07:44:30 2015
+++ src/lib/libc/gen/syslog.c Wed Jan 11 19:38:01 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: syslog.c,v 1.55 2015/10/26 11:44:30 roy Exp $ */
+/* $NetBSD: syslog.c,v 1.56 2017/01/12 00:38:01 christos Exp $ */
/*
* Copyright (c) 1983, 1988, 1993
@@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)syslog.c 8.5 (Berkeley) 4/29/95";
#else
-__RCSID("$NetBSD: syslog.c,v 1.55 2015/10/26 11:44:30 roy Exp $");
+__RCSID("$NetBSD: syslog.c,v 1.56 2017/01/12 00:38:01 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -48,6 +48,7 @@ __RCSID("$NetBSD: syslog.c,v 1.55 2015/1
#include <netdb.h>
#include <errno.h>
+#include <stdio.h>
#include <fcntl.h>
#include <paths.h>
#include <stdarg.h>
@@ -56,32 +57,61 @@ __RCSID("$NetBSD: syslog.c,v 1.55 2015/1
#include <string.h>
#include <time.h>
#include <unistd.h>
+
+#include "syslog_private.h"
#include "reentrant.h"
#include "extern.h"
#ifdef __weak_alias
-__weak_alias(closelog,_closelog)
-__weak_alias(openlog,_openlog)
-__weak_alias(setlogmask,_setlogmask)
__weak_alias(syslog,_syslog)
__weak_alias(vsyslog,_vsyslog)
__weak_alias(syslogp,_syslogp)
__weak_alias(vsyslogp,_vsyslogp)
#endif
-static struct syslog_data sdata = SYSLOG_DATA_INIT;
-
-static void openlog_unlocked_r(const char *, int, int,
- struct syslog_data *);
-static void disconnectlog_r(struct syslog_data *);
-static void connectlog_r(struct syslog_data *);
-
-#define LOG_SIGNAL_SAFE (int)0x80000000
-
+static size_t
+timefun(char *p, size_t tbuf_left)
+{
+ struct timeval tv;
+ time_t now;
+ struct tm tmnow;
+ size_t prlen;
+ char *op = p;
-#ifdef _REENTRANT
-static mutex_t syslog_mutex = MUTEX_INITIALIZER;
+ if (gettimeofday(&tv, NULL) == -1)
+ return snprintf_ss(p, tbuf_left, "-");
+
+ /* strftime() implies tzset(), localtime_r() doesn't. */
+ tzset();
+ now = (time_t) tv.tv_sec;
+ localtime_r(&now, &tmnow);
+
+ prlen = strftime(p, tbuf_left, "%FT%T", &tmnow);
+ DEC();
+ prlen = snprintf(p, tbuf_left, ".%06ld", (long)tv.tv_usec);
+ DEC();
+ prlen = strftime(p, tbuf_left-1, "%z", &tmnow);
+ /* strftime gives eg. "+0200", but we need "+02:00" */
+ if (prlen == 5) {
+ p[prlen+1] = p[prlen];
+ p[prlen] = p[prlen-1];
+ p[prlen-1] = p[prlen-2];
+ p[prlen-2] = ':';
+ prlen += 1;
+ }
+ DEC();
+ return (size_t)(p - op);
+}
+
+static struct syslog_fun _syslog_fun = {
+ timefun,
+ strerror_r,
+#ifndef __lint__
+ _vsnprintf,
+#else
+ vsnprintf,
#endif
+};
/*
* syslog, vsyslog --
@@ -93,14 +123,14 @@ syslog(int pri, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
- vsyslog(pri, fmt, ap);
+ _vxsyslogp_r(pri, &_syslog_fun, &_syslog_data, NULL, NULL, fmt, ap);
va_end(ap);
}
void
vsyslog(int pri, const char *fmt, va_list ap)
{
- vsyslog_r(pri, &sdata, fmt, ap);
+ _vxsyslogp_r(pri, &_syslog_fun, &_syslog_data, NULL, NULL, fmt, ap);
}
/*
@@ -113,44 +143,33 @@ syslogp(int pri, const char *msgid, cons
va_list ap;
va_start(ap, msgfmt);
- vsyslogp(pri, msgid, sdfmt, msgfmt, ap);
+ _vxsyslogp_r(pri, &_syslog_fun, &_syslog_data,
+ msgid, sdfmt, msgfmt, ap);
va_end(ap);
}
void
-vsyslogp(int pri, const char *msgid, const char *sdfmt, const char *msgfmt, va_list ap)
+vsyslogp(int pri, const char *msgid, const char *sdfmt, const char *msgfmt,
+ va_list ap)
{
- vsyslogp_r(pri, &sdata, msgid, sdfmt, msgfmt, ap);
+ _vxsyslogp_r(pri, &_syslog_fun, &_syslog_data,
+ msgid, sdfmt, msgfmt, ap);
}
void
-openlog(const char *ident, int logstat, int logfac)
-{
- openlog_r(ident, logstat, logfac, &sdata);
-}
-
-void
-closelog(void)
-{
- closelog_r(&sdata);
-}
-
-/* setlogmask -- set the log mask level */
-int
-setlogmask(int pmask)
+vsyslogp_r(int pri, struct syslog_data *data, const char *msgid,
+ const char *sdfmt, const char *msgfmt, va_list ap)
{
- return setlogmask_r(pmask, &sdata);
+ _vxsyslogp_r(pri, &_syslog_fun, data, msgid, sdfmt, msgfmt, ap);
}
-/* Reentrant version of syslog, i.e. syslog_r() */
-
void
syslog_r(int pri, struct syslog_data *data, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
- vsyslog_r(pri, data, fmt, ap);
+ _vxsyslogp_r(pri, &_syslog_fun, data, NULL, NULL, fmt, ap);
va_end(ap);
}
@@ -161,409 +180,12 @@ syslogp_r(int pri, struct syslog_data *d
va_list ap;
va_start(ap, msgfmt);
- vsyslogp_r(pri, data, msgid, sdfmt, msgfmt, ap);
- va_end(ap);
-}
-
-void
-syslog_ss(int pri, struct syslog_data *data, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vsyslog_r(pri | LOG_SIGNAL_SAFE, data, fmt, ap);
- va_end(ap);
-}
-
-void
-syslogp_ss(int pri, struct syslog_data *data, const char *msgid,
- const char *sdfmt, const char *msgfmt, ...)
-{
- va_list ap;
-
- va_start(ap, msgfmt);
- vsyslogp_r(pri | LOG_SIGNAL_SAFE, data, msgid, sdfmt, msgfmt, ap);
+ _vxsyslogp_r(pri, &_syslog_fun, data, msgid, sdfmt, msgfmt, ap);
va_end(ap);
}
void
-vsyslog_ss(int pri, struct syslog_data *data, const char *fmt, va_list ap)
-{
- vsyslog_r(pri | LOG_SIGNAL_SAFE, data, fmt, ap);
-}
-
-void
-vsyslogp_ss(int pri, struct syslog_data *data, const char *msgid,
- const char *sdfmt, const char *msgfmt, va_list ap)
-{
- vsyslogp_r(pri | LOG_SIGNAL_SAFE, data, msgid, sdfmt, msgfmt, ap);
-}
-
-
-void
vsyslog_r(int pri, struct syslog_data *data, const char *fmt, va_list ap)
{
- vsyslogp_r(pri, data, NULL, NULL, fmt, ap);
-}
-
-void
-vsyslogp_r(int pri, struct syslog_data *data, const char *msgid,
- const char *sdfmt, const char *msgfmt, va_list ap)
-{
- static const char BRCOSP[] = "]: ";
- static const char CRLF[] = "\r\n";
- size_t cnt, prlen, tries;
- char ch, *p, *t;
- struct timeval tv;
- struct tm tmnow;
- time_t now;
- int fd, saved_errno;
-#define TBUF_LEN 2048
-#define FMT_LEN 1024
-#define MAXTRIES 10
- char tbuf[TBUF_LEN], fmt_cpy[FMT_LEN], fmt_cat[FMT_LEN] = "";
- size_t tbuf_left, fmt_left, msgsdlen;
- char *fmt = fmt_cat;
- int signal_safe = pri & LOG_SIGNAL_SAFE;
- struct iovec iov[7]; /* prog + [ + pid + ]: + fmt + crlf */
- int opened, iovcnt;
-
- pri &= ~LOG_SIGNAL_SAFE;
-
-#define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
- /* Check for invalid bits. */
- if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
- syslog_r(INTERNALLOG | signal_safe, data,
- "syslog_r: unknown facility/priority: %x", pri);
- pri &= LOG_PRIMASK|LOG_FACMASK;
- }
-
- /* Check priority against setlogmask values. */
- 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 |= data->log_fac;
-
- /* Build the message. */
- p = tbuf;
- tbuf_left = TBUF_LEN;
-
-#define DEC() \
- do { \
- if (prlen >= tbuf_left) \
- prlen = tbuf_left - 1; \
- p += prlen; \
- tbuf_left -= prlen; \
- } while (/*CONSTCOND*/0)
-
- prlen = snprintf_ss(p, tbuf_left, "<%d>1 ", pri);
- DEC();
-
- if (!signal_safe && (gettimeofday(&tv, NULL) != -1)) {
- /* strftime() implies tzset(), localtime_r() doesn't. */
- tzset();
- now = (time_t) tv.tv_sec;
- localtime_r(&now, &tmnow);
-
- prlen = strftime(p, tbuf_left, "%FT%T", &tmnow);
- DEC();
- prlen = snprintf(p, tbuf_left, ".%06ld", (long)tv.tv_usec);
- DEC();
- prlen = strftime(p, tbuf_left-1, "%z", &tmnow);
- /* strftime gives eg. "+0200", but we need "+02:00" */
- if (prlen == 5) {
- p[prlen+1] = p[prlen];
- p[prlen] = p[prlen-1];
- p[prlen-1] = p[prlen-2];
- p[prlen-2] = ':';
- prlen += 1;
- }
- } else {
- prlen = snprintf_ss(p, tbuf_left, "-");
-#if 0
- /*
- * if gmtime_r() was signal-safe we could output
- * the UTC-time:
- */
- gmtime_r(&now, &tmnow);
- prlen = strftime(p, tbuf_left, "%FT%TZ", &tmnow);
-#endif
- }
-
- if (data == &sdata)
- mutex_lock(&syslog_mutex);
-
- if (data->log_hostname[0] == '\0' && gethostname(data->log_hostname,
- sizeof(data->log_hostname)) == -1) {
- /* can this really happen? */
- data->log_hostname[0] = '-';
- data->log_hostname[1] = '\0';
- }
-
- DEC();
- prlen = snprintf_ss(p, tbuf_left, " %s ", data->log_hostname);
-
- if (data->log_tag == NULL)
- data->log_tag = getprogname();
-
- DEC();
- prlen = snprintf_ss(p, tbuf_left, "%s ",
- data->log_tag ? data->log_tag : "-");
-
- if (data == &sdata)
- mutex_unlock(&syslog_mutex);
-
- if (data->log_stat & (LOG_PERROR|LOG_CONS)) {
- iovcnt = 0;
- iov[iovcnt].iov_base = p;
- iov[iovcnt].iov_len = prlen - 1;
- iovcnt++;
- }
- DEC();
-
- if (data->log_stat & LOG_PID) {
- prlen = snprintf_ss(p, tbuf_left, "%d ", getpid());
- if (data->log_stat & (LOG_PERROR|LOG_CONS)) {
- iov[iovcnt].iov_base = __UNCONST("[");
- iov[iovcnt].iov_len = 1;
- iovcnt++;
- iov[iovcnt].iov_base = p;
- iov[iovcnt].iov_len = prlen - 1;
- iovcnt++;
- iov[iovcnt].iov_base = __UNCONST(BRCOSP);
- iov[iovcnt].iov_len = 3;
- iovcnt++;
- }
- } else {
- prlen = snprintf_ss(p, tbuf_left, "- ");
- if (data->log_stat & (LOG_PERROR|LOG_CONS)) {
- iov[iovcnt].iov_base = __UNCONST(BRCOSP + 1);
- iov[iovcnt].iov_len = 2;
- iovcnt++;
- }
- }
- DEC();
-
- /*
- * concat the format strings, then use one vsnprintf()
- */
- if (msgid != NULL && *msgid != '\0') {
- strlcat(fmt_cat, msgid, FMT_LEN);
- strlcat(fmt_cat, " ", FMT_LEN);
- } else
- strlcat(fmt_cat, "- ", FMT_LEN);
-
- if (sdfmt != NULL && *sdfmt != '\0') {
- strlcat(fmt_cat, sdfmt, FMT_LEN);
- } else
- strlcat(fmt_cat, "-", FMT_LEN);
-
- if (data->log_stat & (LOG_PERROR|LOG_CONS))
- msgsdlen = strlen(fmt_cat) + 1;
- else
- msgsdlen = 0; /* XXX: GCC */
-
- if (msgfmt != NULL && *msgfmt != '\0') {
- strlcat(fmt_cat, " ", FMT_LEN);
- strlcat(fmt_cat, msgfmt, FMT_LEN);
- }
-
- /*
- * We wouldn't need this mess if printf handled %m, or if
- * strerror() had been invented before syslog().
- */
- for (t = fmt_cpy, fmt_left = FMT_LEN; (ch = *fmt) != '\0'; ++fmt) {
- if (ch == '%' && fmt[1] == 'm') {
- const char *s;
-
- if (signal_safe || (s = strerror(saved_errno)) == NULL)
- prlen = snprintf_ss(t, fmt_left, "Error %d",
- saved_errno);
- else
- prlen = strlcpy(t, s, fmt_left);
- if (prlen >= fmt_left)
- prlen = fmt_left - 1;
- t += prlen;
- fmt++;
- fmt_left -= prlen;
- } else if (ch == '%' && fmt[1] == '%' && fmt_left > 2) {
- *t++ = '%';
- *t++ = '%';
- fmt++;
- fmt_left -= 2;
- } else {
- if (fmt_left > 1) {
- *t++ = ch;
- fmt_left--;
- }
- }
- }
- *t = '\0';
-
- if (signal_safe)
- prlen = vsnprintf_ss(p, tbuf_left, fmt_cpy, ap);
- else
- prlen = vsnprintf(p, tbuf_left, fmt_cpy, ap);
-
- if (data->log_stat & (LOG_PERROR|LOG_CONS)) {
- iov[iovcnt].iov_base = p + msgsdlen;
- iov[iovcnt].iov_len = prlen - msgsdlen;
- iovcnt++;
- }
-
- DEC();
- cnt = p - tbuf;
-
- /* Output to stderr if requested. */
- if (data->log_stat & LOG_PERROR) {
- iov[iovcnt].iov_base = __UNCONST(CRLF + 1);
- iov[iovcnt].iov_len = 1;
- (void)writev(STDERR_FILENO, iov, iovcnt + 1);
- }
-
- /* Get connected, output the message to the local logger. */
- if (data == &sdata)
- mutex_lock(&syslog_mutex);
- opened = !data->log_opened;
- if (opened)
- openlog_unlocked_r(data->log_tag, data->log_stat, 0, data);
- connectlog_r(data);
-
- /*
- * If the send() failed, there are two likely scenarios:
- * 1) syslogd was restarted
- * 2) /dev/log is out of socket buffer space
- * We attempt to reconnect to /dev/log to take care of
- * case #1 and keep send()ing data to cover case #2
- * to give syslogd a chance to empty its socket buffer.
- */
- for (tries = 0; tries < MAXTRIES; tries++) {
- if (send(data->log_file, tbuf, cnt, 0) != -1)
- break;
- if (errno != ENOBUFS) {
- disconnectlog_r(data);
- connectlog_r(data);
- } else
- (void)usleep(1);
- }
-
- /*
- * Output the message to the console; try not to block
- * as a blocking console should not stop other processes.
- * Make sure the error reported is the one from the syslogd failure.
- */
- if (tries == MAXTRIES && (data->log_stat & LOG_CONS) &&
- (fd = open(_PATH_CONSOLE,
- O_WRONLY | O_NONBLOCK | O_CLOEXEC, 0)) >= 0) {
- iov[iovcnt].iov_base = __UNCONST(CRLF);
- iov[iovcnt].iov_len = 2;
- (void)writev(fd, iov, iovcnt + 1);
- (void)close(fd);
- }
-
- if (data == &sdata)
- mutex_unlock(&syslog_mutex);
-
- if (data != &sdata && opened) {
- /* preserve log tag */
- const char *ident = data->log_tag;
- closelog_r(data);
- data->log_tag = ident;
- }
-}
-
-static void
-disconnectlog_r(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 (data->log_file != -1) {
- (void)close(data->log_file);
- data->log_file = -1;
- }
- data->log_connected = 0; /* retry connect */
-}
-
-static void
-connectlog_r(struct syslog_data *data)
-{
- /* AF_UNIX address of local logger */
- static const struct sockaddr_un sun = {
- .sun_family = AF_LOCAL,
- .sun_len = sizeof(sun),
- .sun_path = _PATH_LOG,
- };
-
- if (data->log_file == -1 || fcntl(data->log_file, F_GETFL, 0) == -1) {
- if ((data->log_file = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC,
- 0)) == -1)
- return;
- data->log_connected = 0;
- }
- if (!data->log_connected) {
- if (connect(data->log_file,
- (const struct sockaddr *)(const void *)&sun,
- (socklen_t)sizeof(sun)) == -1) {
- (void)close(data->log_file);
- data->log_file = -1;
- } else
- data->log_connected = 1;
- }
-}
-
-static void
-openlog_unlocked_r(const char *ident, int logstat, int logfac,
- struct syslog_data *data)
-{
- if (ident != NULL)
- data->log_tag = ident;
- data->log_stat = logstat;
- if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
- data->log_fac = logfac;
-
- if (data->log_stat & LOG_NDELAY) /* open immediately */
- connectlog_r(data);
-
- data->log_opened = 1;
-}
-
-void
-openlog_r(const char *ident, int logstat, int logfac, struct syslog_data *data)
-{
- if (data == &sdata)
- mutex_lock(&syslog_mutex);
- openlog_unlocked_r(ident, logstat, logfac, data);
- if (data == &sdata)
- mutex_unlock(&syslog_mutex);
-}
-
-void
-closelog_r(struct syslog_data *data)
-{
- if (data == &sdata)
- mutex_lock(&syslog_mutex);
- (void)close(data->log_file);
- data->log_file = -1;
- data->log_connected = 0;
- data->log_tag = NULL;
- if (data == &sdata)
- mutex_unlock(&syslog_mutex);
-}
-
-int
-setlogmask_r(int pmask, struct syslog_data *data)
-{
- int omask;
-
- omask = data->log_mask;
- if (pmask != 0)
- data->log_mask = pmask;
- return omask;
+ _vxsyslogp_r(pri, &_syslog_fun, data, NULL, NULL, fmt, ap);
}
Added files:
Index: src/lib/libc/gen/syslog_private.h
diff -u /dev/null src/lib/libc/gen/syslog_private.h:1.1
--- /dev/null Wed Jan 11 19:38:01 2017
+++ src/lib/libc/gen/syslog_private.h Wed Jan 11 19:38:01 2017
@@ -0,0 +1,50 @@
+/* $NetBSD: syslog_private.h,v 1.1 2017/01/12 00:38:01 christos Exp $ */
+
+/*-
+ * Copyright (c) 2016 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define DEC() \
+ do { \
+ if (prlen >= tbuf_left) \
+ prlen = tbuf_left - 1; \
+ p += prlen; \
+ tbuf_left -= prlen; \
+ } while (/*CONSTCOND*/0)
+
+struct syslog_fun {
+ size_t (*timefun)(char *, size_t);
+ int (*errfun)(int, char *, size_t);
+ int __printflike(3, 0) (*prfun)(char *, size_t, const char *, va_list);
+};
+
+void _vxsyslogp_r(int , struct syslog_fun *, struct syslog_data *,
+ const char *, const char *, const char *, va_list);
+
+extern struct syslog_data _syslog_data;
+extern struct syslog_fun _syslog_ss_fun;
Index: src/lib/libc/gen/syslog_ss.c
diff -u /dev/null src/lib/libc/gen/syslog_ss.c:1.1
--- /dev/null Wed Jan 11 19:38:01 2017
+++ src/lib/libc/gen/syslog_ss.c Wed Jan 11 19:38:01 2017
@@ -0,0 +1,95 @@
+/* $NetBSD: syslog_ss.c,v 1.1 2017/01/12 00:38:01 christos Exp $ */
+
+/*-
+ * Copyright (c) 2016 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: syslog_ss.c,v 1.1 2017/01/12 00:38:01 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+#include <stdio.h>
+#include "extern.h"
+#include "syslog_private.h"
+
+
+static size_t
+timefun_ss(char *p, size_t tbuf_left)
+{
+ return snprintf_ss(p, tbuf_left, "-");
+#if 0
+ /*
+ * if gmtime_r() was signal-safe we could output
+ * the UTC-time:
+ */
+ gmtime_r(&now, &tmnow);
+ prlen = strftime(p, tbuf_left, "%FT%TZ", &tmnow);
+ return prlen;
+#endif
+}
+
+struct syslog_fun _syslog_ss_fun = {
+ timefun_ss,
+ strerror_r_ss,
+ vsnprintf_ss,
+};
+
+void
+syslog_ss(int pri, struct syslog_data *data, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ _vxsyslogp_r(pri, NULL, data, NULL, NULL, fmt, ap);
+ va_end(ap);
+}
+
+void
+syslogp_ss(int pri, struct syslog_data *data, const char *msgid,
+ const char *sdfmt, const char *msgfmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, msgfmt);
+ _vxsyslogp_r(pri, NULL, data, msgid, sdfmt, msgfmt, ap);
+ va_end(ap);
+}
+
+void
+vsyslog_ss(int pri, struct syslog_data *data, const char *fmt, va_list ap)
+{
+ _vxsyslogp_r(pri, NULL, data, NULL, NULL, fmt, ap);
+}
+
+void
+vsyslogp_ss(int pri, struct syslog_data *data, const char *msgid,
+ const char *sdfmt, const char *msgfmt, va_list ap)
+{
+ _vxsyslogp_r(pri, NULL, data, msgid, sdfmt, msgfmt, ap);
+}
Index: src/lib/libc/gen/xsyslog.c
diff -u /dev/null src/lib/libc/gen/xsyslog.c:1.1
--- /dev/null Wed Jan 11 19:38:01 2017
+++ src/lib/libc/gen/xsyslog.c Wed Jan 11 19:38:01 2017
@@ -0,0 +1,422 @@
+/* $NetBSD: xsyslog.c,v 1.1 2017/01/12 00:38:01 christos Exp $ */
+
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)syslog.c 8.5 (Berkeley) 4/29/95";
+#else
+__RCSID("$NetBSD: xsyslog.c,v 1.1 2017/01/12 00:38:01 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <paths.h>
+#include "syslog_private.h"
+#include "reentrant.h"
+#include "extern.h"
+
+#ifdef __weak_alias
+__weak_alias(closelog,_closelog)
+__weak_alias(openlog,_openlog)
+__weak_alias(setlogmask,_setlogmask)
+#endif
+
+struct syslog_data _syslog_data = SYSLOG_DATA_INIT;
+
+static void openlog_unlocked_r(const char *, int, int,
+ struct syslog_data *);
+static void disconnectlog_r(struct syslog_data *);
+static void connectlog_r(struct syslog_data *);
+
+#ifdef _REENTRANT
+static mutex_t syslog_mutex = MUTEX_INITIALIZER;
+#endif
+
+void
+openlog(const char *ident, int logstat, int logfac)
+{
+ openlog_r(ident, logstat, logfac, &_syslog_data);
+}
+
+void
+closelog(void)
+{
+ closelog_r(&_syslog_data);
+}
+
+/* setlogmask -- set the log mask level */
+int
+setlogmask(int pmask)
+{
+ return setlogmask_r(pmask, &_syslog_data);
+}
+
+static void
+_xsyslogp_r(int pri, struct syslog_fun *fun,
+ struct syslog_data *data, const char *msgid,
+ const char *sdfmt, const char *msgfmt, ...)
+{
+ va_list ap;
+ va_start(ap, msgfmt);
+ _vxsyslogp_r(pri, fun, data, msgid, sdfmt, msgfmt, ap);
+ va_end(ap);
+}
+
+void
+_vxsyslogp_r(int pri, struct syslog_fun *fun,
+ struct syslog_data *data, const char *msgid,
+ const char *sdfmt, const char *msgfmt, va_list ap)
+{
+ static const char BRCOSP[] = "]: ";
+ static const char CRLF[] = "\r\n";
+ size_t cnt, prlen, tries;
+ char ch, *p, *t;
+ int fd, saved_errno;
+#define TBUF_LEN 2048
+#define FMT_LEN 1024
+#define MAXTRIES 10
+ char tbuf[TBUF_LEN], fmt_cpy[FMT_LEN], fmt_cat[FMT_LEN] = "";
+ size_t tbuf_left, fmt_left, msgsdlen;
+ char *fmt = fmt_cat;
+ struct iovec iov[7]; /* prog + [ + pid + ]: + fmt + crlf */
+ int opened, iovcnt;
+
+#define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
+ /* Check for invalid bits. */
+ if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
+ _xsyslogp_r(INTERNALLOG, &_syslog_ss_fun, data, NULL, NULL,
+ "%s: unknown facility/priority: %x", pri);
+ pri &= LOG_PRIMASK|LOG_FACMASK;
+ }
+
+ /* Check priority against setlogmask values. */
+ 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 |= data->log_fac;
+
+ /* Build the message. */
+ p = tbuf;
+ tbuf_left = TBUF_LEN;
+
+ prlen = snprintf_ss(p, tbuf_left, "<%d>1 ", pri);
+ DEC();
+
+ prlen = (*fun->timefun)(p, tbuf_left);
+
+ if (data == &_syslog_data)
+ mutex_lock(&syslog_mutex);
+
+ if (data->log_hostname[0] == '\0' && gethostname(data->log_hostname,
+ sizeof(data->log_hostname)) == -1) {
+ /* can this really happen? */
+ data->log_hostname[0] = '-';
+ data->log_hostname[1] = '\0';
+ }
+
+ DEC();
+ prlen = snprintf_ss(p, tbuf_left, " %s ", data->log_hostname);
+
+ if (data->log_tag == NULL)
+ data->log_tag = getprogname();
+
+ DEC();
+ prlen = snprintf_ss(p, tbuf_left, "%s ",
+ data->log_tag ? data->log_tag : "-");
+
+ if (data == &_syslog_data)
+ mutex_unlock(&syslog_mutex);
+
+ if (data->log_stat & (LOG_PERROR|LOG_CONS)) {
+ iovcnt = 0;
+ iov[iovcnt].iov_base = p;
+ iov[iovcnt].iov_len = prlen - 1;
+ iovcnt++;
+ }
+ DEC();
+
+ if (data->log_stat & LOG_PID) {
+ prlen = snprintf_ss(p, tbuf_left, "%d ", getpid());
+ if (data->log_stat & (LOG_PERROR|LOG_CONS)) {
+ iov[iovcnt].iov_base = __UNCONST("[");
+ iov[iovcnt].iov_len = 1;
+ iovcnt++;
+ iov[iovcnt].iov_base = p;
+ iov[iovcnt].iov_len = prlen - 1;
+ iovcnt++;
+ iov[iovcnt].iov_base = __UNCONST(BRCOSP);
+ iov[iovcnt].iov_len = 3;
+ iovcnt++;
+ }
+ } else {
+ prlen = snprintf_ss(p, tbuf_left, "- ");
+ if (data->log_stat & (LOG_PERROR|LOG_CONS)) {
+ iov[iovcnt].iov_base = __UNCONST(BRCOSP + 1);
+ iov[iovcnt].iov_len = 2;
+ iovcnt++;
+ }
+ }
+ DEC();
+
+ /*
+ * concat the format strings, then use one vsnprintf()
+ */
+ if (msgid != NULL && *msgid != '\0') {
+ strlcat(fmt_cat, msgid, FMT_LEN);
+ strlcat(fmt_cat, " ", FMT_LEN);
+ } else
+ strlcat(fmt_cat, "- ", FMT_LEN);
+
+ if (sdfmt != NULL && *sdfmt != '\0') {
+ strlcat(fmt_cat, sdfmt, FMT_LEN);
+ } else
+ strlcat(fmt_cat, "-", FMT_LEN);
+
+ if (data->log_stat & (LOG_PERROR|LOG_CONS))
+ msgsdlen = strlen(fmt_cat) + 1;
+ else
+ msgsdlen = 0; /* XXX: GCC */
+
+ if (msgfmt != NULL && *msgfmt != '\0') {
+ strlcat(fmt_cat, " ", FMT_LEN);
+ strlcat(fmt_cat, msgfmt, FMT_LEN);
+ }
+
+ /*
+ * We wouldn't need this mess if printf handled %m, or if
+ * strerror() had been invented before syslog().
+ */
+ for (t = fmt_cpy, fmt_left = FMT_LEN; (ch = *fmt) != '\0'; ++fmt) {
+ if (ch == '%' && fmt[1] == 'm') {
+ char buf[256];
+
+ if ((*fun->errfun)(saved_errno, buf, sizeof(buf)) != 0)
+ prlen = snprintf_ss(t, fmt_left, "Error %d",
+ saved_errno);
+ else
+ prlen = strlcpy(t, buf, fmt_left);
+ if (prlen >= fmt_left)
+ prlen = fmt_left - 1;
+ t += prlen;
+ fmt++;
+ fmt_left -= prlen;
+ } else if (ch == '%' && fmt[1] == '%' && fmt_left > 2) {
+ *t++ = '%';
+ *t++ = '%';
+ fmt++;
+ fmt_left -= 2;
+ } else {
+ if (fmt_left > 1) {
+ *t++ = ch;
+ fmt_left--;
+ }
+ }
+ }
+ *t = '\0';
+
+ prlen = (*fun->prfun)(p, tbuf_left, fmt_cpy, ap);
+ if (data->log_stat & (LOG_PERROR|LOG_CONS)) {
+ iov[iovcnt].iov_base = p + msgsdlen;
+ iov[iovcnt].iov_len = prlen - msgsdlen;
+ iovcnt++;
+ }
+
+ DEC();
+ cnt = p - tbuf;
+
+ /* Output to stderr if requested. */
+ if (data->log_stat & LOG_PERROR) {
+ iov[iovcnt].iov_base = __UNCONST(CRLF + 1);
+ iov[iovcnt].iov_len = 1;
+ (void)writev(STDERR_FILENO, iov, iovcnt + 1);
+ }
+
+ /* Get connected, output the message to the local logger. */
+ if (data == &_syslog_data)
+ mutex_lock(&syslog_mutex);
+ opened = !data->log_opened;
+ if (opened)
+ openlog_unlocked_r(data->log_tag, data->log_stat, 0, data);
+ connectlog_r(data);
+
+ /*
+ * If the send() failed, there are two likely scenarios:
+ * 1) syslogd was restarted
+ * 2) /dev/log is out of socket buffer space
+ * We attempt to reconnect to /dev/log to take care of
+ * case #1 and keep send()ing data to cover case #2
+ * to give syslogd a chance to empty its socket buffer.
+ */
+ for (tries = 0; tries < MAXTRIES; tries++) {
+ if (send(data->log_file, tbuf, cnt, 0) != -1)
+ break;
+ if (errno != ENOBUFS) {
+ disconnectlog_r(data);
+ connectlog_r(data);
+ } else
+ (void)usleep(1);
+ }
+
+ /*
+ * Output the message to the console; try not to block
+ * as a blocking console should not stop other processes.
+ * Make sure the error reported is the one from the syslogd failure.
+ */
+ if (tries == MAXTRIES && (data->log_stat & LOG_CONS) &&
+ (fd = open(_PATH_CONSOLE,
+ O_WRONLY | O_NONBLOCK | O_CLOEXEC, 0)) >= 0) {
+ iov[iovcnt].iov_base = __UNCONST(CRLF);
+ iov[iovcnt].iov_len = 2;
+ (void)writev(fd, iov, iovcnt + 1);
+ (void)close(fd);
+ }
+
+ if (data == &_syslog_data)
+ mutex_unlock(&syslog_mutex);
+
+ if (data != &_syslog_data && opened) {
+ /* preserve log tag */
+ const char *ident = data->log_tag;
+ closelog_r(data);
+ data->log_tag = ident;
+ }
+}
+
+static void
+disconnectlog_r(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 (data->log_file != -1) {
+ (void)close(data->log_file);
+ data->log_file = -1;
+ }
+ data->log_connected = 0; /* retry connect */
+}
+
+static void
+connectlog_r(struct syslog_data *data)
+{
+ /* AF_UNIX address of local logger */
+ static const struct sockaddr_un sun = {
+ .sun_family = AF_LOCAL,
+ .sun_len = sizeof(sun),
+ .sun_path = _PATH_LOG,
+ };
+
+ if (data->log_file == -1 || fcntl(data->log_file, F_GETFL, 0) == -1) {
+ if ((data->log_file = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC,
+ 0)) == -1)
+ return;
+ data->log_connected = 0;
+ }
+ if (!data->log_connected) {
+ if (connect(data->log_file,
+ (const struct sockaddr *)(const void *)&sun,
+ (socklen_t)sizeof(sun)) == -1) {
+ (void)close(data->log_file);
+ data->log_file = -1;
+ } else
+ data->log_connected = 1;
+ }
+}
+
+static void
+openlog_unlocked_r(const char *ident, int logstat, int logfac,
+ struct syslog_data *data)
+{
+ if (ident != NULL)
+ data->log_tag = ident;
+ data->log_stat = logstat;
+ if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
+ data->log_fac = logfac;
+
+ if (data->log_stat & LOG_NDELAY) /* open immediately */
+ connectlog_r(data);
+
+ data->log_opened = 1;
+}
+
+void
+openlog_r(const char *ident, int logstat, int logfac, struct syslog_data *data)
+{
+ if (data == &_syslog_data)
+ mutex_lock(&syslog_mutex);
+ openlog_unlocked_r(ident, logstat, logfac, data);
+ if (data == &_syslog_data)
+ mutex_unlock(&syslog_mutex);
+}
+
+void
+closelog_r(struct syslog_data *data)
+{
+ if (data == &_syslog_data)
+ mutex_lock(&syslog_mutex);
+ (void)close(data->log_file);
+ data->log_file = -1;
+ data->log_connected = 0;
+ data->log_tag = NULL;
+ if (data == &_syslog_data)
+ mutex_unlock(&syslog_mutex);
+}
+
+int
+setlogmask_r(int pmask, struct syslog_data *data)
+{
+ int omask;
+
+ omask = data->log_mask;
+ if (pmask != 0)
+ data->log_mask = pmask;
+ return omask;
+}