1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 #if HAVE_VALGRIND_VALGRIND_H
10 #include <valgrind/valgrind.h>
13 #define SD_JOURNAL_SUPPRESS_LOCATION
15 #include "sd-journal.h"
17 #include "alloc-util.h"
18 #include "errno-util.h"
22 #include "journal-send.h"
23 #include "memfd-util.h"
24 #include "socket-util.h"
25 #include "stdio-util.h"
26 #include "string-util.h"
27 #include "tmpfile-util.h"
29 #define SNDBUF_SIZE (8*1024*1024)
31 #define ALLOCA_CODE_FUNC(f, func) \
34 const char *_func = (func); \
36 _fl = strlen(_func) + 1; \
37 *_f = newa(char, _fl + 10); \
38 memcpy(*_f, "CODE_FUNC=", 10); \
39 memcpy(*_f + 10, _func, _fl); \
42 /* We open a single fd, and we'll share it with the current process,
43 * all its threads, and all its subprocesses. This means we need to
44 * initialize it atomically, and need to operate on it atomically
45 * never assuming we are the only user */
46 static int fd_plus_one
= 0;
48 static int journal_fd(void) {
53 return fd_plus_one
- 1;
55 fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
59 fd_inc_sndbuf(fd
, SNDBUF_SIZE
);
61 if (!__atomic_compare_exchange_n(&fd_plus_one
, &(int){0}, fd
+1,
62 false, __ATOMIC_SEQ_CST
, __ATOMIC_SEQ_CST
)) {
70 int journal_fd_nonblock(bool nonblock
) {
77 return fd_nonblock(r
, nonblock
);
81 void close_journal_fd(void) {
82 /* Be nice to valgrind. This is not atomic. This must be used only in tests. */
84 if (!RUNNING_ON_VALGRIND
)
87 if (getpid() != gettid())
93 safe_close(fd_plus_one
- 1);
98 _public_
int sd_journal_print(int priority
, const char *format
, ...) {
102 va_start(ap
, format
);
103 r
= sd_journal_printv(priority
, format
, ap
);
109 _public_
int sd_journal_printv(int priority
, const char *format
, va_list ap
) {
110 char p
[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int) + 1];
111 char sbuf
[LINE_MAX
+ 8] = "MESSAGE=";
117 assert_return(priority
>= 0, -EINVAL
);
118 assert_return(priority
<= 7, -EINVAL
);
119 assert_return(format
, -EINVAL
);
121 xsprintf(p
, "PRIORITY=%i", priority
& LOG_PRIMASK
);
124 len
= vsnprintf(buffer
+ 8, LINE_MAX
, format
, aq
);
127 if (len
>= (int)LONG_LINE_MAX
- 8)
130 /* Allocate large buffer to accommodate big message */
131 if (len
>= LINE_MAX
) {
132 buffer
= alloca_safe(len
+ 9);
133 memcpy(buffer
, "MESSAGE=", 8);
134 assert_se(vsnprintf(buffer
+ 8, len
+ 1, format
, ap
) == len
);
137 /* Strip trailing whitespace, keep prefix whitespace. */
138 (void) strstrip(buffer
);
140 /* Suppress empty lines */
141 if (isempty(buffer
+ 8))
144 iov
[0] = IOVEC_MAKE_STRING(buffer
);
145 iov
[1] = IOVEC_MAKE_STRING(p
);
147 return sd_journal_sendv(iov
, 2);
150 _printf_(1, 0) static int fill_iovec_sprintf(const char *format
, va_list ap
, int extra
, struct iovec
**_iov
) {
152 int r
, n
= 0, i
= 0, j
;
153 struct iovec
*iov
= NULL
;
158 n
= MAX(extra
* 2, extra
+ 4);
159 iov
= malloc0(n
* sizeof(struct iovec
));
175 c
= reallocarray(iov
, n
, sizeof(struct iovec
));
185 if (vasprintf(&buffer
, format
, aq
) < 0) {
192 VA_FORMAT_ADVANCE(format
, ap
);
194 (void) strstrip(buffer
); /* strip trailing whitespace, keep prefixing whitespace */
196 iov
[i
++] = IOVEC_MAKE_STRING(buffer
);
198 format
= va_arg(ap
, char *);
206 for (j
= 0; j
< i
; j
++)
207 free(iov
[j
].iov_base
);
214 _public_
int sd_journal_send(const char *format
, ...) {
217 struct iovec
*iov
= NULL
;
219 va_start(ap
, format
);
220 i
= fill_iovec_sprintf(format
, ap
, 0, &iov
);
223 if (_unlikely_(i
< 0)) {
228 r
= sd_journal_sendv(iov
, i
);
231 for (j
= 0; j
< i
; j
++)
232 free(iov
[j
].iov_base
);
239 _public_
int sd_journal_sendv(const struct iovec
*iov
, int n
) {
242 _cleanup_close_
int buffer_fd
= -EBADF
;
246 static const union sockaddr_union sa
= {
247 .un
.sun_family
= AF_UNIX
,
248 .un
.sun_path
= "/run/systemd/journal/socket",
251 .msg_name
= (struct sockaddr
*) &sa
.sa
,
252 .msg_namelen
= SOCKADDR_UN_LEN(sa
.un
),
255 bool have_syslog_identifier
= false;
258 assert_return(iov
, -EINVAL
);
259 assert_return(n
> 0, -EINVAL
);
261 w
= newa(struct iovec
, n
* 5 + 3);
262 l
= newa(uint64_t, n
);
264 for (i
= 0; i
< n
; i
++) {
267 if (_unlikely_(!iov
[i
].iov_base
|| iov
[i
].iov_len
<= 1))
270 c
= memchr(iov
[i
].iov_base
, '=', iov
[i
].iov_len
);
271 if (_unlikely_(!c
|| c
== iov
[i
].iov_base
))
274 have_syslog_identifier
= have_syslog_identifier
||
275 (c
== (char *) iov
[i
].iov_base
+ 17 &&
276 startswith(iov
[i
].iov_base
, "SYSLOG_IDENTIFIER"));
278 nl
= memchr(iov
[i
].iov_base
, '\n', iov
[i
].iov_len
);
280 if (_unlikely_(nl
< c
))
283 /* Already includes a newline? Bummer, then
284 * let's write the variable name, then a
285 * newline, then the size (64bit LE), followed
286 * by the data and a final newline */
288 w
[j
++] = IOVEC_MAKE(iov
[i
].iov_base
, c
- (char*) iov
[i
].iov_base
);
289 w
[j
++] = IOVEC_MAKE_STRING("\n");
291 l
[i
] = htole64(iov
[i
].iov_len
- (c
- (char*) iov
[i
].iov_base
) - 1);
292 w
[j
++] = IOVEC_MAKE(&l
[i
], sizeof(uint64_t));
294 w
[j
++] = IOVEC_MAKE(c
+ 1, iov
[i
].iov_len
- (c
- (char*) iov
[i
].iov_base
) - 1);
296 /* Nothing special? Then just add the line and
297 * append a newline */
300 w
[j
++] = IOVEC_MAKE_STRING("\n");
303 if (!have_syslog_identifier
&&
304 string_is_safe(program_invocation_short_name
)) {
306 /* Implicitly add program_invocation_short_name, if it
307 * is not set explicitly. We only do this for
308 * program_invocation_short_name, and nothing else
309 * since everything else is much nicer to retrieve
310 * from the outside. */
312 w
[j
++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=");
313 w
[j
++] = IOVEC_MAKE_STRING(program_invocation_short_name
);
314 w
[j
++] = IOVEC_MAKE_STRING("\n");
318 if (_unlikely_(fd
< 0))
324 k
= sendmsg(fd
, &mh
, MSG_NOSIGNAL
);
328 /* Fail silently if the journal is not available */
332 if (!IN_SET(errno
, EMSGSIZE
, ENOBUFS
, EAGAIN
))
335 /* Message doesn't fit... Let's dump the data in a memfd or
336 * temporary file and just pass a file descriptor of it to the
339 * For the temporary files we use /dev/shm instead of /tmp
340 * here, since we want this to be a tmpfs, and one that is
341 * available from early boot on and where unprivileged users
342 * can create files. */
343 buffer_fd
= memfd_new(NULL
);
345 if (buffer_fd
== -ENOSYS
) {
346 buffer_fd
= open_tmpfile_unlinkable("/dev/shm", O_RDWR
| O_CLOEXEC
);
355 n
= writev(buffer_fd
, w
, j
);
360 r
= memfd_set_sealed(buffer_fd
);
365 r
= send_one_fd_sa(fd
, buffer_fd
, mh
.msg_name
, mh
.msg_namelen
, 0);
367 /* Fail silently if the journal is not available */
372 static int fill_iovec_perror_and_send(const char *message
, int skip
, struct iovec iov
[]) {
376 k
= isempty(message
) ? 0 : strlen(message
) + 2;
384 j
= strerror_r(_saved_errno_
, buffer
+ 8 + k
, n
- 8 - k
);
386 char error
[STRLEN("ERRNO=") + DECIMAL_STR_MAX(int) + 1];
388 if (j
!= buffer
+ 8 + k
)
389 memmove(buffer
+ 8 + k
, j
, strlen(j
)+1);
391 memcpy(buffer
, "MESSAGE=", 8);
394 memcpy(buffer
+ 8, message
, k
- 2);
395 memcpy(buffer
+ 8 + k
- 2, ": ", 2);
398 xsprintf(error
, "ERRNO=%i", _saved_errno_
);
400 assert_cc(3 == LOG_ERR
);
401 iov
[skip
+0] = IOVEC_MAKE_STRING("PRIORITY=3");
402 iov
[skip
+1] = IOVEC_MAKE_STRING(buffer
);
403 iov
[skip
+2] = IOVEC_MAKE_STRING(error
);
405 return sd_journal_sendv(iov
, skip
+ 3);
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 _cleanup_close_
int fd
= -EBADF
;
427 assert_return(priority
>= 0, -EINVAL
);
428 assert_return(priority
<= 7, -EINVAL
);
430 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
, 0);
434 r
= connect_unix_path(fd
, AT_FDCWD
, "/run/systemd/journal/stdout");
438 if (shutdown(fd
, SHUT_RD
) < 0)
441 (void) fd_inc_sndbuf(fd
, SNDBUF_SIZE
);
443 identifier
= strempty(identifier
);
445 l
= strlen(identifier
);
446 header
= newa(char, l
+ 1 + 1 + 2 + 2 + 2 + 2 + 2);
448 memcpy(header
, identifier
, l
);
450 header
[l
++] = '\n'; /* unit id */
451 header
[l
++] = '0' + priority
;
453 header
[l
++] = '0' + !!level_prefix
;
462 r
= loop_write(fd
, header
, l
, false);
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 p
[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int) + 1];
482 char sbuf
[LINE_MAX
+ 8] = "MESSAGE=";
489 assert_return(priority
>= 0, -EINVAL
);
490 assert_return(priority
<= 7, -EINVAL
);
491 assert_return(format
, -EINVAL
);
493 xsprintf(p
, "PRIORITY=%i", priority
& LOG_PRIMASK
);
496 len
= vsnprintf(buffer
+ 8, LINE_MAX
, format
, aq
);
499 if (len
>= (int)LONG_LINE_MAX
- 8)
502 /* Allocate large buffer to accommodate big message */
503 if (len
>= LINE_MAX
) {
504 buffer
= alloca_safe(len
+ 9);
505 memcpy(buffer
, "MESSAGE=", 8);
506 assert_se(vsnprintf(buffer
+ 8, len
+ 1, format
, ap
) == len
);
509 /* Strip trailing whitespace, keep prefixing whitespace */
510 (void) strstrip(buffer
);
512 /* Suppress empty lines */
513 if (isempty(buffer
+ 8))
516 /* func is initialized from __func__ which is not a macro, but
517 * a static const char[], hence cannot easily be prefixed with
518 * CODE_FUNC=, hence let's do it manually here. */
519 ALLOCA_CODE_FUNC(f
, func
);
521 iov
[0] = IOVEC_MAKE_STRING(buffer
);
522 iov
[1] = IOVEC_MAKE_STRING(p
);
523 iov
[2] = IOVEC_MAKE_STRING(file
);
524 iov
[3] = IOVEC_MAKE_STRING(line
);
525 iov
[4] = IOVEC_MAKE_STRING(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
, ...) {
531 _cleanup_free_
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 iov
[0] = IOVEC_MAKE_STRING(file
);
548 iov
[1] = IOVEC_MAKE_STRING(line
);
549 iov
[2] = IOVEC_MAKE_STRING(f
);
551 r
= sd_journal_sendv(iov
, i
);
554 for (j
= 3; j
< i
; j
++)
555 free(iov
[j
].iov_base
);
560 _public_
int sd_journal_sendv_with_location(
561 const char *file
, const char *line
,
563 const struct iovec
*iov
, int n
) {
568 assert_return(iov
, -EINVAL
);
569 assert_return(n
> 0, -EINVAL
);
571 niov
= newa(struct iovec
, n
+ 3);
572 memcpy(niov
, iov
, sizeof(struct iovec
) * n
);
574 ALLOCA_CODE_FUNC(f
, func
);
576 niov
[n
++] = IOVEC_MAKE_STRING(file
);
577 niov
[n
++] = IOVEC_MAKE_STRING(line
);
578 niov
[n
++] = IOVEC_MAKE_STRING(f
);
580 return sd_journal_sendv(niov
, n
);
583 _public_
int sd_journal_perror_with_location(
584 const char *file
, const char *line
,
586 const char *message
) {
591 ALLOCA_CODE_FUNC(f
, func
);
593 iov
[0] = IOVEC_MAKE_STRING(file
);
594 iov
[1] = IOVEC_MAKE_STRING(line
);
595 iov
[2] = IOVEC_MAKE_STRING(f
);
597 return fill_iovec_perror_and_send(message
, 3, iov
);