]> git.ipfire.org Git - thirdparty/glibc.git/blame - misc/syslog.c
malloc: set NON_MAIN_ARENA flag for reclaimed memalign chunk (BZ #30101)
[thirdparty/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>
37233df9 44
0cc15f45
AZ
45static int LogType = SOCK_DGRAM; /* type of socket connection */
46static int LogFile = -1; /* fd for log */
47static bool connected; /* have done connect */
48static int LogStat; /* status bits, set by openlog() */
790aa1f2 49static const char *LogTag; /* string to tag the entry with */
0cc15f45
AZ
50static int LogFacility = LOG_USER; /* default facility code */
51static int LogMask = 0xff; /* mask of priorities to be logged */
52extern char *__progname; /* Program name, from crt0. */
790aa1f2
UD
53
54/* Define the lock. */
55__libc_lock_define_initialized (static, syslog_lock)
0cc15f45
AZ
56static void openlog_internal (const char *, int, int);
57static void closelog_internal (void);
790aa1f2
UD
58
59struct cleanup_arg
60{
61 void *buf;
62 struct sigaction *oldaction;
63};
64
65static void
66cancel_handler (void *ptr)
67{
790aa1f2
UD
68 /* Restore the old signal handler. */
69 struct cleanup_arg *clarg = (struct cleanup_arg *) ptr;
70
c4e4b2e1 71 if (clarg != NULL)
ded3cef3
AZ
72 /* Free the memstream buffer, */
73 free (clarg->buf);
c4e4b2e1 74
790aa1f2
UD
75 /* Free the lock. */
76 __libc_lock_unlock (syslog_lock);
77}
78
79
80/*
81 * syslog, vsyslog --
82 * print message on log file; output is intended for syslogd(8).
83 */
84void
0cc15f45 85__syslog (int pri, const char *fmt, ...)
790aa1f2 86{
0cc15f45 87 va_list ap;
790aa1f2 88
0cc15f45
AZ
89 va_start (ap, fmt);
90 __vsyslog_internal (pri, fmt, ap, 0);
91 va_end (ap);
790aa1f2 92}
c6251f03
RM
93ldbl_hidden_def (__syslog, syslog)
94ldbl_strong_alias (__syslog, syslog)
790aa1f2 95
124fc732 96void
0cc15f45 97__vsyslog (int pri, const char *fmt, va_list ap)
124fc732 98{
0cc15f45 99 __vsyslog_internal (pri, fmt, ap, 0);
124fc732
ZW
100}
101ldbl_weak_alias (__vsyslog, vsyslog)
102
790aa1f2 103void
0cc15f45 104__syslog_chk (int pri, int flag, const char *fmt, ...)
29c21e49 105{
0cc15f45 106 va_list ap;
29c21e49 107
0cc15f45
AZ
108 va_start (ap, fmt);
109 __vsyslog_internal (pri, fmt, ap, (flag > 0) ? PRINTF_FORTIFY : 0);
110 va_end (ap);
29c21e49
UD
111}
112
113void
0cc15f45 114__vsyslog_chk (int pri, int flag, const char *fmt, va_list ap)
124fc732 115{
0cc15f45 116 __vsyslog_internal (pri, fmt, ap, (flag > 0) ? PRINTF_FORTIFY : 0);
124fc732
ZW
117}
118
119void
0cc15f45
AZ
120__vsyslog_internal (int pri, const char *fmt, va_list ap,
121 unsigned int mode_flags)
790aa1f2 122{
a583b6ad
AZ
123 /* Try to use a static buffer as an optimization. */
124 char bufs[1024];
125 char *buf = NULL;
0cc15f45 126 size_t bufsize = 0;
f9f5c70e 127 int msgoff;
0cc15f45 128 int saved_errno = errno;
0cc15f45
AZ
129
130#define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
131 /* Check for invalid bits. */
132 if (pri & ~(LOG_PRIMASK | LOG_FACMASK))
133 {
134 syslog (INTERNALLOG, "syslog: unknown facility/priority: %x", pri);
135 pri &= LOG_PRIMASK | LOG_FACMASK;
136 }
137
138 /* Prepare for multiple users. We have to take care: most syscalls we are
139 using are cancellation points. */
f9f5c70e 140 struct cleanup_arg clarg = { NULL, NULL };
0cc15f45
AZ
141 __libc_cleanup_push (cancel_handler, &clarg);
142 __libc_lock_lock (syslog_lock);
143
144 /* Check priority against setlogmask values. */
145 if ((LOG_MASK (LOG_PRI (pri)) & LogMask) == 0)
146 goto out;
147
148 /* Set default facility if none specified. */
149 if ((pri & LOG_FACMASK) == 0)
150 pri |= LogFacility;
151
a583b6ad
AZ
152 pid_t pid = LogStat & LOG_PID ? __getpid () : 0;
153
154 /* "%b %e %H:%M:%S " */
155 char timestamp[sizeof "MMM DD hh:mm:ss "];
ac0d208b 156 __time64_t now = time64_now ();
a583b6ad 157 struct tm now_tm;
ac0d208b
AZ
158 struct tm *now_tmp = __localtime64_r (&now, &now_tm);
159 bool has_ts = now_tmp != NULL;
160
161 /* In the unlikely case of localtime_r failure (tm_year out of int range)
162 skip the hostname so the message is handled as valid PRI but without
163 TIMESTAMP or invalid TIMESTAMP (which should force the relay to add the
164 timestamp itself). */
165 if (has_ts)
166 __strftime_l (timestamp, sizeof timestamp, "%h %e %T ", now_tmp,
167 _nl_C_locobj_ptr);
a583b6ad
AZ
168
169#define SYSLOG_HEADER(__pri, __timestamp, __msgoff, pid) \
45459476 170 "<%d>%s%n%s%s%.0d%s: ", \
a583b6ad
AZ
171 __pri, __timestamp, __msgoff, \
172 LogTag == NULL ? __progname : LogTag, \
173 "[" + (pid == 0), pid, "]" + (pid == 0)
174
ac0d208b
AZ
175#define SYSLOG_HEADER_WITHOUT_TS(__pri, __msgoff) \
176 "<%d>: %n", __pri, __msgoff
177
178 int l;
179 if (has_ts)
180 l = __snprintf (bufs, sizeof bufs,
181 SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
182 else
183 l = __snprintf (bufs, sizeof bufs,
184 SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
a583b6ad 185 if (0 <= l && l < sizeof bufs)
0cc15f45 186 {
a583b6ad
AZ
187 va_list apc;
188 va_copy (apc, ap);
189
0cc15f45
AZ
190 /* Restore errno for %m format. */
191 __set_errno (saved_errno);
192
a583b6ad
AZ
193 int vl = __vsnprintf_internal (bufs + l, sizeof bufs - l, fmt, apc,
194 mode_flags);
195 if (0 <= vl && vl < sizeof bufs - l)
52a5be0d
AZ
196 buf = bufs;
197 bufsize = l + vl;
0cc15f45 198
a583b6ad 199 va_end (apc);
0cc15f45 200 }
a583b6ad
AZ
201
202 if (buf == NULL)
f9f5c70e 203 {
52a5be0d 204 buf = malloc ((bufsize + 1) * sizeof (char));
a583b6ad
AZ
205 if (buf != NULL)
206 {
207 /* Tell the cancellation handler to free this buffer. */
208 clarg.buf = buf;
209
ac0d208b 210 if (has_ts)
52a5be0d 211 __snprintf (buf, l + 1,
ac0d208b
AZ
212 SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
213 else
52a5be0d 214 __snprintf (buf, l + 1,
ac0d208b 215 SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
52a5be0d
AZ
216
217 va_list apc;
218 va_copy (apc, ap);
219 __vsnprintf_internal (buf + l, bufsize - l + 1, fmt, apc,
220 mode_flags);
221 va_end (apc);
a583b6ad
AZ
222 }
223 else
224 {
225 /* Nothing much to do but emit an error message. */
226 bufsize = __snprintf (bufs, sizeof bufs,
227 "out of memory[%d]", __getpid ());
228 buf = bufs;
229 }
f9f5c70e 230 }
0cc15f45
AZ
231
232 /* Output to stderr if requested. */
233 if (LogStat & LOG_PERROR)
f9f5c70e
AZ
234 __dprintf (STDERR_FILENO, "%s%s", buf + msgoff,
235 "\n" + (buf[bufsize - 1] == '\n'));
0cc15f45
AZ
236
237 /* Get connected, output the message to the local logger. */
238 if (!connected)
239 openlog_internal (NULL, LogStat | LOG_NDELAY, LogFacility);
240
241 /* If we have a SOCK_STREAM connection, also send ASCII NUL as a record
242 terminator. */
243 if (LogType == SOCK_STREAM)
244 ++bufsize;
245
246 if (!connected || __send (LogFile, buf, bufsize, MSG_NOSIGNAL) < 0)
247 {
248 if (connected)
249 {
250 /* Try to reopen the syslog connection. Maybe it went down. */
251 closelog_internal ();
252 openlog_internal (NULL, LogStat | LOG_NDELAY, LogFacility);
790aa1f2
UD
253 }
254
0cc15f45
AZ
255 if (!connected || __send (LogFile, buf, bufsize, MSG_NOSIGNAL) < 0)
256 {
257 closelog_internal (); /* attempt re-open next time */
258 /*
259 * Output the message to the console; don't worry
260 * about blocking, if console blocks everything will.
261 * Make sure the error reported is the one from the
262 * syslogd failure.
263 */
f9f5c70e 264 int fd;
0cc15f45
AZ
265 if (LogStat & LOG_CONS &&
266 (fd = __open (_PATH_CONSOLE, O_WRONLY | O_NOCTTY
267 | O_CLOEXEC, 0)) >= 0)
268 {
269 __dprintf (fd, "%s\r\n", buf + msgoff);
270 __close (fd);
271 }
272 }
273 }
274
275out:
276 /* End of critical section. */
277 __libc_cleanup_pop (0);
278 __libc_lock_unlock (syslog_lock);
279
a583b6ad 280 if (buf != bufs)
0cc15f45 281 free (buf);
790aa1f2 282}
790aa1f2 283
5ad1a81c
AZ
284/* AF_UNIX address of local logger */
285static const struct sockaddr_un SyslogAddr =
286 {
287 .sun_family = AF_UNIX,
288 .sun_path = _PATH_LOG
289 };
790aa1f2
UD
290
291static void
0cc15f45 292openlog_internal (const char *ident, int logstat, int logfac)
790aa1f2 293{
0cc15f45
AZ
294 if (ident != NULL)
295 LogTag = ident;
296 LogStat = logstat;
297 if ((logfac & ~LOG_FACMASK) == 0)
298 LogFacility = logfac;
299
300 int retry = 0;
301 while (retry < 2)
302 {
303 if (LogFile == -1)
304 {
305 if (LogStat & LOG_NDELAY)
306 {
307 LogFile = __socket (AF_UNIX, LogType | SOCK_CLOEXEC, 0);
308 if (LogFile == -1)
309 return;
310 }
311 }
312 if (LogFile != -1 && !connected)
313 {
314 int old_errno = errno;
315 if (__connect (LogFile, &SyslogAddr, sizeof (SyslogAddr)) == -1)
316 {
317 int saved_errno = errno;
318 int fd = LogFile;
319 LogFile = -1;
320 __close (fd);
321 __set_errno (old_errno);
322 if (saved_errno == EPROTOTYPE)
790aa1f2 323 {
0cc15f45
AZ
324 /* retry with the other type: */
325 LogType = LogType == SOCK_DGRAM ? SOCK_STREAM : SOCK_DGRAM;
326 ++retry;
327 continue;
790aa1f2 328 }
0cc15f45
AZ
329 }
330 else
331 connected = true;
790aa1f2 332 }
0cc15f45
AZ
333 break;
334 }
790aa1f2
UD
335}
336
337void
338openlog (const char *ident, int logstat, int logfac)
339{
340 /* Protect against multiple users and cancellation. */
341 __libc_cleanup_push (cancel_handler, NULL);
342 __libc_lock_lock (syslog_lock);
343
344 openlog_internal (ident, logstat, logfac);
345
346 __libc_cleanup_pop (1);
347}
348
790aa1f2 349static void
60d2f8f3 350closelog_internal (void)
790aa1f2
UD
351{
352 if (!connected)
353 return;
354
355 __close (LogFile);
356 LogFile = -1;
7cb10381 357 connected = false;
790aa1f2
UD
358}
359
360void
60d2f8f3 361closelog (void)
790aa1f2
UD
362{
363 /* Protect against multiple users and cancellation. */
364 __libc_cleanup_push (cancel_handler, NULL);
365 __libc_lock_lock (syslog_lock);
366
367 closelog_internal ();
368 LogTag = NULL;
369 LogType = SOCK_DGRAM; /* this is the default */
370
371 /* Free the lock. */
372 __libc_cleanup_pop (1);
373}
374
375/* setlogmask -- set the log mask level */
376int
9d46370c 377setlogmask (int pmask)
790aa1f2 378{
0cc15f45 379 int omask;
790aa1f2 380
0cc15f45
AZ
381 /* Protect against multiple users. */
382 __libc_lock_lock (syslog_lock);
c4e4b2e1 383
0cc15f45
AZ
384 omask = LogMask;
385 if (pmask != 0)
386 LogMask = pmask;
c4e4b2e1 387
0cc15f45 388 __libc_lock_unlock (syslog_lock);
c4e4b2e1 389
0cc15f45 390 return (omask);
790aa1f2 391}