journal-send.c revision ee55db41442ad8055f5a84a339b1e0e22bc037c4
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/***
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2011 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering***/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <sys/socket.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <sys/un.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <errno.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <stddef.h>
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering#include <unistd.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <fcntl.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <printf.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define SD_JOURNAL_SUPPRESS_LOCATION
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "sd-journal.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "socket-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define SNDBUF_SIZE (8*1024*1024)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define ALLOCA_CODE_FUNC(f, func) \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering do { \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering size_t _fl; \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *_func = (func); \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char **_f = &(f); \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _fl = strlen(_func) + 1; \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *_f = alloca(_fl + 10); \
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering memcpy(*_f, "CODE_FUNC=", 10); \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering memcpy(*_f + 10, _func, _fl); \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } while(false)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/* We open a single fd, and we'll share it with the current process,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * all its threads, and all its subprocesses. This means we need to
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * initialize it atomically, and need to operate on it atomically
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * never assuming we are the only user */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int journal_fd(void) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int fd;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering static int fd_plus_one = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringretry:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (fd_plus_one > 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return fd_plus_one - 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (fd < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fd_inc_sndbuf(fd, SNDBUF_SIZE);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering close_nointr_nofail(fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto retry;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return fd;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen_public_ int sd_journal_print(int priority, const char *format, ...) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering va_list ap;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering va_start(ap, format);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_journal_printv(priority, format, ap);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering va_end(ap);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen_public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering /* FIXME: Instead of limiting things to LINE_MAX we could do a
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering C99 variable-length array on the stack here in a loop. */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering char buffer[8 + LINE_MAX], p[11]; struct iovec iov[2];
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (priority < 0 || priority > 7)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return -EINVAL;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (!format)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return -EINVAL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering char_array_0(p);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering memcpy(buffer, "MESSAGE=", 8);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering char_array_0(buffer);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering zero(iov);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering IOVEC_SET_STRING(iov[0], buffer);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering IOVEC_SET_STRING(iov[1], p);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return sd_journal_sendv(iov, 2);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering int r, n = 0, i = 0, j;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering struct iovec *iov = NULL;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering int saved_errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(_iov);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering saved_errno = errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (extra > 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering n = MAX(extra * 2, extra + 4);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering iov = malloc0(n * sizeof(struct iovec));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!iov) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering i = extra;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
c5ed93163e6ef51a7462aa558a7e0912b17c4951Lennart Poettering while (format) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct iovec *c;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering char *buffer;
cc7844e78751916acb639443c119763cafe2c684Lennart Poettering va_list aq;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (i >= n) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering n = MAX(i*2, 4);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering c = realloc(iov, n * sizeof(struct iovec));
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (!c) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen iov = c;
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen }
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering va_copy(aq, ap);
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen if (vasprintf(&buffer, format, aq) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering va_end(aq);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen }
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen va_end(aq);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering VA_FORMAT_ADVANCE(format, ap);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering IOVEC_SET_STRING(iov[i++], buffer);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen format = va_arg(ap, char *);
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen }
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *_iov = iov;
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen errno = saved_errno;
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen return i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersenfail:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (j = 0; j < i; j++)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering free(iov[j].iov_base);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering free(iov);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering errno = saved_errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen_public_ int sd_journal_send(const char *format, ...) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r, i, j;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering va_list ap;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct iovec *iov = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering va_start(ap, format);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering i = fill_iovec_sprintf(format, ap, 0, &iov);
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen va_end(ap);
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (_unlikely_(i < 0)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto finish;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering r = sd_journal_sendv(iov, i);
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poetteringfinish:
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering for (j = 0; j < i; j++)
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering free(iov[j].iov_base);
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering free(iov);
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering return r;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering}
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering_public_ int sd_journal_sendv(const struct iovec *iov, int n) {
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering int fd, buffer_fd;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering struct iovec *w;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering uint64_t *l;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering int r, i, j = 0;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering struct msghdr mh;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering struct sockaddr_un sa;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering ssize_t k;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering int saved_errno;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering union {
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering struct cmsghdr cmsghdr;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering uint8_t buf[CMSG_SPACE(sizeof(int))];
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering } control;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering struct cmsghdr *cmsg;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering /* We use /dev/shm instead of /tmp here, since we want this to
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering * be a tmpfs, and one that is available from early boot on
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering * and where unprivileged users can create files. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char path[] = "/dev/shm/journal.XXXXXX";
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bool have_syslog_identifier = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen if (_unlikely_(!iov))
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering return -EINVAL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (_unlikely_(n <= 0))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -EINVAL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering saved_errno = errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering w = alloca(sizeof(struct iovec) * n * 5 + 3);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering l = alloca(sizeof(uint64_t) * n);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = 0; i < n; i++) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char *c, *nl;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1)) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = -EINVAL;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering goto finish;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (_unlikely_(!c || c == iov[i].iov_base)) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = -EINVAL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto finish;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering have_syslog_identifier =
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering have_syslog_identifier || (c == iov[i].iov_base + 17 && memcmp(iov[i].iov_base, "SYSLOG_IDENTIFIER", 17) == 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (nl) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (_unlikely_(nl < c)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = -EINVAL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto finish;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering /* Already includes a newline? Bummer, then
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * let's write the variable name, then a
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * newline, then the size (64bit LE), followed
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * by the data and a final newline */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering w[j].iov_base = iov[i].iov_base;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering w[j].iov_len = c - (char*) iov[i].iov_base;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering j++;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering IOVEC_SET_STRING(w[j++], "\n");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering w[j].iov_base = &l[i];
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen w[j].iov_len = sizeof(uint64_t);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering j++;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering w[j].iov_base = c + 1;
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering j++;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Nothing special? Then just add the line and
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * append a newline */
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering w[j++] = iov[i];
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering IOVEC_SET_STRING(w[j++], "\n");
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering }
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (!have_syslog_identifier &&
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering string_is_safe(program_invocation_short_name)) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering /* Implicitly add program_invocation_short_name, if it
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering * is not set explicitly. We only do this for
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering * program_invocation_short_name, and nothing else
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering * since everything else is much nicer to retrieve
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering * from the outside. */
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering IOVEC_SET_STRING(w[j++], "SYSLOG_IDENTIFIER=");
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering IOVEC_SET_STRING(w[j++], program_invocation_short_name);
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering IOVEC_SET_STRING(w[j++], "\n");
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering }
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering fd = journal_fd();
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (_unlikely_(fd < 0)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = fd;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto finish;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering zero(sa);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sa.sun_family = AF_UNIX;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strncpy(sa.sun_path, "/run/systemd/journal/socket", sizeof(sa.sun_path));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering zero(mh);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_name = &sa;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_iov = w;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_iovlen = j;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering k = sendmsg(fd, &mh, MSG_NOSIGNAL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (k >= 0) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering r = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto finish;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (errno != EMSGSIZE && errno != ENOBUFS) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto finish;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Message doesn't fit... Let's dump the data in a temporary
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * file and just pass a file descriptor of it to the other
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * side */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering buffer_fd = mkostemp(path, O_CLOEXEC|O_RDWR);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (buffer_fd < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto finish;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (unlink(path) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering close_nointr_nofail(buffer_fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto finish;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering n = writev(buffer_fd, w, j);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (n < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering close_nointr_nofail(buffer_fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto finish;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_iov = NULL;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering mh.msg_iovlen = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering zero(control);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering mh.msg_control = &control;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering mh.msg_controllen = sizeof(control);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering cmsg = CMSG_FIRSTHDR(&mh);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering cmsg->cmsg_level = SOL_SOCKET;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering cmsg->cmsg_type = SCM_RIGHTS;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering cmsg->cmsg_len = CMSG_LEN(sizeof(int));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering mh.msg_controllen = cmsg->cmsg_len;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering k = sendmsg(fd, &mh, MSG_NOSIGNAL);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering close_nointr_nofail(buffer_fd);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (k < 0) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = -errno;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering goto finish;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringfinish:
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering errno = saved_errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringstatic int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering size_t n, k, r;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering int saved_errno;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering saved_errno = errno;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering k = isempty(message) ? 0 : strlen(message) + 2;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering n = 8 + k + 256 + 1;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering for (;;) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering char buffer[n];
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering char* j;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering errno = 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering j = strerror_r(saved_errno, buffer + 8 + k, n - 8 - k);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (errno == 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering char error[6 + 10 + 1]; /* for a 32bit value */
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (j != buffer + 8 + k)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering memmove(buffer + 8 + k, j, strlen(j)+1);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering memcpy(buffer, "MESSAGE=", 8);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (k > 0) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering memcpy(buffer + 8, message, k - 2);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering memcpy(buffer + 8 + k - 2, ": ", 2);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering snprintf(error, sizeof(error), "ERRNO=%u", saved_errno);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering char_array_0(error);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering IOVEC_SET_STRING(iov[skip+1], buffer);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering IOVEC_SET_STRING(iov[skip+2], error);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = sd_journal_sendv(iov, skip + 3);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
cc7844e78751916acb639443c119763cafe2c684Lennart Poettering errno = saved_errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
cc7844e78751916acb639443c119763cafe2c684Lennart Poettering if (errno != ERANGE) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering errno = saved_errno;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering n *= 2;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering_public_ int sd_journal_perror(const char *message) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering struct iovec iovec[3];
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return fill_iovec_perror_and_send(message, 0, iovec);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering union sockaddr_union sa;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering int fd;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering char *header;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering size_t l;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering ssize_t r;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (priority < 0 || priority > 7)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return -EINVAL;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (fd < 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return -errno;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering zero(sa);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering sa.un.sun_family = AF_UNIX;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r < 0) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering close_nointr_nofail(fd);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return -errno;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (shutdown(fd, SHUT_RD) < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering close_nointr_nofail(fd);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return -errno;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering fd_inc_sndbuf(fd, SNDBUF_SIZE);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (!identifier)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering identifier = "";
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering l = strlen(identifier);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering memcpy(header, identifier, l);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering header[l++] = '\n';
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering header[l++] = '\n'; /* unit id */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering header[l++] = '0' + priority;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering header[l++] = '\n';
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering header[l++] = '0' + !!level_prefix;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering header[l++] = '\n';
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering header[l++] = '0';
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering header[l++] = '\n';
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering header[l++] = '0';
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering header[l++] = '\n';
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering header[l++] = '0';
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering header[l++] = '\n';
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = loop_write(fd, header, l, false);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r < 0) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering close_nointr_nofail(fd);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return (int) r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if ((size_t) r != l) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering close_nointr_nofail(fd);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return fd;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering_public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering va_list ap;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering va_start(ap, format);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering va_end(ap);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering_public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char buffer[8 + LINE_MAX], p[11];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct iovec iov[5];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char *f;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (priority < 0 || priority > 7)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -EINVAL;
7b85d72f824cdf34554b349712b6b8e39095dbd4Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (_unlikely_(!format))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -EINVAL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char_array_0(p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering memcpy(buffer, "MESSAGE=", 8);
vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
char_array_0(buffer);
/* func is initialized from __func__ which is not a macro, but
* a static const char[], hence cannot easily be prefixed with
* CODE_FUNC=, hence let's do it manually here. */
ALLOCA_CODE_FUNC(f, func);
zero(iov);
IOVEC_SET_STRING(iov[0], buffer);
IOVEC_SET_STRING(iov[1], p);
IOVEC_SET_STRING(iov[2], file);
IOVEC_SET_STRING(iov[3], line);
IOVEC_SET_STRING(iov[4], f);
return sd_journal_sendv(iov, ELEMENTSOF(iov));
}
_public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
int r, i, j;
va_list ap;
struct iovec *iov = NULL;
char *f;
va_start(ap, format);
i = fill_iovec_sprintf(format, ap, 3, &iov);
va_end(ap);
if (_unlikely_(i < 0)) {
r = i;
goto finish;
}
ALLOCA_CODE_FUNC(f, func);
IOVEC_SET_STRING(iov[0], file);
IOVEC_SET_STRING(iov[1], line);
IOVEC_SET_STRING(iov[2], f);
r = sd_journal_sendv(iov, i);
finish:
for (j = 3; j < i; j++)
free(iov[j].iov_base);
free(iov);
return r;
}
_public_ int sd_journal_sendv_with_location(
const char *file, const char *line,
const char *func,
const struct iovec *iov, int n) {
struct iovec *niov;
char *f;
if (_unlikely_(!iov))
return -EINVAL;
if (_unlikely_(n <= 0))
return -EINVAL;
niov = alloca(sizeof(struct iovec) * (n + 3));
memcpy(niov, iov, sizeof(struct iovec) * n);
ALLOCA_CODE_FUNC(f, func);
IOVEC_SET_STRING(niov[n++], file);
IOVEC_SET_STRING(niov[n++], line);
IOVEC_SET_STRING(niov[n++], f);
return sd_journal_sendv(niov, n);
}
_public_ int sd_journal_perror_with_location(
const char *file, const char *line,
const char *func,
const char *message) {
struct iovec iov[6];
char *f;
ALLOCA_CODE_FUNC(f, func);
IOVEC_SET_STRING(iov[0], file);
IOVEC_SET_STRING(iov[1], line);
IOVEC_SET_STRING(iov[2], f);
return fill_iovec_perror_and_send(message, 3, iov);
}