journal-send.c revision c004493cdefc1f43a3956ca529e8070f8d70be56
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <fcntl.h>
#include <printf.h>
#include <stddef.h>
#include <unistd.h>
#define SD_JOURNAL_SUPPRESS_LOCATION
#include "sd-journal.h"
#include "fd-util.h"
#include "io-util.h"
#include "memfd-util.h"
#include "socket-util.h"
#include "string-util.h"
#include "util.h"
#define ALLOCA_CODE_FUNC(f, func) \
do { \
char **_f = &(f); \
} while(false)
/* We open a single fd, and we'll share it with the current process,
* all its threads, and all its subprocesses. This means we need to
* initialize it atomically, and need to operate on it atomically
* never assuming we are the only user */
static int journal_fd(void) {
int fd;
static int fd_plus_one = 0;
if (fd_plus_one > 0)
return fd_plus_one - 1;
if (fd < 0)
return -errno;
safe_close(fd);
goto retry;
}
return fd;
}
int r;
return r;
}
/* FIXME: Instead of limiting things to LINE_MAX we could do a
C99 variable-length array on the stack here in a loop. */
}
_printf_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
int r, n = 0, i = 0, j;
if (extra > 0) {
if (!iov) {
r = -ENOMEM;
goto fail;
}
i = extra;
}
while (format) {
struct iovec *c;
char *buffer;
if (i >= n) {
if (!c) {
r = -ENOMEM;
goto fail;
}
iov = c;
}
r = -ENOMEM;
goto fail;
}
}
return i;
fail:
for (j = 0; j < i; j++)
return r;
}
int r, i, j;
if (_unlikely_(i < 0)) {
r = i;
goto finish;
}
r = sd_journal_sendv(iov, i);
for (j = 0; j < i; j++)
return r;
}
int fd, r;
struct iovec *w;
uint64_t *l;
int i, j = 0;
struct sockaddr_un sa = {
.sun_family = AF_UNIX,
};
};
ssize_t k;
bool have_syslog_identifier = false;
bool seal = true;
assert_return(n > 0, -EINVAL);
for (i = 0; i < n; i++) {
char *c, *nl;
return -EINVAL;
return -EINVAL;
if (nl) {
if (_unlikely_(nl < c))
return -EINVAL;
/* Already includes a newline? Bummer, then
* let's write the variable name, then a
* newline, then the size (64bit LE), followed
* by the data and a final newline */
j++;
IOVEC_SET_STRING(w[j++], "\n");
w[j].iov_base = &l[i];
j++;
w[j].iov_base = c + 1;
j++;
} else
/* Nothing special? Then just add the line and
* append a newline */
w[j++] = iov[i];
IOVEC_SET_STRING(w[j++], "\n");
}
if (!have_syslog_identifier &&
/* Implicitly add program_invocation_short_name, if it
* is not set explicitly. We only do this for
* program_invocation_short_name, and nothing else
* since everything else is much nicer to retrieve
* from the outside. */
IOVEC_SET_STRING(w[j++], "SYSLOG_IDENTIFIER=");
IOVEC_SET_STRING(w[j++], "\n");
}
fd = journal_fd();
if (_unlikely_(fd < 0))
return fd;
mh.msg_iovlen = j;
if (k >= 0)
return 0;
/* Fail silently if the journal is not available */
return 0;
return -errno;
/* Message doesn't fit... Let's dump the data in a memfd or
* temporary file and just pass a file descriptor of it to the
* other side.
*
* here, since we want this to be a tmpfs, and one that is
* available from early boot on and where unprivileged users
* can create files. */
if (buffer_fd < 0) {
if (buffer_fd < 0)
return buffer_fd;
seal = false;
} else
return buffer_fd;
}
if (n < 0)
return -errno;
if (seal) {
r = memfd_set_sealed(buffer_fd);
if (r < 0)
return r;
}
}
size_t n, k;
n = 8 + k + 256 + 1;
for (;;) {
char buffer[n];
char* j;
errno = 0;
if (errno == 0) {
if (j != buffer + 8 + k)
if (k > 0) {
}
}
return -errno;
n *= 2;
}
}
}
union sockaddr_union sa = {
};
char *header;
size_t l;
int r;
if (fd < 0)
return -errno;
if (r < 0)
return -errno;
return -errno;
if (!identifier)
identifier = "";
l = strlen(identifier);
header[l++] = '\n';
header[l++] = '\n';
header[l++] = '\n';
header[l++] = '0';
header[l++] = '\n';
header[l++] = '0';
header[l++] = '\n';
header[l++] = '0';
header[l++] = '\n';
if (r < 0)
return r;
r = fd;
fd = -1;
return r;
}
_public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
int r;
return r;
}
_public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
char *f;
/* func is initialized from __func__ which is not a macro, but
* a static const char[], hence cannot easily be prefixed with
* CODE_FUNC=, hence let's do it manually here. */
ALLOCA_CODE_FUNC(f, func);
}
_public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
int r, i, j;
char *f;
if (_unlikely_(i < 0)) {
r = i;
goto finish;
}
ALLOCA_CODE_FUNC(f, func);
r = sd_journal_sendv(iov, i);
for (j = 3; j < i; j++)
return r;
}
const char *func,
char *f;
assert_return(n > 0, -EINVAL);
ALLOCA_CODE_FUNC(f, func);
IOVEC_SET_STRING(niov[n++], f);
return sd_journal_sendv(niov, n);
}
const char *func,
const char *message) {
char *f;
ALLOCA_CODE_FUNC(f, func);
}