syslog.c revision 1.57 1 1.57 christos /* $NetBSD: syslog.c,v 1.57 2017/01/12 01:58:39 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.57 christos __RCSID("$NetBSD: syslog.c,v 1.57 2017/01/12 01:58:39 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 #ifndef __lint__
137 1.56 christos _vsnprintf,
138 1.56 christos #else
139 1.56 christos vsnprintf,
140 1.20 kleink #endif
141 1.57 christos lock,
142 1.57 christos unlock,
143 1.56 christos };
144 1.20 kleink
145 1.57 christos void
146 1.57 christos openlog(const char *ident, int logstat, int logfac)
147 1.57 christos {
148 1.57 christos openlog_r(ident, logstat, logfac, &_syslog_data);
149 1.57 christos }
150 1.57 christos
151 1.57 christos void
152 1.57 christos closelog(void)
153 1.57 christos {
154 1.57 christos closelog_r(&_syslog_data);
155 1.57 christos }
156 1.57 christos
157 1.57 christos /* setlogmask -- set the log mask level */
158 1.57 christos int
159 1.57 christos setlogmask(int pmask)
160 1.57 christos {
161 1.57 christos return setlogmask_r(pmask, &_syslog_data);
162 1.57 christos }
163 1.57 christos
164 1.57 christos void
165 1.57 christos openlog_r(const char *ident, int logstat, int logfac, struct syslog_data *data)
166 1.57 christos {
167 1.57 christos lock(data);
168 1.57 christos _openlog_unlocked_r(ident, logstat, logfac, data);
169 1.57 christos unlock(data);
170 1.57 christos }
171 1.57 christos
172 1.57 christos void
173 1.57 christos closelog_r(struct syslog_data *data)
174 1.57 christos {
175 1.57 christos lock(data);
176 1.57 christos _closelog_unlocked_r(data);
177 1.57 christos data->log_tag = NULL;
178 1.57 christos unlock(data);
179 1.57 christos }
180 1.57 christos
181 1.1 cgd /*
182 1.1 cgd * syslog, vsyslog --
183 1.1 cgd * print message on log file; output is intended for syslogd(8).
184 1.1 cgd */
185 1.1 cgd void
186 1.1 cgd syslog(int pri, const char *fmt, ...)
187 1.1 cgd {
188 1.1 cgd va_list ap;
189 1.1 cgd
190 1.1 cgd va_start(ap, fmt);
191 1.56 christos _vxsyslogp_r(pri, &_syslog_fun, &_syslog_data, NULL, NULL, fmt, ap);
192 1.1 cgd va_end(ap);
193 1.1 cgd }
194 1.1 cgd
195 1.1 cgd void
196 1.32 christos vsyslog(int pri, const char *fmt, va_list ap)
197 1.32 christos {
198 1.56 christos _vxsyslogp_r(pri, &_syslog_fun, &_syslog_data, NULL, NULL, fmt, ap);
199 1.32 christos }
200 1.32 christos
201 1.43 christos /*
202 1.43 christos * syslogp, vsyslogp --
203 1.43 christos * like syslog but take additional arguments for MSGID and SD
204 1.43 christos */
205 1.43 christos void
206 1.43 christos syslogp(int pri, const char *msgid, const char *sdfmt, const char *msgfmt, ...)
207 1.43 christos {
208 1.43 christos va_list ap;
209 1.43 christos
210 1.43 christos va_start(ap, msgfmt);
211 1.56 christos _vxsyslogp_r(pri, &_syslog_fun, &_syslog_data,
212 1.56 christos msgid, sdfmt, msgfmt, ap);
213 1.43 christos va_end(ap);
214 1.43 christos }
215 1.43 christos
216 1.43 christos void
217 1.56 christos vsyslogp(int pri, const char *msgid, const char *sdfmt, const char *msgfmt,
218 1.56 christos va_list ap)
219 1.43 christos {
220 1.56 christos _vxsyslogp_r(pri, &_syslog_fun, &_syslog_data,
221 1.56 christos msgid, sdfmt, msgfmt, ap);
222 1.43 christos }
223 1.43 christos
224 1.32 christos void
225 1.56 christos vsyslogp_r(int pri, struct syslog_data *data, const char *msgid,
226 1.56 christos const char *sdfmt, const char *msgfmt, va_list ap)
227 1.32 christos {
228 1.56 christos _vxsyslogp_r(pri, &_syslog_fun, data, msgid, sdfmt, msgfmt, ap);
229 1.32 christos }
230 1.32 christos
231 1.32 christos void
232 1.32 christos syslog_r(int pri, struct syslog_data *data, const char *fmt, ...)
233 1.32 christos {
234 1.32 christos va_list ap;
235 1.32 christos
236 1.32 christos va_start(ap, fmt);
237 1.56 christos _vxsyslogp_r(pri, &_syslog_fun, data, NULL, NULL, fmt, ap);
238 1.32 christos va_end(ap);
239 1.32 christos }
240 1.32 christos
241 1.32 christos void
242 1.43 christos syslogp_r(int pri, struct syslog_data *data, const char *msgid,
243 1.43 christos const char *sdfmt, const char *msgfmt, ...)
244 1.43 christos {
245 1.43 christos va_list ap;
246 1.43 christos
247 1.43 christos va_start(ap, msgfmt);
248 1.56 christos _vxsyslogp_r(pri, &_syslog_fun, data, msgid, sdfmt, msgfmt, ap);
249 1.43 christos va_end(ap);
250 1.43 christos }
251 1.43 christos
252 1.43 christos void
253 1.32 christos vsyslog_r(int pri, struct syslog_data *data, const char *fmt, va_list ap)
254 1.32 christos {
255 1.56 christos _vxsyslogp_r(pri, &_syslog_fun, data, NULL, NULL, fmt, ap);
256 1.1 cgd }
257