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";
222 bool have_syslog_identifier = false;
224 if (_unlikely_(!iov))
227 if (_unlikely_(n <= 0))
232 w = alloca(sizeof(struct iovec) * n * 5 + 3);
233 l = alloca(sizeof(uint64_t) * n);
235 for (i = 0; i < n; i++) {
238 if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1)) {
243 c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
244 if (_unlikely_(!c || c == iov[i].iov_base)) {
249 have_syslog_identifier =
250 have_syslog_identifier || (c == iov[i].iov_base + 17 && memcmp(iov[i].iov_base, "SYSLOG_IDENTIFIER", 17) == 0);
252 nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
254 if (_unlikely_(nl < c)) {
259 /* Already includes a newline? Bummer, then
260 * let's write the variable name, then a
261 * newline, then the size (64bit LE), followed
262 * by the data and a final newline */
264 w[j].iov_base = iov[i].iov_base;
265 w[j].iov_len = c - (char*) iov[i].iov_base;
268 IOVEC_SET_STRING(w[j++], "\n");
270 l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
271 w[j].iov_base = &l[i];
272 w[j].iov_len = sizeof(uint64_t);
275 w[j].iov_base = c + 1;
276 w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
280 /* Nothing special? Then just add the line and
281 * append a newline */
284 IOVEC_SET_STRING(w[j++], "\n");
287 if (!have_syslog_identifier &&
288 string_is_safe(program_invocation_short_name)) {
290 /* Implicitly add program_invocation_short_name, if it
291 * is not set explicitly. We only do this for
292 * program_invocation_short_name, and nothing else
293 * since everything else is much nicer to retrieve
294 * from the outside. */
296 IOVEC_SET_STRING(w[j++], "SYSLOG_IDENTIFIER=");
297 IOVEC_SET_STRING(w[j++], program_invocation_short_name);
298 IOVEC_SET_STRING(w[j++], "\n");
302 if (_unlikely_(fd < 0)) {
308 sa.sun_family = AF_UNIX;
309 strncpy(sa.sun_path, "/run/systemd/journal/socket", sizeof(sa.sun_path));
313 mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
317 k = sendmsg(fd, &mh, MSG_NOSIGNAL);
323 if (errno != EMSGSIZE && errno != ENOBUFS) {
328 /* Message doesn't fit... Let's dump the data in a temporary
329 * file and just pass a file descriptor of it to the other
332 buffer_fd = mkostemp(path, O_CLOEXEC|O_RDWR);
338 if (unlink(path) < 0) {
339 close_nointr_nofail(buffer_fd);
344 n = writev(buffer_fd, w, j);
346 close_nointr_nofail(buffer_fd);
355 mh.msg_control = &control;
356 mh.msg_controllen = sizeof(control);
358 cmsg = CMSG_FIRSTHDR(&mh);
359 cmsg->cmsg_level = SOL_SOCKET;
360 cmsg->cmsg_type = SCM_RIGHTS;
361 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
362 memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int));
364 mh.msg_controllen = cmsg->cmsg_len;
366 k = sendmsg(fd, &mh, MSG_NOSIGNAL);
367 close_nointr_nofail(buffer_fd);
382 static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
388 k = isempty(message) ? 0 : strlen(message) + 2;
396 j = strerror_r(saved_errno, buffer + 8 + k, n - 8 - k);
398 char error[6 + 10 + 1]; /* for a 32bit value */
400 if (j != buffer + 8 + k)
401 memmove(buffer + 8 + k, j, strlen(j)+1);
403 memcpy(buffer, "MESSAGE=", 8);
406 memcpy(buffer + 8, message, k - 2);
407 memcpy(buffer + 8 + k - 2, ": ", 2);
410 snprintf(error, sizeof(error), "ERRNO=%u", saved_errno);
413 IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
414 IOVEC_SET_STRING(iov[skip+1], buffer);
415 IOVEC_SET_STRING(iov[skip+2], error);
417 r = sd_journal_sendv(iov, skip + 3);
423 if (errno != ERANGE) {
433 _public_ int sd_journal_perror(const char *message) {
434 struct iovec iovec[3];
436 return fill_iovec_perror_and_send(message, 0, iovec);
439 _public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
440 union sockaddr_union sa;
446 if (priority < 0 || priority > 7)
449 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
454 sa.un.sun_family = AF_UNIX;
455 strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
457 r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
459 close_nointr_nofail(fd);
463 if (shutdown(fd, SHUT_RD) < 0) {
464 close_nointr_nofail(fd);
468 fd_inc_sndbuf(fd, SNDBUF_SIZE);
473 l = strlen(identifier);
474 header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
476 memcpy(header, identifier, l);
478 header[l++] = '\n'; /* unit id */
479 header[l++] = '0' + priority;
481 header[l++] = '0' + !!level_prefix;
490 r = loop_write(fd, header, l, false);
492 close_nointr_nofail(fd);
496 if ((size_t) r != l) {
497 close_nointr_nofail(fd);
504 _public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
508 va_start(ap, format);
509 r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
515 _public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
516 char buffer[8 + LINE_MAX], p[11];
520 if (priority < 0 || priority > 7)
523 if (_unlikely_(!format))
526 snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
529 memcpy(buffer, "MESSAGE=", 8);
530 vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
531 char_array_0(buffer);
533 /* func is initialized from __func__ which is not a macro, but
534 * a static const char[], hence cannot easily be prefixed with
535 * CODE_FUNC=, hence let's do it manually here. */
536 ALLOCA_CODE_FUNC(f, func);
539 IOVEC_SET_STRING(iov[0], buffer);
540 IOVEC_SET_STRING(iov[1], p);
541 IOVEC_SET_STRING(iov[2], file);
542 IOVEC_SET_STRING(iov[3], line);
543 IOVEC_SET_STRING(iov[4], f);
545 return sd_journal_sendv(iov, ELEMENTSOF(iov));
548 _public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
551 struct iovec *iov = NULL;
554 va_start(ap, format);
555 i = fill_iovec_sprintf(format, ap, 3, &iov);
558 if (_unlikely_(i < 0)) {
563 ALLOCA_CODE_FUNC(f, func);
565 IOVEC_SET_STRING(iov[0], file);
566 IOVEC_SET_STRING(iov[1], line);
567 IOVEC_SET_STRING(iov[2], f);
569 r = sd_journal_sendv(iov, i);
572 for (j = 3; j < i; j++)
573 free(iov[j].iov_base);
580 _public_ int sd_journal_sendv_with_location(
581 const char *file, const char *line,
583 const struct iovec *iov, int n) {
588 if (_unlikely_(!iov))
591 if (_unlikely_(n <= 0))
594 niov = alloca(sizeof(struct iovec) * (n + 3));
595 memcpy(niov, iov, sizeof(struct iovec) * n);
597 ALLOCA_CODE_FUNC(f, func);
599 IOVEC_SET_STRING(niov[n++], file);
600 IOVEC_SET_STRING(niov[n++], line);
601 IOVEC_SET_STRING(niov[n++], f);
603 return sd_journal_sendv(niov, n);
606 _public_ int sd_journal_perror_with_location(
607 const char *file, const char *line,
609 const char *message) {
614 ALLOCA_CODE_FUNC(f, func);
616 IOVEC_SET_STRING(iov[0], file);
617 IOVEC_SET_STRING(iov[1], line);
618 IOVEC_SET_STRING(iov[2], f);
620 return fill_iovec_perror_and_send(message, 3, iov);