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