journal-send.c revision 5430f7f2bc7330f3088b894166bf3524a067e3d8
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2011 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
8bdbb8d9cbe1d35708385573d70984ab4533812dLennart Poettering#include <sys/socket.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/un.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <errno.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <stddef.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <unistd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <fcntl.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#define SD_JOURNAL_SUPPRESS_LOCATION
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include "sd-journal.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "util.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "socket-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define SNDBUF_SIZE (8*1024*1024)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/* We open a single fd, and we'll share it with the current process,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * all its threads, and all its subprocesses. This means we need to
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * initialize it atomically, and need to operate on it atomically
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * never assuming we are the only user */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int journal_fd(void) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int fd;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering static int fd_plus_one = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringretry:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd_plus_one > 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fd_plus_one - 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen if (fd < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering fd_inc_sndbuf(fd, SNDBUF_SIZE);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr_nofail(fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto retry;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering_public_ int sd_journal_print(int priority, const char *format, ...) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen va_list ap;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen va_start(ap, format);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_journal_printv(priority, format, ap);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering va_end(ap);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen_public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char buffer[8 + LINE_MAX], p[11];
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen struct iovec iov[2];
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (priority < 0 || priority > 7)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -EINVAL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!format)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -EINVAL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char_array_0(p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering memcpy(buffer, "MESSAGE=", 8);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen char_array_0(buffer);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen zero(iov);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen IOVEC_SET_STRING(iov[0], buffer);
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering IOVEC_SET_STRING(iov[1], p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return sd_journal_sendv(iov, 2);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r, n = 0, i, j;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen struct iovec *iov = NULL;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering int saved_errno;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(_iov);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen saved_errno = errno;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (extra > 0) {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen n = MAX(extra * 2, extra + 4);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen iov = malloc0(n * sizeof(struct iovec));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!iov) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = -ENOMEM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen i = extra;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen } else
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering i = 0;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering while (format) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct iovec *c;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering char *buffer;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (i >= n) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering n = MAX(i*2, 4);
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering c = realloc(iov, n * sizeof(struct iovec));
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (!c) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = -ENOMEM;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering goto fail;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering iov = c;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (vasprintf(&buffer, format, ap) < 0) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = -ENOMEM;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering goto fail;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen IOVEC_SET_STRING(iov[i++], buffer);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering format = va_arg(ap, char *);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering *_iov = iov;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering errno = saved_errno;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering return i;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringfail:
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering for (j = 0; j < i; j++)
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering free(iov[j].iov_base);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering free(iov);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering errno = saved_errno;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering_public_ int sd_journal_send(const char *format, ...) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering int r, i, j;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering va_list ap;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct iovec *iov = NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering va_start(ap, format);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering i = fill_iovec_sprintf(format, ap, 0, &iov);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering va_end(ap);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (_unlikely_(i < 0)) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = i;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering goto finish;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = sd_journal_sendv(iov, i);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringfinish:
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering for (j = 0; j < i; j++)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering free(iov[j].iov_base);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering free(iov);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering_public_ int sd_journal_sendv(const struct iovec *iov, int n) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering int fd, buffer_fd;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering struct iovec *w;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering uint64_t *l;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering int r, i, j = 0;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering struct msghdr mh;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering struct sockaddr_un sa;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering ssize_t k;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering int saved_errno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering union {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering struct cmsghdr cmsghdr;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering uint8_t buf[CMSG_SPACE(sizeof(int))];
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering } control;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering struct cmsghdr *cmsg;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* We use /dev/shm instead of /tmp here, since we want this to
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * be a tmpfs, and one that is available from early boot on
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * and where unprivileged users can create files. */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering char path[] = "/dev/shm/journal.XXXXXX";
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (_unlikely_(!iov))
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return -EINVAL;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (_unlikely_(n <= 0))
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return -EINVAL;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering saved_errno = errno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering w = alloca(sizeof(struct iovec) * n * 5);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering l = alloca(sizeof(uint64_t) * n);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering for (i = 0; i < n; i++) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering char *c, *nl;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1)) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = -EINVAL;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering goto finish;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (_unlikely_(!c || c == iov[i].iov_base)) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = -EINVAL;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering goto finish;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (nl) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (_unlikely_(nl < c)) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = -EINVAL;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering goto finish;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* Already includes a newline? Bummer, then
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * let's write the variable name, then a
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * newline, then the size (64bit LE), followed
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * by the data and a final newline */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering w[j].iov_base = iov[i].iov_base;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering w[j].iov_len = c - (char*) iov[i].iov_base;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering j++;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering IOVEC_SET_STRING(w[j++], "\n");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering w[j].iov_base = &l[i];
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering w[j].iov_len = sizeof(uint64_t);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering j++;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering w[j].iov_base = c + 1;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering j++;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering } else
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* Nothing special? Then just add the line and
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * append a newline */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering w[j++] = iov[i];
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering IOVEC_SET_STRING(w[j++], "\n");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering fd = journal_fd();
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (_unlikely_(fd < 0)) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = fd;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering goto finish;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering zero(sa);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers sa.sun_family = AF_UNIX;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering strncpy(sa.sun_path, "/run/systemd/journal/socket", sizeof(sa.sun_path));
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers zero(mh);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering mh.msg_name = &sa;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mh.msg_iov = w;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mh.msg_iovlen = j;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering k = sendmsg(fd, &mh, MSG_NOSIGNAL);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (k >= 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto finish;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (errno != EMSGSIZE && errno != ENOBUFS) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto finish;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Message doesn't fit... Let's dump the data in a temporary
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * file and just pass a file descriptor of it to the other
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * side */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering buffer_fd = mkostemp(path, O_CLOEXEC|O_RDWR);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (buffer_fd < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto finish;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (unlink(path) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr_nofail(buffer_fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto finish;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering n = writev(buffer_fd, w, j);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (n < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr_nofail(buffer_fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto finish;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mh.msg_iov = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mh.msg_iovlen = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering zero(control);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mh.msg_control = &control;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mh.msg_controllen = sizeof(control);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering cmsg = CMSG_FIRSTHDR(&mh);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering cmsg->cmsg_level = SOL_SOCKET;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering cmsg->cmsg_type = SCM_RIGHTS;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int));
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering mh.msg_controllen = cmsg->cmsg_len;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering k = sendmsg(fd, &mh, MSG_NOSIGNAL);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering close_nointr_nofail(buffer_fd);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (k < 0) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = -errno;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering goto finish;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
a6c616024db23fef34152c1432892824a07799ccLennart Poetteringfinish:
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers errno = saved_errno;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return r;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers union sockaddr_union sa;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers int fd;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers char *header;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers size_t l;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers ssize_t r;
a6c616024db23fef34152c1432892824a07799ccLennart Poettering
a6c616024db23fef34152c1432892824a07799ccLennart Poettering if (priority < 0 || priority > 7)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -EINVAL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers zero(sa);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers sa.un.sun_family = AF_UNIX;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen close_nointr_nofail(fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (shutdown(fd, SHUT_RD) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr_nofail(fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers fd_inc_sndbuf(fd, SNDBUF_SIZE);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (!identifier)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering identifier = "";
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strlen(identifier);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers header = alloca(l + 1 + 2 + 2 + 2 + 2 + 2);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering memcpy(header, identifier, l);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers header[l++] = '\n';
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers header[l++] = '0' + priority;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering header[l++] = '\n';
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers header[l++] = '0' + !!level_prefix;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers header[l++] = '\n';
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering header[l++] = '0';
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers header[l++] = '\n';
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen header[l++] = '0';
27e72d6b22890ba4a8cbc05c49667cd1cccf1461Simon Peeters header[l++] = '\n';
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen header[l++] = '0';
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers header[l++] = '\n';
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = loop_write(fd, header, l, false);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr_nofail(fd);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return (int) r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if ((size_t) r != l) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr_nofail(fd);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering_public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering va_list ap;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen va_start(ap, format);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering va_end(ap);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
8c841f21f5042b11acc91cc1b039cb162cbbe8f4Djalal Harouni return r;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char buffer[8 + LINE_MAX], p[11];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct iovec iov[5];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *f;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen size_t fl;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (priority < 0 || priority > 7)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -EINVAL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (_unlikely_(!format))
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -EINVAL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char_array_0(p);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen memcpy(buffer, "MESSAGE=", 8);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char_array_0(buffer);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering /* func is initialized from __func__ which is not a macro, but
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering * a static const char[], hence cannot easily be prefixed with
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * CODE_FUNC=, hence let's do it manually here. */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers fl = strlen(func);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers f = alloca(fl + 10);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers memcpy(f, "CODE_FUNC=", 10);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers memcpy(f + 10, func, fl + 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering zero(iov);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers IOVEC_SET_STRING(iov[0], buffer);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iov[1], p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iov[2], file);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen IOVEC_SET_STRING(iov[3], line);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen IOVEC_SET_STRING(iov[4], f);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return sd_journal_sendv(iov, ELEMENTSOF(iov));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering_public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r, i, j;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering va_list ap;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct iovec *iov = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *f;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size_t fl;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen va_start(ap, format);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen i = fill_iovec_sprintf(format, ap, 3, &iov);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen va_end(ap);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (_unlikely_(i < 0)) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = i;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen goto finish;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen fl = strlen(func);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering f = alloca(fl + 10);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen memcpy(f, "CODE_FUNC=", 10);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering memcpy(f + 10, func, fl + 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iov[0], file);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iov[1], line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iov[2], f);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering r = sd_journal_sendv(iov, i);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringfinish:
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering for (j = 3; j < i; j++)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering free(iov[j].iov_base);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering free(iov);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering_public_ int sd_journal_sendv_with_location(const char *file, const char *line, const char *func, const struct iovec *iov, int n) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct iovec *niov;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering char *f;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering size_t fl;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (_unlikely_(!iov))
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering return -EINVAL;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (_unlikely_(n <= 0))
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering return -EINVAL;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering niov = alloca(sizeof(struct iovec) * (n + 3));
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering memcpy(niov, iov, sizeof(struct iovec) * n);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering fl = strlen(func);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering f = alloca(fl + 10);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering memcpy(f, "CODE_FUNC=", 10);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering memcpy(f + 10, func, fl + 1);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering IOVEC_SET_STRING(niov[n++], file);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering IOVEC_SET_STRING(niov[n++], line);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering IOVEC_SET_STRING(niov[n++], f);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering return sd_journal_sendv(niov, n);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering}
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering