]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/journal-send.c
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 General Public License as published by
10 the Free Software Foundation; either version 2 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 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/socket.h>
27 #include "sd-journal.h"
29 #include "socket-util.h"
31 /* We open a single fd, and we'll share it with the current process,
32 * all its threads, and all its subprocesses. This means we need to
33 * initialize it atomically, and need to operate on it atomically
34 * never assuming we are the only user */
36 static int journal_fd(void) {
38 static int fd_plus_one
= 0;
42 return fd_plus_one
- 1;
44 fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
48 if (!__sync_bool_compare_and_swap(&fd_plus_one
, 0, fd
+1)) {
49 close_nointr_nofail(fd
);
56 int sd_journal_print(int priority
, const char *format
, ...) {
61 r
= sd_journal_printv(priority
, format
, ap
);
67 int sd_journal_printv(int priority
, const char *format
, va_list ap
) {
68 char buffer
[8 + LINE_MAX
], p
[11];
71 if (priority
< 0 || priority
> 7)
77 snprintf(p
, sizeof(p
), "PRIORITY=%i", priority
& LOG_PRIMASK
);
80 memcpy(buffer
, "MESSAGE=", 8);
81 vsnprintf(buffer
+8, sizeof(buffer
) - 8, format
, ap
);
85 IOVEC_SET_STRING(iov
[0], buffer
);
86 IOVEC_SET_STRING(iov
[1], p
);
88 return sd_journal_sendv(iov
, 2);
91 int sd_journal_send(const char *format
, ...) {
92 int r
, n
= 0, i
= 0, j
;
94 struct iovec
*iov
= NULL
;
103 c
= realloc(iov
, n
* sizeof(struct iovec
));
112 if (vasprintf(&buffer
, format
, ap
) < 0) {
117 IOVEC_SET_STRING(iov
[i
++], buffer
);
119 format
= va_arg(ap
, char *);
123 r
= sd_journal_sendv(iov
, i
);
126 for (j
= 0; j
< i
; j
++)
127 free(iov
[j
].iov_base
);
134 int sd_journal_sendv(const struct iovec
*iov
, int n
) {
140 struct sockaddr_un sa
;
145 w
= alloca(sizeof(struct iovec
) * n
* 5);
146 l
= alloca(sizeof(uint64_t) * n
);
148 for (i
= 0; i
< n
; i
++) {
151 c
= memchr(iov
[i
].iov_base
, '=', iov
[i
].iov_len
);
155 nl
= memchr(iov
[i
].iov_base
, '\n', iov
[i
].iov_len
);
160 /* Already includes a newline? Bummer, then
161 * let's write the variable name, then a
162 * newline, then the size (64bit LE), followed
163 * by the data and a final newline */
165 w
[j
].iov_base
= iov
[i
].iov_base
;
166 w
[j
].iov_len
= c
- (char*) iov
[i
].iov_base
;
169 IOVEC_SET_STRING(w
[j
++], "\n");
171 l
[i
] = htole64(iov
[i
].iov_len
- (c
- (char*) iov
[i
].iov_base
) - 1);
172 w
[j
].iov_base
= &l
[i
];
173 w
[j
].iov_len
= sizeof(uint64_t);
176 w
[j
].iov_base
= c
+ 1;
177 w
[j
].iov_len
= iov
[i
].iov_len
- (c
- (char*) iov
[i
].iov_base
) - 1;
181 /* Nothing special? Then just add the line and
182 * append a newline */
185 IOVEC_SET_STRING(w
[j
++], "\n");
193 sa
.sun_family
= AF_UNIX
;
194 strncpy(sa
.sun_path
,"/run/systemd/journal", sizeof(sa
.sun_path
));
198 mh
.msg_namelen
= offsetof(struct sockaddr_un
, sun_path
) + strlen(sa
.sun_path
);
202 if (sendmsg(fd
, &mh
, MSG_NOSIGNAL
) < 0)
208 int sd_journal_stream_fd(const char *tag
, int priority
, int priority_prefix
) {
209 union sockaddr_union sa
;
215 if (priority
< 0 || priority
> 7)
218 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
, 0);
223 sa
.un
.sun_family
= AF_UNIX
;
224 strncpy(sa
.un
.sun_path
, "/run/systemd/stdout", sizeof(sa
.un
.sun_path
));
226 r
= connect(fd
, &sa
.sa
, offsetof(union sockaddr_union
, un
.sun_path
) + strlen(sa
.un
.sun_path
));
228 close_nointr_nofail(fd
);
236 header
= alloca(l
+ 1 + 2 + 2 + 2);
238 memcpy(header
, tag
, l
);
240 header
[l
++] = '0' + priority
;
242 header
[l
++] = '0' + !!priority_prefix
;
247 r
= loop_write(fd
, header
, l
, false);
249 close_nointr_nofail(fd
);
253 if ((size_t) r
!= l
) {
254 close_nointr_nofail(fd
);