chiark / gitweb /
core: add new ConditionNeedsUpdate= unit condition
[elogind.git] / src / journal / journal-send.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <errno.h>
25 #include <stddef.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <printf.h>
29
30 #define SD_JOURNAL_SUPPRESS_LOCATION
31
32 #include "sd-journal.h"
33 #include "util.h"
34 #include "socket-util.h"
35
36 #define SNDBUF_SIZE (8*1024*1024)
37
38 #define ALLOCA_CODE_FUNC(f, func)                 \
39         do {                                      \
40                 size_t _fl;                       \
41                 const char *_func = (func);       \
42                 char **_f = &(f);                 \
43                 _fl = strlen(_func) + 1;          \
44                 *_f = alloca(_fl + 10);           \
45                 memcpy(*_f, "CODE_FUNC=", 10);    \
46                 memcpy(*_f + 10, _func, _fl);     \
47         } while(false)
48
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 */
53
54 static int journal_fd(void) {
55         int fd;
56         static int fd_plus_one = 0;
57
58 retry:
59         if (fd_plus_one > 0)
60                 return fd_plus_one - 1;
61
62         fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
63         if (fd < 0)
64                 return -errno;
65
66         fd_inc_sndbuf(fd, SNDBUF_SIZE);
67
68         if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
69                 safe_close(fd);
70                 goto retry;
71         }
72
73         return fd;
74 }
75
76 _public_ int sd_journal_print(int priority, const char *format, ...) {
77         int r;
78         va_list ap;
79
80         va_start(ap, format);
81         r = sd_journal_printv(priority, format, ap);
82         va_end(ap);
83
84         return r;
85 }
86
87 _public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
88
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. */
91
92         char buffer[8 + LINE_MAX], p[11]; struct iovec iov[2];
93
94         assert_return(priority >= 0, -EINVAL);
95         assert_return(priority <= 7, -EINVAL);
96         assert_return(format, -EINVAL);
97
98         snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
99         char_array_0(p);
100
101         memcpy(buffer, "MESSAGE=", 8);
102         vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
103         char_array_0(buffer);
104
105         zero(iov);
106         IOVEC_SET_STRING(iov[0], buffer);
107         IOVEC_SET_STRING(iov[1], p);
108
109         return sd_journal_sendv(iov, 2);
110 }
111
112 _printf_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
113         PROTECT_ERRNO;
114         int r, n = 0, i = 0, j;
115         struct iovec *iov = NULL;
116
117         assert(_iov);
118
119         if (extra > 0) {
120                 n = MAX(extra * 2, extra + 4);
121                 iov = malloc0(n * sizeof(struct iovec));
122                 if (!iov) {
123                         r = -ENOMEM;
124                         goto fail;
125                 }
126
127                 i = extra;
128         }
129
130         while (format) {
131                 struct iovec *c;
132                 char *buffer;
133                 va_list aq;
134
135                 if (i >= n) {
136                         n = MAX(i*2, 4);
137                         c = realloc(iov, n * sizeof(struct iovec));
138                         if (!c) {
139                                 r = -ENOMEM;
140                                 goto fail;
141                         }
142
143                         iov = c;
144                 }
145
146                 va_copy(aq, ap);
147                 if (vasprintf(&buffer, format, aq) < 0) {
148                         va_end(aq);
149                         r = -ENOMEM;
150                         goto fail;
151                 }
152                 va_end(aq);
153
154                 VA_FORMAT_ADVANCE(format, ap);
155
156                 IOVEC_SET_STRING(iov[i++], buffer);
157
158                 format = va_arg(ap, char *);
159         }
160
161         *_iov = iov;
162
163         return i;
164
165 fail:
166         for (j = 0; j < i; j++)
167                 free(iov[j].iov_base);
168
169         free(iov);
170
171         return r;
172 }
173
174 _public_ int sd_journal_send(const char *format, ...) {
175         int r, i, j;
176         va_list ap;
177         struct iovec *iov = NULL;
178
179         va_start(ap, format);
180         i = fill_iovec_sprintf(format, ap, 0, &iov);
181         va_end(ap);
182
183         if (_unlikely_(i < 0)) {
184                 r = i;
185                 goto finish;
186         }
187
188         r = sd_journal_sendv(iov, i);
189
190 finish:
191         for (j = 0; j < i; j++)
192                 free(iov[j].iov_base);
193
194         free(iov);
195
196         return r;
197 }
198
199 _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
200         PROTECT_ERRNO;
201         int fd, buffer_fd;
202         struct iovec *w;
203         uint64_t *l;
204         int i, j = 0;
205         struct sockaddr_un sa = {
206                 .sun_family = AF_UNIX,
207                 .sun_path = "/run/systemd/journal/socket",
208         };
209         struct msghdr mh = {
210                 .msg_name = &sa,
211                 .msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path),
212         };
213         ssize_t k;
214         union {
215                 struct cmsghdr cmsghdr;
216                 uint8_t buf[CMSG_SPACE(sizeof(int))];
217         } control;
218         struct cmsghdr *cmsg;
219         bool have_syslog_identifier = false;
220
221         assert_return(iov, -EINVAL);
222         assert_return(n > 0, -EINVAL);
223
224         w = alloca(sizeof(struct iovec) * n * 5 + 3);
225         l = alloca(sizeof(uint64_t) * n);
226
227         for (i = 0; i < n; i++) {
228                 char *c, *nl;
229
230                 if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1))
231                         return -EINVAL;
232
233                 c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
234                 if (_unlikely_(!c || c == iov[i].iov_base))
235                         return -EINVAL;
236
237                 have_syslog_identifier = have_syslog_identifier ||
238                         (c == (char *) iov[i].iov_base + 17 &&
239                          startswith(iov[i].iov_base, "SYSLOG_IDENTIFIER"));
240
241                 nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
242                 if (nl) {
243                         if (_unlikely_(nl < c))
244                                 return -EINVAL;
245
246                         /* Already includes a newline? Bummer, then
247                          * let's write the variable name, then a
248                          * newline, then the size (64bit LE), followed
249                          * by the data and a final newline */
250
251                         w[j].iov_base = iov[i].iov_base;
252                         w[j].iov_len = c - (char*) iov[i].iov_base;
253                         j++;
254
255                         IOVEC_SET_STRING(w[j++], "\n");
256
257                         l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
258                         w[j].iov_base = &l[i];
259                         w[j].iov_len = sizeof(uint64_t);
260                         j++;
261
262                         w[j].iov_base = c + 1;
263                         w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
264                         j++;
265
266                 } else
267                         /* Nothing special? Then just add the line and
268                          * append a newline */
269                         w[j++] = iov[i];
270
271                 IOVEC_SET_STRING(w[j++], "\n");
272         }
273
274         if (!have_syslog_identifier &&
275             string_is_safe(program_invocation_short_name)) {
276
277                 /* Implicitly add program_invocation_short_name, if it
278                  * is not set explicitly. We only do this for
279                  * program_invocation_short_name, and nothing else
280                  * since everything else is much nicer to retrieve
281                  * from the outside. */
282
283                 IOVEC_SET_STRING(w[j++], "SYSLOG_IDENTIFIER=");
284                 IOVEC_SET_STRING(w[j++], program_invocation_short_name);
285                 IOVEC_SET_STRING(w[j++], "\n");
286         }
287
288         fd = journal_fd();
289         if (_unlikely_(fd < 0))
290                 return fd;
291
292         mh.msg_iov = w;
293         mh.msg_iovlen = j;
294
295         k = sendmsg(fd, &mh, MSG_NOSIGNAL);
296         if (k >= 0)
297                 return 0;
298
299         /* Fail silently if the journal is not available */
300         if (errno == ENOENT)
301                 return 0;
302
303         if (errno != EMSGSIZE && errno != ENOBUFS)
304                 return -errno;
305
306         /* Message doesn't fit... Let's dump the data in a temporary
307          * file and just pass a file descriptor of it to the other
308          * side.
309          *
310          * We use /dev/shm instead of /tmp here, since we want this to
311          * be a tmpfs, and one that is available from early boot on
312          * and where unprivileged users can create files. */
313         buffer_fd = open_tmpfile("/dev/shm", O_RDWR | O_CLOEXEC);
314         if (buffer_fd < 0)
315                 return buffer_fd;
316
317         n = writev(buffer_fd, w, j);
318         if (n < 0) {
319                 safe_close(buffer_fd);
320                 return -errno;
321         }
322
323         mh.msg_iov = NULL;
324         mh.msg_iovlen = 0;
325
326         zero(control);
327         mh.msg_control = &control;
328         mh.msg_controllen = sizeof(control);
329
330         cmsg = CMSG_FIRSTHDR(&mh);
331         cmsg->cmsg_level = SOL_SOCKET;
332         cmsg->cmsg_type = SCM_RIGHTS;
333         cmsg->cmsg_len = CMSG_LEN(sizeof(int));
334         memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int));
335
336         mh.msg_controllen = cmsg->cmsg_len;
337
338         k = sendmsg(fd, &mh, MSG_NOSIGNAL);
339         safe_close(buffer_fd);
340
341         if (k < 0)
342                 return -errno;
343
344         return 0;
345 }
346
347 static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
348         PROTECT_ERRNO;
349         size_t n, k;
350
351         k = isempty(message) ? 0 : strlen(message) + 2;
352         n = 8 + k + 256 + 1;
353
354         for (;;) {
355                 char buffer[n];
356                 char* j;
357
358                 errno = 0;
359                 j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
360                 if (errno == 0) {
361                         char error[6 + 10 + 1]; /* for a 32bit value */
362
363                         if (j != buffer + 8 + k)
364                                 memmove(buffer + 8 + k, j, strlen(j)+1);
365
366                         memcpy(buffer, "MESSAGE=", 8);
367
368                         if (k > 0) {
369                                 memcpy(buffer + 8, message, k - 2);
370                                 memcpy(buffer + 8 + k - 2, ": ", 2);
371                         }
372
373                         snprintf(error, sizeof(error), "ERRNO=%u", _saved_errno_);
374                         char_array_0(error);
375
376                         IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
377                         IOVEC_SET_STRING(iov[skip+1], buffer);
378                         IOVEC_SET_STRING(iov[skip+2], error);
379
380                         return sd_journal_sendv(iov, skip + 3);
381                 }
382
383                 if (errno != ERANGE)
384                         return -errno;
385
386                 n *= 2;
387         }
388 }
389
390 _public_ int sd_journal_perror(const char *message) {
391         struct iovec iovec[3];
392
393         return fill_iovec_perror_and_send(message, 0, iovec);
394 }
395
396 _public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
397         union sockaddr_union sa = {
398                 .un.sun_family = AF_UNIX,
399                 .un.sun_path = "/run/systemd/journal/stdout",
400         };
401         int fd;
402         char *header;
403         size_t l;
404         ssize_t r;
405
406         assert_return(priority >= 0, -EINVAL);
407         assert_return(priority <= 7, -EINVAL);
408
409         fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
410         if (fd < 0)
411                 return -errno;
412
413         r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
414         if (r < 0) {
415                 safe_close(fd);
416                 return -errno;
417         }
418
419         if (shutdown(fd, SHUT_RD) < 0) {
420                 safe_close(fd);
421                 return -errno;
422         }
423
424         fd_inc_sndbuf(fd, SNDBUF_SIZE);
425
426         if (!identifier)
427                 identifier = "";
428
429         l = strlen(identifier);
430         header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
431
432         memcpy(header, identifier, l);
433         header[l++] = '\n';
434         header[l++] = '\n'; /* unit id */
435         header[l++] = '0' + priority;
436         header[l++] = '\n';
437         header[l++] = '0' + !!level_prefix;
438         header[l++] = '\n';
439         header[l++] = '0';
440         header[l++] = '\n';
441         header[l++] = '0';
442         header[l++] = '\n';
443         header[l++] = '0';
444         header[l++] = '\n';
445
446         r = loop_write(fd, header, l, false);
447         if (r < 0) {
448                 safe_close(fd);
449                 return (int) r;
450         }
451
452         if ((size_t) r != l) {
453                 safe_close(fd);
454                 return -errno;
455         }
456
457         return fd;
458 }
459
460 _public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
461         int r;
462         va_list ap;
463
464         va_start(ap, format);
465         r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
466         va_end(ap);
467
468         return r;
469 }
470
471 _public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
472         char buffer[8 + LINE_MAX], p[11];
473         struct iovec iov[5];
474         char *f;
475
476         assert_return(priority >= 0, -EINVAL);
477         assert_return(priority <= 7, -EINVAL);
478         assert_return(format, -EINVAL);
479
480         snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
481         char_array_0(p);
482
483         memcpy(buffer, "MESSAGE=", 8);
484         vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
485         char_array_0(buffer);
486
487         /* func is initialized from __func__ which is not a macro, but
488          * a static const char[], hence cannot easily be prefixed with
489          * CODE_FUNC=, hence let's do it manually here. */
490         ALLOCA_CODE_FUNC(f, func);
491
492         zero(iov);
493         IOVEC_SET_STRING(iov[0], buffer);
494         IOVEC_SET_STRING(iov[1], p);
495         IOVEC_SET_STRING(iov[2], file);
496         IOVEC_SET_STRING(iov[3], line);
497         IOVEC_SET_STRING(iov[4], f);
498
499         return sd_journal_sendv(iov, ELEMENTSOF(iov));
500 }
501
502 _public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
503         int r, i, j;
504         va_list ap;
505         struct iovec *iov = NULL;
506         char *f;
507
508         va_start(ap, format);
509         i = fill_iovec_sprintf(format, ap, 3, &iov);
510         va_end(ap);
511
512         if (_unlikely_(i < 0)) {
513                 r = i;
514                 goto finish;
515         }
516
517         ALLOCA_CODE_FUNC(f, func);
518
519         IOVEC_SET_STRING(iov[0], file);
520         IOVEC_SET_STRING(iov[1], line);
521         IOVEC_SET_STRING(iov[2], f);
522
523         r = sd_journal_sendv(iov, i);
524
525 finish:
526         for (j = 3; j < i; j++)
527                 free(iov[j].iov_base);
528
529         free(iov);
530
531         return r;
532 }
533
534 _public_ int sd_journal_sendv_with_location(
535                 const char *file, const char *line,
536                 const char *func,
537                 const struct iovec *iov, int n) {
538
539         struct iovec *niov;
540         char *f;
541
542         assert_return(iov, -EINVAL);
543         assert_return(n > 0, -EINVAL);
544
545         niov = alloca(sizeof(struct iovec) * (n + 3));
546         memcpy(niov, iov, sizeof(struct iovec) * n);
547
548         ALLOCA_CODE_FUNC(f, func);
549
550         IOVEC_SET_STRING(niov[n++], file);
551         IOVEC_SET_STRING(niov[n++], line);
552         IOVEC_SET_STRING(niov[n++], f);
553
554         return sd_journal_sendv(niov, n);
555 }
556
557 _public_ int sd_journal_perror_with_location(
558                 const char *file, const char *line,
559                 const char *func,
560                 const char *message) {
561
562         struct iovec iov[6];
563         char *f;
564
565         ALLOCA_CODE_FUNC(f, func);
566
567         IOVEC_SET_STRING(iov[0], file);
568         IOVEC_SET_STRING(iov[1], line);
569         IOVEC_SET_STRING(iov[2], f);
570
571         return fill_iovec_perror_and_send(message, 3, iov);
572 }