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
) {
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 /* We use /dev/shm instead of /tmp here, since we want this to
222 * be a tmpfs, and one that is available from early boot on
223 * and where unprivileged users can create files. */
224 char path
[] = "/dev/shm/journal.XXXXXX";
225 bool have_syslog_identifier
= false;
227 if (_unlikely_(!iov
))
230 if (_unlikely_(n
<= 0))
233 w
= alloca(sizeof(struct iovec
) * n
* 5 + 3);
234 l
= alloca(sizeof(uint64_t) * n
);
236 for (i
= 0; i
< n
; i
++) {
239 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
))
246 have_syslog_identifier
= have_syslog_identifier
||
247 (c
== (char *) iov
[i
].iov_base
+ 17 &&
248 hasprefix(iov
[i
].iov_base
, "SYSLOG_IDENTIFIER"));
250 nl
= memchr(iov
[i
].iov_base
, '\n', iov
[i
].iov_len
);
252 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");
283 if (!have_syslog_identifier
&&
284 string_is_safe(program_invocation_short_name
)) {
286 /* Implicitly add program_invocation_short_name, if it
287 * is not set explicitly. We only do this for
288 * program_invocation_short_name, and nothing else
289 * since everything else is much nicer to retrieve
290 * from the outside. */
292 IOVEC_SET_STRING(w
[j
++], "SYSLOG_IDENTIFIER=");
293 IOVEC_SET_STRING(w
[j
++], program_invocation_short_name
);
294 IOVEC_SET_STRING(w
[j
++], "\n");
298 if (_unlikely_(fd
< 0))
304 k
= sendmsg(fd
, &mh
, MSG_NOSIGNAL
);
308 if (errno
!= EMSGSIZE
&& errno
!= ENOBUFS
)
311 /* Message doesn't fit... Let's dump the data in a temporary
312 * file and just pass a file descriptor of it to the other
315 buffer_fd
= mkostemp(path
, O_CLOEXEC
|O_RDWR
);
319 if (unlink(path
) < 0) {
320 close_nointr_nofail(buffer_fd
);
324 n
= writev(buffer_fd
, w
, j
);
326 close_nointr_nofail(buffer_fd
);
334 mh
.msg_control
= &control
;
335 mh
.msg_controllen
= sizeof(control
);
337 cmsg
= CMSG_FIRSTHDR(&mh
);
338 cmsg
->cmsg_level
= SOL_SOCKET
;
339 cmsg
->cmsg_type
= SCM_RIGHTS
;
340 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
341 memcpy(CMSG_DATA(cmsg
), &buffer_fd
, sizeof(int));
343 mh
.msg_controllen
= cmsg
->cmsg_len
;
345 k
= sendmsg(fd
, &mh
, MSG_NOSIGNAL
);
346 close_nointr_nofail(buffer_fd
);
354 static int fill_iovec_perror_and_send(const char *message
, int skip
, struct iovec iov
[]) {
358 k
= isempty(message
) ? 0 : strlen(message
) + 2;
366 j
= strerror_r(_saved_errno_
, buffer
+ 8 + k
, n
- 8 - k
);
368 char error
[6 + 10 + 1]; /* for a 32bit value */
370 if (j
!= buffer
+ 8 + k
)
371 memmove(buffer
+ 8 + k
, j
, strlen(j
)+1);
373 memcpy(buffer
, "MESSAGE=", 8);
376 memcpy(buffer
+ 8, message
, k
- 2);
377 memcpy(buffer
+ 8 + k
- 2, ": ", 2);
380 snprintf(error
, sizeof(error
), "ERRNO=%u", _saved_errno_
);
383 IOVEC_SET_STRING(iov
[skip
+0], "PRIORITY=3");
384 IOVEC_SET_STRING(iov
[skip
+1], buffer
);
385 IOVEC_SET_STRING(iov
[skip
+2], error
);
387 return sd_journal_sendv(iov
, skip
+ 3);
397 _public_
int sd_journal_perror(const char *message
) {
398 struct iovec iovec
[3];
400 return fill_iovec_perror_and_send(message
, 0, iovec
);
403 _public_
int sd_journal_stream_fd(const char *identifier
, int priority
, int level_prefix
) {
404 union sockaddr_union sa
= {
405 .un
.sun_family
= AF_UNIX
,
406 .un
.sun_path
= "/run/systemd/journal/stdout",
413 if (priority
< 0 || priority
> 7)
416 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
, 0);
420 r
= connect(fd
, &sa
.sa
, offsetof(union sockaddr_union
, un
.sun_path
) + strlen(sa
.un
.sun_path
));
422 close_nointr_nofail(fd
);
426 if (shutdown(fd
, SHUT_RD
) < 0) {
427 close_nointr_nofail(fd
);
431 fd_inc_sndbuf(fd
, SNDBUF_SIZE
);
436 l
= strlen(identifier
);
437 header
= alloca(l
+ 1 + 1 + 2 + 2 + 2 + 2 + 2);
439 memcpy(header
, identifier
, l
);
441 header
[l
++] = '\n'; /* unit id */
442 header
[l
++] = '0' + priority
;
444 header
[l
++] = '0' + !!level_prefix
;
453 r
= loop_write(fd
, header
, l
, false);
455 close_nointr_nofail(fd
);
459 if ((size_t) r
!= l
) {
460 close_nointr_nofail(fd
);
467 _public_
int sd_journal_print_with_location(int priority
, const char *file
, const char *line
, const char *func
, const char *format
, ...) {
471 va_start(ap
, format
);
472 r
= sd_journal_printv_with_location(priority
, file
, line
, func
, format
, ap
);
478 _public_
int sd_journal_printv_with_location(int priority
, const char *file
, const char *line
, const char *func
, const char *format
, va_list ap
) {
479 char buffer
[8 + LINE_MAX
], p
[11];
483 if (priority
< 0 || priority
> 7)
486 if (_unlikely_(!format
))
489 snprintf(p
, sizeof(p
), "PRIORITY=%i", priority
& LOG_PRIMASK
);
492 memcpy(buffer
, "MESSAGE=", 8);
493 vsnprintf(buffer
+8, sizeof(buffer
) - 8, format
, ap
);
494 char_array_0(buffer
);
496 /* func is initialized from __func__ which is not a macro, but
497 * a static const char[], hence cannot easily be prefixed with
498 * CODE_FUNC=, hence let's do it manually here. */
499 ALLOCA_CODE_FUNC(f
, func
);
502 IOVEC_SET_STRING(iov
[0], buffer
);
503 IOVEC_SET_STRING(iov
[1], p
);
504 IOVEC_SET_STRING(iov
[2], file
);
505 IOVEC_SET_STRING(iov
[3], line
);
506 IOVEC_SET_STRING(iov
[4], f
);
508 return sd_journal_sendv(iov
, ELEMENTSOF(iov
));
511 _public_
int sd_journal_send_with_location(const char *file
, const char *line
, const char *func
, const char *format
, ...) {
514 struct iovec
*iov
= NULL
;
517 va_start(ap
, format
);
518 i
= fill_iovec_sprintf(format
, ap
, 3, &iov
);
521 if (_unlikely_(i
< 0)) {
526 ALLOCA_CODE_FUNC(f
, func
);
528 IOVEC_SET_STRING(iov
[0], file
);
529 IOVEC_SET_STRING(iov
[1], line
);
530 IOVEC_SET_STRING(iov
[2], f
);
532 r
= sd_journal_sendv(iov
, i
);
535 for (j
= 3; j
< i
; j
++)
536 free(iov
[j
].iov_base
);
543 _public_
int sd_journal_sendv_with_location(
544 const char *file
, const char *line
,
546 const struct iovec
*iov
, int n
) {
551 if (_unlikely_(!iov
))
554 if (_unlikely_(n
<= 0))
557 niov
= alloca(sizeof(struct iovec
) * (n
+ 3));
558 memcpy(niov
, iov
, sizeof(struct iovec
) * n
);
560 ALLOCA_CODE_FUNC(f
, func
);
562 IOVEC_SET_STRING(niov
[n
++], file
);
563 IOVEC_SET_STRING(niov
[n
++], line
);
564 IOVEC_SET_STRING(niov
[n
++], f
);
566 return sd_journal_sendv(niov
, n
);
569 _public_
int sd_journal_perror_with_location(
570 const char *file
, const char *line
,
572 const char *message
) {
577 ALLOCA_CODE_FUNC(f
, func
);
579 IOVEC_SET_STRING(iov
[0], file
);
580 IOVEC_SET_STRING(iov
[1], line
);
581 IOVEC_SET_STRING(iov
[2], f
);
583 return fill_iovec_perror_and_send(message
, 3, iov
);