diff --git a/Makefile.am b/Makefile.am
index 311ff09d4ea..60cb991272e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3247,6 +3247,8 @@ libsystemd_journal_core_la_SOURCES = \
src/journal/journald-server.h \
src/journal/journald-console.c \
src/journal/journald-console.h \
+ src/journal/journald-wall.c \
+ src/journal/journald-wall.h \
src/journal/journald-native.c \
src/journal/journald-native.h \
src/journal/journald-rate-limit.c \
diff --git a/man/journald.conf.xml b/man/journald.conf.xml
index a814ec1ec35..239a2ec95c4 100644
--- a/man/journald.conf.xml
+++ b/man/journald.conf.xml
@@ -381,24 +381,28 @@
ForwardToSyslog=
ForwardToKMsg=
ForwardToConsole=
+ ForwardToWall=
Control whether log
messages received by the journal
daemon shall be forwarded to a
traditional syslog daemon, to the
- kernel log buffer (kmsg), or to the
- system console. These options take
- boolean arguments. If forwarding to
- syslog is enabled but no syslog daemon
- is running, the respective option has
- no effect. By default, only forwarding
- to syslog is enabled. These settings
- may be overridden at boot time with
- the kernel command line options
+ kernel log buffer (kmsg), to the
+ system console, or sent as wall
+ messages to all logged-in users. These
+ options take boolean arguments. If
+ forwarding to syslog is enabled but no
+ syslog daemon is running, the
+ respective option has no effect. By
+ default, only forwarding to syslog and
+ wall is enabled. These settings may be
+ overridden at boot time with the
+ kernel command line options
systemd.journald.forward_to_syslog=,
- systemd.journald.forward_to_kmsg=
+ systemd.journald.forward_to_kmsg=,
+ systemd.journald.forward_to_console=
and
- systemd.journald.forward_to_console=.
+ systemd.journald.forward_to_wall=.
When forwarding to the console, the
TTY to log to can be changed
with TTYPath=,
@@ -410,12 +414,14 @@
MaxLevelSyslog=
MaxLevelKMsg=
MaxLevelConsole=
+ MaxLevelWall=
Controls the maximum
log level of messages that are stored
- on disk, forwarded to syslog, kmsg or
- the console (if that is enabled, see
- above). As argument, takes one of
+ on disk, forwarded to syslog, kmsg,
+ the console or wall (if that is
+ enabled, see above). As argument,
+ takes one of
emerg,
alert,
crit,
@@ -436,9 +442,11 @@
written to disk and forwarded to
syslog. Defaults to
notice for
- MaxLevelKMsg= and
+ MaxLevelKMsg=,
info for
- MaxLevelConsole=.
+ MaxLevelConsole= and
+ emerg for
+ MaxLevelWall=.
diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
index afcff7cbb90..dbfec612891 100644
--- a/man/kernel-command-line.xml
+++ b/man/kernel-command-line.xml
@@ -207,6 +207,7 @@
systemd.journald.forward_to_syslog=
systemd.journald.forward_to_kmsg=
systemd.journald.forward_to_console=
+ systemd.journald.forward_to_wall=
Parameters understood by
diff --git a/man/systemd-journald.service.xml b/man/systemd-journald.service.xml
index 4d2cb40805d..f0ce7aae64a 100644
--- a/man/systemd-journald.service.xml
+++ b/man/systemd-journald.service.xml
@@ -142,11 +142,12 @@
systemd.journald.forward_to_syslog=
systemd.journald.forward_to_kmsg=
systemd.journald.forward_to_console=
+ systemd.journald.forward_to_wall=
Enables/disables
forwarding of collected log messages
- to syslog, the kernel log buffer or
- the system console.
+ to syslog, the kernel log buffer, the
+ system console or wall.
See
diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf
index 83bbbc8d2dc..74554c1c342 100644
--- a/src/journal/journald-gperf.gperf
+++ b/src/journal/journald-gperf.gperf
@@ -32,9 +32,11 @@ Journal.MaxFileSec, config_parse_sec, 0, offsetof(Server, max_fil
Journal.ForwardToSyslog, config_parse_bool, 0, offsetof(Server, forward_to_syslog)
Journal.ForwardToKMsg, config_parse_bool, 0, offsetof(Server, forward_to_kmsg)
Journal.ForwardToConsole, config_parse_bool, 0, offsetof(Server, forward_to_console)
+Journal.ForwardToWall, config_parse_bool, 0, offsetof(Server, forward_to_wall)
Journal.TTYPath, config_parse_path, 0, offsetof(Server, tty_path)
Journal.MaxLevelStore, config_parse_log_level, 0, offsetof(Server, max_level_store)
Journal.MaxLevelSyslog, config_parse_log_level, 0, offsetof(Server, max_level_syslog)
Journal.MaxLevelKMsg, config_parse_log_level, 0, offsetof(Server, max_level_kmsg)
Journal.MaxLevelConsole, config_parse_log_level, 0, offsetof(Server, max_level_console)
+Journal.MaxLevelWall, config_parse_log_level, 0, offsetof(Server, max_level_wall)
Journal.SplitMode, config_parse_split_mode, 0, offsetof(Server, split_mode)
diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
index 359d962c72c..0509c1eaeed 100644
--- a/src/journal/journald-native.c
+++ b/src/journal/journald-native.c
@@ -31,6 +31,7 @@
#include "journald-kmsg.h"
#include "journald-console.h"
#include "journald-syslog.h"
+#include "journald-wall.h"
/* Make sure not to make this smaller than the maximum coredump
* size. See COREDUMP_MAX in coredump.c */
@@ -265,6 +266,9 @@ void server_process_native_message(
if (s->forward_to_console)
server_forward_console(s, priority, identifier, message, ucred);
+
+ if (s->forward_to_wall)
+ server_forward_wall(s, priority, identifier, message, ucred);
}
server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid);
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 86806507592..f0117e742ee 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -1319,6 +1319,12 @@ static int server_parse_proc_cmdline(Server *s) {
log_warning("Failed to parse forward to console switch %s. Ignoring.", word + 36);
else
s->forward_to_console = r;
+ } else if (startswith(word, "systemd.journald.forward_to_wall=")) {
+ r = parse_boolean(word + 33);
+ if (r < 0)
+ log_warning("Failed to parse forward to wall switch %s. Ignoring.", word + 33);
+ else
+ s->forward_to_wall = r;
} else if (startswith(word, "systemd.journald"))
log_warning("Invalid systemd.journald parameter. Ignoring.");
}
@@ -1466,11 +1472,13 @@ int server_init(Server *s) {
s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST;
s->forward_to_syslog = true;
+ s->forward_to_wall = true;
s->max_level_store = LOG_DEBUG;
s->max_level_syslog = LOG_DEBUG;
s->max_level_kmsg = LOG_NOTICE;
s->max_level_console = LOG_INFO;
+ s->max_level_wall = LOG_EMERG;
memset(&s->system_metrics, 0xFF, sizeof(s->system_metrics));
memset(&s->runtime_metrics, 0xFF, sizeof(s->runtime_metrics));
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
index 2a81061f262..e468b829312 100644
--- a/src/journal/journald-server.h
+++ b/src/journal/journald-server.h
@@ -97,6 +97,7 @@ typedef struct Server {
bool forward_to_kmsg;
bool forward_to_syslog;
bool forward_to_console;
+ bool forward_to_wall;
unsigned n_forward_syslog_missed;
usec_t last_warn_forward_syslog_missed;
@@ -119,6 +120,7 @@ typedef struct Server {
int max_level_syslog;
int max_level_kmsg;
int max_level_console;
+ int max_level_wall;
Storage storage;
SplitMode split_mode;
diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
index 36fc755260f..c46ffe5d455 100644
--- a/src/journal/journald-stream.c
+++ b/src/journal/journald-stream.c
@@ -35,6 +35,7 @@
#include "journald-syslog.h"
#include "journald-kmsg.h"
#include "journald-console.h"
+#include "journald-wall.h"
#define STDOUT_STREAMS_MAX 4096
@@ -106,6 +107,9 @@ static int stdout_stream_log(StdoutStream *s, const char *p) {
if (s->forward_to_console || s->server->forward_to_console)
server_forward_console(s->server, priority, s->identifier, p, &s->ucred);
+ if (s->server->forward_to_wall)
+ server_forward_wall(s->server, priority, s->identifier, p, &s->ucred);
+
IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=stdout");
syslog_priority[strlen("PRIORITY=")] = '0' + LOG_PRI(priority);
diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c
index 241f7edb6e1..cbb944f287d 100644
--- a/src/journal/journald-syslog.c
+++ b/src/journal/journald-syslog.c
@@ -30,6 +30,7 @@
#include "journald-syslog.h"
#include "journald-kmsg.h"
#include "journald-console.h"
+#include "journald-wall.h"
/* Warn once every 30s if we missed syslog message */
#define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC)
@@ -380,6 +381,9 @@ void server_process_syslog_message(
if (s->forward_to_console)
server_forward_console(s, priority, identifier, buf, ucred);
+ if (s->forward_to_wall)
+ server_forward_wall(s, priority, identifier, buf, ucred);
+
IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=syslog");
if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0)
diff --git a/src/journal/journald-wall.c b/src/journal/journald-wall.c
new file mode 100644
index 00000000000..fcbd9183fea
--- /dev/null
+++ b/src/journal/journald-wall.c
@@ -0,0 +1,69 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Sebastian Thorarensen
+
+ systemd is free software; you can redistribute it and/or modify it
+ 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 .
+***/
+
+#include "utmp-wtmp.h"
+#include "journald-server.h"
+#include "journald-wall.h"
+
+void server_forward_wall(
+ Server *s,
+ int priority,
+ const char *identifier,
+ const char *message,
+ struct ucred *ucred) {
+
+ _cleanup_free_ char *ident_buf = NULL, *l_buf = NULL;
+ const char *l;
+ int r;
+
+ assert(s);
+ assert(message);
+
+ if (LOG_PRI(priority) > s->max_level_wall)
+ return;
+
+ if (ucred) {
+ if (!identifier) {
+ get_process_comm(ucred->pid, &ident_buf);
+ identifier = ident_buf;
+ }
+
+ if (asprintf(&l_buf, "%s["PID_FMT"]: %s", strempty(identifier), ucred->pid, message) < 0) {
+ log_oom();
+ return;
+ }
+
+ l = l_buf;
+
+ } else if (identifier) {
+
+ l = l_buf = strjoin(identifier, ": ", message, NULL);
+ if (!l_buf) {
+ log_oom();
+ return;
+ }
+ } else
+ l = message;
+
+ r = utmp_wall(l, "systemd-journald", NULL);
+ if (r < 0)
+ log_debug("Failed to send wall message: %s", strerror(-r));
+}
diff --git a/src/journal/journald-wall.h b/src/journal/journald-wall.h
new file mode 100644
index 00000000000..93c3cec1d24
--- /dev/null
+++ b/src/journal/journald-wall.h
@@ -0,0 +1,26 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Sebastian Thorarensen
+
+ systemd is free software; you can redistribute it and/or modify it
+ 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 .
+***/
+
+#include "journald-server.h"
+
+void server_forward_wall(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred);
diff --git a/src/journal/journald.conf b/src/journal/journald.conf
index 54f6833a175..d106d00b5ec 100644
--- a/src/journal/journald.conf
+++ b/src/journal/journald.conf
@@ -26,8 +26,10 @@
#ForwardToSyslog=yes
#ForwardToKMsg=no
#ForwardToConsole=no
+#ForwardToWall=yes
#TTYPath=/dev/console
#MaxLevelStore=debug
#MaxLevelSyslog=debug
#MaxLevelKMsg=notice
#MaxLevelConsole=info
+#MaxLevelWall=emerg