[systemd-commits] 7 commits - .gitignore Makefile.am configure.ac src/.gitignore src/ask-password-api.c src/job.c src/journal src/log.c src/systemctl.c src/systemd src/util.c src/util.h sysctl.d/.gitignore sysctl.d/Makefile sysctl.d/coredump.conf.in
Lennart Poettering
lennart at kemper.freedesktop.org
Fri Jan 13 16:54:50 PST 2012
.gitignore | 2
Makefile.am | 35 ++++++++
configure.ac | 8 +
src/.gitignore | 1
src/ask-password-api.c | 4
src/job.c | 8 -
src/journal/cat.c | 181 +++++++++++++++++++++++++++++++++++++++++++++
src/journal/coredump.c | 173 +++++++++++++++++++++++++++++++++++++++++++
src/journal/journal-send.c | 57 +++++++++++++-
src/journal/journald.c | 112 +++++++++++++++++++++++----
src/log.c | 2
src/systemctl.c | 32 +++----
src/systemd/sd-messages.h | 2
src/util.c | 24 +++--
src/util.h | 4
sysctl.d/.gitignore | 1
sysctl.d/Makefile | 1
sysctl.d/coredump.conf.in | 10 ++
18 files changed, 603 insertions(+), 54 deletions(-)
New commits:
commit 4c7de07481080d19c7c22a8437184c515ebaeafb
Author: Lennart Poettering <lennart at poettering.net>
Date: Sat Jan 14 01:54:02 2012 +0100
journal: handle empty syslog identifier properly
diff --git a/src/journal/journald.c b/src/journal/journald.c
index 39263bf..f63a12f 100644
--- a/src/journal/journald.c
+++ b/src/journal/journald.c
@@ -1405,10 +1405,14 @@ static int stdout_stream_line(StdoutStream *s, char *p) {
switch (s->state) {
case STDOUT_STREAM_IDENTIFIER:
- s->identifier = strdup(p);
- if (!s->identifier) {
- log_error("Out of memory");
- return -ENOMEM;
+ if (isempty(p))
+ s->identifier = NULL;
+ else {
+ s->identifier = strdup(p);
+ if (!s->identifier) {
+ log_error("Out of memory");
+ return -ENOMEM;
+ }
}
s->state = STDOUT_STREAM_PRIORITY;
commit 5c3759bf8a3d418fa877e6a278f3150f404745b2
Author: Lennart Poettering <lennart at poettering.net>
Date: Sat Jan 14 01:53:47 2012 +0100
journal: fix bad memory access
diff --git a/src/journal/journald.c b/src/journal/journald.c
index 53dbf8e..39263bf 100644
--- a/src/journal/journald.c
+++ b/src/journal/journald.c
@@ -489,7 +489,7 @@ static void dispatch_message_real(Server *s,
exe = strappend("_EXE=", t);
free(t);
- if (comm)
+ if (exe)
IOVEC_SET_STRING(iovec[n++], exe);
}
commit 0dad12c190b7493955cd60d2a1625199b1709f69
Author: Lennart Poettering <lennart at poettering.net>
Date: Sat Jan 14 01:53:20 2012 +0100
journal: if the data to be sent is larger than the maximum datagram size resort to passing a temporary fd over native protocol
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index d51aec9..03bd170 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -23,6 +23,8 @@
#include <sys/un.h>
#include <errno.h>
#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
#include "sd-journal.h"
#include "util.h"
@@ -132,12 +134,19 @@ fail:
}
_public_ int sd_journal_sendv(const struct iovec *iov, int n) {
- int fd;
+ int fd, buffer_fd;
struct iovec *w;
uint64_t *l;
int i, j = 0;
struct msghdr mh;
struct sockaddr_un sa;
+ char path[] = "/tmp/journal.XXXXXX";
+ ssize_t k;
+ union {
+ struct cmsghdr cmsghdr;
+ uint8_t buf[CMSG_SPACE(sizeof(int))];
+ } control;
+ struct cmsghdr *cmsg;
if (!iov || n <= 0)
return -EINVAL;
@@ -203,7 +212,51 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
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)
+ 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;
diff --git a/src/journal/journald.c b/src/journal/journald.c
index f924c93..53dbf8e 100644
--- a/src/journal/journald.c
+++ b/src/journal/journald.c
@@ -70,6 +70,8 @@
#define N_IOVEC_META_FIELDS 17
+#define ENTRY_SIZE_MAX (1024*1024*32)
+
typedef enum StdoutStreamState {
STDOUT_STREAM_IDENTIFIER,
STDOUT_STREAM_PRIORITY,
@@ -1291,6 +1293,52 @@ finish:
free(message);
}
+static void process_native_file(Server *s, int fd, struct ucred *ucred, struct timeval *tv) {
+ struct stat st;
+ void *p;
+ ssize_t n;
+
+ assert(s);
+ assert(fd >= 0);
+
+ /* Data is in the passed file, since it didn't fit in a
+ * datagram. We can't map the file here, since clients might
+ * then truncate it and trigger a SIGBUS for us. So let's
+ * stupidly read it */
+
+ if (fstat(fd, &st) < 0) {
+ log_error("Failed to stat passed file, ignoring: %m");
+ return;
+ }
+
+ if (!S_ISREG(st.st_mode)) {
+ log_error("File passed is not regular. Ignoring.");
+ return;
+ }
+
+ if (st.st_size <= 0)
+ return;
+
+ if (st.st_size > ENTRY_SIZE_MAX) {
+ log_error("File passed too large. Ignoring.");
+ return;
+ }
+
+ p = malloc(st.st_size);
+ if (!p) {
+ log_error("Out of memory");
+ return;
+ }
+
+ n = pread(fd, p, st.st_size, 0);
+ if (n < 0)
+ log_error("Failed to read file, ignoring: %s", strerror(-n));
+ else if (n > 0)
+ process_native_message(s, p, n, ucred, tv);
+
+ free(p);
+}
+
static int stdout_stream_log(StdoutStream *s, const char *p) {
struct iovec iovec[N_IOVEC_META_FIELDS + 5];
char *message = NULL, *syslog_priority = NULL, *syslog_facility = NULL, *syslog_identifier = NULL;
@@ -1300,6 +1348,9 @@ static int stdout_stream_log(StdoutStream *s, const char *p) {
assert(s);
assert(p);
+ if (isempty(p))
+ return 0;
+
priority = s->priority;
if (s->level_prefix)
@@ -1649,6 +1700,9 @@ static void proc_kmsg_line(Server *s, const char *p) {
assert(s);
assert(p);
+ if (isempty(p))
+ return;
+
parse_syslog_priority((char **) &p, &priority);
if (s->forward_to_kmsg && (priority & LOG_FACMASK) != LOG_KERN)
@@ -1697,7 +1751,6 @@ static void proc_kmsg_line(Server *s, const char *p) {
if (message)
IOVEC_SET_STRING(iovec[n++], message);
-
dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, priority);
free(message);
@@ -2027,19 +2080,19 @@ static int process_event(Server *s, struct epoll_event *ev) {
union {
struct cmsghdr cmsghdr;
uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
- CMSG_SPACE(sizeof(struct timeval))];
+ CMSG_SPACE(sizeof(struct timeval)) +
+ CMSG_SPACE(sizeof(int))];
} control;
ssize_t n;
int v;
+ int *fds = NULL;
+ unsigned n_fds = 0;
if (ioctl(ev->data.fd, SIOCINQ, &v) < 0) {
log_error("SIOCINQ failed: %m");
return -errno;
}
- if (v <= 0)
- return 1;
-
if (s->buffer_size < (size_t) v) {
void *b;
size_t l;
@@ -2067,7 +2120,7 @@ static int process_event(Server *s, struct epoll_event *ev) {
msghdr.msg_control = &control;
msghdr.msg_controllen = sizeof(control);
- n = recvmsg(ev->data.fd, &msghdr, MSG_DONTWAIT);
+ n = recvmsg(ev->data.fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (n < 0) {
if (errno == EINTR || errno == EAGAIN)
@@ -2087,20 +2140,37 @@ static int process_event(Server *s, struct epoll_event *ev) {
cmsg->cmsg_type == SO_TIMESTAMP &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
tv = (struct timeval*) CMSG_DATA(cmsg);
+ else if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_RIGHTS) {
+ fds = (int*) CMSG_DATA(cmsg);
+ n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+ }
}
if (ev->data.fd == s->syslog_fd) {
char *e;
- e = memchr(s->buffer, '\n', n);
- if (e)
- *e = 0;
- else
- s->buffer[n] = 0;
+ if (n > 0 && n_fds == 0) {
+ e = memchr(s->buffer, '\n', n);
+ if (e)
+ *e = 0;
+ else
+ s->buffer[n] = 0;
+
+ process_syslog_message(s, strstrip(s->buffer), ucred, tv);
+ } else if (n_fds > 0)
+ log_warning("Got file descriptors via syslog socket. Ignoring.");
+
+ } else {
+ if (n > 0 && n_fds == 0)
+ process_native_message(s, s->buffer, n, ucred, tv);
+ else if (n == 0 && n_fds == 1)
+ process_native_file(s, fds[0], ucred, tv);
+ else if (n_fds > 0)
+ log_warning("Got too many file descriptors via native socket. Ignoring.");
+ }
- process_syslog_message(s, strstrip(s->buffer), ucred, tv);
- } else
- process_native_message(s, s->buffer, n, ucred, tv);
+ close_many(fds, n_fds);
}
return 1;
commit f5e04665ebf7124f3ea17dcf258793ed73a95fe1
Author: Lennart Poettering <lennart at poettering.net>
Date: Sat Jan 14 00:37:35 2012 +0100
journal: hook up coredumping with journal
diff --git a/.gitignore b/.gitignore
index c260210..011aece 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/systemd-coredump
/systemd-cat
/systemd-rc-local-generator
/libsystemd-id128.pc
diff --git a/Makefile.am b/Makefile.am
index d94de56..607ae7e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -52,6 +52,7 @@ bashcompletiondir=$(sysconfdir)/bash_completion.d
pkgsysconfdir=$(sysconfdir)/systemd
userunitdir=$(prefix)/lib/systemd/user
tmpfilesdir=$(prefix)/lib/tmpfiles.d
+sysctldir=$(prefix)/lib/sysctl.d
usergeneratordir=$(pkglibexecdir)/user-generators
pkgincludedir=$(includedir)/systemd
@@ -1397,6 +1398,27 @@ EXTRA_DIST += \
CLEANFILES += \
src/journal/journald-gperf.c
+if ENABLE_COREDUMP
+
+systemd_coredump_SOURCES = \
+ src/journal/coredump.c
+
+systemd_coredump_LDADD = \
+ libsystemd-basic.la \
+ libsystemd-journal.la \
+ libsystemd-login.la
+
+rootlibexec_PROGRAMS += \
+ systemd-coredump
+
+sysctl_DATA = \
+ sysctl.d/coredump.conf
+
+EXTRA_DIST += \
+ sysctl.d/coredump.conf.in
+
+endif
+
# ------------------------------------------------------------------------------
if ENABLE_BINFMT
systemd_binfmt_SOURCES = \
@@ -2074,6 +2096,9 @@ units/%: units/%.in Makefile
man/%: man/%.in Makefile
$(SED_PROCESS)
+sysctl.d/%: sysctl.d/%.in Makefile
+ $(SED_PROCESS)
+
%.pc: %.pc.in Makefile
$(SED_PROCESS)
diff --git a/configure.ac b/configure.ac
index 80d0156..194caa5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -372,6 +372,13 @@ if test "x$enable_localed" != "xno"; then
fi
AM_CONDITIONAL(ENABLE_LOCALED, [test "$have_localed" = "yes"])
+have_coredump=no
+AC_ARG_ENABLE(coredump, AS_HELP_STRING([--disable-coredump], [disable coredump hook]))
+if test "x$enable_coredump" != "xno"; then
+ have_coredump=yes
+fi
+AM_CONDITIONAL(ENABLE_COREDUMP, [test "$have_coredump" = "yes"])
+
have_gtk=no
AC_ARG_ENABLE(gtk, AS_HELP_STRING([--disable-gtk], [disable GTK tools]))
if test "x$enable_gtk" != "xno"; then
@@ -646,6 +653,7 @@ AC_MSG_RESULT([
hostnamed: ${have_hostnamed}
timedated: ${have_timedated}
localed: ${have_localed}
+ coredump: ${have_coredump}
plymouth: ${have_plymouth}
prefix: ${prefix}
rootprefix: ${with_rootprefix}
diff --git a/src/.gitignore b/src/.gitignore
index ff2737b..c54c6f6 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,3 +1,4 @@
+/*.pc
load-fragment-gperf-nulstr.c
load-fragment-gperf.c
load-fragment-gperf.gperf
diff --git a/src/journal/coredump.c b/src/journal/coredump.c
new file mode 100644
index 0000000..f160270
--- /dev/null
+++ b/src/journal/coredump.c
@@ -0,0 +1,173 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2012 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <systemd/sd-journal.h>
+#include <systemd/sd-login.h>
+
+#include "log.h"
+#include "util.h"
+
+#define COREDUMP_MAX (64*1024)
+
+enum {
+ ARG_PID = 1,
+ ARG_UID,
+ ARG_GID,
+ ARG_SIGNAL,
+ ARG_TIMESTAMP,
+ ARG_COMM,
+ _ARG_MAX
+};
+
+int main(int argc, char* argv[]) {
+ int r, j = 0;
+ char *p = NULL;
+ ssize_t n;
+ pid_t pid;
+ struct iovec iovec[14];
+ char *core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL,
+ *core_timestamp = NULL, *core_comm = NULL, *core_exe = NULL, *core_unit = NULL,
+ *core_session = NULL, *core_message = NULL, *core_cmdline = NULL, *t;
+
+ log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
+ log_parse_environment();
+ log_open();
+
+ if (argc != _ARG_MAX) {
+ log_error("Invalid number of arguments passed from kernel.");
+ r = -EINVAL;
+ goto finish;
+ }
+
+ r = parse_pid(argv[ARG_PID], &pid);
+ if (r < 0) {
+ log_error("Failed to parse PID.");
+ r = -EINVAL;
+ goto finish;
+ }
+
+ p = malloc(9 + COREDUMP_MAX);
+ if (!p) {
+ log_error("Out of memory");
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ memcpy(p, "COREDUMP=", 9);
+
+ n = loop_read(STDIN_FILENO, p + 9, COREDUMP_MAX, false);
+ if (n < 0) {
+ log_error("Failed to read core dump data: %s", strerror(-n));
+ r = (int) n;
+ goto finish;
+ }
+
+ zero(iovec);
+ iovec[j].iov_base = p;
+ iovec[j].iov_len = 9 + n;
+ j++;
+
+ core_pid = strappend("COREDUMP_PID=", argv[ARG_PID]);
+ if (core_pid)
+ IOVEC_SET_STRING(iovec[j++], core_pid);
+
+ core_uid = strappend("COREDUMP_UID=", argv[ARG_UID]);
+ if (core_uid)
+ IOVEC_SET_STRING(iovec[j++], core_uid);
+
+ core_gid = strappend("COREDUMP_GID=", argv[ARG_GID]);
+ if (core_gid)
+ IOVEC_SET_STRING(iovec[j++], core_gid);
+
+ core_signal = strappend("COREDUMP_SIGNAL=", argv[ARG_SIGNAL]);
+ if (core_signal)
+ IOVEC_SET_STRING(iovec[j++], core_signal);
+
+ core_comm = strappend("COREDUMP_COMM=", argv[ARG_COMM]);
+ if (core_comm)
+ IOVEC_SET_STRING(iovec[j++], core_comm);
+
+ if (sd_pid_get_session(pid, &t) >= 0) {
+ core_session = strappend("COREDUMP_SESSION=", t);
+ free(t);
+
+ if (core_session)
+ IOVEC_SET_STRING(iovec[j++], core_session);
+ }
+
+ if (sd_pid_get_unit(pid, &t) >= 0) {
+ core_unit = strappend("COREDUMP_UNIT=", t);
+ free(t);
+
+ if (core_unit)
+ IOVEC_SET_STRING(iovec[j++], core_unit);
+ }
+
+ if (get_process_exe(pid, &t) >= 0) {
+ core_exe = strappend("COREDUMP_EXE=", t);
+ free(t);
+
+ if (core_exe)
+ IOVEC_SET_STRING(iovec[j++], core_exe);
+ }
+
+ if (get_process_cmdline(pid, LINE_MAX, false, &t) >= 0) {
+ core_cmdline = strappend("COREDUMP_CMDLINE=", t);
+ free(t);
+
+ if (core_cmdline)
+ IOVEC_SET_STRING(iovec[j++], core_cmdline);
+ }
+
+ core_timestamp = join("COREDUMP_TIMESTAMP=", argv[ARG_TIMESTAMP], "000000", NULL);
+ if (core_timestamp)
+ IOVEC_SET_STRING(iovec[j++], core_timestamp);
+
+ IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
+ IOVEC_SET_STRING(iovec[j++], "PRIORITY=2");
+
+ core_message = join("MESSAGE=Process ", argv[ARG_PID], " (", argv[ARG_COMM], ") dumped core.", NULL);
+ if (core_message)
+ IOVEC_SET_STRING(iovec[j++], core_message);
+
+ r = sd_journal_sendv(iovec, j);
+ if (r < 0)
+ log_error("Failed to send coredump: %s", strerror(-r));
+
+finish:
+ free(p);
+ free(core_pid);
+ free(core_uid);
+ free(core_gid);
+ free(core_signal);
+ free(core_timestamp);
+ free(core_comm);
+ free(core_exe);
+ free(core_cmdline);
+ free(core_unit);
+ free(core_session);
+ free(core_message);
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h
index 5fd1aa7..c5ac3ab 100644
--- a/src/systemd/sd-messages.h
+++ b/src/systemd/sd-messages.h
@@ -32,6 +32,8 @@ extern "C" {
#define SD_MESSAGE_JOURNAL_STOP SD_ID128_MAKE(d9,3f,b3,c9,c2,4d,45,1a,97,ce,a6,15,ce,59,c0,0b)
#define SD_MESSAGE_JOURNAL_DROPPED SD_ID128_MAKE(a5,96,d6,fe,7b,fa,49,94,82,8e,72,30,9e,95,d6,1e)
+#define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1)
+
#ifdef __cplusplus
}
#endif
diff --git a/sysctl.d/.gitignore b/sysctl.d/.gitignore
new file mode 100644
index 0000000..7563539
--- /dev/null
+++ b/sysctl.d/.gitignore
@@ -0,0 +1 @@
+/coredump.conf
diff --git a/sysctl.d/Makefile b/sysctl.d/Makefile
new file mode 120000
index 0000000..bd10475
--- /dev/null
+++ b/sysctl.d/Makefile
@@ -0,0 +1 @@
+../src/Makefile
\ No newline at end of file
diff --git a/sysctl.d/coredump.conf.in b/sysctl.d/coredump.conf.in
new file mode 100644
index 0000000..ab19b1e
--- /dev/null
+++ b/sysctl.d/coredump.conf.in
@@ -0,0 +1,10 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# See sysctl.d(5) for details
+
+kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %p %u %g %s %t %e
commit 755a02c6800246e7e293897d0594fe7e7531ba59
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Jan 13 23:17:54 2012 +0100
journal: add new system-cat tool as kind of a more powerfull BSD logger
diff --git a/.gitignore b/.gitignore
index 8daf8f0..c260210 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/systemd-cat
/systemd-rc-local-generator
/libsystemd-id128.pc
systemd-journalctl
diff --git a/Makefile.am b/Makefile.am
index 42da4fb..d94de56 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1237,6 +1237,13 @@ systemd_journald_LDADD += \
$(XZ_LIBS)
endif
+systemd_cat_SOURCES = \
+ src/journal/cat.c
+
+systemd_cat_LDADD = \
+ libsystemd-basic.la \
+ libsystemd-journal.la
+
systemd_journalctl_SOURCES = \
src/journal/journalctl.c \
src/pager.c \
@@ -1345,6 +1352,9 @@ rootlibexec_PROGRAMS += \
rootbin_PROGRAMS += \
systemd-journalctl
+bin_PROGRAMS += \
+ systemd-cat
+
dist_systemunit_DATA += \
units/systemd-journald.socket
diff --git a/src/journal/cat.c b/src/journal/cat.c
new file mode 100644
index 0000000..6745f1c
--- /dev/null
+++ b/src/journal/cat.c
@@ -0,0 +1,181 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2012 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdio.h>
+#include <getopt.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/fcntl.h>
+
+#include <systemd/sd-journal.h>
+
+#include "util.h"
+#include "build.h"
+
+static char *arg_identifier = NULL;
+static char arg_priority = LOG_INFO;
+static bool arg_level_prefix = true;
+
+static int help(void) {
+
+ printf("%s [OPTIONS...] {COMMAND} ...\n\n"
+ "Execute process with stdout/stderr connected to the journal.\n\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " -t --identifier=STRING Set syslog identifier\n"
+ " -p --priority=PRIORITY Set priority value (0..7)\n"
+ " --level-prefix=BOOL Control whether level prefix shall be parsed\n",
+ program_invocation_short_name);
+
+ return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+ enum {
+ ARG_VERSION = 0x100,
+ ARG_LEVEL_PREFIX
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version" , no_argument, NULL, ARG_VERSION },
+ { "identifier", required_argument, NULL, 't' },
+ { "priority", required_argument, NULL, 'p' },
+ { "level-prefix", required_argument, NULL, ARG_LEVEL_PREFIX },
+ { NULL, 0, NULL, 0 }
+ };
+
+ int c;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "+ht:p:", options, NULL)) >= 0) {
+
+ switch (c) {
+
+ case 'h':
+ help();
+ return 0;
+
+ case ARG_VERSION:
+ puts(PACKAGE_STRING);
+ puts(DISTRIBUTION);
+ puts(SYSTEMD_FEATURES);
+ return 0;
+
+ case 't':
+ free(arg_identifier);
+ if (isempty(optarg))
+ arg_identifier = NULL;
+ else {
+ arg_identifier = strdup(optarg);
+ if (!arg_identifier) {
+ log_error("Out of memory.");
+ return -ENOMEM;
+ }
+ }
+ break;
+
+ case 'p':
+ arg_priority = log_level_from_string(optarg);
+ if (arg_priority < 0) {
+ log_error("Failed to parse priority value.");
+ return arg_priority;
+ }
+ break;
+
+ case ARG_LEVEL_PREFIX: {
+ int k;
+
+ k = parse_boolean(optarg);
+ if (k < 0) {
+ log_error("Failed to parse level prefix value.");
+ return k;
+ }
+ arg_level_prefix = k;
+ break;
+ }
+
+ default:
+ log_error("Unknown option code %c", c);
+ return -EINVAL;
+ }
+ }
+
+ return 1;
+}
+
+int main(int argc, char *argv[]) {
+ int r, fd = -1, saved_stderr = -1;
+
+ log_parse_environment();
+ log_open();
+
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ goto finish;
+
+ fd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix);
+ if (fd < 0) {
+ log_error("Failed to create stream fd: %s", strerror(fd));
+ r = fd;
+ goto finish;
+ }
+
+ saved_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3);
+
+ if (dup3(fd, STDOUT_FILENO, 0) < 0 ||
+ dup3(fd, STDERR_FILENO, 0) < 0) {
+ log_error("Failed to duplicate fd: %s", strerror(fd));
+ r = -errno;
+ goto finish;
+ }
+
+ if (fd >= 3)
+ close_nointr_nofail(fd);
+
+ fd = -1;
+
+ if (argc <= optind)
+ execl("/bin/cat", "/bin/cat", NULL);
+ else
+ execvp(argv[optind], argv + optind);
+
+ /* Let's try to restore a working stderr, so we can print the error message */
+ if (saved_stderr >= 0)
+ dup3(saved_stderr, STDERR_FILENO, 0);
+
+ log_error("Failed to execute process: %m");
+ r = -errno;
+
+finish:
+ if (fd >= 0)
+ close_nointr_nofail(fd);
+
+ if (saved_stderr >= 0)
+ close_nointr_nofail(saved_stderr);
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
commit 3043935f02da2e680b37cf282587106ad05440ee
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Jan 13 21:56:28 2012 +0100
util: split out tty_is_vc_resolve() from default_term_for_tty()
diff --git a/src/util.c b/src/util.c
index a6cdfd5..7450565 100644
--- a/src/util.c
+++ b/src/util.c
@@ -4402,31 +4402,37 @@ int vtnr_from_tty(const char *tty) {
return i;
}
-const char *default_term_for_tty(const char *tty) {
+bool tty_is_vc_resolve(const char *tty) {
char *active = NULL;
- const char *term;
+ bool b;
assert(tty);
if (startswith(tty, "/dev/"))
tty += 5;
- /* Resolve where /dev/console is pointing when determining
- * TERM */
+ /* Resolve where /dev/console is pointing to */
if (streq(tty, "console"))
if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
/* If multiple log outputs are configured the
* last one is what /dev/console points to */
- if ((tty = strrchr(active, ' ')))
+ tty = strrchr(active, ' ');
+ if (tty)
tty++;
else
tty = active;
}
- term = tty_is_vc(tty) ? "TERM=linux" : "TERM=vt100";
+ b = tty_is_vc(tty);
free(active);
- return term;
+ return b;
+}
+
+const char *default_term_for_tty(const char *tty) {
+ assert(tty);
+
+ return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt100";
}
bool dirent_is_file(const struct dirent *de) {
diff --git a/src/util.h b/src/util.h
index a52ac64..e6ffad6 100644
--- a/src/util.h
+++ b/src/util.h
@@ -411,6 +411,7 @@ char *fstab_node_to_udev_node(const char *p);
void filter_environ(const char *prefix);
bool tty_is_vc(const char *tty);
+bool tty_is_vc_resolve(const char *tty);
int vtnr_from_tty(const char *tty);
const char *default_term_for_tty(const char *tty);
commit c1072ea0dade39a4188de5e511adfffd4ba8e42c
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Jan 13 21:56:09 2012 +0100
util: rework ANSI escape code macros
diff --git a/src/ask-password-api.c b/src/ask-password-api.c
index f57105c..ce2f3cb 100644
--- a/src/ask-password-api.c
+++ b/src/ask-password-api.c
@@ -89,10 +89,10 @@ int ask_password_tty(
goto finish;
}
- loop_write(ttyfd, "\x1B[1m", 4, false);
+ loop_write(ttyfd, ANSI_HIGHLIGHT_ON, sizeof(ANSI_HIGHLIGHT_ON)-1, false);
loop_write(ttyfd, message, strlen(message), false);
loop_write(ttyfd, " ", 1, false);
- loop_write(ttyfd, "\x1B[0m", 4, false);
+ loop_write(ttyfd, ANSI_HIGHLIGHT_OFF, sizeof(ANSI_HIGHLIGHT_OFF)-1, false);
new_termios = old_termios;
new_termios.c_lflag &= ~(ICANON|ECHO);
diff --git a/src/job.c b/src/job.c
index 1520d81..85f2dee 100644
--- a/src/job.c
+++ b/src/job.c
@@ -488,16 +488,16 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
break;
case JOB_FAILED:
- unit_status_printf(u, ANSI_HIGHLIGHT_ON "FAILED" ANSI_HIGHLIGHT_OFF, "Failed to start %s", unit_description(u));
+ unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, "Failed to start %s", unit_description(u));
unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->meta.id);
break;
case JOB_DEPENDENCY:
- unit_status_printf(u, ANSI_HIGHLIGHT_ON " ABORT" ANSI_HIGHLIGHT_OFF, "Dependency failed. Aborted start of %s", unit_description(u));
+ unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " ABORT" ANSI_HIGHLIGHT_OFF, "Dependency failed. Aborted start of %s", unit_description(u));
break;
case JOB_TIMEOUT:
- unit_status_printf(u, ANSI_HIGHLIGHT_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out starting %s", unit_description(u));
+ unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out starting %s", unit_description(u));
break;
default:
@@ -509,7 +509,7 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
switch (result) {
case JOB_TIMEOUT:
- unit_status_printf(u, ANSI_HIGHLIGHT_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out stopping %s", unit_description(u));
+ unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, "Timed out stopping %s", unit_description(u));
break;
case JOB_DONE:
diff --git a/src/log.c b/src/log.c
index 6caa5fa..79c63a1 100644
--- a/src/log.c
+++ b/src/log.c
@@ -344,7 +344,7 @@ static int write_to_console(
}
if (highlight)
- IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_ON);
+ IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED_ON);
IOVEC_SET_STRING(iovec[n++], buffer);
if (highlight)
IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_OFF);
diff --git a/src/systemctl.c b/src/systemctl.c
index b72fcbf..d7d7d67 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -166,12 +166,12 @@ static void agent_open_if_enabled(void) {
agent_open();
}
-static const char *ansi_highlight(bool b) {
+static const char *ansi_highlight_red(bool b) {
if (!on_tty())
return "";
- return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
+ return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
}
static const char *ansi_highlight_green(bool b) {
@@ -383,14 +383,14 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
n_shown++;
if (streq(u->load_state, "error")) {
- on_loaded = ansi_highlight(true);
- off_loaded = ansi_highlight(false);
+ on_loaded = ansi_highlight_red(true);
+ off_loaded = ansi_highlight_red(false);
} else
on_loaded = off_loaded = "";
if (streq(u->active_state, "failed")) {
- on_active = ansi_highlight(true);
- off_active = ansi_highlight(false);
+ on_active = ansi_highlight_red(true);
+ off_active = ansi_highlight_red(false);
} else
on_active = off_active = "";
@@ -593,8 +593,8 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
if (u->state == UNIT_FILE_MASKED ||
u->state == UNIT_FILE_MASKED_RUNTIME ||
u->state == UNIT_FILE_DISABLED) {
- on = ansi_highlight(true);
- off = ansi_highlight(false);
+ on = ansi_highlight_red(true);
+ off = ansi_highlight_red(false);
} else if (u->state == UNIT_FILE_ENABLED) {
on = ansi_highlight_green(true);
off = ansi_highlight_green(false);
@@ -2069,8 +2069,8 @@ static void print_status_info(UnitStatusInfo *i) {
printf("\t Follow: unit currently follows state of %s\n", i->following);
if (streq_ptr(i->load_state, "error")) {
- on = ansi_highlight(true);
- off = ansi_highlight(false);
+ on = ansi_highlight_red(true);
+ off = ansi_highlight_red(false);
} else
on = off = "";
@@ -2086,8 +2086,8 @@ static void print_status_info(UnitStatusInfo *i) {
ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
if (streq_ptr(i->active_state, "failed")) {
- on = ansi_highlight(true);
- off = ansi_highlight(false);
+ on = ansi_highlight_red(true);
+ off = ansi_highlight_red(false);
} else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
on = ansi_highlight_green(true);
off = ansi_highlight_green(false);
@@ -2163,8 +2163,8 @@ static void print_status_info(UnitStatusInfo *i) {
good = is_clean_exit(p->code, p->status);
if (!good) {
- on = ansi_highlight(true);
- off = ansi_highlight(false);
+ on = ansi_highlight_red(true);
+ off = ansi_highlight_red(false);
} else
on = off = "";
@@ -2274,8 +2274,8 @@ static void print_status_info(UnitStatusInfo *i) {
if (i->need_daemon_reload)
printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
- ansi_highlight(true),
- ansi_highlight(false),
+ ansi_highlight_red(true),
+ ansi_highlight_red(false),
arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
}
diff --git a/src/util.c b/src/util.c
index 3179502..a6cdfd5 100644
--- a/src/util.c
+++ b/src/util.c
@@ -2467,14 +2467,14 @@ int ask(char *ret, const char *replies, const char *text, ...) {
bool need_nl = true;
if (on_tty)
- fputs("\x1B[1m", stdout);
+ fputs(ANSI_HIGHLIGHT_ON, stdout);
va_start(ap, text);
vprintf(text, ap);
va_end(ap);
if (on_tty)
- fputs("\x1B[0m", stdout);
+ fputs(ANSI_HIGHLIGHT_OFF, stdout);
fflush(stdout);
diff --git a/src/util.h b/src/util.h
index 8de608f..a52ac64 100644
--- a/src/util.h
+++ b/src/util.h
@@ -68,7 +68,8 @@ typedef struct dual_timestamp {
#define FORMAT_TIMESTAMP_PRETTY_MAX 256
#define FORMAT_TIMESPAN_MAX 64
-#define ANSI_HIGHLIGHT_ON "\x1B[1;31m"
+#define ANSI_HIGHLIGHT_ON "\x1B[1;39m"
+#define ANSI_HIGHLIGHT_RED_ON "\x1B[1;32m"
#define ANSI_HIGHLIGHT_GREEN_ON "\x1B[1;32m"
#define ANSI_HIGHLIGHT_OFF "\x1B[0m"
More information about the systemd-commits
mailing list