[systemd-commits] 5 commits - Makefile.am src/initctl.c src/journal src/kmsg-syslogd.c src/log.c src/login src/logs-show.h src/machine-id-setup.c src/manager.c src/notify.c src/nspawn.c src/readahead src/sd-daemon.h src/sd-id128.c src/sd-id128.h src/shutdownd.c src/stdout-syslog-bridge.c src/systemctl.c src/systemd src/test-daemon.c src/test-id128.c src/unit.c src/util.c src/util.h

Lennart Poettering lennart at kemper.freedesktop.org
Thu Jan 5 07:06:16 PST 2012


 Makefile.am                       |   14 
 src/initctl.c                     |    2 
 src/journal/journal-def.h         |    3 
 src/journal/journal-file.h        |    3 
 src/journal/journal-internal.h    |    3 
 src/journal/journal-send.c        |    6 
 src/journal/journalctl.c          |    3 
 src/journal/journald-gperf.gperf  |    3 
 src/journal/journald.c            |  678 +++++++++++++++++++++++++++-----------
 src/journal/journald.h            |    4 
 src/journal/sd-journal.h          |  124 ------
 src/journal/systemd-journald.conf |    3 
 src/journal/test-journal.c        |    3 
 src/kmsg-syslogd.c                |    3 
 src/log.c                         |   13 
 src/login/logind.c                |    3 
 src/login/pam-module.c            |    3 
 src/login/sd-login.h              |  125 -------
 src/login/test-login.c            |    3 
 src/login/uaccess.c               |    5 
 src/logs-show.h                   |    3 
 src/machine-id-setup.c            |    3 
 src/manager.c                     |    3 
 src/notify.c                      |    3 
 src/nspawn.c                      |    3 
 src/readahead/readahead-collect.c |    3 
 src/readahead/readahead-replay.c  |    3 
 src/readahead/sd-readahead.h      |   73 ----
 src/sd-daemon.h                   |  277 ---------------
 src/sd-id128.c                    |    1 
 src/sd-id128.h                    |   63 ---
 src/shutdownd.c                   |    3 
 src/stdout-syslog-bridge.c        |    3 
 src/systemctl.c                   |    3 
 src/systemd/sd-daemon.h           |  277 +++++++++++++++
 src/systemd/sd-id128.h            |   63 +++
 src/systemd/sd-journal.h          |  124 ++++++
 src/systemd/sd-login.h            |  125 +++++++
 src/systemd/sd-readahead.h        |   73 ++++
 src/test-daemon.c                 |    2 
 src/test-id128.c                  |    3 
 src/unit.c                        |   18 -
 src/util.c                        |   90 ++++-
 src/util.h                        |    5 
 44 files changed, 1314 insertions(+), 914 deletions(-)

New commits:
commit 81527be142678057215665be66e4b3c8306a7ab3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 5 16:01:58 2012 +0100

    build-sys: move public header files into a dir of their own

diff --git a/Makefile.am b/Makefile.am
index e668c09..0c8804f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -100,7 +100,8 @@ AM_CPPFLAGS = \
 	-I $(top_srcdir)/src \
 	-I $(top_srcdir)/src/readahead \
 	-I $(top_srcdir)/src/login \
-	-I $(top_srcdir)/src/journal
+	-I $(top_srcdir)/src/journal \
+	-I $(top_srcdir)/src/systemd
 
 if TARGET_GENTOO
 AM_CPPFLAGS += \
@@ -1053,7 +1054,7 @@ libsystemd_daemon_la_LDFLAGS = \
 	-Wl,--version-script=$(top_srcdir)/src/libsystemd-daemon.sym
 
 pkginclude_HEADERS += \
-	src/sd-daemon.h
+	src/systemd/sd-daemon.h
 
 # move lib from $(libdir) to $(rootlibdir) and update devel link, if needed
 libsystemd-daemon-install-hook:
@@ -1131,7 +1132,7 @@ noinst_PROGRAMS += \
 	test-id128
 
 pkginclude_HEADERS += \
-	src/sd-id128.h
+	src/systemd/sd-id128.h
 
 lib_LTLIBRARIES += \
 	libsystemd-id128.la
@@ -1290,8 +1291,8 @@ noinst_PROGRAMS += \
 	test-journal
 
 pkginclude_HEADERS += \
-	src/journal/sd-journal.h \
-        src/journal/sd-messages.h
+	src/systemd/sd-journal.h \
+        src/systemd/sd-messages.h
 
 lib_LTLIBRARIES += \
 	libsystemd-journal.la
@@ -1451,7 +1452,7 @@ nodist_systemunit_DATA += \
 	units/systemd-readahead-done.service
 
 EXTRA_DIST += \
-	src/readahead/sd-readahead.h \
+	src/systemd/sd-readahead.h \
 	src/readahead/readahead-common.h \
 	units/systemd-readahead-collect.service.in \
 	units/systemd-readahead-replay.service.in \
@@ -1878,7 +1879,7 @@ dist_pkgsysconf_DATA += \
 	src/login/systemd-logind.conf
 
 pkginclude_HEADERS += \
-	src/login/sd-login.h
+	src/systemd/sd-login.h
 
 lib_LTLIBRARIES += \
 	libsystemd-login.la
diff --git a/src/initctl.c b/src/initctl.c
index 097c85f..e2189e9 100644
--- a/src/initctl.c
+++ b/src/initctl.c
@@ -34,13 +34,13 @@
 #include <ctype.h>
 
 #include <dbus/dbus.h>
+#include <systemd/sd-daemon.h>
 
 #include "util.h"
 #include "log.h"
 #include "list.h"
 #include "initreq.h"
 #include "special.h"
-#include "sd-daemon.h"
 #include "dbus-common.h"
 #include "def.h"
 
diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h
index ef0cb6d..964e0c2 100644
--- a/src/journal/journal-def.h
+++ b/src/journal/journal-def.h
@@ -24,8 +24,9 @@
 
 #include <inttypes.h>
 
+#include <systemd/sd-id128.h>
+
 #include "macro.h"
-#include "sd-id128.h"
 
 typedef struct Header Header;
 typedef struct ObjectHeader ObjectHeader;
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
index 51d7119..0be3932 100644
--- a/src/journal/journal-file.h
+++ b/src/journal/journal-file.h
@@ -24,9 +24,10 @@
 
 #include <inttypes.h>
 
+#include <systemd/sd-id128.h>
+
 #include "journal-def.h"
 #include "util.h"
-#include "sd-id128.h"
 
 typedef struct Window {
         void *ptr;
diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
index 1b64666..e5914bf 100644
--- a/src/journal/journal-internal.h
+++ b/src/journal/journal-internal.h
@@ -26,8 +26,9 @@
 #include <inttypes.h>
 #include <stdbool.h>
 
+#include <systemd/sd-id128.h>
+
 #include "list.h"
-#include "sd-id128.h"
 
 typedef struct Match Match;
 
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 17d6a7f..2e708e9 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -30,7 +30,8 @@
 #include <time.h>
 #include <getopt.h>
 
-#include "sd-journal.h"
+#include <systemd/sd-journal.h>
+
 #include "log.h"
 #include "util.h"
 #include "build.h"
diff --git a/src/journal/journald.c b/src/journal/journald.c
index d6206a8..d7f0ed5 100644
--- a/src/journal/journald.c
+++ b/src/journal/journald.c
@@ -32,19 +32,20 @@
 #include <linux/sockios.h>
 #include <sys/statvfs.h>
 
+#include <systemd/sd-journal.h>
+#include <systemd/sd-login.h>
+#include <systemd/sd-messages.h>
+#include <systemd/sd-daemon.h>
+
 #include "hashmap.h"
 #include "journal-file.h"
-#include "sd-daemon.h"
 #include "socket-util.h"
 #include "acl-util.h"
 #include "cgroup-util.h"
 #include "list.h"
 #include "journal-rate-limit.h"
-#include "sd-journal.h"
-#include "sd-login.h"
 #include "journal-internal.h"
 #include "conf-parser.h"
-#include "sd-messages.h"
 #include "journald.h"
 
 #define USER_JOURNALS_MAX 1024
diff --git a/src/journal/sd-journal.h b/src/journal/sd-journal.h
deleted file mode 100644
index 87da17d..0000000
--- a/src/journal/sd-journal.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foojournalhfoo
-#define foojournalhfoo
-
-/***
-  This file is part of systemd.
-
-  Copyright 2011 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 <inttypes.h>
-#include <sys/types.h>
-#include <stdarg.h>
-#include <sys/uio.h>
-
-#include "sd-id128.h"
-
-/* TODO:
- *
- *   - add options for copy-to-console, copy-to-kmsg
- *   - OR of matches is borked...
- *   - extend hash tables table as we go
- *   - accelerate looking for "all hostnames" and suchlike.
- *   - handle incomplete header
- *
- *   - local deserializer
- *   - http server
- *   - message catalog
- *
- *   - check LE/BE conversion for 8bit, 16bit, 32bit values
- *   - cryptographic hash
- *   - think about manipulations of header
- *   - implement audit gateway
- */
-
-/* Write to daemon */
-
-int sd_journal_print(int piority, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
-int sd_journal_printv(int priority, const char *format, va_list ap);
-
-int sd_journal_send(const char *format, ...) __attribute__((sentinel));
-int sd_journal_sendv(const struct iovec *iov, int n);
-
-int sd_journal_stream_fd(const char *tag, int priority, int priority_prefix);
-
-/* Browse journal stream */
-
-typedef struct sd_journal sd_journal;
-
-enum {
-        SD_JOURNAL_LOCAL_ONLY = 1,
-        SD_JOURNAL_RUNTIME_ONLY = 2,
-        SD_JOURNAL_SYSTEM_ONLY = 4
-};
-
-int sd_journal_open(sd_journal **ret, int flags);
-void sd_journal_close(sd_journal *j);
-
-int sd_journal_previous(sd_journal *j);
-int sd_journal_next(sd_journal *j);
-
-int sd_journal_previous_skip(sd_journal *j, uint64_t skip);
-int sd_journal_next_skip(sd_journal *j, uint64_t skip);
-
-int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret);
-int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id);
-int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l);
-int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l);
-void sd_journal_restart_data(sd_journal *j);
-
-int sd_journal_add_match(sd_journal *j, const void *data, size_t size);
-void sd_journal_flush_matches(sd_journal *j);
-
-int sd_journal_seek_head(sd_journal *j);
-int sd_journal_seek_tail(sd_journal *j);
-int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec);
-int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec);
-int sd_journal_seek_cursor(sd_journal *j, const char *cursor);
-
-int sd_journal_get_cursor(sd_journal *j, char **cursor);
-
-int sd_journal_query_unique(sd_journal *j, const char *field);      /* missing */
-int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l); /* missing */
-void sd_journal_restart_unique(sd_journal *j);                      /* missing */
-
-enum {
-        SD_JOURNAL_NOP,
-        SD_JOURNAL_APPEND,
-        SD_JOURNAL_INVALIDATE_ADD,
-        SD_JOURNAL_INVALIDATE_REMOVE
-};
-
-int sd_journal_get_fd(sd_journal *j);
-int sd_journal_process(sd_journal *j);
-
-#define SD_JOURNAL_FOREACH(j)                                           \
-        if (sd_journal_seek_head(j) >= 0)                               \
-                while (sd_journal_next(j) > 0)
-
-#define SD_JOURNAL_FOREACH_BACKWARDS(j)                                 \
-        if (sd_journal_seek_tail(j) >= 0)                               \
-                while (sd_journal_previous(j) > 0)
-
-#define SD_JOURNAL_FOREACH_DATA(j, data, l)                             \
-        for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
-
-#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l)                           \
-        for (sd_journal_restart_unique(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
-
-#endif
diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c
index 3d429be..a023509 100644
--- a/src/journal/test-journal.c
+++ b/src/journal/test-journal.c
@@ -22,7 +22,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-#include "sd-journal.h"
+#include <systemd/sd-journal.h>
+
 #include "journal-file.h"
 #include "log.h"
 
diff --git a/src/kmsg-syslogd.c b/src/kmsg-syslogd.c
index f42f72c..da83bb2 100644
--- a/src/kmsg-syslogd.c
+++ b/src/kmsg-syslogd.c
@@ -33,9 +33,10 @@
 #include <fcntl.h>
 #include <sys/signalfd.h>
 
+#include <systemd/sd-daemon.h>
+
 #include "util.h"
 #include "log.h"
-#include "sd-daemon.h"
 #include "fdset.h"
 
 #define SERVER_FD_MAX 16
diff --git a/src/login/logind.c b/src/login/logind.c
index 99534a5..4aeac0c 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -29,8 +29,9 @@
 #include <sys/ioctl.h>
 #include <linux/vt.h>
 
+#include <systemd/sd-daemon.h>
+
 #include "logind.h"
-#include "sd-daemon.h"
 #include "dbus-common.h"
 #include "dbus-loop.h"
 #include "strv.h"
diff --git a/src/login/pam-module.c b/src/login/pam-module.c
index 14e706b..82594c3 100644
--- a/src/login/pam-module.c
+++ b/src/login/pam-module.c
@@ -32,9 +32,10 @@
 #include <security/pam_ext.h>
 #include <security/pam_misc.h>
 
+#include <systemd/sd-daemon.h>
+
 #include "util.h"
 #include "macro.h"
-#include "sd-daemon.h"
 #include "strv.h"
 #include "dbus-common.h"
 #include "def.h"
diff --git a/src/login/sd-login.h b/src/login/sd-login.h
deleted file mode 100644
index 00de671..0000000
--- a/src/login/sd-login.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foosdloginhfoo
-#define foosdloginhfoo
-
-/***
-  This file is part of systemd.
-
-  Copyright 2011 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 <sys/types.h>
-
-/*
- * A few points:
- *
- * Instead of returning an empty string array or empty uid array, we
- * may return NULL.
- *
- * Free the data we return with libc free().
- *
- * We return error codes as negative errno, kernel-style. 0 or
- * positive on success.
- *
- * These functions access data in /proc, /sys/fs/cgroup and /run. All
- * of these are virtual file systems, hence the accesses are
- * relatively cheap.
- */
-
-/* Get session from PID. Note that 'shared' processes of a user are
- * not attached to a session, but only attached to a user. This will
- * return an error for system processes and 'shared' processes of a
- * user. */
-int sd_pid_get_session(pid_t pid, char **session);
-
-/* Get UID of the owner of the session of the PID (or in case the
- * process is a 'shared' user process the UID of that user is
- * returned). This will not return the UID of the process, but rather
- * the UID of the owner of the cgroup the process is in. This will
- * return an error for system processes. */
-int sd_pid_get_owner_uid(pid_t pid, uid_t *uid);
-
-/* Get systemd unit (i.e. service) name from PID. This will return an
- * error for non-service processes. */
-int sd_pid_get_unit(pid_t, char **unit);
-
-/* Get state from uid. Possible states: offline, lingering, online, active */
-int sd_uid_get_state(uid_t uid, char**state);
-
-/* Return 1 if uid has session on seat. If require_active is true will
- * look for active sessions only. */
-int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat);
-
-/* Return sessions of user. If require_active is true will look for
- * active sessions only. Returns number of sessions as return
- * value. If sessions is NULL will just return number of sessions. */
-int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions);
-
-/* Return seats of user is on. If require_active is true will look for
- * active seats only.  Returns number of seats. If seats is NULL will
- * just return number of seats.*/
-int sd_uid_get_seats(uid_t uid, int require_active, char ***seats);
-
-/* Return 1 if the session is a active */
-int sd_session_is_active(const char *session);
-
-/* Determine user id of session */
-int sd_session_get_uid(const char *session, uid_t *uid);
-
-/* Determine seat of session */
-int sd_session_get_seat(const char *session, char **seat);
-
-/* Return active session and user of seat */
-int sd_seat_get_active(const char *seat, char **session, uid_t *uid);
-
-/* Return sessions and users on seat. Returns number of sessions as
- * return value. If sessions is NULL returns only the number of
- * sessions. */
-int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids);
-
-/* Return whether the seat is multi-session capable */
-int sd_seat_can_multi_session(const char *seat);
-
-/* Get all seats, store in *seats. Returns the number of seats. If
- * seats is NULL only returns number of seats. */
-int sd_get_seats(char ***seats);
-
-/* Get all sessions, store in *sessions. Returns the number of
- * sessions. If sessions is NULL only returns number of sessions. */
-int sd_get_sessions(char ***sessions);
-
-/* Get all logged in users, store in *users. Returns the number of
- * users. If users is NULL only returns the number of users. */
-int sd_get_uids(uid_t **users);
-
-/* Monitor object */
-typedef struct sd_login_monitor sd_login_monitor;
-
-/* Create a new monitor. Category must be NULL, "seat", "session",
- * "uid" to get monitor events for the specific category (or all). */
-int sd_login_monitor_new(const char *category, sd_login_monitor** ret);
-
-/* Destroys the passed monitor. Returns NULL. */
-sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m);
-
-/* Flushes the monitor */
-int sd_login_monitor_flush(sd_login_monitor *m);
-
-/* Get FD from monitor */
-int sd_login_monitor_get_fd(sd_login_monitor *m);
-
-#endif
diff --git a/src/login/test-login.c b/src/login/test-login.c
index 7d6f082..ae041b6 100644
--- a/src/login/test-login.c
+++ b/src/login/test-login.c
@@ -22,7 +22,8 @@
 #include <sys/poll.h>
 #include <string.h>
 
-#include "sd-login.h"
+#include <systemd/sd-login.h>
+
 #include "util.h"
 #include "strv.h"
 
diff --git a/src/login/uaccess.c b/src/login/uaccess.c
index 49ac4af..e1af5bf 100644
--- a/src/login/uaccess.c
+++ b/src/login/uaccess.c
@@ -22,11 +22,12 @@
 #include <errno.h>
 #include <string.h>
 
+#include <systemd/sd-daemon.h>
+#include <systemd/sd-login.h>
+
 #include "logind-acl.h"
 #include "util.h"
 #include "log.h"
-#include "sd-daemon.h"
-#include "sd-login.h"
 
 int main(int argc, char *argv[]) {
         int r;
diff --git a/src/logs-show.h b/src/logs-show.h
index 5cf1a63..d3f3c75 100644
--- a/src/logs-show.h
+++ b/src/logs-show.h
@@ -24,7 +24,8 @@
 
 #include <stdbool.h>
 
-#include "sd-journal.h"
+#include <systemd/sd-journal.h>
+
 #include "util.h"
 
 typedef enum OutputMode {
diff --git a/src/machine-id-setup.c b/src/machine-id-setup.c
index 9b25b10..531f3b2 100644
--- a/src/machine-id-setup.c
+++ b/src/machine-id-setup.c
@@ -27,11 +27,12 @@
 #include <fcntl.h>
 #include <sys/mount.h>
 
+#include <systemd/sd-id128.h>
+
 #include "machine-id-setup.h"
 #include "macro.h"
 #include "util.h"
 #include "log.h"
-#include "sd-id128.h"
 
 static int generate(char id[34]) {
         int fd, r;
diff --git a/src/manager.c b/src/manager.c
index 9957bbf..7fd860e 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -41,6 +41,8 @@
 #include <libaudit.h>
 #endif
 
+#include <systemd/sd-daemon.h>
+
 #include "manager.h"
 #include "hashmap.h"
 #include "macro.h"
@@ -58,7 +60,6 @@
 #include "special.h"
 #include "bus-errors.h"
 #include "exit-status.h"
-#include "sd-daemon.h"
 #include "virt.h"
 
 /* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
diff --git a/src/notify.c b/src/notify.c
index a9bc51e..9d52bdf 100644
--- a/src/notify.c
+++ b/src/notify.c
@@ -27,10 +27,11 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <systemd/sd-daemon.h>
+
 #include "strv.h"
 #include "util.h"
 #include "log.h"
-#include "sd-daemon.h"
 #include "sd-readahead.h"
 
 static bool arg_ready = false;
diff --git a/src/nspawn.c b/src/nspawn.c
index 3ea603f..b8b379d 100644
--- a/src/nspawn.c
+++ b/src/nspawn.c
@@ -39,11 +39,12 @@
 #include <grp.h>
 #include <linux/fs.h>
 
+#include <systemd/sd-daemon.h>
+
 #include "log.h"
 #include "util.h"
 #include "missing.h"
 #include "cgroup-util.h"
-#include "sd-daemon.h"
 #include "strv.h"
 #include "loopback-setup.h"
 
diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c
index eac11e7..6bff32f 100644
--- a/src/readahead/readahead-collect.c
+++ b/src/readahead/readahead-collect.c
@@ -43,10 +43,11 @@
 #include <getopt.h>
 #include <sys/inotify.h>
 
+#include <systemd/sd-daemon.h>
+
 #include "missing.h"
 #include "util.h"
 #include "set.h"
-#include "sd-daemon.h"
 #include "ioprio.h"
 #include "readahead-common.h"
 #include "virt.h"
diff --git a/src/readahead/readahead-replay.c b/src/readahead/readahead-replay.c
index 65011ac..88c7a21 100644
--- a/src/readahead/readahead-replay.c
+++ b/src/readahead/readahead-replay.c
@@ -35,10 +35,11 @@
 #include <getopt.h>
 #include <sys/inotify.h>
 
+#include <systemd/sd-daemon.h>
+
 #include "missing.h"
 #include "util.h"
 #include "set.h"
-#include "sd-daemon.h"
 #include "ioprio.h"
 #include "readahead-common.h"
 #include "virt.h"
diff --git a/src/readahead/sd-readahead.h b/src/readahead/sd-readahead.h
deleted file mode 100644
index ee7e306..0000000
--- a/src/readahead/sd-readahead.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foosdreadaheadhfoo
-#define foosdreadaheadhfoo
-
-/***
-  Copyright 2010 Lennart Poettering
-
-  Permission is hereby granted, free of charge, to any person
-  obtaining a copy of this software and associated documentation files
-  (the "Software"), to deal in the Software without restriction,
-  including without limitation the rights to use, copy, modify, merge,
-  publish, distribute, sublicense, and/or sell copies of the Software,
-  and to permit persons to whom the Software is furnished to do so,
-  subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be
-  included in all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-  SOFTWARE.
-***/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-  Reference implementation of a few boot readahead related
-  interfaces. These interfaces are trivial to implement. To simplify
-  porting we provide this reference implementation.  Applications are
-  welcome to reimplement the algorithms described here if they do not
-  want to include these two source files.
-
-  You may compile this with -DDISABLE_SYSTEMD to disable systemd
-  support. This makes all calls NOPs.
-
-  Since this is drop-in code we don't want any of our symbols to be
-  exported in any case. Hence we declare hidden visibility for all of
-  them.
-
-  You may find an up-to-date version of these source files online:
-
-  http://cgit.freedesktop.org/systemd/plain/src/sd-readahead.h
-  http://cgit.freedesktop.org/systemd/plain/src/sd-readahead.c
-
-  This should compile on non-Linux systems, too, but all functions
-  will become NOPs.
-
-  See sd-readahead(7) for more information.
-*/
-
-/*
-  Controls ongoing disk read-ahead operations during boot-up. The argument
-  must be a string, and either "cancel", "done" or "noreplay".
-
-  cancel = terminate read-ahead data collection, drop collected information
-  done = terminate read-ahead data collection, keep collected information
-  noreplay = terminate read-ahead replay
-*/
-int sd_readahead(const char *action);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/sd-daemon.h b/src/sd-daemon.h
deleted file mode 100644
index 46dc7fd..0000000
--- a/src/sd-daemon.h
+++ /dev/null
@@ -1,277 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foosddaemonhfoo
-#define foosddaemonhfoo
-
-/***
-  Copyright 2010 Lennart Poettering
-
-  Permission is hereby granted, free of charge, to any person
-  obtaining a copy of this software and associated documentation files
-  (the "Software"), to deal in the Software without restriction,
-  including without limitation the rights to use, copy, modify, merge,
-  publish, distribute, sublicense, and/or sell copies of the Software,
-  and to permit persons to whom the Software is furnished to do so,
-  subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be
-  included in all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-  SOFTWARE.
-***/
-
-#include <sys/types.h>
-#include <inttypes.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-  Reference implementation of a few systemd related interfaces for
-  writing daemons. These interfaces are trivial to implement. To
-  simplify porting we provide this reference implementation.
-  Applications are welcome to reimplement the algorithms described
-  here if they do not want to include these two source files.
-
-  The following functionality is provided:
-
-  - Support for logging with log levels on stderr
-  - File descriptor passing for socket-based activation
-  - Daemon startup and status notification
-  - Detection of systemd boots
-
-  You may compile this with -DDISABLE_SYSTEMD to disable systemd
-  support. This makes all those calls NOPs that are directly related to
-  systemd (i.e. only sd_is_xxx() will stay useful).
-
-  Since this is drop-in code we don't want any of our symbols to be
-  exported in any case. Hence we declare hidden visibility for all of
-  them.
-
-  You may find an up-to-date version of these source files online:
-
-  http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h
-  http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c
-
-  This should compile on non-Linux systems, too, but with the
-  exception of the sd_is_xxx() calls all functions will become NOPs.
-
-  See sd-daemon(7) for more information.
-*/
-
-#ifndef _sd_printf_attr_
-#if __GNUC__ >= 4
-#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
-#else
-#define _sd_printf_attr_(a,b)
-#endif
-#endif
-
-/*
-  Log levels for usage on stderr:
-
-          fprintf(stderr, SD_NOTICE "Hello World!\n");
-
-  This is similar to printk() usage in the kernel.
-*/
-#define SD_EMERG   "<0>"  /* system is unusable */
-#define SD_ALERT   "<1>"  /* action must be taken immediately */
-#define SD_CRIT    "<2>"  /* critical conditions */
-#define SD_ERR     "<3>"  /* error conditions */
-#define SD_WARNING "<4>"  /* warning conditions */
-#define SD_NOTICE  "<5>"  /* normal but significant condition */
-#define SD_INFO    "<6>"  /* informational */
-#define SD_DEBUG   "<7>"  /* debug-level messages */
-
-/* The first passed file descriptor is fd 3 */
-#define SD_LISTEN_FDS_START 3
-
-/*
-  Returns how many file descriptors have been passed, or a negative
-  errno code on failure. Optionally, removes the $LISTEN_FDS and
-  $LISTEN_PID file descriptors from the environment (recommended, but
-  problematic in threaded environments). If r is the return value of
-  this function you'll find the file descriptors passed as fds
-  SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative
-  errno style error code on failure. This function call ensures that
-  the FD_CLOEXEC flag is set for the passed file descriptors, to make
-  sure they are not passed on to child processes. If FD_CLOEXEC shall
-  not be set, the caller needs to unset it after this call for all file
-  descriptors that are used.
-
-  See sd_listen_fds(3) for more information.
-*/
-int sd_listen_fds(int unset_environment);
-
-/*
-  Helper call for identifying a passed file descriptor. Returns 1 if
-  the file descriptor is a FIFO in the file system stored under the
-  specified path, 0 otherwise. If path is NULL a path name check will
-  not be done and the call only verifies if the file descriptor
-  refers to a FIFO. Returns a negative errno style error code on
-  failure.
-
-  See sd_is_fifo(3) for more information.
-*/
-int sd_is_fifo(int fd, const char *path);
-
-/*
-  Helper call for identifying a passed file descriptor. Returns 1 if
-  the file descriptor is a special character device on the file
-  system stored under the specified path, 0 otherwise.
-  If path is NULL a path name check will not be done and the call
-  only verifies if the file descriptor refers to a special character.
-  Returns a negative errno style error code on failure.
-
-  See sd_is_special(3) for more information.
-*/
-int sd_is_special(int fd, const char *path);
-
-/*
-  Helper call for identifying a passed file descriptor. Returns 1 if
-  the file descriptor is a socket of the specified family (AF_INET,
-  ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If
-  family is 0 a socket family check will not be done. If type is 0 a
-  socket type check will not be done and the call only verifies if
-  the file descriptor refers to a socket. If listening is > 0 it is
-  verified that the socket is in listening mode. (i.e. listen() has
-  been called) If listening is == 0 it is verified that the socket is
-  not in listening mode. If listening is < 0 no listening mode check
-  is done. Returns a negative errno style error code on failure.
-
-  See sd_is_socket(3) for more information.
-*/
-int sd_is_socket(int fd, int family, int type, int listening);
-
-/*
-  Helper call for identifying a passed file descriptor. Returns 1 if
-  the file descriptor is an Internet socket, of the specified family
-  (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM,
-  SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version
-  check is not done. If type is 0 a socket type check will not be
-  done. If port is 0 a socket port check will not be done. The
-  listening flag is used the same way as in sd_is_socket(). Returns a
-  negative errno style error code on failure.
-
-  See sd_is_socket_inet(3) for more information.
-*/
-int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port);
-
-/*
-  Helper call for identifying a passed file descriptor. Returns 1 if
-  the file descriptor is an AF_UNIX socket of the specified type
-  (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0
-  a socket type check will not be done. If path is NULL a socket path
-  check will not be done. For normal AF_UNIX sockets set length to
-  0. For abstract namespace sockets set length to the length of the
-  socket name (including the initial 0 byte), and pass the full
-  socket path in path (including the initial 0 byte). The listening
-  flag is used the same way as in sd_is_socket(). Returns a negative
-  errno style error code on failure.
-
-  See sd_is_socket_unix(3) for more information.
-*/
-int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length);
-
-/*
-  Helper call for identifying a passed file descriptor. Returns 1 if
-  the file descriptor is a POSIX Message Queue of the specified name,
-  0 otherwise. If path is NULL a message queue name check is not
-  done. Returns a negative errno style error code on failure.
-*/
-int sd_is_mq(int fd, const char *path);
-
-/*
-  Informs systemd about changed daemon state. This takes a number of
-  newline separated environment-style variable assignments in a
-  string. The following variables are known:
-
-     READY=1      Tells systemd that daemon startup is finished (only
-                  relevant for services of Type=notify). The passed
-                  argument is a boolean "1" or "0". Since there is
-                  little value in signaling non-readiness the only
-                  value daemons should send is "READY=1".
-
-     STATUS=...   Passes a single-line status string back to systemd
-                  that describes the daemon state. This is free-from
-                  and can be used for various purposes: general state
-                  feedback, fsck-like programs could pass completion
-                  percentages and failing programs could pass a human
-                  readable error message. Example: "STATUS=Completed
-                  66% of file system check..."
-
-     ERRNO=...    If a daemon fails, the errno-style error code,
-                  formatted as string. Example: "ERRNO=2" for ENOENT.
-
-     BUSERROR=... If a daemon fails, the D-Bus error-style error
-                  code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut"
-
-     MAINPID=...  The main pid of a daemon, in case systemd did not
-                  fork off the process itself. Example: "MAINPID=4711"
-
-  Daemons can choose to send additional variables. However, it is
-  recommended to prefix variable names not listed above with X_.
-
-  Returns a negative errno-style error code on failure. Returns > 0
-  if systemd could be notified, 0 if it couldn't possibly because
-  systemd is not running.
-
-  Example: When a daemon finished starting up, it could issue this
-  call to notify systemd about it:
-
-     sd_notify(0, "READY=1");
-
-  See sd_notifyf() for more complete examples.
-
-  See sd_notify(3) for more information.
-*/
-int sd_notify(int unset_environment, const char *state);
-
-/*
-  Similar to sd_notify() but takes a format string.
-
-  Example 1: A daemon could send the following after initialization:
-
-     sd_notifyf(0, "READY=1\n"
-                   "STATUS=Processing requests...\n"
-                   "MAINPID=%lu",
-                   (unsigned long) getpid());
-
-  Example 2: A daemon could send the following shortly before
-  exiting, on failure:
-
-     sd_notifyf(0, "STATUS=Failed to start up: %s\n"
-                   "ERRNO=%i",
-                   strerror(errno),
-                   errno);
-
-  See sd_notifyf(3) for more information.
-*/
-int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3);
-
-/*
-  Returns > 0 if the system was booted with systemd. Returns < 0 on
-  error. Returns 0 if the system was not booted with systemd. Note
-  that all of the functions above handle non-systemd boots just
-  fine. You should NOT protect them with a call to this function. Also
-  note that this function checks whether the system, not the user
-  session is controlled by systemd. However the functions above work
-  for both user and system services.
-
-  See sd_booted(3) for more information.
-*/
-int sd_booted(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/sd-id128.c b/src/sd-id128.c
index 387cf91..289bcdc 100644
--- a/src/sd-id128.c
+++ b/src/sd-id128.c
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include "sd-id128.h"
+
 #include "util.h"
 #include "macro.h"
 
diff --git a/src/sd-id128.h b/src/sd-id128.h
deleted file mode 100644
index d835cf4..0000000
--- a/src/sd-id128.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef fooid128hfoo
-#define fooid128hfoo
-
-/***
-  This file is part of systemd.
-
-  Copyright 2011 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 <inttypes.h>
-#include <stdbool.h>
-#include <string.h>
-
-typedef union sd_id128 sd_id128_t;
-
-union sd_id128 {
-        uint8_t bytes[16];
-        uint64_t qwords[2];
-};
-
-char *sd_id128_to_string(sd_id128_t id, char s[33]);
-
-int sd_id128_from_string(const char s[33], sd_id128_t *ret);
-
-int sd_id128_randomize(sd_id128_t *ret);
-
-sd_id128_t sd_id128_make_v4_uuid(sd_id128_t id);
-
-int sd_id128_get_machine(sd_id128_t *ret);
-
-int sd_id128_get_boot(sd_id128_t *ret);
-
-#define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \
-        ((sd_id128_t) { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \
-                                   0x##v8, 0x##v9, 0x##v10, 0x##v11, 0x##v12, 0x##v13, 0x##v14, 0x##v15 }})
-
-/* Note that SD_ID128_FORMAT_VAL will evaluate the passed argument 16
- * times. It is hence not a good idea to call this macro with an
- * expensive function as paramater or an expression with side
- * effects */
-#define SD_ID128_FORMAT_STR "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
-#define SD_ID128_FORMAT_VAL(x) (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15]
-
-static inline bool sd_id128_equal(sd_id128_t a, sd_id128_t b) {
-        return memcmp(&a, &b, 16) == 0;
-}
-
-#endif
diff --git a/src/shutdownd.c b/src/shutdownd.c
index 46856b0..19b16cb 100644
--- a/src/shutdownd.c
+++ b/src/shutdownd.c
@@ -29,11 +29,12 @@
 #include <unistd.h>
 #include <fcntl.h>
 
+#include <systemd/sd-daemon.h>
+
 #include "shutdownd.h"
 #include "log.h"
 #include "macro.h"
 #include "util.h"
-#include "sd-daemon.h"
 #include "utmp-wtmp.h"
 
 static int read_packet(int fd, struct shutdownd_command *_c) {
diff --git a/src/stdout-syslog-bridge.c b/src/stdout-syslog-bridge.c
index 6ec23ec..e82716a 100644
--- a/src/stdout-syslog-bridge.c
+++ b/src/stdout-syslog-bridge.c
@@ -32,10 +32,11 @@
 #include <sys/un.h>
 #include <fcntl.h>
 
+#include <systemd/sd-daemon.h>
+
 #include "util.h"
 #include "log.h"
 #include "list.h"
-#include "sd-daemon.h"
 #include "tcpwrap.h"
 #include "def.h"
 
diff --git a/src/systemctl.c b/src/systemctl.c
index 2f03f6b..9b915f6 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -35,6 +35,8 @@
 #include <sys/prctl.h>
 #include <dbus/dbus.h>
 
+#include <systemd/sd-daemon.h>
+
 #include "log.h"
 #include "util.h"
 #include "macro.h"
@@ -49,7 +51,6 @@
 #include "list.h"
 #include "path-lookup.h"
 #include "conf-parser.h"
-#include "sd-daemon.h"
 #include "shutdownd.h"
 #include "exit-status.h"
 #include "bus-errors.h"
diff --git a/src/systemd/sd-daemon.h b/src/systemd/sd-daemon.h
new file mode 100644
index 0000000..46dc7fd
--- /dev/null
+++ b/src/systemd/sd-daemon.h
@@ -0,0 +1,277 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef foosddaemonhfoo
+#define foosddaemonhfoo
+
+/***
+  Copyright 2010 Lennart Poettering
+
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation files
+  (the "Software"), to deal in the Software without restriction,
+  including without limitation the rights to use, copy, modify, merge,
+  publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so,
+  subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+***/
+
+#include <sys/types.h>
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+  Reference implementation of a few systemd related interfaces for
+  writing daemons. These interfaces are trivial to implement. To
+  simplify porting we provide this reference implementation.
+  Applications are welcome to reimplement the algorithms described
+  here if they do not want to include these two source files.
+
+  The following functionality is provided:
+
+  - Support for logging with log levels on stderr
+  - File descriptor passing for socket-based activation
+  - Daemon startup and status notification
+  - Detection of systemd boots
+
+  You may compile this with -DDISABLE_SYSTEMD to disable systemd
+  support. This makes all those calls NOPs that are directly related to
+  systemd (i.e. only sd_is_xxx() will stay useful).
+
+  Since this is drop-in code we don't want any of our symbols to be
+  exported in any case. Hence we declare hidden visibility for all of
+  them.
+
+  You may find an up-to-date version of these source files online:
+
+  http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h
+  http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c
+
+  This should compile on non-Linux systems, too, but with the
+  exception of the sd_is_xxx() calls all functions will become NOPs.
+
+  See sd-daemon(7) for more information.
+*/
+
+#ifndef _sd_printf_attr_
+#if __GNUC__ >= 4
+#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
+#else
+#define _sd_printf_attr_(a,b)
+#endif
+#endif
+
+/*
+  Log levels for usage on stderr:
+
+          fprintf(stderr, SD_NOTICE "Hello World!\n");
+
+  This is similar to printk() usage in the kernel.
+*/
+#define SD_EMERG   "<0>"  /* system is unusable */
+#define SD_ALERT   "<1>"  /* action must be taken immediately */
+#define SD_CRIT    "<2>"  /* critical conditions */
+#define SD_ERR     "<3>"  /* error conditions */
+#define SD_WARNING "<4>"  /* warning conditions */
+#define SD_NOTICE  "<5>"  /* normal but significant condition */
+#define SD_INFO    "<6>"  /* informational */
+#define SD_DEBUG   "<7>"  /* debug-level messages */
+
+/* The first passed file descriptor is fd 3 */
+#define SD_LISTEN_FDS_START 3
+
+/*
+  Returns how many file descriptors have been passed, or a negative
+  errno code on failure. Optionally, removes the $LISTEN_FDS and
+  $LISTEN_PID file descriptors from the environment (recommended, but
+  problematic in threaded environments). If r is the return value of
+  this function you'll find the file descriptors passed as fds
+  SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative
+  errno style error code on failure. This function call ensures that
+  the FD_CLOEXEC flag is set for the passed file descriptors, to make
+  sure they are not passed on to child processes. If FD_CLOEXEC shall
+  not be set, the caller needs to unset it after this call for all file
+  descriptors that are used.
+
+  See sd_listen_fds(3) for more information.
+*/
+int sd_listen_fds(int unset_environment);
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is a FIFO in the file system stored under the
+  specified path, 0 otherwise. If path is NULL a path name check will
+  not be done and the call only verifies if the file descriptor
+  refers to a FIFO. Returns a negative errno style error code on
+  failure.
+
+  See sd_is_fifo(3) for more information.
+*/
+int sd_is_fifo(int fd, const char *path);
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is a special character device on the file
+  system stored under the specified path, 0 otherwise.
+  If path is NULL a path name check will not be done and the call
+  only verifies if the file descriptor refers to a special character.
+  Returns a negative errno style error code on failure.
+
+  See sd_is_special(3) for more information.
+*/
+int sd_is_special(int fd, const char *path);
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is a socket of the specified family (AF_INET,
+  ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If
+  family is 0 a socket family check will not be done. If type is 0 a
+  socket type check will not be done and the call only verifies if
+  the file descriptor refers to a socket. If listening is > 0 it is
+  verified that the socket is in listening mode. (i.e. listen() has
+  been called) If listening is == 0 it is verified that the socket is
+  not in listening mode. If listening is < 0 no listening mode check
+  is done. Returns a negative errno style error code on failure.
+
+  See sd_is_socket(3) for more information.
+*/
+int sd_is_socket(int fd, int family, int type, int listening);
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is an Internet socket, of the specified family
+  (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM,
+  SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version
+  check is not done. If type is 0 a socket type check will not be
+  done. If port is 0 a socket port check will not be done. The
+  listening flag is used the same way as in sd_is_socket(). Returns a
+  negative errno style error code on failure.
+
+  See sd_is_socket_inet(3) for more information.
+*/
+int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port);
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is an AF_UNIX socket of the specified type
+  (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0
+  a socket type check will not be done. If path is NULL a socket path
+  check will not be done. For normal AF_UNIX sockets set length to
+  0. For abstract namespace sockets set length to the length of the
+  socket name (including the initial 0 byte), and pass the full
+  socket path in path (including the initial 0 byte). The listening
+  flag is used the same way as in sd_is_socket(). Returns a negative
+  errno style error code on failure.
+
+  See sd_is_socket_unix(3) for more information.
+*/
+int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length);
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is a POSIX Message Queue of the specified name,
+  0 otherwise. If path is NULL a message queue name check is not
+  done. Returns a negative errno style error code on failure.
+*/
+int sd_is_mq(int fd, const char *path);
+
+/*
+  Informs systemd about changed daemon state. This takes a number of
+  newline separated environment-style variable assignments in a
+  string. The following variables are known:
+
+     READY=1      Tells systemd that daemon startup is finished (only
+                  relevant for services of Type=notify). The passed
+                  argument is a boolean "1" or "0". Since there is
+                  little value in signaling non-readiness the only
+                  value daemons should send is "READY=1".
+
+     STATUS=...   Passes a single-line status string back to systemd
+                  that describes the daemon state. This is free-from
+                  and can be used for various purposes: general state
+                  feedback, fsck-like programs could pass completion
+                  percentages and failing programs could pass a human
+                  readable error message. Example: "STATUS=Completed
+                  66% of file system check..."
+
+     ERRNO=...    If a daemon fails, the errno-style error code,
+                  formatted as string. Example: "ERRNO=2" for ENOENT.
+
+     BUSERROR=... If a daemon fails, the D-Bus error-style error
+                  code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut"
+
+     MAINPID=...  The main pid of a daemon, in case systemd did not
+                  fork off the process itself. Example: "MAINPID=4711"
+
+  Daemons can choose to send additional variables. However, it is
+  recommended to prefix variable names not listed above with X_.
+
+  Returns a negative errno-style error code on failure. Returns > 0
+  if systemd could be notified, 0 if it couldn't possibly because
+  systemd is not running.
+
+  Example: When a daemon finished starting up, it could issue this
+  call to notify systemd about it:
+
+     sd_notify(0, "READY=1");
+
+  See sd_notifyf() for more complete examples.
+
+  See sd_notify(3) for more information.
+*/
+int sd_notify(int unset_environment, const char *state);
+
+/*
+  Similar to sd_notify() but takes a format string.
+
+  Example 1: A daemon could send the following after initialization:
+
+     sd_notifyf(0, "READY=1\n"
+                   "STATUS=Processing requests...\n"
+                   "MAINPID=%lu",
+                   (unsigned long) getpid());
+
+  Example 2: A daemon could send the following shortly before
+  exiting, on failure:
+
+     sd_notifyf(0, "STATUS=Failed to start up: %s\n"
+                   "ERRNO=%i",
+                   strerror(errno),
+                   errno);
+
+  See sd_notifyf(3) for more information.
+*/
+int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3);
+
+/*
+  Returns > 0 if the system was booted with systemd. Returns < 0 on
+  error. Returns 0 if the system was not booted with systemd. Note
+  that all of the functions above handle non-systemd boots just
+  fine. You should NOT protect them with a call to this function. Also
+  note that this function checks whether the system, not the user
+  session is controlled by systemd. However the functions above work
+  for both user and system services.
+
+  See sd_booted(3) for more information.
+*/
+int sd_booted(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h
new file mode 100644
index 0000000..d835cf4
--- /dev/null
+++ b/src/systemd/sd-id128.h
@@ -0,0 +1,63 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef fooid128hfoo
+#define fooid128hfoo
+
+/***
+  This file is part of systemd.
+
+  Copyright 2011 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 <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+
+typedef union sd_id128 sd_id128_t;
+
+union sd_id128 {
+        uint8_t bytes[16];
+        uint64_t qwords[2];
+};
+
+char *sd_id128_to_string(sd_id128_t id, char s[33]);
+
+int sd_id128_from_string(const char s[33], sd_id128_t *ret);
+
+int sd_id128_randomize(sd_id128_t *ret);
+
+sd_id128_t sd_id128_make_v4_uuid(sd_id128_t id);
+
+int sd_id128_get_machine(sd_id128_t *ret);
+
+int sd_id128_get_boot(sd_id128_t *ret);
+
+#define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \
+        ((sd_id128_t) { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \
+                                   0x##v8, 0x##v9, 0x##v10, 0x##v11, 0x##v12, 0x##v13, 0x##v14, 0x##v15 }})
+
+/* Note that SD_ID128_FORMAT_VAL will evaluate the passed argument 16
+ * times. It is hence not a good idea to call this macro with an
+ * expensive function as paramater or an expression with side
+ * effects */
+#define SD_ID128_FORMAT_STR "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+#define SD_ID128_FORMAT_VAL(x) (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15]
+
+static inline bool sd_id128_equal(sd_id128_t a, sd_id128_t b) {
+        return memcmp(&a, &b, 16) == 0;
+}
+
+#endif
diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
new file mode 100644
index 0000000..87da17d
--- /dev/null
+++ b/src/systemd/sd-journal.h
@@ -0,0 +1,124 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef foojournalhfoo
+#define foojournalhfoo
+
+/***
+  This file is part of systemd.
+
+  Copyright 2011 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 <inttypes.h>
+#include <sys/types.h>
+#include <stdarg.h>
+#include <sys/uio.h>
+
+#include "sd-id128.h"
+
+/* TODO:
+ *
+ *   - add options for copy-to-console, copy-to-kmsg
+ *   - OR of matches is borked...
+ *   - extend hash tables table as we go
+ *   - accelerate looking for "all hostnames" and suchlike.
+ *   - handle incomplete header
+ *
+ *   - local deserializer
+ *   - http server
+ *   - message catalog
+ *
+ *   - check LE/BE conversion for 8bit, 16bit, 32bit values
+ *   - cryptographic hash
+ *   - think about manipulations of header
+ *   - implement audit gateway
+ */
+
+/* Write to daemon */
+
+int sd_journal_print(int piority, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+int sd_journal_printv(int priority, const char *format, va_list ap);
+
+int sd_journal_send(const char *format, ...) __attribute__((sentinel));
+int sd_journal_sendv(const struct iovec *iov, int n);
+
+int sd_journal_stream_fd(const char *tag, int priority, int priority_prefix);
+
+/* Browse journal stream */
+
+typedef struct sd_journal sd_journal;
+
+enum {
+        SD_JOURNAL_LOCAL_ONLY = 1,
+        SD_JOURNAL_RUNTIME_ONLY = 2,
+        SD_JOURNAL_SYSTEM_ONLY = 4
+};
+
+int sd_journal_open(sd_journal **ret, int flags);
+void sd_journal_close(sd_journal *j);
+
+int sd_journal_previous(sd_journal *j);
+int sd_journal_next(sd_journal *j);
+
+int sd_journal_previous_skip(sd_journal *j, uint64_t skip);
+int sd_journal_next_skip(sd_journal *j, uint64_t skip);
+
+int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret);
+int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id);
+int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l);
+int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l);
+void sd_journal_restart_data(sd_journal *j);
+
+int sd_journal_add_match(sd_journal *j, const void *data, size_t size);
+void sd_journal_flush_matches(sd_journal *j);
+
+int sd_journal_seek_head(sd_journal *j);
+int sd_journal_seek_tail(sd_journal *j);
+int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec);
+int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec);
+int sd_journal_seek_cursor(sd_journal *j, const char *cursor);
+
+int sd_journal_get_cursor(sd_journal *j, char **cursor);
+
+int sd_journal_query_unique(sd_journal *j, const char *field);      /* missing */
+int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l); /* missing */
+void sd_journal_restart_unique(sd_journal *j);                      /* missing */
+
+enum {
+        SD_JOURNAL_NOP,
+        SD_JOURNAL_APPEND,
+        SD_JOURNAL_INVALIDATE_ADD,
+        SD_JOURNAL_INVALIDATE_REMOVE
+};
+
+int sd_journal_get_fd(sd_journal *j);
+int sd_journal_process(sd_journal *j);
+
+#define SD_JOURNAL_FOREACH(j)                                           \
+        if (sd_journal_seek_head(j) >= 0)                               \
+                while (sd_journal_next(j) > 0)
+
+#define SD_JOURNAL_FOREACH_BACKWARDS(j)                                 \
+        if (sd_journal_seek_tail(j) >= 0)                               \
+                while (sd_journal_previous(j) > 0)
+
+#define SD_JOURNAL_FOREACH_DATA(j, data, l)                             \
+        for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
+
+#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l)                           \
+        for (sd_journal_restart_unique(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
+
+#endif
diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h
new file mode 100644
index 0000000..00de671
--- /dev/null
+++ b/src/systemd/sd-login.h
@@ -0,0 +1,125 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef foosdloginhfoo
+#define foosdloginhfoo
+
+/***
+  This file is part of systemd.
+
+  Copyright 2011 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 <sys/types.h>
+
+/*
+ * A few points:
+ *
+ * Instead of returning an empty string array or empty uid array, we
+ * may return NULL.
+ *
+ * Free the data we return with libc free().
+ *
+ * We return error codes as negative errno, kernel-style. 0 or
+ * positive on success.
+ *
+ * These functions access data in /proc, /sys/fs/cgroup and /run. All
+ * of these are virtual file systems, hence the accesses are
+ * relatively cheap.
+ */
+
+/* Get session from PID. Note that 'shared' processes of a user are
+ * not attached to a session, but only attached to a user. This will
+ * return an error for system processes and 'shared' processes of a
+ * user. */
+int sd_pid_get_session(pid_t pid, char **session);
+
+/* Get UID of the owner of the session of the PID (or in case the
+ * process is a 'shared' user process the UID of that user is
+ * returned). This will not return the UID of the process, but rather
+ * the UID of the owner of the cgroup the process is in. This will
+ * return an error for system processes. */
+int sd_pid_get_owner_uid(pid_t pid, uid_t *uid);
+
+/* Get systemd unit (i.e. service) name from PID. This will return an
+ * error for non-service processes. */
+int sd_pid_get_unit(pid_t, char **unit);
+
+/* Get state from uid. Possible states: offline, lingering, online, active */
+int sd_uid_get_state(uid_t uid, char**state);
+
+/* Return 1 if uid has session on seat. If require_active is true will
+ * look for active sessions only. */
+int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat);
+
+/* Return sessions of user. If require_active is true will look for
+ * active sessions only. Returns number of sessions as return
+ * value. If sessions is NULL will just return number of sessions. */
+int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions);
+
+/* Return seats of user is on. If require_active is true will look for
+ * active seats only.  Returns number of seats. If seats is NULL will
+ * just return number of seats.*/
+int sd_uid_get_seats(uid_t uid, int require_active, char ***seats);
+
+/* Return 1 if the session is a active */
+int sd_session_is_active(const char *session);
+
+/* Determine user id of session */
+int sd_session_get_uid(const char *session, uid_t *uid);
+
+/* Determine seat of session */
+int sd_session_get_seat(const char *session, char **seat);
+
+/* Return active session and user of seat */
+int sd_seat_get_active(const char *seat, char **session, uid_t *uid);
+
+/* Return sessions and users on seat. Returns number of sessions as
+ * return value. If sessions is NULL returns only the number of
+ * sessions. */
+int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids);
+
+/* Return whether the seat is multi-session capable */
+int sd_seat_can_multi_session(const char *seat);
+
+/* Get all seats, store in *seats. Returns the number of seats. If
+ * seats is NULL only returns number of seats. */
+int sd_get_seats(char ***seats);
+
+/* Get all sessions, store in *sessions. Returns the number of
+ * sessions. If sessions is NULL only returns number of sessions. */
+int sd_get_sessions(char ***sessions);
+
+/* Get all logged in users, store in *users. Returns the number of
+ * users. If users is NULL only returns the number of users. */
+int sd_get_uids(uid_t **users);
+
+/* Monitor object */
+typedef struct sd_login_monitor sd_login_monitor;
+
+/* Create a new monitor. Category must be NULL, "seat", "session",
+ * "uid" to get monitor events for the specific category (or all). */
+int sd_login_monitor_new(const char *category, sd_login_monitor** ret);
+
+/* Destroys the passed monitor. Returns NULL. */
+sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m);
+
+/* Flushes the monitor */
+int sd_login_monitor_flush(sd_login_monitor *m);
+
+/* Get FD from monitor */
+int sd_login_monitor_get_fd(sd_login_monitor *m);
+
+#endif
diff --git a/src/systemd/sd-readahead.h b/src/systemd/sd-readahead.h
new file mode 100644
index 0000000..ee7e306
--- /dev/null
+++ b/src/systemd/sd-readahead.h
@@ -0,0 +1,73 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef foosdreadaheadhfoo
+#define foosdreadaheadhfoo
+
+/***
+  Copyright 2010 Lennart Poettering
+
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation files
+  (the "Software"), to deal in the Software without restriction,
+  including without limitation the rights to use, copy, modify, merge,
+  publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so,
+  subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+***/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+  Reference implementation of a few boot readahead related
+  interfaces. These interfaces are trivial to implement. To simplify
+  porting we provide this reference implementation.  Applications are
+  welcome to reimplement the algorithms described here if they do not
+  want to include these two source files.
+
+  You may compile this with -DDISABLE_SYSTEMD to disable systemd
+  support. This makes all calls NOPs.
+
+  Since this is drop-in code we don't want any of our symbols to be
+  exported in any case. Hence we declare hidden visibility for all of
+  them.
+
+  You may find an up-to-date version of these source files online:
+
+  http://cgit.freedesktop.org/systemd/plain/src/sd-readahead.h
+  http://cgit.freedesktop.org/systemd/plain/src/sd-readahead.c
+
+  This should compile on non-Linux systems, too, but all functions
+  will become NOPs.
+
+  See sd-readahead(7) for more information.
+*/
+
+/*
+  Controls ongoing disk read-ahead operations during boot-up. The argument
+  must be a string, and either "cancel", "done" or "noreplay".
+
+  cancel = terminate read-ahead data collection, drop collected information
+  done = terminate read-ahead data collection, keep collected information
+  noreplay = terminate read-ahead replay
+*/
+int sd_readahead(const char *action);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/test-daemon.c b/src/test-daemon.c
index c7600d4..20c5d15 100644
--- a/src/test-daemon.c
+++ b/src/test-daemon.c
@@ -21,7 +21,7 @@
 
 #include <unistd.h>
 
-#include "sd-daemon.h"
+#include <systemd/sd-daemon.h>
 
 int main(int argc, char*argv[]) {
 
diff --git a/src/test-id128.c b/src/test-id128.c
index d7c9d43..617c955 100644
--- a/src/test-id128.c
+++ b/src/test-id128.c
@@ -21,7 +21,8 @@
 
 #include <string.h>
 
-#include "sd-id128.h"
+#include <systemd/sd-id128.h>
+
 #include "util.h"
 #include "macro.h"
 

commit 67e5cc4f3ed41feaed399cfed77c6fbb41e14a8c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 5 15:35:16 2012 +0100

    util: never ellipsize welcome message

diff --git a/src/unit.c b/src/unit.c
index dea8f4a..3191071 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -2455,7 +2455,7 @@ void unit_status_printf(Unit *u, const char *status, const char *format, ...) {
                 return;
 
         va_start(ap, format);
-        status_vprintf(status, format, ap);
+        status_vprintf(status, true, format, ap);
         va_end(ap);
 }
 
diff --git a/src/util.c b/src/util.c
index 72eb059..d3d521b 100644
--- a/src/util.c
+++ b/src/util.c
@@ -3577,7 +3577,7 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
         }
 }
 
-void status_vprintf(const char *status, const char *format, va_list ap) {
+void status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
         char *s = NULL, *spaces = NULL, *e;
         int fd = -1, c;
         size_t emax, sl, left;
@@ -3592,38 +3592,42 @@ void status_vprintf(const char *status, const char *format, va_list ap) {
         if (vasprintf(&s, format, ap) < 0)
                 goto finish;
 
-        fd = open_terminal("/dev/tty", O_WRONLY|O_NOCTTY|O_CLOEXEC);
+        fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
         if (fd < 0)
                 goto finish;
 
-        c = fd_columns(fd);
-        if (c <= 0)
-                c = 80;
+        if (ellipse) {
+                c = fd_columns(fd);
+                if (c <= 0)
+                        c = 80;
 
-        if (status) {
-                sl = 2 + 6 + 1; /* " [" status "]" */
-                emax = (size_t) c > sl ? c - sl - 1 : 0;
-        } else
-                emax = c - 1;
+                if (status) {
+                        sl = 2 + 6 + 1; /* " [" status "]" */
+                        emax = (size_t) c > sl ? c - sl - 1 : 0;
+                } else
+                        emax = c - 1;
 
-        e = ellipsize(s, emax, 75);
-        if (e) {
-                free(s);
-                s = e;
+                e = ellipsize(s, emax, 75);
+                if (e) {
+                        free(s);
+                        s = e;
+                }
         }
 
         zero(iovec);
         IOVEC_SET_STRING(iovec[n++], s);
 
-        sl = strlen(s);
-        left = emax > sl ? emax - sl : 0;
-        if (left > 0) {
-                spaces = malloc(left);
-                if (spaces) {
-                        memset(spaces, ' ', left);
-                        iovec[n].iov_base = spaces;
-                        iovec[n].iov_len = left;
-                        n++;
+        if (ellipse) {
+                sl = strlen(s);
+                left = emax > sl ? emax - sl : 0;
+                if (left > 0) {
+                        spaces = malloc(left);
+                        if (spaces) {
+                                memset(spaces, ' ', left);
+                                iovec[n].iov_base = spaces;
+                                iovec[n].iov_len = left;
+                                n++;
+                        }
                 }
         }
 
@@ -3644,13 +3648,13 @@ finish:
                 close_nointr_nofail(fd);
 }
 
-void status_printf(const char *status, const char *format, ...) {
+void status_printf(const char *status, bool ellipse, const char *format, ...) {
         va_list ap;
 
         assert(format);
 
         va_start(ap, format);
-        status_vprintf(status, format, ap);
+        status_vprintf(status, ellipse, format, ap);
         va_end(ap);
 }
 
@@ -3808,6 +3812,7 @@ void status_welcome(void) {
                 const_color = "1";
 
         status_printf(NULL,
+                      false,
                       "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
                       const_color ? const_color : ansi_color,
                       const_pretty ? const_pretty : pretty_name);
diff --git a/src/util.h b/src/util.h
index d96ce7e..4d27c4b 100644
--- a/src/util.h
+++ b/src/util.h
@@ -374,8 +374,8 @@ int pipe_eof(int fd);
 
 cpu_set_t* cpu_set_malloc(unsigned *ncpus);
 
-void status_vprintf(const char *status, const char *format, va_list ap);
-void status_printf(const char *status, const char *format, ...);
+void status_vprintf(const char *status, bool ellipse, const char *format, va_list ap);
+void status_printf(const char *status, bool ellipse, const char *format, ...);
 void status_welcome(void);
 
 int fd_columns(int fd);

commit 224f2ee221e77c326d1d7761abb6e812432b2163
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 5 15:34:13 2012 +0100

    journald: add configuration file options to forward all logged data to kmsg, console, syslog

diff --git a/Makefile.am b/Makefile.am
index 7eea06f..e668c09 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1290,7 +1290,8 @@ noinst_PROGRAMS += \
 	test-journal
 
 pkginclude_HEADERS += \
-	src/journal/sd-journal.h
+	src/journal/sd-journal.h \
+        src/journal/sd-messages.h
 
 lib_LTLIBRARIES += \
 	libsystemd-journal.la
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index db5dbc0..e7e3fa2 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -237,7 +237,7 @@ _public_ int sd_journal_stream_fd(const char *tag, int priority, int priority_pr
                 tag = "";
 
         l = strlen(tag);
-        header = alloca(l + 1 + 2 + 2 + 2);
+        header = alloca(l + 1 + 2 + 2 + 2 + 2 + 2);
 
         memcpy(header, tag, l);
         header[l++] = '\n';
@@ -247,6 +247,10 @@ _public_ int sd_journal_stream_fd(const char *tag, int priority, int priority_pr
         header[l++] = '\n';
         header[l++] = '0';
         header[l++] = '\n';
+        header[l++] = '0';
+        header[l++] = '\n';
+        header[l++] = '0';
+        header[l++] = '\n';
 
         r = loop_write(fd, header, l, false);
         if (r < 0) {
diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf
index ace373b..26e85b4 100644
--- a/src/journal/journald-gperf.gperf
+++ b/src/journal/journald-gperf.gperf
@@ -25,3 +25,6 @@ Journal.RuntimeMaxUse,      config_parse_bytes,    0, offsetof(Server, runtime_m
 Journal.RuntimeMaxFileSize, config_parse_bytes,    0, offsetof(Server, runtime_metrics.max_size)
 Journal.RuntimeMinFileSize, config_parse_bytes,    0, offsetof(Server, runtime_metrics.min_size)
 Journal.RuntimeKeepFree,    config_parse_bytes,    0, offsetof(Server, runtime_metrics.keep_free)
+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)
diff --git a/src/journal/journald.c b/src/journal/journald.c
index 68c1c23..d6206a8 100644
--- a/src/journal/journald.c
+++ b/src/journal/journald.c
@@ -44,6 +44,7 @@
 #include "sd-login.h"
 #include "journal-internal.h"
 #include "conf-parser.h"
+#include "sd-messages.h"
 #include "journald.h"
 
 #define USER_JOURNALS_MAX 1024
@@ -58,11 +59,15 @@
 
 #define SYSLOG_TIMEOUT_USEC (5*USEC_PER_SEC)
 
+#define N_IOVEC_META_FIELDS 16
+
 typedef enum StdoutStreamState {
         STDOUT_STREAM_TAG,
         STDOUT_STREAM_PRIORITY,
         STDOUT_STREAM_PRIORITY_PREFIX,
-        STDOUT_STREAM_TEE_CONSOLE,
+        STDOUT_STREAM_FORWARD_TO_SYSLOG,
+        STDOUT_STREAM_FORWARD_TO_KMSG,
+        STDOUT_STREAM_FORWARD_TO_CONSOLE,
         STDOUT_STREAM_RUNNING
 } StdoutStreamState;
 
@@ -77,7 +82,9 @@ struct StdoutStream {
         char *tag;
         int priority;
         bool priority_prefix:1;
-        bool tee_console:1;
+        bool forward_to_syslog:1;
+        bool forward_to_kmsg:1;
+        bool forward_to_console:1;
 
         char buffer[LINE_MAX+1];
         size_t length;
@@ -412,7 +419,7 @@ static void dispatch_message_real(Server *s,
         assert(s);
         assert(iovec);
         assert(n > 0);
-        assert(n + 16 <= m);
+        assert(n + N_IOVEC_META_FIELDS <= m);
 
         if (ucred) {
                 uint32_t audit;
@@ -567,6 +574,38 @@ retry:
         free(unit);
 }
 
+static void driver_message(Server *s, sd_id128_t message_id, const char *format, ...) {
+        char mid[11 + 32 + 1];
+        char buffer[16 + LINE_MAX + 1];
+        struct iovec iovec[N_IOVEC_META_FIELDS + 3];
+        int n = 0;
+        va_list ap;
+        struct ucred ucred;
+
+        assert(s);
+        assert(format);
+
+        IOVEC_SET_STRING(iovec[n++], "PRIORITY=5");
+
+        memcpy(buffer, "MESSAGE=", 8);
+        va_start(ap, format);
+        vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap);
+        va_end(ap);
+        char_array_0(buffer);
+        IOVEC_SET_STRING(iovec[n++], buffer);
+
+        snprintf(mid, sizeof(mid), "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(message_id));
+        char_array_0(mid);
+        IOVEC_SET_STRING(iovec[n++], mid);
+
+        zero(ucred);
+        ucred.pid = getpid();
+        ucred.uid = getuid();
+        ucred.gid = getgid();
+
+        dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL);
+}
+
 static void dispatch_message(Server *s,
                              struct iovec *iovec, unsigned n, unsigned m,
                              struct ucred *ucred,
@@ -604,62 +643,354 @@ static void dispatch_message(Server *s,
                 }
         }
 
-        rl = journal_rate_limit_test(s->rate_limit, path, priority, available_space(s));
+        rl = journal_rate_limit_test(s->rate_limit, path, priority & LOG_PRIMASK, available_space(s));
 
         if (rl == 0) {
                 free(path);
                 return;
         }
 
-        if (rl > 1) {
-                int j = 0;
-                char suppress_message[LINE_MAX];
-                struct iovec suppress_iovec[18];
+        /* Write a suppression message if we suppressed something */
+        if (rl > 1)
+                driver_message(s, SD_MESSAGE_JOURNAL_DROPPED, "Suppressed %u messages from %s", rl - 1, path);
+
+        free(path);
+
+finish:
+        dispatch_message_real(s, iovec, n, m, ucred, tv);
+}
+
+static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned n_iovec, struct ucred *ucred, struct timeval *tv) {
+        struct msghdr msghdr;
+        struct cmsghdr *cmsg;
+        union {
+                struct cmsghdr cmsghdr;
+                uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
+        } control;
+        union sockaddr_union sa;
+
+        assert(s);
+        assert(iovec);
+        assert(n_iovec > 0);
+
+        zero(msghdr);
+        msghdr.msg_iov = (struct iovec*) iovec;
+        msghdr.msg_iovlen = n_iovec;
+
+        zero(sa);
+        sa.un.sun_family = AF_UNIX;
+        strncpy(sa.un.sun_path, "/run/systemd/syslog", sizeof(sa.un.sun_path));
+        msghdr.msg_name = &sa;
+        msghdr.msg_namelen = offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path);
+
+        if (ucred) {
+                zero(control);
+                msghdr.msg_control = &control;
+                msghdr.msg_controllen = sizeof(control);
+
+                cmsg = CMSG_FIRSTHDR(&msghdr);
+                cmsg->cmsg_level = SOL_SOCKET;
+                cmsg->cmsg_type = SCM_CREDENTIALS;
+                cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
+                memcpy(CMSG_DATA(cmsg), ucred, sizeof(struct ucred));
+                msghdr.msg_controllen = cmsg->cmsg_len;
+        }
+
+        /* Forward the syslog message we received via /dev/log to
+         * /run/systemd/syslog. Unfortunately we currently can't set
+         * the SO_TIMESTAMP auxiliary data, and hence we don't. */
 
-                /* Write a suppression message if we suppressed something */
+        if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
+                return;
 
-                snprintf(suppress_message, sizeof(suppress_message), "MESSAGE=Suppressed %u messages from %s", rl - 1, path);
-                char_array_0(suppress_message);
+        if (ucred && errno == ESRCH) {
+                struct ucred u;
 
-                IOVEC_SET_STRING(suppress_iovec[j++], "PRIORITY=5");
-                IOVEC_SET_STRING(suppress_iovec[j++], suppress_message);
+                /* Hmm, presumably the sender process vanished
+                 * by now, so let's fix it as good as we
+                 * can, and retry */
 
-                dispatch_message_real(s, suppress_iovec, j, ELEMENTSOF(suppress_iovec), NULL, NULL);
+                u = *ucred;
+                u.pid = getpid();
+                memcpy(CMSG_DATA(cmsg), &u, sizeof(struct ucred));
+
+                if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
+                        return;
         }
 
-        free(path);
+        log_debug("Failed to forward syslog message: %m");
+}
+
+static void forward_syslog_raw(Server *s, const char *buffer, struct ucred *ucred, struct timeval *tv) {
+        struct iovec iovec;
+
+        assert(s);
+        assert(buffer);
+
+        IOVEC_SET_STRING(iovec, buffer);
+        forward_syslog_iovec(s, &iovec, 1, ucred, tv);
+}
+
+static void forward_syslog(Server *s, int priority, const char *tag, const char *message, struct ucred *ucred, struct timeval *tv) {
+        struct iovec iovec[5];
+        char header_priority[6], header_time[64], header_pid[16];
+        int n = 0;
+        time_t t;
+        struct tm *tm;
+        char *tag_buf = NULL;
+
+        assert(s);
+        assert(priority >= 0);
+        assert(priority <= 999);
+        assert(message);
+
+        /* First: priority field */
+        snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
+        char_array_0(header_priority);
+        IOVEC_SET_STRING(iovec[n++], header_priority);
+
+        /* Second: timestamp */
+        t = tv ? tv->tv_sec : ((time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC));
+        tm = localtime(&t);
+        if (!tm)
+                return;
+        if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
+                return;
+        IOVEC_SET_STRING(iovec[n++], header_time);
+
+        /* Third: tag and PID */
+        if (ucred) {
+                if (!tag) {
+                        get_process_comm(ucred->pid, &tag_buf);
+                        tag = tag_buf;
+                }
+
+                snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
+                char_array_0(header_pid);
+
+                if (tag)
+                        IOVEC_SET_STRING(iovec[n++], tag);
+
+                IOVEC_SET_STRING(iovec[n++], header_pid);
+        } else if (tag) {
+                IOVEC_SET_STRING(iovec[n++], tag);
+                IOVEC_SET_STRING(iovec[n++], ": ");
+        }
+
+        /* Fourth: message */
+        IOVEC_SET_STRING(iovec[n++], message);
+
+        forward_syslog_iovec(s, iovec, n, ucred, tv);
+
+        free(tag_buf);
+}
+
+static int fixup_priority(int priority) {
+
+        if ((priority & LOG_FACMASK) == 0)
+                return (priority & LOG_PRIMASK) | LOG_USER;
+
+        return priority;
+}
+
+static void forward_kmsg(Server *s, int priority, const char *tag, const char *message, struct ucred *ucred) {
+        struct iovec iovec[5];
+        char header_priority[6], header_pid[16];
+        int n = 0;
+        char *tag_buf = NULL;
+        int fd;
+
+        assert(s);
+        assert(priority >= 0);
+        assert(priority <= 999);
+        assert(message);
+
+        /* Never allow messages with kernel facility to be written to
+         * kmsg, regardless where the data comes from. */
+        priority = fixup_priority(priority);
+
+        /* First: priority field */
+        snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
+        char_array_0(header_priority);
+        IOVEC_SET_STRING(iovec[n++], header_priority);
+
+        /* Second: tag and PID */
+        if (ucred) {
+                if (!tag) {
+                        get_process_comm(ucred->pid, &tag_buf);
+                        tag = tag_buf;
+                }
+
+                snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
+                char_array_0(header_pid);
+
+                if (tag)
+                        IOVEC_SET_STRING(iovec[n++], tag);
+
+                IOVEC_SET_STRING(iovec[n++], header_pid);
+        } else if (tag) {
+                IOVEC_SET_STRING(iovec[n++], tag);
+                IOVEC_SET_STRING(iovec[n++], ": ");
+        }
+
+        /* Fourth: message */
+        IOVEC_SET_STRING(iovec[n++], message);
+        IOVEC_SET_STRING(iovec[n++], "\n");
+
+        fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0) {
+                log_debug("Failed to open /dev/kmsg for logging: %s", strerror(errno));
+                goto finish;
+        }
+
+        if (writev(fd, iovec, n) < 0)
+                log_debug("Failed to write to /dev/kmsg for logging: %s", strerror(errno));
+
+        close_nointr_nofail(fd);
 
 finish:
-        dispatch_message_real(s, iovec, n, m, ucred, tv);
+        free(tag_buf);
+}
+
+static void forward_console(Server *s, const char *tag, const char *message, struct ucred *ucred) {
+        struct iovec iovec[4];
+        char header_pid[16];
+        int n = 0, fd;
+        char *tag_buf = NULL;
+
+        assert(s);
+        assert(message);
+
+        /* First: tag and PID */
+        if (ucred) {
+                if (!tag) {
+                        get_process_comm(ucred->pid, &tag_buf);
+                        tag = tag_buf;
+                }
+
+                snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
+                char_array_0(header_pid);
+
+                if (tag)
+                        IOVEC_SET_STRING(iovec[n++], tag);
+
+                IOVEC_SET_STRING(iovec[n++], header_pid);
+        } else if (tag) {
+                IOVEC_SET_STRING(iovec[n++], tag);
+                IOVEC_SET_STRING(iovec[n++], ": ");
+        }
+
+        /* Third: message */
+        IOVEC_SET_STRING(iovec[n++], message);
+        IOVEC_SET_STRING(iovec[n++], "\n");
+
+        fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0) {
+                log_debug("Failed to open /dev/console for logging: %s", strerror(errno));
+                goto finish;
+        }
+
+        if (writev(fd, iovec, n) < 0)
+                log_debug("Failed to write to /dev/console for logging: %s", strerror(errno));
+
+        close_nointr_nofail(fd);
+
+finish:
+        free(tag_buf);
+}
+
+static void read_tag(const char **buf, char **tag) {
+        const char *p;
+        char *t;
+        size_t l, e;
+
+        assert(buf);
+        assert(tag);
+
+        p = *buf;
+
+        p += strspn(p, WHITESPACE);
+        l = strcspn(p, WHITESPACE);
+
+        if (l <= 0 ||
+            p[l-1] != ':')
+                return;
+
+        e = l;
+        l--;
+
+        if (p[l-1] == ']') {
+                size_t k = l-1;
+
+                for (;;) {
+
+                        if (p[k] == '[') {
+                                l = k;
+                                break;
+                        }
+
+                        if (k == 0)
+                                break;
+
+                        k--;
+                }
+        }
+
+        t = strndup(p, l);
+        if (t)
+                *tag = t;
+
+        *buf = p + e;
+        *buf += strspn(*buf, WHITESPACE);
 }
 
 static void process_syslog_message(Server *s, const char *buf, struct ucred *ucred, struct timeval *tv) {
-        char *message = NULL, *syslog_priority = NULL, *syslog_facility = NULL;
-        struct iovec iovec[19];
+        char *message = NULL, *syslog_priority = NULL, *syslog_facility = NULL, *syslog_tag = NULL;
+        struct iovec iovec[N_IOVEC_META_FIELDS + 4];
         unsigned n = 0;
         int priority = LOG_USER | LOG_INFO;
+        char *tag = NULL;
 
         assert(s);
         assert(buf);
 
+        if (s->forward_to_syslog)
+                forward_syslog_raw(s, buf, ucred, tv);
+
         parse_syslog_priority((char**) &buf, &priority);
         skip_syslog_date((char**) &buf);
+        read_tag(&buf, &tag);
+
+        if (s->forward_to_kmsg)
+                forward_kmsg(s, priority, tag, buf, ucred);
+
+        if (s->forward_to_console)
+                forward_console(s, tag, buf, ucred);
 
         if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0)
                 IOVEC_SET_STRING(iovec[n++], syslog_priority);
 
-        if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0)
-                IOVEC_SET_STRING(iovec[n++], syslog_facility);
+        if (priority & LOG_FACMASK)
+                if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0)
+                        IOVEC_SET_STRING(iovec[n++], syslog_facility);
+
+        if (tag) {
+                syslog_tag = strappend("SYSLOG_TAG=", tag);
+                if (syslog_tag)
+                        IOVEC_SET_STRING(iovec[n++], syslog_tag);
+        }
 
         message = strappend("MESSAGE=", buf);
         if (message)
                 IOVEC_SET_STRING(iovec[n++], message);
 
-        dispatch_message(s, iovec, n, ELEMENTSOF(iovec), ucred, tv, priority & LOG_PRIMASK);
+        dispatch_message(s, iovec, n, ELEMENTSOF(iovec), ucred, tv, priority);
 
         free(message);
-        free(syslog_facility);
+        free(tag);
         free(syslog_priority);
+        free(syslog_facility);
+        free(syslog_tag);
 }
 
 static bool valid_user_field(const char *p, size_t l) {
@@ -703,6 +1034,7 @@ static void process_native_message(Server *s, const void *buffer, size_t buffer_
         const char *p;
         size_t remaining;
         int priority = LOG_INFO;
+        char *tag = NULL, *message = NULL;
 
         assert(s);
         assert(buffer || n == 0);
@@ -742,11 +1074,11 @@ static void process_native_message(Server *s, const void *buffer, size_t buffer_
 
                 /* A property follows */
 
-                if (n+16 >= m) {
+                if (n+N_IOVEC_META_FIELDS >= m) {
                         struct iovec *c;
                         unsigned u;
 
-                        u = MAX((n+16U) * 2U, 4U);
+                        u = MAX((n+N_IOVEC_META_FIELDS) * 2U, 4U);
                         c = realloc(iovec, u * sizeof(struct iovec));
                         if (!c) {
                                 log_error("Out of memory");
@@ -760,22 +1092,56 @@ static void process_native_message(Server *s, const void *buffer, size_t buffer_
                 q = memchr(p, '=', e - p);
                 if (q) {
                         if (valid_user_field(p, q - p)) {
+                                size_t l;
+
+                                l = e - p;
+
                                 /* If the field name starts with an
                                  * underscore, skip the variable,
                                  * since that indidates a trusted
                                  * field */
                                 iovec[n].iov_base = (char*) p;
-                                iovec[n].iov_len = e - p;
+                                iovec[n].iov_len = l;
                                 n++;
 
                                 /* We need to determine the priority
                                  * of this entry for the rate limiting
                                  * logic */
-                                if (e - p == 10 &&
-                                    memcmp(p, "PRIORITY=", 10) == 0 &&
-                                    p[10] >= '0' &&
-                                    p[10] <= '9')
-                                        priority = p[10] - '0';
+                                if (l == 10 &&
+                                    memcmp(p, "PRIORITY=", 9) == 0 &&
+                                    p[9] >= '0' && p[9] <= '9')
+                                        priority = (priority & LOG_FACMASK) | (p[9] - '0');
+
+                                else if (l == 17 &&
+                                         memcmp(p, "SYSLOG_FACILITY=", 16) == 0 &&
+                                         p[16] >= '0' && p[16] <= '9')
+                                        priority = (priority & LOG_PRIMASK) | ((p[16] - '0') << 3);
+
+                                else if (l == 18 &&
+                                         memcmp(p, "SYSLOG_FACILITY=", 16) == 0 &&
+                                         p[16] >= '0' && p[16] <= '9' &&
+                                         p[17] >= '0' && p[17] <= '9')
+                                        priority = (priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3);
+
+                                else if (l >= 12 &&
+                                         memcmp(p, "SYSLOG_TAG=", 11) == 0) {
+                                        char *t;
+
+                                        t = strndup(p + 11, l - 11);
+                                        if (t) {
+                                                free(tag);
+                                                tag = t;
+                                        }
+                                } else if (l >= 8 &&
+                                           memcmp(p, "MESSAGE=", 8) == 0) {
+                                        char *t;
+
+                                        t = strndup(p + 8, l - 8);
+                                        if (t) {
+                                                free(message);
+                                                message = t;
+                                        }
+                                }
                         }
 
                         remaining -= (e - p) + 1;
@@ -821,19 +1187,32 @@ static void process_native_message(Server *s, const void *buffer, size_t buffer_
                 }
         }
 
+        if (message) {
+                if (s->forward_to_syslog)
+                        forward_syslog(s, priority, tag, message, ucred, tv);
+
+                if (s->forward_to_kmsg)
+                        forward_kmsg(s, priority, tag, message, ucred);
+
+                if (s->forward_to_console)
+                        forward_console(s, tag, message, ucred);
+        }
+
         dispatch_message(s, iovec, n, m, ucred, tv, priority);
 
         for (j = 0; j < n; j++)
                 if (iovec[j].iov_base < buffer ||
                     (const uint8_t*) iovec[j].iov_base >= (const uint8_t*) buffer + buffer_size)
                         free(iovec[j].iov_base);
+
+        free(tag);
+        free(message);
 }
 
-static int stdout_stream_log(StdoutStream *s, const char *p, size_t l) {
-        struct iovec iovec[18];
-        char *message = NULL, *syslog_priority = NULL;
+static int stdout_stream_log(StdoutStream *s, const char *p) {
+        struct iovec iovec[N_IOVEC_META_FIELDS + 4];
+        char *message = NULL, *syslog_priority = NULL, *syslog_facility = NULL, *syslog_tag = NULL;
         unsigned n = 0;
-        size_t tag_len;
         int priority;
 
         assert(s);
@@ -841,127 +1220,121 @@ static int stdout_stream_log(StdoutStream *s, const char *p, size_t l) {
 
         priority = s->priority;
 
-        if (s->priority_prefix &&
-            l > 3 &&
-            p[0] == '<' &&
-            p[1] >= '0' && p[1] <= '7' &&
-            p[2] == '>') {
+        if (s->priority_prefix)
+                parse_syslog_priority((char**) &p, &priority);
 
-                priority = p[1] - '0';
-                p += 3;
-                l -= 3;
-        }
+        if (s->forward_to_syslog || s->server->forward_to_syslog)
+                forward_syslog(s->server, fixup_priority(priority), s->tag, p, &s->ucred, NULL);
 
-        if (l <= 0)
-                return 0;
+        if (s->forward_to_kmsg || s->server->forward_to_kmsg)
+                forward_kmsg(s->server, priority, s->tag, p, &s->ucred);
 
-        if (asprintf(&syslog_priority, "PRIORITY=%i", priority) >= 0)
+        if (s->forward_to_console || s->server->forward_to_console)
+                forward_console(s->server, s->tag, p, &s->ucred);
+
+        if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0)
                 IOVEC_SET_STRING(iovec[n++], syslog_priority);
 
-        tag_len = s->tag ? strlen(s->tag) + 2: 0;
-        message = malloc(8 + tag_len + l);
-        if (message) {
-                memcpy(message, "MESSAGE=", 8);
+        if (priority & LOG_FACMASK)
+                if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0)
+                        IOVEC_SET_STRING(iovec[n++], syslog_facility);
 
-                if (s->tag) {
-                        memcpy(message+8, s->tag, tag_len-2);
-                        memcpy(message+8+tag_len-2, ": ", 2);
-                }
-
-                memcpy(message+8+tag_len, p, l);
-                iovec[n].iov_base = message;
-                iovec[n].iov_len = 8+tag_len+l;
-                n++;
+        if (s->tag) {
+                syslog_tag = strappend("SYSLOG_TAG=", s->tag);
+                if (syslog_tag)
+                        IOVEC_SET_STRING(iovec[n++], syslog_tag);
         }
 
-        dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, priority);
-
-        if (s->tee_console) {
-                int console;
-
-                console = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
-                if (console >= 0) {
-                        n = 0;
-                        if (s->tag) {
-                                IOVEC_SET_STRING(iovec[n++], s->tag);
-                                IOVEC_SET_STRING(iovec[n++], ": ");
-                        }
-
-                        iovec[n].iov_base = (void*) p;
-                        iovec[n].iov_len = l;
-                        n++;
-
-                        IOVEC_SET_STRING(iovec[n++], (char*) "\n");
+        message = strappend("MESSAGE=", p);
+        if (message)
+                IOVEC_SET_STRING(iovec[n++], message);
 
-                        writev(console, iovec, n);
-                }
-        }
+        dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, priority);
 
         free(message);
         free(syslog_priority);
+        free(syslog_facility);
+        free(syslog_tag);
 
         return 0;
 }
 
-static int stdout_stream_line(StdoutStream *s, const char *p, size_t l) {
+static int stdout_stream_line(StdoutStream *s, char *p) {
+        int r;
+
         assert(s);
         assert(p);
 
-        while (l > 0 && strchr(WHITESPACE, *p)) {
-                l--;
-                p++;
-        }
-
-        while (l > 0 && strchr(WHITESPACE, *(p+l-1)))
-                l--;
+        p = strstrip(p);
 
         switch (s->state) {
 
         case STDOUT_STREAM_TAG:
-
-                if (l > 0) {
-                        s->tag = strndup(p, l);
-                        if (!s->tag) {
-                                log_error("Out of memory");
-                                return -EINVAL;
-                        }
+                s->tag = strdup(p);
+                if (!s->tag) {
+                        log_error("Out of memory");
+                        return -ENOMEM;
                 }
 
                 s->state = STDOUT_STREAM_PRIORITY;
                 return 0;
 
         case STDOUT_STREAM_PRIORITY:
-                if (l != 1 || *p < '0' || *p > '7') {
+                r = safe_atoi(p, &s->priority);
+                if (r < 0 || s->priority <= 0 || s->priority >= 999) {
                         log_warning("Failed to parse log priority line.");
                         return -EINVAL;
                 }
 
-                s->priority = *p - '0';
                 s->state = STDOUT_STREAM_PRIORITY_PREFIX;
                 return 0;
 
         case STDOUT_STREAM_PRIORITY_PREFIX:
-                if (l != 1 || *p < '0' || *p > '1') {
+                r = parse_boolean(p);
+                if (r < 0) {
                         log_warning("Failed to parse priority prefix line.");
                         return -EINVAL;
                 }
 
-                s->priority_prefix = *p - '0';
-                s->state = STDOUT_STREAM_TEE_CONSOLE;
+                s->priority_prefix = !!r;
+                s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG;
                 return 0;
 
-        case STDOUT_STREAM_TEE_CONSOLE:
-                if (l != 1 || *p < '0' || *p > '1') {
-                        log_warning("Failed to parse tee to console line.");
+        case STDOUT_STREAM_FORWARD_TO_SYSLOG:
+                r = parse_boolean(p);
+                if (r < 0) {
+                        log_warning("Failed to parse forward to syslog line.");
                         return -EINVAL;
                 }
 
-                s->tee_console = *p - '0';
+                s->forward_to_syslog = !!r;
+                s->state = STDOUT_STREAM_FORWARD_TO_KMSG;
+                return 0;
+
+        case STDOUT_STREAM_FORWARD_TO_KMSG:
+                r = parse_boolean(p);
+                if (r < 0) {
+                        log_warning("Failed to parse copy to kmsg line.");
+                        return -EINVAL;
+                }
+
+                s->forward_to_kmsg = !!r;
+                s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE;
+                return 0;
+
+        case STDOUT_STREAM_FORWARD_TO_CONSOLE:
+                r = parse_boolean(p);
+                if (r < 0) {
+                        log_warning("Failed to parse copy to console line.");
+                        return -EINVAL;
+                }
+
+                s->forward_to_console = !!r;
                 s->state = STDOUT_STREAM_RUNNING;
                 return 0;
 
         case STDOUT_STREAM_RUNNING:
-                return stdout_stream_log(s, p, l);
+                return stdout_stream_log(s, p);
         }
 
         assert_not_reached("Unknown stream state");
@@ -981,16 +1354,17 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
                 size_t skip;
 
                 end = memchr(p, '\n', remaining);
-                if (!end) {
-                        if (remaining >= LINE_MAX) {
-                                end = p + LINE_MAX;
-                                skip = LINE_MAX;
-                        } else
-                                break;
-                } else
+                if (end)
                         skip = end - p + 1;
+                else if (remaining >= sizeof(s->buffer) - 1) {
+                        end = p + sizeof(s->buffer) - 1;
+                        skip = sizeof(s->buffer) - 1;
+                } else
+                        break;
+
+                *end = 0;
 
-                r = stdout_stream_line(s, p, end - p);
+                r = stdout_stream_line(s, p);
                 if (r < 0)
                         return r;
 
@@ -999,7 +1373,8 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
         }
 
         if (force_flush && remaining > 0) {
-                r = stdout_stream_line(s, p, remaining);
+                p[remaining] = 0;
+                r = stdout_stream_line(s, p);
                 if (r < 0)
                         return r;
 
@@ -1307,69 +1682,6 @@ finish:
         return r;
 }
 
-static void forward_syslog(Server *s, const void *buffer, size_t length, struct ucred *ucred, struct timeval *tv) {
-        struct msghdr msghdr;
-        struct iovec iovec;
-        struct cmsghdr *cmsg;
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
-                            CMSG_SPACE(sizeof(struct timeval))];
-        } control;
-        union sockaddr_union sa;
-
-        assert(s);
-
-        zero(msghdr);
-
-        zero(iovec);
-        iovec.iov_base = (void*) buffer;
-        iovec.iov_len = length;
-        msghdr.msg_iov = &iovec;
-        msghdr.msg_iovlen = 1;
-
-        zero(sa);
-        sa.un.sun_family = AF_UNIX;
-        strncpy(sa.un.sun_path, "/run/systemd/syslog", sizeof(sa.un.sun_path));
-        msghdr.msg_name = &sa;
-        msghdr.msg_namelen = offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path);
-
-        zero(control);
-        msghdr.msg_control = &control;
-        msghdr.msg_controllen = sizeof(control);
-
-        cmsg = CMSG_FIRSTHDR(&msghdr);
-        cmsg->cmsg_level = SOL_SOCKET;
-        cmsg->cmsg_type = SCM_CREDENTIALS;
-        cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
-        memcpy(CMSG_DATA(cmsg), ucred, sizeof(struct ucred));
-        msghdr.msg_controllen = cmsg->cmsg_len;
-
-        /* Forward the syslog message we received via /dev/log to
-         * /run/systemd/syslog. Unfortunately we currently can't set
-         * the SO_TIMESTAMP auxiliary data, and hence we don't. */
-
-        if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
-                return;
-
-        if (errno == ESRCH) {
-                struct ucred u;
-
-                /* Hmm, presumably the sender process vanished
-                 * by now, so let's fix it as good as we
-                 * can, and retry */
-
-                u = *ucred;
-                u.pid = getpid();
-                memcpy(CMSG_DATA(cmsg), &u, sizeof(struct ucred));
-
-                if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
-                        return;
-        }
-
-        log_debug("Failed to forward syslog message: %m");
-}
-
 static int process_event(Server *s, struct epoll_event *ev) {
         assert(s);
 
@@ -1490,7 +1802,6 @@ static int process_event(Server *s, struct epoll_event *ev) {
                                 else
                                         s->buffer[n] = 0;
 
-                                forward_syslog(s, s->buffer, n, ucred, tv);
                                 process_syslog_message(s, strstrip(s->buffer), ucred, tv);
                         } else
                                 process_native_message(s, s->buffer, n, ucred, tv);
@@ -1767,6 +2078,8 @@ static int server_init(Server *s) {
         s->rate_limit_interval = DEFAULT_RATE_LIMIT_INTERVAL;
         s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST;
 
+        s->forward_to_syslog = true;
+
         memset(&s->system_metrics, 0xFF, sizeof(s->system_metrics));
         memset(&s->runtime_metrics, 0xFF, sizeof(s->runtime_metrics));
 
@@ -1919,6 +2232,7 @@ int main(int argc, char *argv[]) {
         server_flush_to_var(&server);
 
         log_debug("systemd-journald running as pid %lu", (unsigned long) getpid());
+        driver_message(&server, SD_MESSAGE_JOURNAL_START, "Journal started");
 
         sd_notify(false,
                   "READY=1\n"
@@ -1947,6 +2261,7 @@ int main(int argc, char *argv[]) {
         }
 
         log_debug("systemd-journald stopped as pid %lu", (unsigned long) getpid());
+        driver_message(&server, SD_MESSAGE_JOURNAL_STOP, "Journal stopped");
 
 finish:
         sd_notify(false,
diff --git a/src/journal/journald.h b/src/journal/journald.h
index 47feca4..3da57c5 100644
--- a/src/journal/journald.h
+++ b/src/journal/journald.h
@@ -59,6 +59,10 @@ typedef struct Server {
 
         bool compress;
 
+        bool forward_to_kmsg;
+        bool forward_to_syslog;
+        bool forward_to_console;
+
         uint64_t cached_available_space;
         usec_t cached_available_space_timestamp;
 
diff --git a/src/journal/systemd-journald.conf b/src/journal/systemd-journald.conf
index f137ab8..7560257 100644
--- a/src/journal/systemd-journald.conf
+++ b/src/journal/systemd-journald.conf
@@ -19,3 +19,6 @@
 #RuntimeKeepFree=
 #RuntimeMaxFileSize=
 #RuntimeMinFileSize=
+#ForwardToSyslog=yes
+#ForwardToKMsg=no
+#ForwardToConsole=no

commit 674f8283698517047a7c0e78cff1e18932a97b05
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 5 03:25:10 2012 +0100

    log: minor optimization

diff --git a/src/log.c b/src/log.c
index 4f57821..3dfe654 100644
--- a/src/log.c
+++ b/src/log.c
@@ -95,7 +95,8 @@ static int log_open_kmsg(void) {
         if (kmsg_fd >= 0)
                 return 0;
 
-        if ((kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0) {
+        kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
+        if (kmsg_fd < 0) {
                 log_error("Failed to open /dev/kmsg for logging: %s", strerror(errno));
                 return -errno;
         }
@@ -265,14 +266,16 @@ static int write_to_console(
         if (console_fd < 0)
                 return 0;
 
-        snprintf(location, sizeof(location), "(%s:%u) ", file, line);
-        char_array_0(location);
-
         highlight = LOG_PRI(level) <= LOG_ERR && show_color;
 
         zero(iovec);
-        if (show_location)
+
+        if (show_location) {
+                snprintf(location, sizeof(location), "(%s:%u) ", file, line);
+                char_array_0(location);
                 IOVEC_SET_STRING(iovec[n++], location);
+        }
+
         if (highlight)
                 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_ON);
         IOVEC_SET_STRING(iovec[n++], buffer);

commit 81beb7508e72b29ae7cec60b50231cbe0c1d582e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 5 03:24:39 2012 +0100

    util: when printing status updates during boot, take terminal width into account

diff --git a/src/unit.c b/src/unit.c
index 03c90f5..dea8f4a 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -2441,9 +2441,6 @@ int unit_coldplug(Unit *u) {
 
 void unit_status_printf(Unit *u, const char *status, const char *format, ...) {
         va_list ap;
-        char *s, *e;
-        int err;
-        const unsigned emax = status ? 80 - (sizeof("[  OK  ]")-1) : 80;
 
         assert(u);
         assert(format);
@@ -2458,21 +2455,8 @@ void unit_status_printf(Unit *u, const char *status, const char *format, ...) {
                 return;
 
         va_start(ap, format);
-        err = vasprintf(&s, format, ap);
+        status_vprintf(status, format, ap);
         va_end(ap);
-        if (err < 0)
-                return;
-
-        e = ellipsize(s, emax, 100);
-        free(s);
-        if (!e)
-                return;
-
-        if (status)
-                status_printf("%s%*s[%s]\n", e, emax - strlen(e), "", status);
-        else
-                status_printf("%s\n", e);
-        free(e);
 }
 
 bool unit_need_daemon_reload(Unit *u) {
diff --git a/src/util.c b/src/util.c
index 8a6c3bb..72eb059 100644
--- a/src/util.c
+++ b/src/util.c
@@ -3577,9 +3577,12 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
         }
 }
 
-void status_vprintf(const char *format, va_list ap) {
-        char *s = NULL;
-        int fd = -1;
+void status_vprintf(const char *status, const char *format, va_list ap) {
+        char *s = NULL, *spaces = NULL, *e;
+        int fd = -1, c;
+        size_t emax, sl, left;
+        struct iovec iovec[5];
+        int n = 0;
 
         assert(format);
 
@@ -3589,25 +3592,65 @@ void status_vprintf(const char *format, va_list ap) {
         if (vasprintf(&s, format, ap) < 0)
                 goto finish;
 
-        if ((fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0)
+        fd = open_terminal("/dev/tty", O_WRONLY|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0)
                 goto finish;
 
-        write(fd, s, strlen(s));
+        c = fd_columns(fd);
+        if (c <= 0)
+                c = 80;
+
+        if (status) {
+                sl = 2 + 6 + 1; /* " [" status "]" */
+                emax = (size_t) c > sl ? c - sl - 1 : 0;
+        } else
+                emax = c - 1;
+
+        e = ellipsize(s, emax, 75);
+        if (e) {
+                free(s);
+                s = e;
+        }
+
+        zero(iovec);
+        IOVEC_SET_STRING(iovec[n++], s);
+
+        sl = strlen(s);
+        left = emax > sl ? emax - sl : 0;
+        if (left > 0) {
+                spaces = malloc(left);
+                if (spaces) {
+                        memset(spaces, ' ', left);
+                        iovec[n].iov_base = spaces;
+                        iovec[n].iov_len = left;
+                        n++;
+                }
+        }
+
+        if (status) {
+                IOVEC_SET_STRING(iovec[n++], " [");
+                IOVEC_SET_STRING(iovec[n++], status);
+                IOVEC_SET_STRING(iovec[n++], "]\n");
+        } else
+                IOVEC_SET_STRING(iovec[n++], "\n");
+
+        writev(fd, iovec, n);
 
 finish:
         free(s);
+        free(spaces);
 
         if (fd >= 0)
                 close_nointr_nofail(fd);
 }
 
-void status_printf(const char *format, ...) {
+void status_printf(const char *status, const char *format, ...) {
         va_list ap;
 
         assert(format);
 
         va_start(ap, format);
-        status_vprintf(format, ap);
+        status_vprintf(status, format, ap);
         va_end(ap);
 }
 
@@ -3764,7 +3807,8 @@ void status_welcome(void) {
         if (!ansi_color && !const_color)
                 const_color = "1";
 
-        status_printf("\nWelcome to \x1B[%sm%s\x1B[0m!\n\n",
+        status_printf(NULL,
+                      "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
                       const_color ? const_color : ansi_color,
                       const_pretty ? const_pretty : pretty_name);
 
@@ -3906,6 +3950,19 @@ char **replace_env_argv(char **argv, char **env) {
         return r;
 }
 
+int fd_columns(int fd) {
+        struct winsize ws;
+        zero(ws);
+
+        if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
+                return -errno;
+
+        if (ws.ws_col <= 0)
+                return -EIO;
+
+        return ws.ws_col;
+}
+
 unsigned columns(void) {
         static __thread int parsed_columns = 0;
         const char *e;
@@ -3913,16 +3970,12 @@ unsigned columns(void) {
         if (_likely_(parsed_columns > 0))
                 return parsed_columns;
 
-        if ((e = getenv("COLUMNS")))
+        e = getenv("COLUMNS");
+        if (e)
                 parsed_columns = atoi(e);
 
-        if (parsed_columns <= 0) {
-                struct winsize ws;
-                zero(ws);
-
-                if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0)
-                        parsed_columns = ws.ws_col;
-        }
+        if (parsed_columns <= 0)
+                parsed_columns = fd_columns(STDOUT_FILENO);
 
         if (parsed_columns <= 0)
                 parsed_columns = 80;
diff --git a/src/util.h b/src/util.h
index e285ec7..d96ce7e 100644
--- a/src/util.h
+++ b/src/util.h
@@ -374,10 +374,11 @@ int pipe_eof(int fd);
 
 cpu_set_t* cpu_set_malloc(unsigned *ncpus);
 
-void status_vprintf(const char *format, va_list ap);
-void status_printf(const char *format, ...);
+void status_vprintf(const char *status, const char *format, va_list ap);
+void status_printf(const char *status, const char *format, ...);
 void status_welcome(void);
 
+int fd_columns(int fd);
 unsigned columns(void);
 
 int running_in_chroot(void);



More information about the systemd-commits mailing list