journal-send.c revision 61c024b328d5493a334242a4d01ba923582093fa
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2011 Lennart 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 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 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 char **_f = &(f); \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } while(false)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/* We open a single fd, and we'll share it with the current process,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * all its threads, and all its subprocesses. This means we need to
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * initialize it atomically, and need to operate on it atomically
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * never assuming we are the only user */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int journal_fd(void) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering_public_ int sd_journal_print(int priority, const char *format, ...) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_journal_printv(priority, format, ap);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering_public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering /* FIXME: Instead of limiting things to LINE_MAX we could do a
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering C99 variable-length array on the stack here in a loop. */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering char buffer[8 + LINE_MAX], p[11]; struct iovec iov[2];
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering_printf_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering int r, n = 0, i = 0, j;
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen if (i >= n) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering c = realloc(iov, n * sizeof(struct iovec));
a2ba62c719224a4b47751623ca5e8b0333f49721Lennart Poettering if (vasprintf(&buffer, format, aq) < 0) {
a2ba62c719224a4b47751623ca5e8b0333f49721Lennart Poettering for (j = 0; j < i; j++)
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen_public_ int sd_journal_send(const char *format, ...) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering i = fill_iovec_sprintf(format, ap, 0, &iov);
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen for (j = 0; j < i; j++)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering_public_ int sd_journal_sendv(const struct iovec *iov, int n) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .sun_path = "/run/systemd/journal/socket",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering w = alloca(sizeof(struct iovec) * n * 5 + 3);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = 0; i < n; i++) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1))
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (_unlikely_(!c || c == iov[i].iov_base))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering have_syslog_identifier = have_syslog_identifier ||
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering startswith(iov[i].iov_base, "SYSLOG_IDENTIFIER"));
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering /* Already includes a newline? Bummer, then
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * let's write the variable name, then a
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * newline, then the size (64bit LE), followed
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * by the data and a final newline */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering w[j].iov_len = c - (char*) iov[i].iov_base;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen /* Nothing special? Then just add the line and
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * append a newline */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering string_is_safe(program_invocation_short_name)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Implicitly add program_invocation_short_name, if it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * is not set explicitly. We only do this for
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * program_invocation_short_name, and nothing else
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen * since everything else is much nicer to retrieve
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * from the outside. */
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering IOVEC_SET_STRING(w[j++], "SYSLOG_IDENTIFIER=");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering IOVEC_SET_STRING(w[j++], program_invocation_short_name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Fail silently if the journal is not available */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (errno != EMSGSIZE && errno != ENOBUFS)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Message doesn't fit... Let's dump the data in a temporary
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * file and just pass a file descriptor of it to the other
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * We use /dev/shm instead of /tmp here, since we want this to
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * be a tmpfs, and one that is available from early boot on
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * and where unprivileged users can create files. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering buffer_fd = open_tmpfile("/dev/shm", O_RDWR | O_CLOEXEC);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int));
size_t n, k;
char buffer[n];
errno = 0;
if (errno == 0) {
return -errno;
char *header;
size_t l;
if (fd < 0)
return -errno;
return -errno;
return -errno;
if (!identifier)
if ((size_t) r != l)
return -errno;
r = fd;
_public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
_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_array_0(p);
_public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
if (_unlikely_(i < 0)) {
goto finish;
const char *func,
const char *func,
const char *message) {