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