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"
36 #define SNDBUF_SIZE (8*1024*1024)
38 #define ALLOCA_CODE_FUNC(f, func) \
41 const char *_func = (func); \
43 _fl = strlen(_func) + 1; \
44 *_f = alloca(_fl + 10); \
45 memcpy(*_f, "CODE_FUNC=", 10); \
46 memcpy(*_f + 10, _func, _fl); \
49 /* We open a single fd, and we'll share it with the current process,
50 * all its threads, and all its subprocesses. This means we need to
51 * initialize it atomically, and need to operate on it atomically
52 * never assuming we are the only user */
54 static int journal_fd(void) {
56 static int fd_plus_one = 0;
60 return fd_plus_one - 1;
62 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
66 fd_inc_sndbuf(fd, SNDBUF_SIZE);
68 if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
69 close_nointr_nofail(fd);
76 _public_ int sd_journal_print(int priority, const char *format, ...) {
81 r = sd_journal_printv(priority, format, ap);
87 _public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
89 /* FIXME: Instead of limiting things to LINE_MAX we could do a
90 C99 variable-length array on the stack here in a loop. */
92 char buffer[8 + LINE_MAX], p[11]; struct iovec iov[2];
94 if (priority < 0 || priority > 7)
100 snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
103 memcpy(buffer, "MESSAGE=", 8);
104 vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
105 char_array_0(buffer);
108 IOVEC_SET_STRING(iov[0], buffer);
109 IOVEC_SET_STRING(iov[1], p);
111 return sd_journal_sendv(iov, 2);
114 _printf_attr_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
116 int r, n = 0, i = 0, j;
117 struct iovec *iov = NULL;
122 n = MAX(extra * 2, extra + 4);
123 iov = malloc0(n * sizeof(struct iovec));
139 c = realloc(iov, n * sizeof(struct iovec));
149 if (vasprintf(&buffer, format, aq) < 0) {
156 VA_FORMAT_ADVANCE(format, ap);
158 IOVEC_SET_STRING(iov[i++], buffer);
160 format = va_arg(ap, char *);
168 for (j = 0; j < i; j++)
169 free(iov[j].iov_base);
176 _public_ int sd_journal_send(const char *format, ...) {
179 struct iovec *iov = NULL;
181 va_start(ap, format);
182 i = fill_iovec_sprintf(format, ap, 0, &iov);
185 if (_unlikely_(i < 0)) {
190 r = sd_journal_sendv(iov, i);
193 for (j = 0; j < i; j++)
194 free(iov[j].iov_base);
201 _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
208 struct sockaddr_un sa;
211 struct cmsghdr cmsghdr;
212 uint8_t buf[CMSG_SPACE(sizeof(int))];
214 struct cmsghdr *cmsg;
215 /* We use /dev/shm instead of /tmp here, since we want this to
216 * be a tmpfs, and one that is available from early boot on
217 * and where unprivileged users can create files. */
218 char path[] = "/dev/shm/journal.XXXXXX";
219 bool have_syslog_identifier = false;
221 if (_unlikely_(!iov))
224 if (_unlikely_(n <= 0))
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 memcmp(iov[i].iov_base, "SYSLOG_IDENTIFIER", 17) == 0);
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))
296 sa.sun_family = AF_UNIX;
297 strncpy(sa.sun_path, "/run/systemd/journal/socket", sizeof(sa.sun_path));
301 mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
305 k = sendmsg(fd, &mh, MSG_NOSIGNAL);
309 if (errno != EMSGSIZE && errno != ENOBUFS)
312 /* Message doesn't fit... Let's dump the data in a temporary
313 * file and just pass a file descriptor of it to the other
316 buffer_fd = mkostemp(path, O_CLOEXEC|O_RDWR);
320 if (unlink(path) < 0) {
321 close_nointr_nofail(buffer_fd);
325 n = writev(buffer_fd, w, j);
327 close_nointr_nofail(buffer_fd);
335 mh.msg_control = &control;
336 mh.msg_controllen = sizeof(control);
338 cmsg = CMSG_FIRSTHDR(&mh);
339 cmsg->cmsg_level = SOL_SOCKET;
340 cmsg->cmsg_type = SCM_RIGHTS;
341 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
342 memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int));
344 mh.msg_controllen = cmsg->cmsg_len;
346 k = sendmsg(fd, &mh, MSG_NOSIGNAL);
347 close_nointr_nofail(buffer_fd);
355 static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
359 k = isempty(message) ? 0 : strlen(message) + 2;
367 j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
369 char error[6 + 10 + 1]; /* for a 32bit value */
371 if (j != buffer + 8 + k)
372 memmove(buffer + 8 + k, j, strlen(j)+1);
374 memcpy(buffer, "MESSAGE=", 8);
377 memcpy(buffer + 8, message, k - 2);
378 memcpy(buffer + 8 + k - 2, ": ", 2);
381 snprintf(error, sizeof(error), "ERRNO=%u", _saved_errno_);
384 IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
385 IOVEC_SET_STRING(iov[skip+1], buffer);
386 IOVEC_SET_STRING(iov[skip+2], error);
388 return sd_journal_sendv(iov, skip + 3);
398 _public_ int sd_journal_perror(const char *message) {
399 struct iovec iovec[3];
401 return fill_iovec_perror_and_send(message, 0, iovec);
404 _public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
405 union sockaddr_union sa;
411 if (priority < 0 || priority > 7)
414 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
419 sa.un.sun_family = AF_UNIX;
420 strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
422 r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
424 close_nointr_nofail(fd);
428 if (shutdown(fd, SHUT_RD) < 0) {
429 close_nointr_nofail(fd);
433 fd_inc_sndbuf(fd, SNDBUF_SIZE);
438 l = strlen(identifier);
439 header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
441 memcpy(header, identifier, l);
443 header[l++] = '\n'; /* unit id */
444 header[l++] = '0' + priority;
446 header[l++] = '0' + !!level_prefix;
455 r = loop_write(fd, header, l, false);
457 close_nointr_nofail(fd);
461 if ((size_t) r != l) {
462 close_nointr_nofail(fd);
469 _public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
473 va_start(ap, format);
474 r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
480 _public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
481 char buffer[8 + LINE_MAX], p[11];
485 if (priority < 0 || priority > 7)
488 if (_unlikely_(!format))
491 snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
494 memcpy(buffer, "MESSAGE=", 8);
495 vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
496 char_array_0(buffer);
498 /* func is initialized from __func__ which is not a macro, but
499 * a static const char[], hence cannot easily be prefixed with
500 * CODE_FUNC=, hence let's do it manually here. */
501 ALLOCA_CODE_FUNC(f, func);
504 IOVEC_SET_STRING(iov[0], buffer);
505 IOVEC_SET_STRING(iov[1], p);
506 IOVEC_SET_STRING(iov[2], file);
507 IOVEC_SET_STRING(iov[3], line);
508 IOVEC_SET_STRING(iov[4], f);
510 return sd_journal_sendv(iov, ELEMENTSOF(iov));
513 _public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
516 struct iovec *iov = NULL;
519 va_start(ap, format);
520 i = fill_iovec_sprintf(format, ap, 3, &iov);
523 if (_unlikely_(i < 0)) {
528 ALLOCA_CODE_FUNC(f, func);
530 IOVEC_SET_STRING(iov[0], file);
531 IOVEC_SET_STRING(iov[1], line);
532 IOVEC_SET_STRING(iov[2], f);
534 r = sd_journal_sendv(iov, i);
537 for (j = 3; j < i; j++)
538 free(iov[j].iov_base);
545 _public_ int sd_journal_sendv_with_location(
546 const char *file, const char *line,
548 const struct iovec *iov, int n) {
553 if (_unlikely_(!iov))
556 if (_unlikely_(n <= 0))
559 niov = alloca(sizeof(struct iovec) * (n + 3));
560 memcpy(niov, iov, sizeof(struct iovec) * n);
562 ALLOCA_CODE_FUNC(f, func);
564 IOVEC_SET_STRING(niov[n++], file);
565 IOVEC_SET_STRING(niov[n++], line);
566 IOVEC_SET_STRING(niov[n++], f);
568 return sd_journal_sendv(niov, n);
571 _public_ int sd_journal_perror_with_location(
572 const char *file, const char *line,
574 const char *message) {
579 ALLOCA_CODE_FUNC(f, func);
581 IOVEC_SET_STRING(iov[0], file);
582 IOVEC_SET_STRING(iov[1], line);
583 IOVEC_SET_STRING(iov[2], f);
585 return fill_iovec_perror_and_send(message, 3, iov);