journal-send.c revision 0dad12c190b7493955cd60d2a1625199b1709f69
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 General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2 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 General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU 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#include "sd-journal.h"
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include "util.h"
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include "socket-util.h"
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering/* We open a single fd, and we'll share it with the current process,
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering * all its threads, and all its subprocesses. This means we need to
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * initialize it atomically, and need to operate on it atomically
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * never assuming we are the only user */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int journal_fd(void) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering static int fd_plus_one = 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenretry:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd_plus_one > 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fd_plus_one - 1;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (fd < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -errno;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering close_nointr_nofail(fd);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering goto retry;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering_public_ int sd_journal_print(int priority, const char *format, ...) {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering va_list ap;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering va_start(ap, format);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_journal_printv(priority, format, ap);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering va_end(ap);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering_public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char buffer[8 + LINE_MAX], p[11];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct iovec iov[2];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (priority < 0 || priority > 7)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (!format)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering return -EINVAL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char_array_0(p);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering memcpy(buffer, "MESSAGE=", 8);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char_array_0(buffer);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering zero(iov);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iov[0], buffer);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iov[1], p);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return sd_journal_sendv(iov, 2);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen_public_ int sd_journal_send(const char *format, ...) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int r, n = 0, i = 0, j;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen va_list ap;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen struct iovec *iov = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen va_start(ap, format);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen while (format) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct iovec *c;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *buffer;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen if (i >= n) {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen n = MAX(i*2, 4);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering c = realloc(iov, n * sizeof(struct iovec));
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!c) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = -ENOMEM;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering goto fail;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering iov = c;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (vasprintf(&buffer, format, ap) < 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = -ENOMEM;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering goto fail;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen IOVEC_SET_STRING(iov[i++], buffer);
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering format = va_arg(ap, char *);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen }
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen va_end(ap);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_journal_sendv(iov, i);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringfail:
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering for (j = 0; j < i; j++)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering free(iov[j].iov_base);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering free(iov);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering_public_ int sd_journal_sendv(const struct iovec *iov, int n) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering int fd, buffer_fd;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering struct iovec *w;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering uint64_t *l;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering int i, j = 0;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering struct msghdr mh;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering struct sockaddr_un sa;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering char path[] = "/tmp/journal.XXXXXX";
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering ssize_t k;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering union {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering struct cmsghdr cmsghdr;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering uint8_t buf[CMSG_SPACE(sizeof(int))];
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering } control;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering struct cmsghdr *cmsg;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (!iov || n <= 0)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering return -EINVAL;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering w = alloca(sizeof(struct iovec) * n * 5);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering l = alloca(sizeof(uint64_t) * n);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering for (i = 0; i < n; i++) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering char *c, *nl;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (!iov[i].iov_base ||
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering iov[i].iov_len <= 1)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -EINVAL;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (!c || c == iov[i].iov_base)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -EINVAL;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (nl) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (nl < c)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -EINVAL;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Already includes a newline? Bummer, then
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * let's write the variable name, then a
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * newline, then the size (64bit LE), followed
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * by the data and a final newline */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering w[j].iov_base = iov[i].iov_base;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering w[j].iov_len = c - (char*) iov[i].iov_base;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering j++;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering IOVEC_SET_STRING(w[j++], "\n");
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering w[j].iov_base = &l[i];
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering w[j].iov_len = sizeof(uint64_t);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering j++;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering w[j].iov_base = c + 1;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering j++;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering } else
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Nothing special? Then just add the line and
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * append a newline */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering w[j++] = iov[i];
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering IOVEC_SET_STRING(w[j++], "\n");
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering fd = journal_fd();
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (fd < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return fd;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering zero(sa);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering sa.sun_family = AF_UNIX;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering strncpy(sa.sun_path, "/run/systemd/journal/socket", sizeof(sa.sun_path));
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering zero(mh);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering mh.msg_name = &sa;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering mh.msg_iov = w;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering mh.msg_iovlen = j;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering k = sendmsg(fd, &mh, MSG_NOSIGNAL);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (k >= 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return 0;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (errno != EMSGSIZE)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -errno;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Message doesn't fit... Let's dump the data in a temporary
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering * file and just pass a file descriptor of it to the other
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * side */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering buffer_fd = mkostemp(path, O_CLOEXEC|O_RDWR);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (buffer_fd < 0)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return -errno;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (unlink(path) < 0) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering close_nointr_nofail(buffer_fd);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return -errno;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering }
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering n = writev(buffer_fd, w, j);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (n < 0) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering close_nointr_nofail(buffer_fd);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return -errno;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering mh.msg_iov = NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering mh.msg_iovlen = 0;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering zero(control);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering mh.msg_control = &control;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering mh.msg_controllen = sizeof(control);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen cmsg = CMSG_FIRSTHDR(&mh);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering cmsg->cmsg_level = SOL_SOCKET;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering cmsg->cmsg_type = SCM_RIGHTS;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen cmsg->cmsg_len = CMSG_LEN(sizeof(int));
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int));
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering mh.msg_controllen = cmsg->cmsg_len;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering k = sendmsg(fd, &mh, MSG_NOSIGNAL);
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering close_nointr_nofail(buffer_fd);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (k < 0)
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering return -errno;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering return 0;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering}
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering union sockaddr_union sa;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering int fd;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering char *header;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering size_t l;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering ssize_t r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (priority < 0 || priority > 7)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return -EINVAL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (fd < 0)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return -errno;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering zero(sa);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering sa.un.sun_family = AF_UNIX;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering close_nointr_nofail(fd);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return -errno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (shutdown(fd, SHUT_RD) < 0) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering close_nointr_nofail(fd);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return -errno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (!identifier)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering identifier = "";
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering l = strlen(identifier);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering header = alloca(l + 1 + 2 + 2 + 2 + 2 + 2);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering memcpy(header, identifier, l);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering header[l++] = '\n';
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering header[l++] = '0' + priority;
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering header[l++] = '\n';
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering header[l++] = '0' + !!level_prefix;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering header[l++] = '\n';
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering header[l++] = '0';
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering header[l++] = '\n';
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering header[l++] = '0';
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering header[l++] = '\n';
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering header[l++] = '0';
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering header[l++] = '\n';
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = loop_write(fd, header, l, false);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering close_nointr_nofail(fd);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return (int) r;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if ((size_t) r != l) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering close_nointr_nofail(fd);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return -errno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return fd;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering