Index: gen/Makefile.inc =================================================================== RCS file: /cvsroot/src/lib/libc/gen/Makefile.inc,v retrieving revision 1.196 diff -u -p -u -r1.196 Makefile.inc --- gen/Makefile.inc 4 Oct 2016 09:41:41 -0000 1.196 +++ gen/Makefile.inc 11 Jan 2017 23:52:07 -0000 @@ -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: gen/syslog.c =================================================================== RCS file: /cvsroot/src/lib/libc/gen/syslog.c,v retrieving revision 1.55 diff -u -p -u -r1.55 syslog.c --- gen/syslog.c 26 Oct 2015 11:44:30 -0000 1.55 +++ gen/syslog.c 11 Jan 2017 23:52:07 -0000 @@ -48,6 +48,7 @@ __RCSID("$NetBSD: syslog.c,v 1.55 2015/1 #include #include +#include #include #include #include @@ -56,32 +57,61 @@ __RCSID("$NetBSD: syslog.c,v 1.55 2015/1 #include #include #include + +#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); + _vxsyslogp_r(pri, &_syslog_fun, 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); - 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); } Index: include/extern.h =================================================================== RCS file: /cvsroot/src/lib/libc/include/extern.h,v retrieving revision 1.23 diff -u -p -u -r1.23 extern.h --- include/extern.h 19 Aug 2013 13:03:12 -0000 1.23 +++ include/extern.h 11 Jan 2017 23:52:07 -0000 @@ -72,4 +72,7 @@ void _malloc_postfork(void); int _sys_setcontext(const ucontext_t *); +__aconst char *strerror_ss(int); +int strerror_r_ss(int, char *, size_t); + __END_DECLS Index: string/Makefile.inc =================================================================== RCS file: /cvsroot/src/lib/libc/string/Makefile.inc,v retrieving revision 1.82 diff -u -p -u -r1.82 Makefile.inc --- string/Makefile.inc 15 Oct 2016 14:22:00 -0000 1.82 +++ string/Makefile.inc 11 Jan 2017 23:52:07 -0000 @@ -10,7 +10,7 @@ SRCS+= bm.c stpcpy.c stpncpy.c \ strcasecmp.c strncasecmp.c strcasestr.c strcoll.c strdup.c \ - strerror.c strlcat.c strlcpy.c strnlen.c \ + strerror.c strerror_ss.c strlcat.c strlcpy.c strnlen.c \ strmode.c strsignal.c strtok.c \ strtok_r.c strxfrm.c __strsignal.c strerror_r.c strndup.c \ stresep.c memrchr.c --- /dev/null 2017-01-11 17:31:35.183832942 -0500 +++ gen/xsyslog.c 2017-01-11 16:01:30.668832388 -0500 @@ -0,0 +1,422 @@ +/* $NetBSD: syslog.c,v 1.55 2015/10/26 11:44:30 roy 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 +#if defined(LIBC_SCCS) && !defined(lint) +#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 $"); +#endif +#endif /* LIBC_SCCS and not lint */ + +#include "namespace.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} --- /dev/null 2017-01-11 17:31:35.183832942 -0500 +++ gen/syslog_ss.c 2017-01-11 16:13:50.158110675 -0500 @@ -0,0 +1,95 @@ +/* $NetBSD: syslog.c,v 1.55 2015/10/26 11:44:30 roy 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 +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: syslog.c,v 1.55 2015/10/26 11:44:30 roy Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "namespace.h" +#include +#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); +} --- /dev/null 2017-01-11 17:31:35.183832942 -0500 +++ string/strerror_ss.c 2017-01-11 16:09:25.449812485 -0500 @@ -0,0 +1,59 @@ +/* $NetBSD: strerror.c,v 1.17 2015/01/20 18:31:25 christos Exp $ */ + +/*- + * Copyright (c) 2017 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 +__RCSID("$NetBSD: strerror.c,v 1.17 2015/01/20 18:31:25 christos Exp $"); + +#include "namespace.h" + +#include +#include +#include + +#include "extern.h" + +int +strerror_r_ss(int num, char *buf, size_t len) +{ + if (num >= 0 || num < sys_nerr) + strlcpy(buf, sys_errlist[num], len); + else + snprintf_ss(buf, len, "Unknown error %d", num); + return 0; +} + +__aconst char * +strerror_ss(int num) +{ + static char buf[64]; + + strerror_r_ss(num, buf, sizeof(buf)); + return buf; +} --- /dev/null 2017-01-11 17:31:35.183832942 -0500 +++ gen/syslog_private.h 2017-01-11 17:27:26.167174286 -0500 @@ -0,0 +1,50 @@ +/* $NetBSD$ */ + +/*- + * 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;