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=%i", _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 = loop_write(fd, header, l, false);
465 _public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
469 va_start(ap, format);
470 r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
476 _public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
477 char buffer[8 + LINE_MAX], p[11];
481 assert_return(priority >= 0, -EINVAL);
482 assert_return(priority <= 7, -EINVAL);
483 assert_return(format, -EINVAL);
485 snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
488 memcpy(buffer, "MESSAGE=", 8);
489 vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
490 char_array_0(buffer);
492 /* func is initialized from __func__ which is not a macro, but
493 * a static const char[], hence cannot easily be prefixed with
494 * CODE_FUNC=, hence let's do it manually here. */
495 ALLOCA_CODE_FUNC(f, func);
498 IOVEC_SET_STRING(iov[0], buffer);
499 IOVEC_SET_STRING(iov[1], p);
500 IOVEC_SET_STRING(iov[2], file);
501 IOVEC_SET_STRING(iov[3], line);
502 IOVEC_SET_STRING(iov[4], f);
504 return sd_journal_sendv(iov, ELEMENTSOF(iov));
507 _public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
510 struct iovec *iov = NULL;
513 va_start(ap, format);
514 i = fill_iovec_sprintf(format, ap, 3, &iov);
517 if (_unlikely_(i < 0)) {
522 ALLOCA_CODE_FUNC(f, func);
524 IOVEC_SET_STRING(iov[0], file);
525 IOVEC_SET_STRING(iov[1], line);
526 IOVEC_SET_STRING(iov[2], f);
528 r = sd_journal_sendv(iov, i);
531 for (j = 3; j < i; j++)
532 free(iov[j].iov_base);
539 _public_ int sd_journal_sendv_with_location(
540 const char *file, const char *line,
542 const struct iovec *iov, int n) {
547 assert_return(iov, -EINVAL);
548 assert_return(n > 0, -EINVAL);
550 niov = alloca(sizeof(struct iovec) * (n + 3));
551 memcpy(niov, iov, sizeof(struct iovec) * n);
553 ALLOCA_CODE_FUNC(f, func);
555 IOVEC_SET_STRING(niov[n++], file);
556 IOVEC_SET_STRING(niov[n++], line);
557 IOVEC_SET_STRING(niov[n++], f);
559 return sd_journal_sendv(niov, n);
562 _public_ int sd_journal_perror_with_location(
563 const char *file, const char *line,
565 const char *message) {
570 ALLOCA_CODE_FUNC(f, func);
572 IOVEC_SET_STRING(iov[0], file);
573 IOVEC_SET_STRING(iov[1], line);
574 IOVEC_SET_STRING(iov[2], f);
576 return fill_iovec_perror_and_send(message, 3, iov);