journal-send.c revision 4941e4aca907f26bf74aa9efe1c70ccad1d10a82
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/***
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering This file is part of systemd.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering Copyright 2011 Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering systemd is free software; you can redistribute it and/or modify it
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering under the terms of the GNU Lesser General Public License as published by
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering (at your option) any later version.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering systemd is distributed in the hope that it will be useful, but
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering Lesser General Public License for more details.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering You should have received a copy of the GNU Lesser General Public License
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering***/
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <errno.h>
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering#include <fcntl.h>
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering#include <printf.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <stddef.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <sys/socket.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <sys/un.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <unistd.h>
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering#define SD_JOURNAL_SUPPRESS_LOCATION
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include "sd-journal.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "fd-util.h"
0d39fa9c69b97a2ceb156053deef69c0866c2b97Lennart Poettering#include "fileio.h"
c004493cdefc1f43a3956ca529e8070f8d70be56Lennart Poettering#include "io-util.h"
a09abc4ae0bdc0200324eaa0416f23ff2170ec4eLennart Poettering#include "memfd-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "socket-util.h"
15a5e95075a7f6007dd97b2a165c8ed16fe683dfLennart Poettering#include "stdio-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "string-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "util.h"
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering#define SNDBUF_SIZE (8*1024*1024)
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#define ALLOCA_CODE_FUNC(f, func) \
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering do { \
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering size_t _fl; \
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering const char *_func = (func); \
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering char **_f = &(f); \
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering _fl = strlen(_func) + 1; \
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering *_f = alloca(_fl + 10); \
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering memcpy(*_f, "CODE_FUNC=", 10); \
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering memcpy(*_f + 10, _func, _fl); \
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering } while(false)
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/* We open a single fd, and we'll share it with the current process,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * all its threads, and all its subprocesses. This means we need to
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * initialize it atomically, and need to operate on it atomically
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * never assuming we are the only user */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic int journal_fd(void) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering int fd;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering static int fd_plus_one = 0;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringretry:
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (fd_plus_one > 0)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return fd_plus_one - 1;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (fd < 0)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return -errno;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering fd_inc_sndbuf(fd, SNDBUF_SIZE);
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering safe_close(fd);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering goto retry;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return fd;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering_public_ int sd_journal_print(int priority, const char *format, ...) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering int r;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering va_list ap;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering va_start(ap, format);
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering r = sd_journal_printv(priority, format, ap);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering va_end(ap);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return r;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering_public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering /* FIXME: Instead of limiting things to LINE_MAX we could do a
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering C99 variable-length array on the stack here in a loop. */
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek char buffer[8 + LINE_MAX], p[sizeof("PRIORITY=")-1 + DECIMAL_STR_MAX(int) + 1];
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek struct iovec iov[2];
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen assert_return(priority >= 0, -EINVAL);
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen assert_return(priority <= 7, -EINVAL);
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen assert_return(format, -EINVAL);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering memcpy(buffer, "MESSAGE=", 8);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering zero(iov);
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering IOVEC_SET_STRING(iov[0], buffer);
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering IOVEC_SET_STRING(iov[1], p);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering return sd_journal_sendv(iov, 2);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
44b601bc79e46722bc0f0862ee0ce34a2284ef11Lennart Poettering_printf_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering PROTECT_ERRNO;
25d042e81516246b1ebf706a57c47ac19abb0b8aLennart Poettering int r, n = 0, i = 0, j;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering struct iovec *iov = NULL;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert(_iov);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (extra > 0) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering n = MAX(extra * 2, extra + 4);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering iov = malloc0(n * sizeof(struct iovec));
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (!iov) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering r = -ENOMEM;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering goto fail;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering }
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering i = extra;
25d042e81516246b1ebf706a57c47ac19abb0b8aLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering while (format) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering struct iovec *c;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering char *buffer;
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering va_list aq;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (i >= n) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering n = MAX(i*2, 4);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering c = realloc(iov, n * sizeof(struct iovec));
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (!c) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = -ENOMEM;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering goto fail;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering iov = c;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering va_copy(aq, ap);
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering if (vasprintf(&buffer, format, aq) < 0) {
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering va_end(aq);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = -ENOMEM;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering goto fail;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering va_end(aq);
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering VA_FORMAT_ADVANCE(format, ap);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering IOVEC_SET_STRING(iov[i++], buffer);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering format = va_arg(ap, char *);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering *_iov = iov;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return i;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poetteringfail:
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering for (j = 0; j < i; j++)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering free(iov[j].iov_base);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering free(iov);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return r;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering}
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering_public_ int sd_journal_send(const char *format, ...) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering int r, i, j;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering va_list ap;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering struct iovec *iov = NULL;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering va_start(ap, format);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering i = fill_iovec_sprintf(format, ap, 0, &iov);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering va_end(ap);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (_unlikely_(i < 0)) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering r = i;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering goto finish;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering }
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = sd_journal_sendv(iov, i);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poetteringfinish:
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering for (j = 0; j < i; j++)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering free(iov[j].iov_base);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering free(iov);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return r;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering_public_ int sd_journal_sendv(const struct iovec *iov, int n) {
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering PROTECT_ERRNO;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering int fd, r;
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek _cleanup_close_ int buffer_fd = -1;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering struct iovec *w;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering uint64_t *l;
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering int i, j = 0;
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek struct sockaddr_un sa = {
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek .sun_family = AF_UNIX,
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek .sun_path = "/run/systemd/journal/socket",
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek };
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek struct msghdr mh = {
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek .msg_name = &sa,
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek .msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path),
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek };
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering ssize_t k;
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering bool have_syslog_identifier = false;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering bool seal = true;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen assert_return(iov, -EINVAL);
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen assert_return(n > 0, -EINVAL);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
9a7800af088cc013573310504ae76e325d44d4b4Zbigniew Jędrzejewski-Szmek w = newa(struct iovec, n * 5 + 3);
9a7800af088cc013573310504ae76e325d44d4b4Zbigniew Jędrzejewski-Szmek l = newa(uint64_t, n);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering for (i = 0; i < n; i++) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering char *c, *nl;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1))
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering return -EINVAL;
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (_unlikely_(!c || c == iov[i].iov_base))
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering return -EINVAL;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
29abad107f8610e73b2fc091216040b579c75453Zbigniew Jędrzejewski-Szmek have_syslog_identifier = have_syslog_identifier ||
29abad107f8610e73b2fc091216040b579c75453Zbigniew Jędrzejewski-Szmek (c == (char *) iov[i].iov_base + 17 &&
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden startswith(iov[i].iov_base, "SYSLOG_IDENTIFIER"));
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (nl) {
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (_unlikely_(nl < c))
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering return -EINVAL;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering /* Already includes a newline? Bummer, then
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * let's write the variable name, then a
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * newline, then the size (64bit LE), followed
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * by the data and a final newline */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering w[j].iov_base = iov[i].iov_base;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering w[j].iov_len = c - (char*) iov[i].iov_base;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering j++;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering IOVEC_SET_STRING(w[j++], "\n");
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering w[j].iov_base = &l[i];
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering w[j].iov_len = sizeof(uint64_t);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering j++;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering w[j].iov_base = c + 1;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering j++;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering } else
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering /* Nothing special? Then just add the line and
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering * append a newline */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering w[j++] = iov[i];
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering IOVEC_SET_STRING(w[j++], "\n");
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering if (!have_syslog_identifier &&
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering string_is_safe(program_invocation_short_name)) {
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering /* Implicitly add program_invocation_short_name, if it
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering * is not set explicitly. We only do this for
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering * program_invocation_short_name, and nothing else
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering * since everything else is much nicer to retrieve
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering * from the outside. */
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering IOVEC_SET_STRING(w[j++], "SYSLOG_IDENTIFIER=");
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering IOVEC_SET_STRING(w[j++], program_invocation_short_name);
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering IOVEC_SET_STRING(w[j++], "\n");
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering }
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering fd = journal_fd();
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (_unlikely_(fd < 0))
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering return fd;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering mh.msg_iov = w;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering mh.msg_iovlen = j;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering k = sendmsg(fd, &mh, MSG_NOSIGNAL);
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (k >= 0)
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering return 0;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
6c045c0b4c49c88a1d3b9360c05efa5084796d2dZbigniew Jędrzejewski-Szmek /* Fail silently if the journal is not available */
6c045c0b4c49c88a1d3b9360c05efa5084796d2dZbigniew Jędrzejewski-Szmek if (errno == ENOENT)
6c045c0b4c49c88a1d3b9360c05efa5084796d2dZbigniew Jędrzejewski-Szmek return 0;
6c045c0b4c49c88a1d3b9360c05efa5084796d2dZbigniew Jędrzejewski-Szmek
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (errno != EMSGSIZE && errno != ENOBUFS)
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering return -errno;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering /* Message doesn't fit... Let's dump the data in a memfd or
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering * temporary file and just pass a file descriptor of it to the
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering * other side.
8e33886ec582336564ae11b80023abe93d7599c0Zbigniew Jędrzejewski-Szmek *
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering * For the temporary files we use /dev/shm instead of /tmp
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering * here, since we want this to be a tmpfs, and one that is
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering * available from early boot on and where unprivileged users
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering * can create files. */
73843b52585d42cc1a970a1c664818ece6942e9eLennart Poettering buffer_fd = memfd_new(NULL);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (buffer_fd < 0) {
73843b52585d42cc1a970a1c664818ece6942e9eLennart Poettering if (buffer_fd == -ENOSYS) {
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering buffer_fd = open_tmpfile("/dev/shm", O_RDWR | O_CLOEXEC);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (buffer_fd < 0)
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering return buffer_fd;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering seal = false;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering } else
73843b52585d42cc1a970a1c664818ece6942e9eLennart Poettering return buffer_fd;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering }
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
87b0284327e34a4b96c22085fa2cdb3219294991Zbigniew Jędrzejewski-Szmek n = writev(buffer_fd, w, j);
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek if (n < 0)
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering return -errno;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (seal) {
73843b52585d42cc1a970a1c664818ece6942e9eLennart Poettering r = memfd_set_sealed(buffer_fd);
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering if (r < 0)
73843b52585d42cc1a970a1c664818ece6942e9eLennart Poettering return r;
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering }
c79e98eadd3056a36a662699fa650db5b1bca0c3Lennart Poettering
4941e4aca907f26bf74aa9efe1c70ccad1d10a82Zbigniew Jędrzejewski-Szmek r = send_one_fd_sa(fd, buffer_fd, mh.msg_name, mh.msg_namelen, 0);
4941e4aca907f26bf74aa9efe1c70ccad1d10a82Zbigniew Jędrzejewski-Szmek if (r == -ENOENT)
4941e4aca907f26bf74aa9efe1c70ccad1d10a82Zbigniew Jędrzejewski-Szmek /* Fail silently if the journal is not available */
4941e4aca907f26bf74aa9efe1c70ccad1d10a82Zbigniew Jędrzejewski-Szmek return 0;
4941e4aca907f26bf74aa9efe1c70ccad1d10a82Zbigniew Jędrzejewski-Szmek return r;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poetteringstatic int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering PROTECT_ERRNO;
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering size_t n, k;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering k = isempty(message) ? 0 : strlen(message) + 2;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering n = 8 + k + 256 + 1;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering for (;;) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering char buffer[n];
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering char* j;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering errno = 0;
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (errno == 0) {
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek char error[sizeof("ERRNO=")-1 + DECIMAL_STR_MAX(int) + 1];
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (j != buffer + 8 + k)
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering memmove(buffer + 8 + k, j, strlen(j)+1);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering memcpy(buffer, "MESSAGE=", 8);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (k > 0) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering memcpy(buffer + 8, message, k - 2);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering memcpy(buffer + 8 + k - 2, ": ", 2);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering }
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek xsprintf(error, "ERRNO=%i", _saved_errno_);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering IOVEC_SET_STRING(iov[skip+1], buffer);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering IOVEC_SET_STRING(iov[skip+2], error);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering return sd_journal_sendv(iov, skip + 3);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering }
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (errno != ERANGE)
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering return -errno;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering n *= 2;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering }
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering}
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering_public_ int sd_journal_perror(const char *message) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering struct iovec iovec[3];
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering return fill_iovec_perror_and_send(message, 0, iovec);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering}
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek union sockaddr_union sa = {
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek .un.sun_family = AF_UNIX,
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek .un.sun_path = "/run/systemd/journal/stdout",
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek };
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek _cleanup_close_ int fd = -1;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering char *header;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering size_t l;
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek int r;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen assert_return(priority >= 0, -EINVAL);
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen assert_return(priority <= 7, -EINVAL);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering if (fd < 0)
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering return -errno;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek if (r < 0)
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering return -errno;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek if (shutdown(fd, SHUT_RD) < 0)
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poettering return -errno;
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poettering
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering fd_inc_sndbuf(fd, SNDBUF_SIZE);
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering if (!identifier)
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering identifier = "";
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering l = strlen(identifier);
8b38f3cc3eb73adf9536cb73d0f319e60d42ea0cLennart Poettering header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering memcpy(header, identifier, l);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering header[l++] = '\n';
a6e87e90ede66815989ba2db92a07102a69906feLennart Poettering header[l++] = '\n'; /* unit id */
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering header[l++] = '0' + priority;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering header[l++] = '\n';
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering header[l++] = '0' + !!level_prefix;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering header[l++] = '\n';
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering header[l++] = '0';
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering header[l++] = '\n';
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering header[l++] = '0';
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering header[l++] = '\n';
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering header[l++] = '0';
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering header[l++] = '\n';
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
553acb7b6b8d4f16a4747b1f978e8b7888fbfb2cZbigniew Jędrzejewski-Szmek r = loop_write(fd, header, l, false);
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek if (r < 0)
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek return r;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek r = fd;
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek fd = -1;
61c024b328d5493a334242a4d01ba923582093faZbigniew Jędrzejewski-Szmek return r;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering}
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering_public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering int r;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering va_list ap;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering va_start(ap, format);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering va_end(ap);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return r;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering}
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart 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) {
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek char buffer[8 + LINE_MAX], p[sizeof("PRIORITY=")-1 + DECIMAL_STR_MAX(int) + 1];
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering struct iovec iov[5];
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering char *f;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen assert_return(priority >= 0, -EINVAL);
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen assert_return(priority <= 7, -EINVAL);
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen assert_return(format, -EINVAL);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering memcpy(buffer, "MESSAGE=", 8);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering /* func is initialized from __func__ which is not a macro, but
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering * a static const char[], hence cannot easily be prefixed with
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering * CODE_FUNC=, hence let's do it manually here. */
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering ALLOCA_CODE_FUNC(f, func);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering zero(iov);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering IOVEC_SET_STRING(iov[0], buffer);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering IOVEC_SET_STRING(iov[1], p);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering IOVEC_SET_STRING(iov[2], file);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering IOVEC_SET_STRING(iov[3], line);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering IOVEC_SET_STRING(iov[4], f);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return sd_journal_sendv(iov, ELEMENTSOF(iov));
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering}
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering_public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering int r, i, j;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering va_list ap;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering struct iovec *iov = NULL;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering char *f;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering va_start(ap, format);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering i = fill_iovec_sprintf(format, ap, 3, &iov);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering va_end(ap);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (_unlikely_(i < 0)) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering r = i;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering goto finish;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering }
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering ALLOCA_CODE_FUNC(f, func);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering IOVEC_SET_STRING(iov[0], file);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering IOVEC_SET_STRING(iov[1], line);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering IOVEC_SET_STRING(iov[2], f);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering r = sd_journal_sendv(iov, i);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poetteringfinish:
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering for (j = 3; j < i; j++)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering free(iov[j].iov_base);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering free(iov);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return r;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering}
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering_public_ int sd_journal_sendv_with_location(
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering const char *file, const char *line,
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering const char *func,
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering const struct iovec *iov, int n) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering struct iovec *niov;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering char *f;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen assert_return(iov, -EINVAL);
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen assert_return(n > 0, -EINVAL);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering niov = alloca(sizeof(struct iovec) * (n + 3));
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering memcpy(niov, iov, sizeof(struct iovec) * n);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering ALLOCA_CODE_FUNC(f, func);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering IOVEC_SET_STRING(niov[n++], file);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering IOVEC_SET_STRING(niov[n++], line);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering IOVEC_SET_STRING(niov[n++], f);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return sd_journal_sendv(niov, n);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering}
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering_public_ int sd_journal_perror_with_location(
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering const char *file, const char *line,
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering const char *func,
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering const char *message) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering struct iovec iov[6];
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering char *f;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering ALLOCA_CODE_FUNC(f, func);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering IOVEC_SET_STRING(iov[0], file);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering IOVEC_SET_STRING(iov[1], line);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering IOVEC_SET_STRING(iov[2], f);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering return fill_iovec_perror_and_send(message, 3, iov);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering}