chiark / gitweb /
journal-send: always send SYSLOG_IDENTIFIER, if we have it
[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                 close_nointr_nofail(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         if (priority < 0 || priority > 7)
95                 return -EINVAL;
96
97         if (!format)
98                 return -EINVAL;
99
100         snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
101         char_array_0(p);
102
103         memcpy(buffer, "MESSAGE=", 8);
104         vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
105         char_array_0(buffer);
106
107         zero(iov);
108         IOVEC_SET_STRING(iov[0], buffer);
109         IOVEC_SET_STRING(iov[1], p);
110
111         return sd_journal_sendv(iov, 2);
112 }
113
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;
117         int saved_errno;
118
119         assert(_iov);
120         saved_errno = errno;
121
122         if (extra > 0) {
123                 n = MAX(extra * 2, extra + 4);
124                 iov = malloc0(n * sizeof(struct iovec));
125                 if (!iov) {
126                         r = -ENOMEM;
127                         goto fail;
128                 }
129
130                 i = extra;
131         }
132
133         while (format) {
134                 struct iovec *c;
135                 char *buffer;
136                 va_list aq;
137
138                 if (i >= n) {
139                         n = MAX(i*2, 4);
140                         c = realloc(iov, n * sizeof(struct iovec));
141                         if (!c) {
142                                 r = -ENOMEM;
143                                 goto fail;
144                         }
145
146                         iov = c;
147                 }
148
149                 va_copy(aq, ap);
150                 if (vasprintf(&buffer, format, aq) < 0) {
151                         va_end(aq);
152                         r = -ENOMEM;
153                         goto fail;
154                 }
155                 va_end(aq);
156
157                 VA_FORMAT_ADVANCE(format, ap);
158
159                 IOVEC_SET_STRING(iov[i++], buffer);
160
161                 format = va_arg(ap, char *);
162         }
163
164         *_iov = iov;
165
166         errno = saved_errno;
167         return i;
168
169 fail:
170         for (j = 0; j < i; j++)
171                 free(iov[j].iov_base);
172
173         free(iov);
174
175         errno = saved_errno;
176         return r;
177 }
178
179 _public_ int sd_journal_send(const char *format, ...) {
180         int r, i, j;
181         va_list ap;
182         struct iovec *iov = NULL;
183
184         va_start(ap, format);
185         i = fill_iovec_sprintf(format, ap, 0, &iov);
186         va_end(ap);
187
188         if (_unlikely_(i < 0)) {
189                 r = i;
190                 goto finish;
191         }
192
193         r = sd_journal_sendv(iov, i);
194
195 finish:
196         for (j = 0; j < i; j++)
197                 free(iov[j].iov_base);
198
199         free(iov);
200
201         return r;
202 }
203
204 _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
205         int fd, buffer_fd;
206         struct iovec *w;
207         uint64_t *l;
208         int r, i, j = 0;
209         struct msghdr mh;
210         struct sockaddr_un sa;
211         ssize_t k;
212         int saved_errno;
213         union {
214                 struct cmsghdr cmsghdr;
215                 uint8_t buf[CMSG_SPACE(sizeof(int))];
216         } control;
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;
223
224         if (_unlikely_(!iov))
225                 return -EINVAL;
226
227         if (_unlikely_(n <= 0))
228                 return -EINVAL;
229
230         saved_errno = errno;
231
232         w = alloca(sizeof(struct iovec) * n * 5 + 3);
233         l = alloca(sizeof(uint64_t) * n);
234
235         for (i = 0; i < n; i++) {
236                 char *c, *nl;
237
238                 if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1)) {
239                         r = -EINVAL;
240                         goto finish;
241                 }
242
243                 c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
244                 if (_unlikely_(!c || c == iov[i].iov_base)) {
245                         r = -EINVAL;
246                         goto finish;
247                 }
248
249                 have_syslog_identifier =
250                         have_syslog_identifier || (c == iov[i].iov_base + 17 && memcmp(iov[i].iov_base, "SYSLOG_IDENTIFIER", 17) == 0);
251
252                 nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
253                 if (nl) {
254                         if (_unlikely_(nl < c)) {
255                                 r = -EINVAL;
256                                 goto finish;
257                         }
258
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 */
263
264                         w[j].iov_base = iov[i].iov_base;
265                         w[j].iov_len = c - (char*) iov[i].iov_base;
266                         j++;
267
268                         IOVEC_SET_STRING(w[j++], "\n");
269
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);
273                         j++;
274
275                         w[j].iov_base = c + 1;
276                         w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
277                         j++;
278
279                 } else
280                         /* Nothing special? Then just add the line and
281                          * append a newline */
282                         w[j++] = iov[i];
283
284                 IOVEC_SET_STRING(w[j++], "\n");
285         }
286
287         if (!have_syslog_identifier &&
288             string_is_safe(program_invocation_short_name)) {
289
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. */
295
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");
299         }
300
301         fd = journal_fd();
302         if (_unlikely_(fd < 0)) {
303                 r = fd;
304                 goto finish;
305         }
306
307         zero(sa);
308         sa.sun_family = AF_UNIX;
309         strncpy(sa.sun_path, "/run/systemd/journal/socket", sizeof(sa.sun_path));
310
311         zero(mh);
312         mh.msg_name = &sa;
313         mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
314         mh.msg_iov = w;
315         mh.msg_iovlen = j;
316
317         k = sendmsg(fd, &mh, MSG_NOSIGNAL);
318         if (k >= 0) {
319                 r = 0;
320                 goto finish;
321         }
322
323         if (errno != EMSGSIZE && errno != ENOBUFS) {
324                 r = -errno;
325                 goto finish;
326         }
327
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
330          * side */
331
332         buffer_fd = mkostemp(path, O_CLOEXEC|O_RDWR);
333         if (buffer_fd < 0) {
334                 r = -errno;
335                 goto finish;
336         }
337
338         if (unlink(path) < 0) {
339                 close_nointr_nofail(buffer_fd);
340                 r = -errno;
341                 goto finish;
342         }
343
344         n = writev(buffer_fd, w, j);
345         if (n < 0) {
346                 close_nointr_nofail(buffer_fd);
347                 r = -errno;
348                 goto finish;
349         }
350
351         mh.msg_iov = NULL;
352         mh.msg_iovlen = 0;
353
354         zero(control);
355         mh.msg_control = &control;
356         mh.msg_controllen = sizeof(control);
357
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));
363
364         mh.msg_controllen = cmsg->cmsg_len;
365
366         k = sendmsg(fd, &mh, MSG_NOSIGNAL);
367         close_nointr_nofail(buffer_fd);
368
369         if (k < 0) {
370                 r = -errno;
371                 goto finish;
372         }
373
374         r = 0;
375
376 finish:
377         errno = saved_errno;
378
379         return r;
380 }
381
382 static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
383         size_t n, k, r;
384         int saved_errno;
385
386         saved_errno = errno;
387
388         k = isempty(message) ? 0 : strlen(message) + 2;
389         n = 8 + k + 256 + 1;
390
391         for (;;) {
392                 char buffer[n];
393                 char* j;
394
395                 errno = 0;
396                 j = strerror_r(saved_errno, buffer + 8 + k, n - 8 - k);
397                 if (errno == 0) {
398                         char error[6 + 10 + 1]; /* for a 32bit value */
399
400                         if (j != buffer + 8 + k)
401                                 memmove(buffer + 8 + k, j, strlen(j)+1);
402
403                         memcpy(buffer, "MESSAGE=", 8);
404
405                         if (k > 0) {
406                                 memcpy(buffer + 8, message, k - 2);
407                                 memcpy(buffer + 8 + k - 2, ": ", 2);
408                         }
409
410                         snprintf(error, sizeof(error), "ERRNO=%u", saved_errno);
411                         char_array_0(error);
412
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);
416
417                         r = sd_journal_sendv(iov, skip + 3);
418
419                         errno = saved_errno;
420                         return r;
421                 }
422
423                 if (errno != ERANGE) {
424                         r = -errno;
425                         errno = saved_errno;
426                         return r;
427                 }
428
429                 n *= 2;
430         }
431 }
432
433 _public_ int sd_journal_perror(const char *message) {
434         struct iovec iovec[3];
435
436         return fill_iovec_perror_and_send(message, 0, iovec);
437 }
438
439 _public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
440         union sockaddr_union sa;
441         int fd;
442         char *header;
443         size_t l;
444         ssize_t r;
445
446         if (priority < 0 || priority > 7)
447                 return -EINVAL;
448
449         fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
450         if (fd < 0)
451                 return -errno;
452
453         zero(sa);
454         sa.un.sun_family = AF_UNIX;
455         strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
456
457         r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
458         if (r < 0) {
459                 close_nointr_nofail(fd);
460                 return -errno;
461         }
462
463         if (shutdown(fd, SHUT_RD) < 0) {
464                 close_nointr_nofail(fd);
465                 return -errno;
466         }
467
468         fd_inc_sndbuf(fd, SNDBUF_SIZE);
469
470         if (!identifier)
471                 identifier = "";
472
473         l = strlen(identifier);
474         header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
475
476         memcpy(header, identifier, l);
477         header[l++] = '\n';
478         header[l++] = '\n'; /* unit id */
479         header[l++] = '0' + priority;
480         header[l++] = '\n';
481         header[l++] = '0' + !!level_prefix;
482         header[l++] = '\n';
483         header[l++] = '0';
484         header[l++] = '\n';
485         header[l++] = '0';
486         header[l++] = '\n';
487         header[l++] = '0';
488         header[l++] = '\n';
489
490         r = loop_write(fd, header, l, false);
491         if (r < 0) {
492                 close_nointr_nofail(fd);
493                 return (int) r;
494         }
495
496         if ((size_t) r != l) {
497                 close_nointr_nofail(fd);
498                 return -errno;
499         }
500
501         return fd;
502 }
503
504 _public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
505         int r;
506         va_list ap;
507
508         va_start(ap, format);
509         r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
510         va_end(ap);
511
512         return r;
513 }
514
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];
517         struct iovec iov[5];
518         char *f;
519
520         if (priority < 0 || priority > 7)
521                 return -EINVAL;
522
523         if (_unlikely_(!format))
524                 return -EINVAL;
525
526         snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
527         char_array_0(p);
528
529         memcpy(buffer, "MESSAGE=", 8);
530         vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
531         char_array_0(buffer);
532
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);
537
538         zero(iov);
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);
544
545         return sd_journal_sendv(iov, ELEMENTSOF(iov));
546 }
547
548 _public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
549         int r, i, j;
550         va_list ap;
551         struct iovec *iov = NULL;
552         char *f;
553
554         va_start(ap, format);
555         i = fill_iovec_sprintf(format, ap, 3, &iov);
556         va_end(ap);
557
558         if (_unlikely_(i < 0)) {
559                 r = i;
560                 goto finish;
561         }
562
563         ALLOCA_CODE_FUNC(f, func);
564
565         IOVEC_SET_STRING(iov[0], file);
566         IOVEC_SET_STRING(iov[1], line);
567         IOVEC_SET_STRING(iov[2], f);
568
569         r = sd_journal_sendv(iov, i);
570
571 finish:
572         for (j = 3; j < i; j++)
573                 free(iov[j].iov_base);
574
575         free(iov);
576
577         return r;
578 }
579
580 _public_ int sd_journal_sendv_with_location(
581                 const char *file, const char *line,
582                 const char *func,
583                 const struct iovec *iov, int n) {
584
585         struct iovec *niov;
586         char *f;
587
588         if (_unlikely_(!iov))
589                 return -EINVAL;
590
591         if (_unlikely_(n <= 0))
592                 return -EINVAL;
593
594         niov = alloca(sizeof(struct iovec) * (n + 3));
595         memcpy(niov, iov, sizeof(struct iovec) * n);
596
597         ALLOCA_CODE_FUNC(f, func);
598
599         IOVEC_SET_STRING(niov[n++], file);
600         IOVEC_SET_STRING(niov[n++], line);
601         IOVEC_SET_STRING(niov[n++], f);
602
603         return sd_journal_sendv(niov, n);
604 }
605
606 _public_ int sd_journal_perror_with_location(
607                 const char *file, const char *line,
608                 const char *func,
609                 const char *message) {
610
611         struct iovec iov[6];
612         char *f;
613
614         ALLOCA_CODE_FUNC(f, func);
615
616         IOVEC_SET_STRING(iov[0], file);
617         IOVEC_SET_STRING(iov[1], line);
618         IOVEC_SET_STRING(iov[2], f);
619
620         return fill_iovec_perror_and_send(message, 3, iov);
621 }