]> sourceware.org Git - glibc.git/blame - misc/syslog.c
x86: Disable non-temporal memset on Skylake Server
[glibc.git] / misc / syslog.c
CommitLineData
790aa1f2
UD
1/*
2 * Copyright (c) 1983, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char sccsid[] = "@(#)syslog.c 8.4 (Berkeley) 3/18/94";
32#endif /* LIBC_SCCS and not lint */
33
0cc15f45 34#include <libio/libioP.h>
790aa1f2 35#include <paths.h>
0cc15f45
AZ
36#include <stdarg.h>
37#include <stdlib.h>
790aa1f2
UD
38#include <stdio.h>
39#include <stdio_ext.h>
0cc15f45
AZ
40#include <sys/socket.h>
41#include <sys/uio.h>
42#include <sys/un.h>
43#include <syslog.h>
ddf542da 44#include <limits.h>
37233df9 45
0cc15f45
AZ
46static int LogType = SOCK_DGRAM; /* type of socket connection */
47static int LogFile = -1; /* fd for log */
48static bool connected; /* have done connect */
49static int LogStat; /* status bits, set by openlog() */
790aa1f2 50static const char *LogTag; /* string to tag the entry with */
0cc15f45
AZ
51static int LogFacility = LOG_USER; /* default facility code */
52static int LogMask = 0xff; /* mask of priorities to be logged */
53extern char *__progname; /* Program name, from crt0. */
790aa1f2
UD
54
55/* Define the lock. */
56__libc_lock_define_initialized (static, syslog_lock)
0cc15f45
AZ
57static void openlog_internal (const char *, int, int);
58static void closelog_internal (void);
790aa1f2
UD
59
60struct cleanup_arg
61{
62 void *buf;
63 struct sigaction *oldaction;
64};
65
66static void
67cancel_handler (void *ptr)
68{
790aa1f2
UD
69 /* Restore the old signal handler. */
70 struct cleanup_arg *clarg = (struct cleanup_arg *) ptr;
71
c4e4b2e1 72 if (clarg != NULL)
ded3cef3
AZ
73 /* Free the memstream buffer, */
74 free (clarg->buf);
c4e4b2e1 75
790aa1f2
UD
76 /* Free the lock. */
77 __libc_lock_unlock (syslog_lock);
78}
79
80
81/*
82 * syslog, vsyslog --
83 * print message on log file; output is intended for syslogd(8).
84 */
85void
0cc15f45 86__syslog (int pri, const char *fmt, ...)
790aa1f2 87{
0cc15f45 88 va_list ap;
790aa1f2 89
0cc15f45
AZ
90 va_start (ap, fmt);
91 __vsyslog_internal (pri, fmt, ap, 0);
92 va_end (ap);
790aa1f2 93}
c6251f03
RM
94ldbl_hidden_def (__syslog, syslog)
95ldbl_strong_alias (__syslog, syslog)
790aa1f2 96
124fc732 97void
0cc15f45 98__vsyslog (int pri, const char *fmt, va_list ap)
124fc732 99{
0cc15f45 100 __vsyslog_internal (pri, fmt, ap, 0);
124fc732
ZW
101}
102ldbl_weak_alias (__vsyslog, vsyslog)
103
790aa1f2 104void
ba745eff 105___syslog_chk (int pri, int flag, const char *fmt, ...)
29c21e49 106{
0cc15f45 107 va_list ap;
29c21e49 108
0cc15f45
AZ
109 va_start (ap, fmt);
110 __vsyslog_internal (pri, fmt, ap, (flag > 0) ? PRINTF_FORTIFY : 0);
111 va_end (ap);
29c21e49 112}
ba745eff
FB
113ldbl_hidden_def (___syslog_chk, __syslog_chk)
114ldbl_strong_alias (___syslog_chk, __syslog_chk)
29c21e49
UD
115
116void
0cc15f45 117__vsyslog_chk (int pri, int flag, const char *fmt, va_list ap)
124fc732 118{
0cc15f45 119 __vsyslog_internal (pri, fmt, ap, (flag > 0) ? PRINTF_FORTIFY : 0);
124fc732
ZW
120}
121
122void
0cc15f45
AZ
123__vsyslog_internal (int pri, const char *fmt, va_list ap,
124 unsigned int mode_flags)
790aa1f2 125{
a583b6ad
AZ
126 /* Try to use a static buffer as an optimization. */
127 char bufs[1024];
6bd0e4ef
AS
128 char *buf = bufs;
129 size_t bufsize;
130
f9f5c70e 131 int msgoff;
0cc15f45 132 int saved_errno = errno;
0cc15f45
AZ
133
134#define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
135 /* Check for invalid bits. */
136 if (pri & ~(LOG_PRIMASK | LOG_FACMASK))
137 {
138 syslog (INTERNALLOG, "syslog: unknown facility/priority: %x", pri);
139 pri &= LOG_PRIMASK | LOG_FACMASK;
140 }
141
142 /* Prepare for multiple users. We have to take care: most syscalls we are
143 using are cancellation points. */
f9f5c70e 144 struct cleanup_arg clarg = { NULL, NULL };
0cc15f45
AZ
145 __libc_cleanup_push (cancel_handler, &clarg);
146 __libc_lock_lock (syslog_lock);
147
148 /* Check priority against setlogmask values. */
149 if ((LOG_MASK (LOG_PRI (pri)) & LogMask) == 0)
150 goto out;
151
152 /* Set default facility if none specified. */
153 if ((pri & LOG_FACMASK) == 0)
154 pri |= LogFacility;
155
a583b6ad
AZ
156 pid_t pid = LogStat & LOG_PID ? __getpid () : 0;
157
158 /* "%b %e %H:%M:%S " */
159 char timestamp[sizeof "MMM DD hh:mm:ss "];
ac0d208b 160 __time64_t now = time64_now ();
a583b6ad 161 struct tm now_tm;
ac0d208b
AZ
162 struct tm *now_tmp = __localtime64_r (&now, &now_tm);
163 bool has_ts = now_tmp != NULL;
164
165 /* In the unlikely case of localtime_r failure (tm_year out of int range)
166 skip the hostname so the message is handled as valid PRI but without
167 TIMESTAMP or invalid TIMESTAMP (which should force the relay to add the
168 timestamp itself). */
169 if (has_ts)
170 __strftime_l (timestamp, sizeof timestamp, "%h %e %T ", now_tmp,
171 _nl_C_locobj_ptr);
a583b6ad
AZ
172
173#define SYSLOG_HEADER(__pri, __timestamp, __msgoff, pid) \
45459476 174 "<%d>%s%n%s%s%.0d%s: ", \
a583b6ad
AZ
175 __pri, __timestamp, __msgoff, \
176 LogTag == NULL ? __progname : LogTag, \
177 "[" + (pid == 0), pid, "]" + (pid == 0)
178
ac0d208b
AZ
179#define SYSLOG_HEADER_WITHOUT_TS(__pri, __msgoff) \
180 "<%d>: %n", __pri, __msgoff
181
6bd0e4ef 182 int l, vl;
ac0d208b
AZ
183 if (has_ts)
184 l = __snprintf (bufs, sizeof bufs,
185 SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
186 else
187 l = __snprintf (bufs, sizeof bufs,
188 SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
7e5a0c28
AS
189 if (l < 0)
190 goto out;
6bd0e4ef
AS
191
192 char *pos;
193 size_t len;
194
7e5a0c28 195 if (l < sizeof bufs)
0cc15f45 196 {
6bd0e4ef
AS
197 /* At this point, there is still a chance that we can print the
198 remaining part of the log into bufs and use that. */
199 pos = bufs + l;
200 len = sizeof (bufs) - l;
201 }
202 else
203 {
204 buf = NULL;
205 /* We already know that bufs is too small to use for this log message.
206 The next vsnprintf into bufs is used only to calculate the total
207 required buffer length. We will discard bufs contents and allocate
208 an appropriately sized buffer later instead. */
209 pos = bufs;
210 len = sizeof (bufs);
211 }
a583b6ad 212
6bd0e4ef
AS
213 {
214 va_list apc;
215 va_copy (apc, ap);
0cc15f45 216
6bd0e4ef
AS
217 /* Restore errno for %m format. */
218 __set_errno (saved_errno);
0cc15f45 219
6bd0e4ef 220 vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags);
7e5a0c28
AS
221 va_end (apc);
222
ddf542da 223 if (vl < 0 || vl >= INT_MAX - l)
7e5a0c28 224 goto out;
6bd0e4ef 225
7e5a0c28 226 if (vl >= len)
6bd0e4ef
AS
227 buf = NULL;
228
229 bufsize = l + vl;
6bd0e4ef 230 }
a583b6ad
AZ
231
232 if (buf == NULL)
f9f5c70e 233 {
52a5be0d 234 buf = malloc ((bufsize + 1) * sizeof (char));
a583b6ad
AZ
235 if (buf != NULL)
236 {
237 /* Tell the cancellation handler to free this buffer. */
238 clarg.buf = buf;
239
7e5a0c28 240 int cl;
ac0d208b 241 if (has_ts)
7e5a0c28
AS
242 cl = __snprintf (buf, l + 1,
243 SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
ac0d208b 244 else
7e5a0c28
AS
245 cl = __snprintf (buf, l + 1,
246 SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
247 if (cl != l)
248 goto out;
52a5be0d
AZ
249
250 va_list apc;
251 va_copy (apc, ap);
7e5a0c28
AS
252 cl = __vsnprintf_internal (buf + l, bufsize - l + 1, fmt, apc,
253 mode_flags);
52a5be0d 254 va_end (apc);
7e5a0c28
AS
255
256 if (cl != vl)
257 goto out;
a583b6ad
AZ
258 }
259 else
260 {
7e5a0c28 261 int bl;
a583b6ad 262 /* Nothing much to do but emit an error message. */
7e5a0c28
AS
263 bl = __snprintf (bufs, sizeof bufs,
264 "out of memory[%d]", __getpid ());
265 if (bl < 0 || bl >= sizeof bufs)
266 goto out;
267
268 bufsize = bl;
a583b6ad 269 buf = bufs;
7e5a0c28 270 msgoff = 0;
a583b6ad 271 }
f9f5c70e 272 }
0cc15f45
AZ
273
274 /* Output to stderr if requested. */
275 if (LogStat & LOG_PERROR)
f9f5c70e
AZ
276 __dprintf (STDERR_FILENO, "%s%s", buf + msgoff,
277 "\n" + (buf[bufsize - 1] == '\n'));
0cc15f45
AZ
278
279 /* Get connected, output the message to the local logger. */
280 if (!connected)
281 openlog_internal (NULL, LogStat | LOG_NDELAY, LogFacility);
282
283 /* If we have a SOCK_STREAM connection, also send ASCII NUL as a record
284 terminator. */
285 if (LogType == SOCK_STREAM)
286 ++bufsize;
287
288 if (!connected || __send (LogFile, buf, bufsize, MSG_NOSIGNAL) < 0)
289 {
290 if (connected)
291 {
292 /* Try to reopen the syslog connection. Maybe it went down. */
293 closelog_internal ();
294 openlog_internal (NULL, LogStat | LOG_NDELAY, LogFacility);
790aa1f2
UD
295 }
296
0cc15f45
AZ
297 if (!connected || __send (LogFile, buf, bufsize, MSG_NOSIGNAL) < 0)
298 {
299 closelog_internal (); /* attempt re-open next time */
300 /*
301 * Output the message to the console; don't worry
302 * about blocking, if console blocks everything will.
303 * Make sure the error reported is the one from the
304 * syslogd failure.
305 */
f9f5c70e 306 int fd;
0cc15f45
AZ
307 if (LogStat & LOG_CONS &&
308 (fd = __open (_PATH_CONSOLE, O_WRONLY | O_NOCTTY
309 | O_CLOEXEC, 0)) >= 0)
310 {
311 __dprintf (fd, "%s\r\n", buf + msgoff);
312 __close (fd);
313 }
314 }
315 }
316
317out:
318 /* End of critical section. */
319 __libc_cleanup_pop (0);
320 __libc_lock_unlock (syslog_lock);
321
a583b6ad 322 if (buf != bufs)
0cc15f45 323 free (buf);
790aa1f2 324}
790aa1f2 325
5ad1a81c
AZ
326/* AF_UNIX address of local logger */
327static const struct sockaddr_un SyslogAddr =
328 {
329 .sun_family = AF_UNIX,
330 .sun_path = _PATH_LOG
331 };
790aa1f2
UD
332
333static void
0cc15f45 334openlog_internal (const char *ident, int logstat, int logfac)
790aa1f2 335{
0cc15f45
AZ
336 if (ident != NULL)
337 LogTag = ident;
338 LogStat = logstat;
339 if ((logfac & ~LOG_FACMASK) == 0)
340 LogFacility = logfac;
341
342 int retry = 0;
343 while (retry < 2)
344 {
345 if (LogFile == -1)
346 {
347 if (LogStat & LOG_NDELAY)
348 {
349 LogFile = __socket (AF_UNIX, LogType | SOCK_CLOEXEC, 0);
350 if (LogFile == -1)
351 return;
352 }
353 }
354 if (LogFile != -1 && !connected)
355 {
356 int old_errno = errno;
357 if (__connect (LogFile, &SyslogAddr, sizeof (SyslogAddr)) == -1)
358 {
359 int saved_errno = errno;
360 int fd = LogFile;
361 LogFile = -1;
362 __close (fd);
363 __set_errno (old_errno);
364 if (saved_errno == EPROTOTYPE)
790aa1f2 365 {
0cc15f45
AZ
366 /* retry with the other type: */
367 LogType = LogType == SOCK_DGRAM ? SOCK_STREAM : SOCK_DGRAM;
368 ++retry;
369 continue;
790aa1f2 370 }
0cc15f45
AZ
371 }
372 else
373 connected = true;
790aa1f2 374 }
0cc15f45
AZ
375 break;
376 }
790aa1f2
UD
377}
378
379void
380openlog (const char *ident, int logstat, int logfac)
381{
382 /* Protect against multiple users and cancellation. */
383 __libc_cleanup_push (cancel_handler, NULL);
384 __libc_lock_lock (syslog_lock);
385
386 openlog_internal (ident, logstat, logfac);
387
388 __libc_cleanup_pop (1);
389}
390
790aa1f2 391static void
60d2f8f3 392closelog_internal (void)
790aa1f2
UD
393{
394 if (!connected)
395 return;
396
397 __close (LogFile);
398 LogFile = -1;
7cb10381 399 connected = false;
790aa1f2
UD
400}
401
402void
60d2f8f3 403closelog (void)
790aa1f2
UD
404{
405 /* Protect against multiple users and cancellation. */
406 __libc_cleanup_push (cancel_handler, NULL);
407 __libc_lock_lock (syslog_lock);
408
409 closelog_internal ();
410 LogTag = NULL;
411 LogType = SOCK_DGRAM; /* this is the default */
412
413 /* Free the lock. */
414 __libc_cleanup_pop (1);
415}
416
417/* setlogmask -- set the log mask level */
418int
9d46370c 419setlogmask (int pmask)
790aa1f2 420{
0cc15f45 421 int omask;
790aa1f2 422
0cc15f45
AZ
423 /* Protect against multiple users. */
424 __libc_lock_lock (syslog_lock);
c4e4b2e1 425
0cc15f45
AZ
426 omask = LogMask;
427 if (pmask != 0)
428 LogMask = pmask;
c4e4b2e1 429
0cc15f45 430 __libc_lock_unlock (syslog_lock);
c4e4b2e1 431
0cc15f45 432 return (omask);
790aa1f2 433}
This page took 0.469777 seconds and 5 git commands to generate.