1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/socket.h>
30 #define SD_JOURNAL_SUPPRESS_LOCATION
32 #include "sd-journal.h"
34 #include "socket-util.h"
35 #include "memfd-util.h"
37 #define SNDBUF_SIZE (8*1024*1024)
39 #define ALLOCA_CODE_FUNC(f, func) \
42 const char *_func = (func); \
44 _fl = strlen(_func) + 1; \
45 *_f = alloca(_fl + 10); \
46 memcpy(*_f, "CODE_FUNC=", 10); \
47 memcpy(*_f + 10, _func, _fl); \
50 /* We open a single fd, and we'll share it with the current process,
51 * all its threads, and all its subprocesses. This means we need to
52 * initialize it atomically, and need to operate on it atomically
53 * never assuming we are the only user */
55 static int journal_fd(void) {
57 static int fd_plus_one = 0;
61 return fd_plus_one - 1;
63 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
67 fd_inc_sndbuf(fd, SNDBUF_SIZE);
69 if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
77 _public_ int sd_journal_print(int priority, const char *format, ...) {
82 r = sd_journal_printv(priority, format, ap);
88 _public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
90 /* FIXME: Instead of limiting things to LINE_MAX we could do a
91 C99 variable-length array on the stack here in a loop. */
93 char buffer[8 + LINE_MAX], p[11]; struct iovec iov[2];
95 assert_return(priority >= 0, -EINVAL);
96 assert_return(priority <= 7, -EINVAL);
97 assert_return(format, -EINVAL);
99 snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
102 memcpy(buffer, "MESSAGE=", 8);
103 vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
104 char_array_0(buffer);
107 IOVEC_SET_STRING(iov[0], buffer);
108 IOVEC_SET_STRING(iov[1], p);
110 return sd_journal_sendv(iov, 2);
113 _printf_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
115 int r, n = 0, i = 0, j;
116 struct iovec *iov = NULL;
121 n = MAX(extra * 2, extra + 4);
122 iov = malloc0(n * sizeof(struct iovec));
138 c = realloc(iov, n * sizeof(struct iovec));
148 if (vasprintf(&buffer, format, aq) < 0) {
155 VA_FORMAT_ADVANCE(format, ap);
157 IOVEC_SET_STRING(iov[i++], buffer);
159 format = va_arg(ap, char *);
167 for (j = 0; j < i; j++)
168 free(iov[j].iov_base);
175 _public_ int sd_journal_send(const char *format, ...) {
178 struct iovec *iov = NULL;
180 va_start(ap, format);
181 i = fill_iovec_sprintf(format, ap, 0, &iov);
184 if (_unlikely_(i < 0)) {
189 r = sd_journal_sendv(iov, i);
192 for (j = 0; j < i; j++)
193 free(iov[j].iov_base);
200 _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
203 _cleanup_close_ int buffer_fd = -1;
207 struct sockaddr_un sa = {
208 .sun_family = AF_UNIX,
209 .sun_path = "/run/systemd/journal/socket",
213 .msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path),
217 struct cmsghdr cmsghdr;
218 uint8_t buf[CMSG_SPACE(sizeof(int))];
220 struct cmsghdr *cmsg;
221 bool have_syslog_identifier = false;
224 assert_return(iov, -EINVAL);
225 assert_return(n > 0, -EINVAL);
227 w = alloca(sizeof(struct iovec) * n * 5 + 3);
228 l = alloca(sizeof(uint64_t) * n);
230 for (i = 0; i < n; i++) {
233 if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1))
236 c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
237 if (_unlikely_(!c || c == iov[i].iov_base))
240 have_syslog_identifier = have_syslog_identifier ||
241 (c == (char *) iov[i].iov_base + 17 &&
242 startswith(iov[i].iov_base, "SYSLOG_IDENTIFIER"));
244 nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
246 if (_unlikely_(nl < c))
249 /* Already includes a newline? Bummer, then
250 * let's write the variable name, then a
251 * newline, then the size (64bit LE), followed
252 * by the data and a final newline */
254 w[j].iov_base = iov[i].iov_base;
255 w[j].iov_len = c - (char*) iov[i].iov_base;
258 IOVEC_SET_STRING(w[j++], "\n");
260 l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
261 w[j].iov_base = &l[i];
262 w[j].iov_len = sizeof(uint64_t);
265 w[j].iov_base = c + 1;
266 w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
270 /* Nothing special? Then just add the line and
271 * append a newline */
274 IOVEC_SET_STRING(w[j++], "\n");
277 if (!have_syslog_identifier &&
278 string_is_safe(program_invocation_short_name)) {
280 /* Implicitly add program_invocation_short_name, if it
281 * is not set explicitly. We only do this for
282 * program_invocation_short_name, and nothing else
283 * since everything else is much nicer to retrieve
284 * from the outside. */
286 IOVEC_SET_STRING(w[j++], "SYSLOG_IDENTIFIER=");
287 IOVEC_SET_STRING(w[j++], program_invocation_short_name);
288 IOVEC_SET_STRING(w[j++], "\n");
292 if (_unlikely_(fd < 0))
298 k = sendmsg(fd, &mh, MSG_NOSIGNAL);
302 /* Fail silently if the journal is not available */
306 if (errno != EMSGSIZE && errno != ENOBUFS)
309 /* Message doesn't fit... Let's dump the data in a memfd or
310 * temporary file and just pass a file descriptor of it to the
313 * For the temporary files we use /dev/shm instead of /tmp
314 * here, since we want this to be a tmpfs, and one that is
315 * available from early boot on and where unprivileged users
316 * can create files. */
317 buffer_fd = memfd_new(NULL);
319 if (buffer_fd == -ENOSYS) {
320 buffer_fd = open_tmpfile("/dev/shm", O_RDWR | O_CLOEXEC);
329 n = writev(buffer_fd, w, j);
334 r = memfd_set_sealed(buffer_fd);
343 mh.msg_control = &control;
344 mh.msg_controllen = sizeof(control);
346 cmsg = CMSG_FIRSTHDR(&mh);
347 cmsg->cmsg_level = SOL_SOCKET;
348 cmsg->cmsg_type = SCM_RIGHTS;
349 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
350 memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int));
352 mh.msg_controllen = cmsg->cmsg_len;
354 k = sendmsg(fd, &mh, MSG_NOSIGNAL);
361 static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
365 k = isempty(message) ? 0 : strlen(message) + 2;
373 j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
375 char error[6 + 10 + 1]; /* for a 32bit value */
377 if (j != buffer + 8 + k)
378 memmove(buffer + 8 + k, j, strlen(j)+1);
380 memcpy(buffer, "MESSAGE=", 8);
383 memcpy(buffer + 8, message, k - 2);
384 memcpy(buffer + 8 + k - 2, ": ", 2);
387 snprintf(error, sizeof(error), "ERRNO=%u", _saved_errno_);
390 IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
391 IOVEC_SET_STRING(iov[skip+1], buffer);
392 IOVEC_SET_STRING(iov[skip+2], error);
394 return sd_journal_sendv(iov, skip + 3);
404 _public_ int sd_journal_perror(const char *message) {
405 struct iovec iovec[3];
407 return fill_iovec_perror_and_send(message, 0, iovec);
410 _public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
411 union sockaddr_union sa = {
412 .un.sun_family = AF_UNIX,
413 .un.sun_path = "/run/systemd/journal/stdout",
415 _cleanup_close_ int fd = -1;
420 assert_return(priority >= 0, -EINVAL);
421 assert_return(priority <= 7, -EINVAL);
423 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
427 r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
431 if (shutdown(fd, SHUT_RD) < 0)
434 fd_inc_sndbuf(fd, SNDBUF_SIZE);
439 l = strlen(identifier);
440 header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
442 memcpy(header, identifier, l);
444 header[l++] = '\n'; /* unit id */
445 header[l++] = '0' + priority;
447 header[l++] = '0' + !!level_prefix;
456 r = (int) loop_write(fd, header, l, false);
468 _public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
472 va_start(ap, format);
473 r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
479 _public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
480 char buffer[8 + LINE_MAX], p[11];
484 assert_return(priority >= 0, -EINVAL);
485 assert_return(priority <= 7, -EINVAL);
486 assert_return(format, -EINVAL);
488 snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
491 memcpy(buffer, "MESSAGE=", 8);
492 vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
493 char_array_0(buffer);
495 /* func is initialized from __func__ which is not a macro, but
496 * a static const char[], hence cannot easily be prefixed with
497 * CODE_FUNC=, hence let's do it manually here. */
498 ALLOCA_CODE_FUNC(f, func);
501 IOVEC_SET_STRING(iov[0], buffer);
502 IOVEC_SET_STRING(iov[1], p);
503 IOVEC_SET_STRING(iov[2], file);
504 IOVEC_SET_STRING(iov[3], line);
505 IOVEC_SET_STRING(iov[4], f);
507 return sd_journal_sendv(iov, ELEMENTSOF(iov));
510 _public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
513 struct iovec *iov = NULL;
516 va_start(ap, format);
517 i = fill_iovec_sprintf(format, ap, 3, &iov);
520 if (_unlikely_(i < 0)) {
525 ALLOCA_CODE_FUNC(f, func);
527 IOVEC_SET_STRING(iov[0], file);
528 IOVEC_SET_STRING(iov[1], line);
529 IOVEC_SET_STRING(iov[2], f);
531 r = sd_journal_sendv(iov, i);
534 for (j = 3; j < i; j++)
535 free(iov[j].iov_base);
542 _public_ int sd_journal_sendv_with_location(
543 const char *file, const char *line,
545 const struct iovec *iov, int n) {
550 assert_return(iov, -EINVAL);
551 assert_return(n > 0, -EINVAL);
553 niov = alloca(sizeof(struct iovec) * (n + 3));
554 memcpy(niov, iov, sizeof(struct iovec) * n);
556 ALLOCA_CODE_FUNC(f, func);
558 IOVEC_SET_STRING(niov[n++], file);
559 IOVEC_SET_STRING(niov[n++], line);
560 IOVEC_SET_STRING(niov[n++], f);
562 return sd_journal_sendv(niov, n);
565 _public_ int sd_journal_perror_with_location(
566 const char *file, const char *line,
568 const char *message) {
573 ALLOCA_CODE_FUNC(f, func);
575 IOVEC_SET_STRING(iov[0], file);
576 IOVEC_SET_STRING(iov[1], line);
577 IOVEC_SET_STRING(iov[2], f);
579 return fill_iovec_perror_and_send(message, 3, iov);