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 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;
123 n = MAX(extra * 2, extra + 4);
124 iov = malloc0(n * sizeof(struct iovec));
140 c = realloc(iov, n * sizeof(struct iovec));
150 if (vasprintf(&buffer, format, aq) < 0) {
157 VA_FORMAT_ADVANCE(format, ap);
159 IOVEC_SET_STRING(iov[i++], buffer);
161 format = va_arg(ap, char *);
170 for (j = 0; j < i; j++)
171 free(iov[j].iov_base);
179 _public_ int sd_journal_send(const char *format, ...) {
182 struct iovec *iov = NULL;
184 va_start(ap, format);
185 i = fill_iovec_sprintf(format, ap, 0, &iov);
188 if (_unlikely_(i < 0)) {
193 r = sd_journal_sendv(iov, i);
196 for (j = 0; j < i; j++)
197 free(iov[j].iov_base);
204 _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
210 struct sockaddr_un sa;
214 struct cmsghdr cmsghdr;
215 uint8_t buf[CMSG_SPACE(sizeof(int))];
217 struct cmsghdr *cmsg;
218 /* We use /dev/shm instead of /tmp here, since we want this to
219 * be a tmpfs, and one that is available from early boot on
220 * and where unprivileged users can create files. */
221 char path[] = "/dev/shm/journal.XXXXXX";
223 if (_unlikely_(!iov))
226 if (_unlikely_(n <= 0))
231 w = alloca(sizeof(struct iovec) * n * 5);
232 l = alloca(sizeof(uint64_t) * n);
234 for (i = 0; i < n; i++) {
237 if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1)) {
242 c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
243 if (_unlikely_(!c || c == iov[i].iov_base)) {
248 nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
250 if (_unlikely_(nl < c)) {
255 /* Already includes a newline? Bummer, then
256 * let's write the variable name, then a
257 * newline, then the size (64bit LE), followed
258 * by the data and a final newline */
260 w[j].iov_base = iov[i].iov_base;
261 w[j].iov_len = c - (char*) iov[i].iov_base;
264 IOVEC_SET_STRING(w[j++], "\n");
266 l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
267 w[j].iov_base = &l[i];
268 w[j].iov_len = sizeof(uint64_t);
271 w[j].iov_base = c + 1;
272 w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
276 /* Nothing special? Then just add the line and
277 * append a newline */
280 IOVEC_SET_STRING(w[j++], "\n");
284 if (_unlikely_(fd < 0)) {
290 sa.sun_family = AF_UNIX;
291 strncpy(sa.sun_path, "/run/systemd/journal/socket", sizeof(sa.sun_path));
295 mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
299 k = sendmsg(fd, &mh, MSG_NOSIGNAL);
305 if (errno != EMSGSIZE && errno != ENOBUFS) {
310 /* Message doesn't fit... Let's dump the data in a temporary
311 * file and just pass a file descriptor of it to the other
314 buffer_fd = mkostemp(path, O_CLOEXEC|O_RDWR);
320 if (unlink(path) < 0) {
321 close_nointr_nofail(buffer_fd);
326 n = writev(buffer_fd, w, j);
328 close_nointr_nofail(buffer_fd);
337 mh.msg_control = &control;
338 mh.msg_controllen = sizeof(control);
340 cmsg = CMSG_FIRSTHDR(&mh);
341 cmsg->cmsg_level = SOL_SOCKET;
342 cmsg->cmsg_type = SCM_RIGHTS;
343 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
344 memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int));
346 mh.msg_controllen = cmsg->cmsg_len;
348 k = sendmsg(fd, &mh, MSG_NOSIGNAL);
349 close_nointr_nofail(buffer_fd);
364 static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
370 k = isempty(message) ? 0 : strlen(message) + 2;
378 j = strerror_r(saved_errno, buffer + 8 + k, n - 8 - k);
380 char error[6 + 10 + 1]; /* for a 32bit value */
382 if (j != buffer + 8 + k)
383 memmove(buffer + 8 + k, j, strlen(j)+1);
385 memcpy(buffer, "MESSAGE=", 8);
388 memcpy(buffer + 8, message, k - 2);
389 memcpy(buffer + 8 + k - 2, ": ", 2);
392 snprintf(error, sizeof(error), "ERRNO=%u", saved_errno);
395 IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
396 IOVEC_SET_STRING(iov[skip+1], buffer);
397 IOVEC_SET_STRING(iov[skip+2], error);
399 r = sd_journal_sendv(iov, skip + 3);
405 if (errno != ERANGE) {
415 _public_ int sd_journal_perror(const char *message) {
416 struct iovec iovec[3];
418 return fill_iovec_perror_and_send(message, 0, iovec);
421 _public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
422 union sockaddr_union sa;
428 if (priority < 0 || priority > 7)
431 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
436 sa.un.sun_family = AF_UNIX;
437 strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
439 r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
441 close_nointr_nofail(fd);
445 if (shutdown(fd, SHUT_RD) < 0) {
446 close_nointr_nofail(fd);
450 fd_inc_sndbuf(fd, SNDBUF_SIZE);
455 l = strlen(identifier);
456 header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
458 memcpy(header, identifier, l);
460 header[l++] = '\n'; /* unit id */
461 header[l++] = '0' + priority;
463 header[l++] = '0' + !!level_prefix;
472 r = loop_write(fd, header, l, false);
474 close_nointr_nofail(fd);
478 if ((size_t) r != l) {
479 close_nointr_nofail(fd);
486 _public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
490 va_start(ap, format);
491 r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
497 _public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
498 char buffer[8 + LINE_MAX], p[11];
502 if (priority < 0 || priority > 7)
505 if (_unlikely_(!format))
508 snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
511 memcpy(buffer, "MESSAGE=", 8);
512 vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
513 char_array_0(buffer);
515 /* func is initialized from __func__ which is not a macro, but
516 * a static const char[], hence cannot easily be prefixed with
517 * CODE_FUNC=, hence let's do it manually here. */
518 ALLOCA_CODE_FUNC(f, func);
521 IOVEC_SET_STRING(iov[0], buffer);
522 IOVEC_SET_STRING(iov[1], p);
523 IOVEC_SET_STRING(iov[2], file);
524 IOVEC_SET_STRING(iov[3], line);
525 IOVEC_SET_STRING(iov[4], f);
527 return sd_journal_sendv(iov, ELEMENTSOF(iov));
530 _public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
533 struct iovec *iov = NULL;
536 va_start(ap, format);
537 i = fill_iovec_sprintf(format, ap, 3, &iov);
540 if (_unlikely_(i < 0)) {
545 ALLOCA_CODE_FUNC(f, func);
547 IOVEC_SET_STRING(iov[0], file);
548 IOVEC_SET_STRING(iov[1], line);
549 IOVEC_SET_STRING(iov[2], f);
551 r = sd_journal_sendv(iov, i);
554 for (j = 3; j < i; j++)
555 free(iov[j].iov_base);
562 _public_ int sd_journal_sendv_with_location(
563 const char *file, const char *line,
565 const struct iovec *iov, int n) {
570 if (_unlikely_(!iov))
573 if (_unlikely_(n <= 0))
576 niov = alloca(sizeof(struct iovec) * (n + 3));
577 memcpy(niov, iov, sizeof(struct iovec) * n);
579 ALLOCA_CODE_FUNC(f, func);
581 IOVEC_SET_STRING(niov[n++], file);
582 IOVEC_SET_STRING(niov[n++], line);
583 IOVEC_SET_STRING(niov[n++], f);
585 return sd_journal_sendv(niov, n);
588 _public_ int sd_journal_perror_with_location(
589 const char *file, const char *line,
591 const char *message) {
596 ALLOCA_CODE_FUNC(f, func);
598 IOVEC_SET_STRING(iov[0], file);
599 IOVEC_SET_STRING(iov[1], line);
600 IOVEC_SET_STRING(iov[2], f);
602 return fill_iovec_perror_and_send(message, 3, iov);