#include <sys/un.h>
#include <errno.h>
#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
#include "sd-journal.h"
#include "util.h"
#include "socket-util.h"
+#define SNDBUF_SIZE (8*1024*1024)
+
/* 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
if (fd < 0)
return -errno;
+ fd_inc_sndbuf(fd, SNDBUF_SIZE);
+
if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
close_nointr_nofail(fd);
goto retry;
return fd;
}
-int sd_journal_print(int priority, const char *format, ...) {
+_public_ int sd_journal_print(int priority, const char *format, ...) {
int r;
va_list ap;
return r;
}
-int sd_journal_printv(int priority, const char *format, va_list ap) {
+_public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
char buffer[8 + LINE_MAX], p[11];
struct iovec iov[2];
return sd_journal_sendv(iov, 2);
}
-int sd_journal_send(const char *format, ...) {
+_public_ int sd_journal_send(const char *format, ...) {
int r, n = 0, i = 0, j;
va_list ap;
struct iovec *iov = NULL;
return r;
}
-int sd_journal_sendv(const struct iovec *iov, int n) {
- int fd;
+_public_ int sd_journal_sendv(const struct iovec *iov, int n) {
+ int fd, buffer_fd;
struct iovec *w;
uint64_t *l;
int i, j = 0;
struct msghdr mh;
struct sockaddr_un sa;
+ ssize_t k;
+ union {
+ struct cmsghdr cmsghdr;
+ uint8_t buf[CMSG_SPACE(sizeof(int))];
+ } control;
+ struct cmsghdr *cmsg;
+ /* We use /dev/shm instead of /tmp 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. */
+ char path[] = "/dev/shm/journal.XXXXXX";
if (!iov || n <= 0)
return -EINVAL;
for (i = 0; i < n; i++) {
char *c, *nl;
+ if (!iov[i].iov_base ||
+ iov[i].iov_len <= 1)
+ return -EINVAL;
+
c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
- if (!c)
+ if (!c || c == iov[i].iov_base)
return -EINVAL;
nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
zero(sa);
sa.sun_family = AF_UNIX;
- strncpy(sa.sun_path,"/run/systemd/journal", sizeof(sa.sun_path));
+ strncpy(sa.sun_path, "/run/systemd/journal/socket", sizeof(sa.sun_path));
zero(mh);
mh.msg_name = &sa;
mh.msg_iov = w;
mh.msg_iovlen = j;
- if (sendmsg(fd, &mh, MSG_NOSIGNAL) < 0)
+ k = sendmsg(fd, &mh, MSG_NOSIGNAL);
+ if (k >= 0)
+ return 0;
+
+ if (errno != EMSGSIZE && errno != ENOBUFS)
+ return -errno;
+
+ /* Message doesn't fit... Let's dump the data in a temporary
+ * file and just pass a file descriptor of it to the other
+ * side */
+
+ buffer_fd = mkostemp(path, O_CLOEXEC|O_RDWR);
+ if (buffer_fd < 0)
+ return -errno;
+
+ if (unlink(path) < 0) {
+ close_nointr_nofail(buffer_fd);
+ return -errno;
+ }
+
+ n = writev(buffer_fd, w, j);
+ if (n < 0) {
+ close_nointr_nofail(buffer_fd);
+ return -errno;
+ }
+
+ mh.msg_iov = NULL;
+ mh.msg_iovlen = 0;
+
+ zero(control);
+ mh.msg_control = &control;
+ mh.msg_controllen = sizeof(control);
+
+ cmsg = CMSG_FIRSTHDR(&mh);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int));
+
+ mh.msg_controllen = cmsg->cmsg_len;
+
+ k = sendmsg(fd, &mh, MSG_NOSIGNAL);
+ close_nointr_nofail(buffer_fd);
+
+ if (k < 0)
return -errno;
return 0;
}
-int sd_journal_stream_fd(const char *tag, int priority, int priority_prefix) {
+_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
union sockaddr_union sa;
int fd;
char *header;
zero(sa);
sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/run/systemd/stdout", sizeof(sa.un.sun_path));
+ strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
if (r < 0) {
return -errno;
}
- if (!tag)
- tag = "";
+ if (shutdown(fd, SHUT_RD) < 0) {
+ close_nointr_nofail(fd);
+ return -errno;
+ }
+
+ fd_inc_sndbuf(fd, SNDBUF_SIZE);
- l = strlen(tag);
- header = alloca(l + 1 + 2 + 2 + 2);
+ if (!identifier)
+ identifier = "";
- memcpy(header, tag, l);
+ l = strlen(identifier);
+ header = alloca(l + 1 + 2 + 2 + 2 + 2 + 2);
+
+ memcpy(header, identifier, l);
header[l++] = '\n';
header[l++] = '0' + priority;
header[l++] = '\n';
- header[l++] = '0' + !!priority_prefix;
+ header[l++] = '0' + !!level_prefix;
+ header[l++] = '\n';
+ header[l++] = '0';
+ header[l++] = '\n';
+ header[l++] = '0';
header[l++] = '\n';
header[l++] = '0';
header[l++] = '\n';