1 /* $NetBSD: syslog.c,v 1.58 2017/01/12 18:16:52 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #if defined(LIBC_SCCS) && !defined(lint) 34 #if 0 35 static char sccsid[] = "@(#)syslog.c 8.5 (Berkeley) 4/29/95"; 36 #else 37 __RCSID("$NetBSD: syslog.c,v 1.58 2017/01/12 18:16:52 christos Exp $"); 38 #endif 39 #endif /* LIBC_SCCS and not lint */ 40 41 #include "namespace.h" 42 #include <sys/types.h> 43 #include <sys/param.h> 44 #include <sys/socket.h> 45 #include <sys/syslog.h> 46 #include <sys/uio.h> 47 #include <sys/un.h> 48 #include <netdb.h> 49 50 #include <errno.h> 51 #include <stdio.h> 52 #include <fcntl.h> 53 #include <paths.h> 54 #include <stdarg.h> 55 #include <stdio.h> 56 #include <stdlib.h> 57 #include <string.h> 58 #include <time.h> 59 #include <unistd.h> 60 61 #include "syslog_private.h" 62 #include "reentrant.h" 63 #include "extern.h" 64 65 #ifdef __weak_alias 66 __weak_alias(syslog,_syslog) 67 __weak_alias(vsyslog,_vsyslog) 68 __weak_alias(syslogp,_syslogp) 69 __weak_alias(vsyslogp,_vsyslogp) 70 __weak_alias(closelog,_closelog) 71 __weak_alias(openlog,_openlog) 72 __weak_alias(setlogmask,_setlogmask) 73 #endif 74 75 static struct syslog_data _syslog_data = SYSLOG_DATA_INIT; 76 77 #ifdef _REENTRANT 78 static mutex_t syslog_mutex = MUTEX_INITIALIZER; 79 #endif 80 81 static size_t 82 timefun(char *p, size_t tbuf_left) 83 { 84 struct timeval tv; 85 time_t now; 86 struct tm tmnow; 87 size_t prlen; 88 char *op = p; 89 90 if (gettimeofday(&tv, NULL) == -1) 91 return snprintf_ss(p, tbuf_left, "-"); 92 93 /* strftime() implies tzset(), localtime_r() doesn't. */ 94 tzset(); 95 now = (time_t) tv.tv_sec; 96 localtime_r(&now, &tmnow); 97 98 prlen = strftime(p, tbuf_left, "%FT%T", &tmnow); 99 DEC(); 100 prlen = snprintf(p, tbuf_left, ".%06ld", (long)tv.tv_usec); 101 DEC(); 102 prlen = strftime(p, tbuf_left-1, "%z", &tmnow); 103 /* strftime gives eg. "+0200", but we need "+02:00" */ 104 if (prlen == 5) { 105 p[prlen+1] = p[prlen]; 106 p[prlen] = p[prlen-1]; 107 p[prlen-1] = p[prlen-2]; 108 p[prlen-2] = ':'; 109 prlen += 1; 110 } 111 DEC(); 112 return (size_t)(p - op); 113 } 114 115 static int 116 lock(const struct syslog_data *data) 117 { 118 int rv = data == &_syslog_data; 119 if (rv) 120 mutex_lock(&syslog_mutex); 121 return rv; 122 } 123 124 static int 125 unlock(const struct syslog_data *data) 126 { 127 int rv = data == &_syslog_data; 128 if (rv) 129 mutex_unlock(&syslog_mutex); 130 return rv; 131 } 132 133 static struct syslog_fun _syslog_fun = { 134 timefun, 135 strerror_r, 136 vsnprintf, 137 lock, 138 unlock, 139 }; 140 141 void 142 openlog(const char *ident, int logstat, int logfac) 143 { 144 openlog_r(ident, logstat, logfac, &_syslog_data); 145 } 146 147 void 148 closelog(void) 149 { 150 closelog_r(&_syslog_data); 151 } 152 153 /* setlogmask -- set the log mask level */ 154 int 155 setlogmask(int pmask) 156 { 157 return setlogmask_r(pmask, &_syslog_data); 158 } 159 160 void 161 openlog_r(const char *ident, int logstat, int logfac, struct syslog_data *data) 162 { 163 lock(data); 164 _openlog_unlocked_r(ident, logstat, logfac, data); 165 unlock(data); 166 } 167 168 void 169 closelog_r(struct syslog_data *data) 170 { 171 lock(data); 172 _closelog_unlocked_r(data); 173 data->log_tag = NULL; 174 unlock(data); 175 } 176 177 /* 178 * syslog, vsyslog -- 179 * print message on log file; output is intended for syslogd(8). 180 */ 181 void 182 syslog(int pri, const char *fmt, ...) 183 { 184 va_list ap; 185 186 va_start(ap, fmt); 187 _vxsyslogp_r(pri, &_syslog_fun, &_syslog_data, NULL, NULL, fmt, ap); 188 va_end(ap); 189 } 190 191 void 192 vsyslog(int pri, const char *fmt, va_list ap) 193 { 194 _vxsyslogp_r(pri, &_syslog_fun, &_syslog_data, NULL, NULL, fmt, ap); 195 } 196 197 /* 198 * syslogp, vsyslogp -- 199 * like syslog but take additional arguments for MSGID and SD 200 */ 201 void 202 syslogp(int pri, const char *msgid, const char *sdfmt, const char *msgfmt, ...) 203 { 204 va_list ap; 205 206 va_start(ap, msgfmt); 207 _vxsyslogp_r(pri, &_syslog_fun, &_syslog_data, 208 msgid, sdfmt, msgfmt, ap); 209 va_end(ap); 210 } 211 212 void 213 vsyslogp(int pri, const char *msgid, const char *sdfmt, const char *msgfmt, 214 va_list ap) 215 { 216 _vxsyslogp_r(pri, &_syslog_fun, &_syslog_data, 217 msgid, sdfmt, msgfmt, ap); 218 } 219 220 void 221 vsyslogp_r(int pri, struct syslog_data *data, const char *msgid, 222 const char *sdfmt, const char *msgfmt, va_list ap) 223 { 224 _vxsyslogp_r(pri, &_syslog_fun, data, msgid, sdfmt, msgfmt, ap); 225 } 226 227 void 228 syslog_r(int pri, struct syslog_data *data, const char *fmt, ...) 229 { 230 va_list ap; 231 232 va_start(ap, fmt); 233 _vxsyslogp_r(pri, &_syslog_fun, data, NULL, NULL, fmt, ap); 234 va_end(ap); 235 } 236 237 void 238 syslogp_r(int pri, struct syslog_data *data, const char *msgid, 239 const char *sdfmt, const char *msgfmt, ...) 240 { 241 va_list ap; 242 243 va_start(ap, msgfmt); 244 _vxsyslogp_r(pri, &_syslog_fun, data, msgid, sdfmt, msgfmt, ap); 245 va_end(ap); 246 } 247 248 void 249 vsyslog_r(int pri, struct syslog_data *data, const char *fmt, va_list ap) 250 { 251 _vxsyslogp_r(pri, &_syslog_fun, data, NULL, NULL, fmt, ap); 252 } 253