journal-send.c revision fe6521272ba203ec8f0d5a94f0729960b3f90525
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
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/socket.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/un.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <errno.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <stddef.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sd-journal.h"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include "util.h"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include "socket-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen/* We open a single fd, and we'll share it with the current process,
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * never assuming we are the only user */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int journal_fd(void) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering static int fd_plus_one = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringretry:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd_plus_one > 0)
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering return fd_plus_one - 1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
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 }
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint sd_journal_print(int priority, const char *format, ...) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering va_list ap;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering va_start(ap, format);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_journal_printv(priority, format, ap);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering va_end(ap);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenint 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;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!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
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering zero(iov);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iov[0], buffer);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iov[1], p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return sd_journal_sendv(iov, 2);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenint sd_journal_send(const char *format, ...) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int r, n = 0, i = 0, j;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering va_list ap;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen struct iovec *iov = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering va_start(ap, format);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while (format) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct iovec *c;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char *buffer;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (i >= n) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen n = MAX(i*2, 4);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen c = realloc(iov, n * sizeof(struct iovec));
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!c) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = -ENOMEM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering iov = c;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (vasprintf(&buffer, format, ap) < 0) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = -ENOMEM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen IOVEC_SET_STRING(iov[i++], buffer);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering format = va_arg(ap, char *);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering va_end(ap);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = sd_journal_sendv(iov, i);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringfail:
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering for (j = 0; j < i; j++)
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering free(iov[j].iov_base);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering free(iov);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringint sd_journal_sendv(const struct iovec *iov, int n) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering int fd;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct iovec *w;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering uint64_t *l;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering int i, j = 0;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering struct msghdr mh;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct sockaddr_un sa;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (!iov || n <= 0)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return -EINVAL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering w = alloca(sizeof(struct iovec) * n * 5);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering l = alloca(sizeof(uint64_t) * n);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering for (i = 0; i < n; i++) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char *c, *nl;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (!c)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return -EINVAL;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (nl) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (nl < c)
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering return -EINVAL;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering /* Already includes a newline? Bummer, then
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * let's write the variable name, then a
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * newline, then the size (64bit LE), followed
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * by the data and a final newline */
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering w[j].iov_base = iov[i].iov_base;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering w[j].iov_len = c - (char*) iov[i].iov_base;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering j++;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering IOVEC_SET_STRING(w[j++], "\n");
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering w[j].iov_base = &l[i];
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering w[j].iov_len = sizeof(uint64_t);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering j++;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering w[j].iov_base = c + 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering j++;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Nothing special? Then just add the line and
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * append a newline */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering w[j++] = iov[i];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen IOVEC_SET_STRING(w[j++], "\n");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = journal_fd();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering zero(sa);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sa.sun_family = AF_UNIX;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering strncpy(sa.sun_path,"/run/systemd/journal", sizeof(sa.sun_path));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering zero(mh);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mh.msg_name = &sa;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering 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 if (sendmsg(fd, &mh, MSG_NOSIGNAL) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint sd_journal_stream_fd(const char *tag, int priority, int priority_prefix) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering union sockaddr_union sa;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *header;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size_t l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ssize_t r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (priority < 0 || priority > 7)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering zero(sa);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sa.un.sun_family = AF_UNIX;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering strncpy(sa.un.sun_path, "/run/systemd/stdout", sizeof(sa.un.sun_path));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr_nofail(fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (!tag)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering tag = "";
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strlen(tag);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen header = alloca(l + 1 + 2 + 2 + 2);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen memcpy(header, tag, l);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen header[l++] = '\n';
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen header[l++] = '0' + priority;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering header[l++] = '\n';
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen header[l++] = '0' + !!priority_prefix;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering header[l++] = '\n';
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering header[l++] = '0';
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen header[l++] = '\n';
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = loop_write(fd, header, l, false);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen close_nointr_nofail(fd);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return (int) r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if ((size_t) r != l) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr_nofail(fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering