[systemd-commits] 5 commits - .gitignore Makefile.am src/analyze src/bus-proxyd src/cgtop src/core src/delta src/firstboot src/fsck src/getty-generator src/import src/initctl src/journal src/journal-remote src/libsystemd src/libsystemd-network src/libsystemd-terminal src/libudev src/login src/machine src/network src/notify src/nspawn src/quotacheck src/resolve src/run src/shared src/shutdownd src/systemctl src/sysusers src/test src/timedate src/tmpfiles src/tty-ask-password-agent src/udev src/update-utmp src/vconsole

Ronny Chevalier rchevalier at kemper.freedesktop.org
Fri Apr 10 15:43:10 PDT 2015


 .gitignore                                          |    2 
 Makefile.am                                         |   20 
 src/analyze/analyze.c                               |    1 
 src/bus-proxyd/bus-proxyd.c                         |    1 
 src/bus-proxyd/bus-xml-policy.c                     |    1 
 src/bus-proxyd/proxy.c                              |    1 
 src/bus-proxyd/stdio-bridge.c                       |    1 
 src/cgtop/cgtop.c                                   |    1 
 src/core/automount.c                                |    2 
 src/core/busname.c                                  |    1 
 src/core/cgroup.c                                   |    1 
 src/core/dbus-manager.c                             |    1 
 src/core/execute.c                                  |    3 
 src/core/failure-action.c                           |    1 
 src/core/job.c                                      |    1 
 src/core/killall.c                                  |    3 
 src/core/machine-id-setup.c                         |    1 
 src/core/main.c                                     |    3 
 src/core/manager.c                                  |    2 
 src/core/mount.c                                    |    1 
 src/core/service.c                                  |    2 
 src/core/shutdown.c                                 |    2 
 src/core/socket.c                                   |    1 
 src/core/swap.c                                     |    1 
 src/core/transaction.c                              |    1 
 src/core/unit-printf.c                              |    1 
 src/core/unit.c                                     |    2 
 src/delta/delta.c                                   |    2 
 src/firstboot/firstboot.c                           |    2 
 src/fsck/fsck.c                                     |    1 
 src/getty-generator/getty-generator.c               |    2 
 src/import/export-tar.c                             |    1 
 src/import/import-tar.c                             |    1 
 src/import/importd.c                                |    1 
 src/import/pull-common.c                            |    1 
 src/import/pull-dkr.c                               |    1 
 src/import/pull-tar.c                               |    1 
 src/initctl/initctl.c                               |    1 
 src/journal-remote/journal-upload.c                 |    1 
 src/journal/coredump.c                              |    1 
 src/journal/coredumpctl.c                           |    2 
 src/journal/journal-file.c                          |    1 
 src/journal/journal-verify.c                        |    1 
 src/journal/journalctl.c                            |    1 
 src/journal/journald-console.c                      |    3 
 src/journal/journald-kmsg.c                         |    2 
 src/journal/journald-rate-limit.c                   |    1 
 src/journal/journald-server.c                       |    2 
 src/journal/journald-syslog.c                       |    2 
 src/journal/journald-wall.c                         |    2 
 src/journal/journald.c                              |    1 
 src/journal/sd-journal.c                            |    1 
 src/journal/stacktrace.c                            |    1 
 src/journal/test-compress.c                         |    1 
 src/journal/test-journal-verify.c                   |    1 
 src/libsystemd-network/sd-dhcp-client.c             |    1 
 src/libsystemd-network/sd-dhcp6-client.c            |    1 
 src/libsystemd-network/sd-ipv4ll.c                  |    1 
 src/libsystemd-network/sd-pppoe.c                   |    1 
 src/libsystemd-network/test-pppoe.c                 |    1 
 src/libsystemd-terminal/modeset.c                   |    2 
 src/libsystemd/sd-bus/bus-container.c               |    1 
 src/libsystemd/sd-bus/bus-creds.c                   |    2 
 src/libsystemd/sd-bus/bus-dump.c                    |    2 
 src/libsystemd/sd-bus/bus-kernel.c                  |    1 
 src/libsystemd/sd-bus/bus-socket.c                  |    1 
 src/libsystemd/sd-bus/busctl.c                      |    1 
 src/libsystemd/sd-bus/test-bus-chat.c               |    1 
 src/libsystemd/sd-id128/sd-id128.c                  |    1 
 src/libsystemd/sd-login/sd-login.c                  |    1 
 src/libsystemd/sd-login/test-login.c                |    1 
 src/libsystemd/sd-rtnl/rtnl-message.c               |    1 
 src/libudev/libudev-monitor.c                       |    1 
 src/login/inhibit.c                                 |    2 
 src/login/loginctl.c                                |    2 
 src/login/logind-acl.c                              |    1 
 src/login/logind-action.c                           |    3 
 src/login/logind-core.c                             |    1 
 src/login/logind-dbus.c                             |    3 
 src/login/logind-inhibit.c                          |    1 
 src/login/logind-seat.c                             |    2 
 src/login/logind-session.c                          |    2 
 src/login/logind-user-dbus.c                        |    1 
 src/login/logind-user.c                             |    1 
 src/login/logind.c                                  |    1 
 src/login/pam_systemd.c                             |    2 
 src/login/sysfs-show.c                              |    1 
 src/machine/machine-dbus.c                          |    2 
 src/machine/machine.c                               |    1 
 src/machine/machinectl.c                            |    2 
 src/machine/machined-dbus.c                         |    1 
 src/machine/machined.c                              |    1 
 src/network/networkctl.c                            |    1 
 src/notify/notify.c                                 |    1 
 src/nspawn/nspawn.c                                 |    4 
 src/quotacheck/quotacheck.c                         |    1 
 src/resolve/resolved-dns-scope.c                    |    1 
 src/resolve/resolved-dns-transaction.c              |    1 
 src/resolve/resolved-manager.c                      |    1 
 src/run/run.c                                       |    1 
 src/shared/ask-password-api.c                       |    3 
 src/shared/audit.c                                  |    1 
 src/shared/cgroup-show.c                            |    3 
 src/shared/cgroup-util.c                            |    2 
 src/shared/clean-ipc.c                              |    1 
 src/shared/env-util.c                               |  144 +
 src/shared/env-util.h                               |    3 
 src/shared/formats-util.h                           |   63 
 src/shared/hashmap.c                                |    1 
 src/shared/install-printf.c                         |    1 
 src/shared/log.c                                    |    3 
 src/shared/logs-show.c                              |    3 
 src/shared/machine-pool.c                           |    1 
 src/shared/pager.c                                  |    2 
 src/shared/process-util.c                           |  538 +++++
 src/shared/process-util.h                           |   65 
 src/shared/random-util.c                            |  127 +
 src/shared/random-util.h                            |   38 
 src/shared/smack-util.c                             |    1 
 src/shared/socket-util.c                            |    1 
 src/shared/spawn-ask-password-agent.c               |    1 
 src/shared/spawn-polkit-agent.c                     |    1 
 src/shared/terminal-util.c                          | 1072 +++++++++++
 src/shared/terminal-util.h                          |  109 +
 src/shared/util.c                                   | 1942 --------------------
 src/shared/util.h                                   |  183 -
 src/shared/utmp-wtmp.c                              |    1 
 src/shared/virt.c                                   |    1 
 src/shutdownd/shutdownd.c                           |    1 
 src/systemctl/systemctl.c                           |    3 
 src/sysusers/sysusers.c                             |    1 
 src/test/test-cgroup-util.c                         |    2 
 src/test/test-ellipsize.c                           |    1 
 src/test/test-fileio.c                              |    1 
 src/test/test-log.c                                 |    1 
 src/test/test-namespace.c                           |    1 
 src/test/test-process-util.c                        |  139 +
 src/test/test-strip-tab-ansi.c                      |    1 
 src/test/test-terminal-util.c                       |   84 
 src/test/test-tmpfiles.c                            |    1 
 src/test/test-util.c                                |  150 -
 src/timedate/timedatectl.c                          |    1 
 src/tmpfiles/tmpfiles.c                             |    1 
 src/tty-ask-password-agent/tty-ask-password-agent.c |    2 
 src/udev/cdrom_id/cdrom_id.c                        |    1 
 src/udev/net/link-config.c                          |    1 
 src/udev/scsi_id/scsi_serial.c                      |    1 
 src/udev/udev-ctrl.c                                |    1 
 src/udev/udev-event.c                               |    1 
 src/udev/udev-node.c                                |    1 
 src/udev/udevadm-monitor.c                          |    1 
 src/udev/udevd.c                                    |    1 
 src/update-utmp/update-utmp.c                       |    1 
 src/vconsole/vconsole-setup.c                       |    2 
 154 files changed, 2681 insertions(+), 2189 deletions(-)

New commits:
commit 3c8000956a66203de381135d417db8ddc2e127e2
Author: Ronny Chevalier <chevalier.ronny at gmail.com>
Date:   Sat Apr 11 00:25:43 2015 +0200

    shared: move replace_env* from util to env-util

diff --git a/src/shared/env-util.c b/src/shared/env-util.c
index 00c2cdd..ac7bbdc 100644
--- a/src/shared/env-util.c
+++ b/src/shared/env-util.c
@@ -448,3 +448,147 @@ char **strv_env_clean_with_callback(char **e, void (*invalid_callback)(const cha
 
         return e;
 }
+
+char *replace_env(const char *format, char **env) {
+        enum {
+                WORD,
+                CURLY,
+                VARIABLE
+        } state = WORD;
+
+        const char *e, *word = format;
+        char *r = NULL, *k;
+
+        assert(format);
+
+        for (e = format; *e; e ++) {
+
+                switch (state) {
+
+                case WORD:
+                        if (*e == '$')
+                                state = CURLY;
+                        break;
+
+                case CURLY:
+                        if (*e == '{') {
+                                k = strnappend(r, word, e-word-1);
+                                if (!k)
+                                        goto fail;
+
+                                free(r);
+                                r = k;
+
+                                word = e-1;
+                                state = VARIABLE;
+
+                        } else if (*e == '$') {
+                                k = strnappend(r, word, e-word);
+                                if (!k)
+                                        goto fail;
+
+                                free(r);
+                                r = k;
+
+                                word = e+1;
+                                state = WORD;
+                        } else
+                                state = WORD;
+                        break;
+
+                case VARIABLE:
+                        if (*e == '}') {
+                                const char *t;
+
+                                t = strempty(strv_env_get_n(env, word+2, e-word-2));
+
+                                k = strappend(r, t);
+                                if (!k)
+                                        goto fail;
+
+                                free(r);
+                                r = k;
+
+                                word = e+1;
+                                state = WORD;
+                        }
+                        break;
+                }
+        }
+
+        k = strnappend(r, word, e-word);
+        if (!k)
+                goto fail;
+
+        free(r);
+        return k;
+
+fail:
+        free(r);
+        return NULL;
+}
+
+char **replace_env_argv(char **argv, char **env) {
+        char **ret, **i;
+        unsigned k = 0, l = 0;
+
+        l = strv_length(argv);
+
+        ret = new(char*, l+1);
+        if (!ret)
+                return NULL;
+
+        STRV_FOREACH(i, argv) {
+
+                /* If $FOO appears as single word, replace it by the split up variable */
+                if ((*i)[0] == '$' && (*i)[1] != '{') {
+                        char *e;
+                        char **w, **m = NULL;
+                        unsigned q;
+
+                        e = strv_env_get(env, *i+1);
+                        if (e) {
+                                int r;
+
+                                r = strv_split_quoted(&m, e, UNQUOTE_RELAX);
+                                if (r < 0) {
+                                        ret[k] = NULL;
+                                        strv_free(ret);
+                                        return NULL;
+                                }
+                        } else
+                                m = NULL;
+
+                        q = strv_length(m);
+                        l = l + q - 1;
+
+                        w = realloc(ret, sizeof(char*) * (l+1));
+                        if (!w) {
+                                ret[k] = NULL;
+                                strv_free(ret);
+                                strv_free(m);
+                                return NULL;
+                        }
+
+                        ret = w;
+                        if (m) {
+                                memcpy(ret + k, m, q * sizeof(char*));
+                                free(m);
+                        }
+
+                        k += q;
+                        continue;
+                }
+
+                /* If ${FOO} appears as part of a word, replace it by the variable as-is */
+                ret[k] = replace_env(*i, env);
+                if (!ret[k]) {
+                        strv_free(ret);
+                        return NULL;
+                }
+                k++;
+        }
+
+        ret[k] = NULL;
+        return ret;
+}
diff --git a/src/shared/env-util.h b/src/shared/env-util.h
index 9de3621..803aa61 100644
--- a/src/shared/env-util.h
+++ b/src/shared/env-util.h
@@ -29,6 +29,9 @@ bool env_name_is_valid(const char *e);
 bool env_value_is_valid(const char *e);
 bool env_assignment_is_valid(const char *e);
 
+char *replace_env(const char *format, char **env);
+char **replace_env_argv(char **argv, char **env);
+
 bool strv_env_is_valid(char **e);
 #define strv_env_clean(l) strv_env_clean_with_callback(l, NULL, NULL)
 char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const char *p, void *userdata), void *userdata);
diff --git a/src/shared/util.c b/src/shared/util.c
index 508b5d1..53f8488 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -2083,150 +2083,6 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
         }
 }
 
-char *replace_env(const char *format, char **env) {
-        enum {
-                WORD,
-                CURLY,
-                VARIABLE
-        } state = WORD;
-
-        const char *e, *word = format;
-        char *r = NULL, *k;
-
-        assert(format);
-
-        for (e = format; *e; e ++) {
-
-                switch (state) {
-
-                case WORD:
-                        if (*e == '$')
-                                state = CURLY;
-                        break;
-
-                case CURLY:
-                        if (*e == '{') {
-                                k = strnappend(r, word, e-word-1);
-                                if (!k)
-                                        goto fail;
-
-                                free(r);
-                                r = k;
-
-                                word = e-1;
-                                state = VARIABLE;
-
-                        } else if (*e == '$') {
-                                k = strnappend(r, word, e-word);
-                                if (!k)
-                                        goto fail;
-
-                                free(r);
-                                r = k;
-
-                                word = e+1;
-                                state = WORD;
-                        } else
-                                state = WORD;
-                        break;
-
-                case VARIABLE:
-                        if (*e == '}') {
-                                const char *t;
-
-                                t = strempty(strv_env_get_n(env, word+2, e-word-2));
-
-                                k = strappend(r, t);
-                                if (!k)
-                                        goto fail;
-
-                                free(r);
-                                r = k;
-
-                                word = e+1;
-                                state = WORD;
-                        }
-                        break;
-                }
-        }
-
-        k = strnappend(r, word, e-word);
-        if (!k)
-                goto fail;
-
-        free(r);
-        return k;
-
-fail:
-        free(r);
-        return NULL;
-}
-
-char **replace_env_argv(char **argv, char **env) {
-        char **ret, **i;
-        unsigned k = 0, l = 0;
-
-        l = strv_length(argv);
-
-        ret = new(char*, l+1);
-        if (!ret)
-                return NULL;
-
-        STRV_FOREACH(i, argv) {
-
-                /* If $FOO appears as single word, replace it by the split up variable */
-                if ((*i)[0] == '$' && (*i)[1] != '{') {
-                        char *e;
-                        char **w, **m = NULL;
-                        unsigned q;
-
-                        e = strv_env_get(env, *i+1);
-                        if (e) {
-                                int r;
-
-                                r = strv_split_quoted(&m, e, UNQUOTE_RELAX);
-                                if (r < 0) {
-                                        ret[k] = NULL;
-                                        strv_free(ret);
-                                        return NULL;
-                                }
-                        } else
-                                m = NULL;
-
-                        q = strv_length(m);
-                        l = l + q - 1;
-
-                        w = realloc(ret, sizeof(char*) * (l+1));
-                        if (!w) {
-                                ret[k] = NULL;
-                                strv_free(ret);
-                                strv_free(m);
-                                return NULL;
-                        }
-
-                        ret = w;
-                        if (m) {
-                                memcpy(ret + k, m, q * sizeof(char*));
-                                free(m);
-                        }
-
-                        k += q;
-                        continue;
-                }
-
-                /* If ${FOO} appears as part of a word, replace it by the variable as-is */
-                ret[k] = replace_env(*i, env);
-                if (!ret[k]) {
-                        strv_free(ret);
-                        return NULL;
-                }
-                k++;
-        }
-
-        ret[k] = NULL;
-        return ret;
-}
-
 int files_same(const char *filea, const char *fileb) {
         struct stat a, b;
 
diff --git a/src/shared/util.h b/src/shared/util.h
index f54722f..9409ad9 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -220,9 +220,6 @@ const char* split(const char **state, size_t *l, const char *separator, bool quo
 char *strappend(const char *s, const char *suffix);
 char *strnappend(const char *s, const char *suffix, size_t length);
 
-char *replace_env(const char *format, char **env);
-char **replace_env_argv(char **argv, char **env);
-
 int readlinkat_malloc(int fd, const char *p, char **ret);
 int readlink_malloc(const char *p, char **r);
 int readlink_value(const char *p, char **ret);

commit 288a74cce597f81d3ba01d8a5ca7d2ba5b654b7e
Author: Ronny Chevalier <chevalier.ronny at gmail.com>
Date:   Fri Apr 10 23:15:59 2015 +0200

    shared: add terminal-util.[ch]

diff --git a/.gitignore b/.gitignore
index 7330c80..bcf21fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -256,6 +256,7 @@
 /test-tables
 /test-term-page
 /test-term-parser
+/test-terminal-util
 /test-time
 /test-tmpfiles
 /test-udev
diff --git a/Makefile.am b/Makefile.am
index f348ef9..114d4a1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -903,6 +903,8 @@ libsystemd_shared_la_SOURCES = \
 	src/shared/process-util.h \
 	src/shared/random-util.c \
 	src/shared/random-util.h \
+	src/shared/terminal-util.c \
+	src/shared/terminal-util.h \
 	src/shared/uid-range.c \
 	src/shared/uid-range.h \
 	src/shared/nss-util.h \
@@ -1394,6 +1396,7 @@ tests += \
 	test-ellipsize \
 	test-util \
 	test-process-util \
+	test-terminal-util \
 	test-path-lookup \
 	test-ring \
 	test-barrier \
@@ -1675,6 +1678,12 @@ test_process_util_SOURCES = \
 test_process_util_LDADD = \
 	libsystemd-shared.la
 
+test_terminal_util_SOURCES = \
+	src/test/test-terminal-util.c
+
+test_terminal_util_LDADD = \
+	libsystemd-shared.la
+
 test_path_lookup_SOURCES = \
 	src/test/test-path-lookup.c
 
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 7abe969..17fc5c8 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -38,6 +38,7 @@
 #include "hashmap.h"
 #include "pager.h"
 #include "analyze-verify.h"
+#include "terminal-util.h"
 
 #define SCALE_X (0.1 / 1000.0)   /* pixels per us */
 #define SCALE_Y (20.0)
diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c
index f951c37..a390cf3 100644
--- a/src/cgtop/cgtop.c
+++ b/src/cgtop/cgtop.c
@@ -29,6 +29,7 @@
 #include <getopt.h>
 
 #include "path-util.h"
+#include "terminal-util.h"
 #include "util.h"
 #include "hashmap.h"
 #include "cgroup-util.h"
diff --git a/src/core/execute.c b/src/core/execute.c
index b00d510..bbd0d2c 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -78,6 +78,7 @@
 #include "cap-list.h"
 #include "formats-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 #ifdef HAVE_APPARMOR
 #include "apparmor-util.h"
diff --git a/src/core/failure-action.c b/src/core/failure-action.c
index ffeb5cd..7c6abb3 100644
--- a/src/core/failure-action.c
+++ b/src/core/failure-action.c
@@ -27,6 +27,7 @@
 #include "bus-error.h"
 #include "special.h"
 #include "failure-action.h"
+#include "terminal-util.h"
 
 static void log_and_status(Manager *m, const char *message) {
         log_warning("%s", message);
diff --git a/src/core/job.c b/src/core/job.c
index 0230f93..e92e24e 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -33,6 +33,7 @@
 #include "async.h"
 #include "virt.h"
 #include "dbus.h"
+#include "terminal-util.h"
 
 Job* job_new_raw(Unit *unit) {
         Job *j;
diff --git a/src/core/killall.c b/src/core/killall.c
index 31bec01..6e85923 100644
--- a/src/core/killall.c
+++ b/src/core/killall.c
@@ -29,6 +29,7 @@
 #include "set.h"
 #include "formats-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 #define TIMEOUT_USEC (10 * USEC_PER_SEC)
 
diff --git a/src/core/main.c b/src/core/main.c
index 80a51ee..af28ac6 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -74,6 +74,7 @@
 #include "kmod-setup.h"
 #include "formats-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 static enum {
         ACTION_RUN,
diff --git a/src/core/manager.c b/src/core/manager.c
index 6d1729b..2b04644 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -72,6 +72,7 @@
 #include "bus-kernel.h"
 #include "time-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 /* Initial delay and the interval for printing status messages about running jobs */
 #define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC)
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index f037a38..aba16b4 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -43,6 +43,7 @@
 #include "def.h"
 #include "switch-root.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 #define FINALIZE_ATTEMPTS 50
 
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 64c2af5..5974b1e 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -25,6 +25,7 @@
 #include "bus-common-errors.h"
 #include "bus-error.h"
 #include "transaction.h"
+#include "terminal-util.h"
 
 static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies);
 
diff --git a/src/delta/delta.c b/src/delta/delta.c
index 106c036..c764bb4 100644
--- a/src/delta/delta.c
+++ b/src/delta/delta.c
@@ -33,6 +33,7 @@
 #include "build.h"
 #include "strv.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 static const char prefixes[] =
         "/etc\0"
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index c92f379..37326df 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -35,6 +35,7 @@
 #include "random-util.h"
 #include "locale-util.h"
 #include "ask-password-api.h"
+#include "terminal-util.h"
 
 static char *arg_root = NULL;
 static char *arg_locale = NULL;  /* $LANG */
diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c
index 0f59f5a..d4688d3 100644
--- a/src/getty-generator/getty-generator.c
+++ b/src/getty-generator/getty-generator.c
@@ -32,6 +32,7 @@
 #include "fileio.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 static const char *arg_dest = "/tmp";
 
diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c
index 4f6ddfa..bcb0ff9 100644
--- a/src/journal/coredumpctl.c
+++ b/src/journal/coredumpctl.c
@@ -38,6 +38,7 @@
 #include "compress.h"
 #include "sigbus.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 static enum {
         ACTION_NONE,
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index 146c10b..ce734d8 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -32,6 +32,7 @@
 #include "journal-verify.h"
 #include "lookup3.h"
 #include "compress.h"
+#include "terminal-util.h"
 
 static void draw_progress(uint64_t p, usec_t *last_usec) {
         unsigned n, i, j, k;
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 40c84b9..a5ed41d 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -60,6 +60,7 @@
 #include "mkdir.h"
 #include "bus-util.h"
 #include "bus-error.h"
+#include "terminal-util.h"
 
 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
 
diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c
index 6c15530..307bdc3 100644
--- a/src/journal/journald-console.c
+++ b/src/journal/journald-console.c
@@ -28,6 +28,7 @@
 #include "journald-console.h"
 #include "formats-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 static bool prefix_timestamp(void) {
 
diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c
index 8008f74..d24502d 100644
--- a/src/journal/test-journal-verify.c
+++ b/src/journal/test-journal-verify.c
@@ -28,6 +28,7 @@
 #include "rm-rf.h"
 #include "journal-file.h"
 #include "journal-verify.h"
+#include "terminal-util.h"
 
 #define N_ENTRIES 6000
 #define RANDOM_RANGE 77
diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c
index d722680..9165dd7 100644
--- a/src/libsystemd/sd-bus/bus-dump.c
+++ b/src/libsystemd/sd-bus/bus-dump.c
@@ -25,6 +25,7 @@
 #include "macro.h"
 #include "cap-list.h"
 #include "formats-util.h"
+#include "terminal-util.h"
 
 #include "bus-message.h"
 #include "bus-internal.h"
diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c
index d52dbdf..39caa4e 100644
--- a/src/libsystemd/sd-bus/busctl.c
+++ b/src/libsystemd/sd-bus/busctl.c
@@ -36,6 +36,7 @@
 #include "bus-signature.h"
 #include "bus-type.h"
 #include "busctl-introspect.h"
+#include "terminal-util.h"
 
 static bool arg_no_pager = false;
 static bool arg_legend = true;
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 7393eb3..4a5a618 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -42,6 +42,7 @@
 #include "spawn-polkit-agent.h"
 #include "verbs.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 static char **arg_property = NULL;
 static bool arg_all = false;
diff --git a/src/login/logind-action.c b/src/login/logind-action.c
index 29e7ed0..f635fb1 100644
--- a/src/login/logind-action.c
+++ b/src/login/logind-action.c
@@ -29,6 +29,7 @@
 #include "logind-action.h"
 #include "formats-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 int manager_handle_action(
                 Manager *m,
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index e8da59a..440c32a 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -31,6 +31,7 @@
 #include "bus-error.h"
 #include "udev-util.h"
 #include "logind.h"
+#include "terminal-util.h"
 
 int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
         Device *d;
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 6bf9205..76070a3 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -42,6 +42,7 @@
 #include "logind.h"
 #include "formats-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index 4c0bebd..11d24ce 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -30,6 +30,7 @@
 #include "util.h"
 #include "mkdir.h"
 #include "formats-util.h"
+#include "terminal-util.h"
 
 Seat *seat_new(Manager *m, const char *id) {
         Seat *s;
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index cebc90c..6a450b0 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -38,6 +38,7 @@
 #include "bus-error.h"
 #include "logind-session.h"
 #include "formats-util.h"
+#include "terminal-util.h"
 
 #define RELEASE_USEC (20*USEC_PER_SEC)
 
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index a0fabfe..cdd45ac 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -41,6 +41,7 @@
 #include "fileio.h"
 #include "bus-error.h"
 #include "formats-util.h"
+#include "terminal-util.h"
 
 static int parse_argv(
                 pam_handle_t *handle,
diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c
index 9bd9152..9a9fb76 100644
--- a/src/login/sysfs-show.c
+++ b/src/login/sysfs-show.c
@@ -27,6 +27,7 @@
 #include "sysfs-show.h"
 #include "path-util.h"
 #include "udev-util.h"
+#include "terminal-util.h"
 
 static int show_sysfs_one(
                 struct udev *udev,
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 87e15d7..26cd5b8 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -53,6 +53,7 @@
 #include "verbs.h"
 #include "import-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 static char **arg_property = NULL;
 static bool arg_all = false;
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 9716499..69b4ab4 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -41,6 +41,7 @@
 #include "socket-util.h"
 #include "ether-addr-util.h"
 #include "verbs.h"
+#include "terminal-util.h"
 
 static bool arg_no_pager = false;
 static bool arg_legend = true;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 6417a8c..6d4aadd 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -94,6 +94,7 @@
 #include "local-addresses.h"
 #include "formats-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 #ifdef HAVE_SECCOMP
 #include "seccomp-util.h"
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
index ad1a773..a3a2e51 100644
--- a/src/shared/ask-password-api.c
+++ b/src/shared/ask-password-api.c
@@ -36,6 +36,7 @@
 #include "mkdir.h"
 #include "strv.h"
 #include "random-util.h"
+#include "terminal-util.h"
 
 #include "ask-password-api.h"
 
diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c
index 0f263e9..1a2c4b2 100644
--- a/src/shared/cgroup-show.c
+++ b/src/shared/cgroup-show.c
@@ -31,6 +31,7 @@
 #include "path-util.h"
 #include "cgroup-util.h"
 #include "cgroup-show.h"
+#include "terminal-util.h"
 
 static int compare(const void *a, const void *b) {
         const pid_t *p = a, *q = b;
diff --git a/src/shared/log.c b/src/shared/log.c
index 7edcf1f..85c0605 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -36,6 +36,7 @@
 #include "socket-util.h"
 #include "formats-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 #define SNDBUF_SIZE (8*1024*1024)
 
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index 7a7a1e9..27f4072 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -33,6 +33,7 @@
 #include "journal-internal.h"
 #include "formats-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 /* up to three lines (each up to 100 characters),
    or 300 characters, whichever is less */
diff --git a/src/shared/pager.c b/src/shared/pager.c
index b5a584b..58b62fd 100644
--- a/src/shared/pager.c
+++ b/src/shared/pager.c
@@ -29,6 +29,7 @@
 #include "util.h"
 #include "process-util.h"
 #include "macro.h"
+#include "terminal-util.h"
 
 static pid_t pager_pid = 0;
 
diff --git a/src/shared/terminal-util.c b/src/shared/terminal-util.c
new file mode 100644
index 0000000..f5b6590
--- /dev/null
+++ b/src/shared/terminal-util.c
@@ -0,0 +1,1072 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <time.h>
+#include <assert.h>
+#include <poll.h>
+#include <linux/vt.h>
+#include <linux/tiocl.h>
+#include <linux/kd.h>
+
+#include "terminal-util.h"
+#include "time-util.h"
+#include "process-util.h"
+#include "util.h"
+#include "fileio.h"
+#include "path-util.h"
+
+static volatile unsigned cached_columns = 0;
+static volatile unsigned cached_lines = 0;
+
+int chvt(int vt) {
+        _cleanup_close_ int fd;
+
+        fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0)
+                return -errno;
+
+        if (vt < 0) {
+                int tiocl[2] = {
+                        TIOCL_GETKMSGREDIRECT,
+                        0
+                };
+
+                if (ioctl(fd, TIOCLINUX, tiocl) < 0)
+                        return -errno;
+
+                vt = tiocl[0] <= 0 ? 1 : tiocl[0];
+        }
+
+        if (ioctl(fd, VT_ACTIVATE, vt) < 0)
+                return -errno;
+
+        return 0;
+}
+
+int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
+        struct termios old_termios, new_termios;
+        char c, line[LINE_MAX];
+
+        assert(f);
+        assert(ret);
+
+        if (tcgetattr(fileno(f), &old_termios) >= 0) {
+                new_termios = old_termios;
+
+                new_termios.c_lflag &= ~ICANON;
+                new_termios.c_cc[VMIN] = 1;
+                new_termios.c_cc[VTIME] = 0;
+
+                if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
+                        size_t k;
+
+                        if (t != USEC_INFINITY) {
+                                if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
+                                        tcsetattr(fileno(f), TCSADRAIN, &old_termios);
+                                        return -ETIMEDOUT;
+                                }
+                        }
+
+                        k = fread(&c, 1, 1, f);
+
+                        tcsetattr(fileno(f), TCSADRAIN, &old_termios);
+
+                        if (k <= 0)
+                                return -EIO;
+
+                        if (need_nl)
+                                *need_nl = c != '\n';
+
+                        *ret = c;
+                        return 0;
+                }
+        }
+
+        if (t != USEC_INFINITY) {
+                if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
+                        return -ETIMEDOUT;
+        }
+
+        errno = 0;
+        if (!fgets(line, sizeof(line), f))
+                return errno ? -errno : -EIO;
+
+        truncate_nl(line);
+
+        if (strlen(line) != 1)
+                return -EBADMSG;
+
+        if (need_nl)
+                *need_nl = false;
+
+        *ret = line[0];
+        return 0;
+}
+
+int ask_char(char *ret, const char *replies, const char *text, ...) {
+        int r;
+
+        assert(ret);
+        assert(replies);
+        assert(text);
+
+        for (;;) {
+                va_list ap;
+                char c;
+                bool need_nl = true;
+
+                if (on_tty())
+                        fputs(ANSI_HIGHLIGHT_ON, stdout);
+
+                va_start(ap, text);
+                vprintf(text, ap);
+                va_end(ap);
+
+                if (on_tty())
+                        fputs(ANSI_HIGHLIGHT_OFF, stdout);
+
+                fflush(stdout);
+
+                r = read_one_char(stdin, &c, USEC_INFINITY, &need_nl);
+                if (r < 0) {
+
+                        if (r == -EBADMSG) {
+                                puts("Bad input, please try again.");
+                                continue;
+                        }
+
+                        putchar('\n');
+                        return r;
+                }
+
+                if (need_nl)
+                        putchar('\n');
+
+                if (strchr(replies, c)) {
+                        *ret = c;
+                        return 0;
+                }
+
+                puts("Read unexpected character, please try again.");
+        }
+}
+
+int ask_string(char **ret, const char *text, ...) {
+        assert(ret);
+        assert(text);
+
+        for (;;) {
+                char line[LINE_MAX];
+                va_list ap;
+
+                if (on_tty())
+                        fputs(ANSI_HIGHLIGHT_ON, stdout);
+
+                va_start(ap, text);
+                vprintf(text, ap);
+                va_end(ap);
+
+                if (on_tty())
+                        fputs(ANSI_HIGHLIGHT_OFF, stdout);
+
+                fflush(stdout);
+
+                errno = 0;
+                if (!fgets(line, sizeof(line), stdin))
+                        return errno ? -errno : -EIO;
+
+                if (!endswith(line, "\n"))
+                        putchar('\n');
+                else {
+                        char *s;
+
+                        if (isempty(line))
+                                continue;
+
+                        truncate_nl(line);
+                        s = strdup(line);
+                        if (!s)
+                                return -ENOMEM;
+
+                        *ret = s;
+                        return 0;
+                }
+        }
+}
+
+int reset_terminal_fd(int fd, bool switch_to_text) {
+        struct termios termios;
+        int r = 0;
+
+        /* Set terminal to some sane defaults */
+
+        assert(fd >= 0);
+
+        /* We leave locked terminal attributes untouched, so that
+         * Plymouth may set whatever it wants to set, and we don't
+         * interfere with that. */
+
+        /* Disable exclusive mode, just in case */
+        ioctl(fd, TIOCNXCL);
+
+        /* Switch to text mode */
+        if (switch_to_text)
+                ioctl(fd, KDSETMODE, KD_TEXT);
+
+        /* Enable console unicode mode */
+        ioctl(fd, KDSKBMODE, K_UNICODE);
+
+        if (tcgetattr(fd, &termios) < 0) {
+                r = -errno;
+                goto finish;
+        }
+
+        /* We only reset the stuff that matters to the software. How
+         * hardware is set up we don't touch assuming that somebody
+         * else will do that for us */
+
+        termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
+        termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
+        termios.c_oflag |= ONLCR;
+        termios.c_cflag |= CREAD;
+        termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
+
+        termios.c_cc[VINTR]    =   03;  /* ^C */
+        termios.c_cc[VQUIT]    =  034;  /* ^\ */
+        termios.c_cc[VERASE]   = 0177;
+        termios.c_cc[VKILL]    =  025;  /* ^X */
+        termios.c_cc[VEOF]     =   04;  /* ^D */
+        termios.c_cc[VSTART]   =  021;  /* ^Q */
+        termios.c_cc[VSTOP]    =  023;  /* ^S */
+        termios.c_cc[VSUSP]    =  032;  /* ^Z */
+        termios.c_cc[VLNEXT]   =  026;  /* ^V */
+        termios.c_cc[VWERASE]  =  027;  /* ^W */
+        termios.c_cc[VREPRINT] =  022;  /* ^R */
+        termios.c_cc[VEOL]     =    0;
+        termios.c_cc[VEOL2]    =    0;
+
+        termios.c_cc[VTIME]  = 0;
+        termios.c_cc[VMIN]   = 1;
+
+        if (tcsetattr(fd, TCSANOW, &termios) < 0)
+                r = -errno;
+
+finish:
+        /* Just in case, flush all crap out */
+        tcflush(fd, TCIOFLUSH);
+
+        return r;
+}
+
+int reset_terminal(const char *name) {
+        _cleanup_close_ int fd = -1;
+
+        fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0)
+                return fd;
+
+        return reset_terminal_fd(fd, true);
+}
+
+int open_terminal(const char *name, int mode) {
+        int fd, r;
+        unsigned c = 0;
+
+        /*
+         * If a TTY is in the process of being closed opening it might
+         * cause EIO. This is horribly awful, but unlikely to be
+         * changed in the kernel. Hence we work around this problem by
+         * retrying a couple of times.
+         *
+         * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
+         */
+
+        assert(!(mode & O_CREAT));
+
+        for (;;) {
+                fd = open(name, mode, 0);
+                if (fd >= 0)
+                        break;
+
+                if (errno != EIO)
+                        return -errno;
+
+                /* Max 1s in total */
+                if (c >= 20)
+                        return -errno;
+
+                usleep(50 * USEC_PER_MSEC);
+                c++;
+        }
+
+        r = isatty(fd);
+        if (r < 0) {
+                safe_close(fd);
+                return -errno;
+        }
+
+        if (!r) {
+                safe_close(fd);
+                return -ENOTTY;
+        }
+
+        return fd;
+}
+
+int acquire_terminal(
+                const char *name,
+                bool fail,
+                bool force,
+                bool ignore_tiocstty_eperm,
+                usec_t timeout) {
+
+        int fd = -1, notify = -1, r = 0, wd = -1;
+        usec_t ts = 0;
+
+        assert(name);
+
+        /* We use inotify to be notified when the tty is closed. We
+         * create the watch before checking if we can actually acquire
+         * it, so that we don't lose any event.
+         *
+         * Note: strictly speaking this actually watches for the
+         * device being closed, it does *not* really watch whether a
+         * tty loses its controlling process. However, unless some
+         * rogue process uses TIOCNOTTY on /dev/tty *after* closing
+         * its tty otherwise this will not become a problem. As long
+         * as the administrator makes sure not configure any service
+         * on the same tty as an untrusted user this should not be a
+         * problem. (Which he probably should not do anyway.) */
+
+        if (timeout != USEC_INFINITY)
+                ts = now(CLOCK_MONOTONIC);
+
+        if (!fail && !force) {
+                notify = inotify_init1(IN_CLOEXEC | (timeout != USEC_INFINITY ? IN_NONBLOCK : 0));
+                if (notify < 0) {
+                        r = -errno;
+                        goto fail;
+                }
+
+                wd = inotify_add_watch(notify, name, IN_CLOSE);
+                if (wd < 0) {
+                        r = -errno;
+                        goto fail;
+                }
+        }
+
+        for (;;) {
+                struct sigaction sa_old, sa_new = {
+                        .sa_handler = SIG_IGN,
+                        .sa_flags = SA_RESTART,
+                };
+
+                if (notify >= 0) {
+                        r = flush_fd(notify);
+                        if (r < 0)
+                                goto fail;
+                }
+
+                /* We pass here O_NOCTTY only so that we can check the return
+                 * value TIOCSCTTY and have a reliable way to figure out if we
+                 * successfully became the controlling process of the tty */
+                fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
+                if (fd < 0)
+                        return fd;
+
+                /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
+                 * if we already own the tty. */
+                assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
+
+                /* First, try to get the tty */
+                if (ioctl(fd, TIOCSCTTY, force) < 0)
+                        r = -errno;
+
+                assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
+
+                /* Sometimes it makes sense to ignore TIOCSCTTY
+                 * returning EPERM, i.e. when very likely we already
+                 * are have this controlling terminal. */
+                if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
+                        r = 0;
+
+                if (r < 0 && (force || fail || r != -EPERM)) {
+                        goto fail;
+                }
+
+                if (r >= 0)
+                        break;
+
+                assert(!fail);
+                assert(!force);
+                assert(notify >= 0);
+
+                for (;;) {
+                        union inotify_event_buffer buffer;
+                        struct inotify_event *e;
+                        ssize_t l;
+
+                        if (timeout != USEC_INFINITY) {
+                                usec_t n;
+
+                                n = now(CLOCK_MONOTONIC);
+                                if (ts + timeout < n) {
+                                        r = -ETIMEDOUT;
+                                        goto fail;
+                                }
+
+                                r = fd_wait_for_event(fd, POLLIN, ts + timeout - n);
+                                if (r < 0)
+                                        goto fail;
+
+                                if (r == 0) {
+                                        r = -ETIMEDOUT;
+                                        goto fail;
+                                }
+                        }
+
+                        l = read(notify, &buffer, sizeof(buffer));
+                        if (l < 0) {
+                                if (errno == EINTR || errno == EAGAIN)
+                                        continue;
+
+                                r = -errno;
+                                goto fail;
+                        }
+
+                        FOREACH_INOTIFY_EVENT(e, buffer, l) {
+                                if (e->wd != wd || !(e->mask & IN_CLOSE)) {
+                                        r = -EIO;
+                                        goto fail;
+                                }
+                        }
+
+                        break;
+                }
+
+                /* We close the tty fd here since if the old session
+                 * ended our handle will be dead. It's important that
+                 * we do this after sleeping, so that we don't enter
+                 * an endless loop. */
+                fd = safe_close(fd);
+        }
+
+        safe_close(notify);
+
+        r = reset_terminal_fd(fd, true);
+        if (r < 0)
+                log_warning_errno(r, "Failed to reset terminal: %m");
+
+        return fd;
+
+fail:
+        safe_close(fd);
+        safe_close(notify);
+
+        return r;
+}
+
+int release_terminal(void) {
+        static const struct sigaction sa_new = {
+                .sa_handler = SIG_IGN,
+                .sa_flags = SA_RESTART,
+        };
+
+        _cleanup_close_ int fd = -1;
+        struct sigaction sa_old;
+        int r = 0;
+
+        fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC);
+        if (fd < 0)
+                return -errno;
+
+        /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
+         * by our own TIOCNOTTY */
+        assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
+
+        if (ioctl(fd, TIOCNOTTY) < 0)
+                r = -errno;
+
+        assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
+
+        return r;
+}
+
+int terminal_vhangup_fd(int fd) {
+        assert(fd >= 0);
+
+        if (ioctl(fd, TIOCVHANGUP) < 0)
+                return -errno;
+
+        return 0;
+}
+
+int terminal_vhangup(const char *name) {
+        _cleanup_close_ int fd;
+
+        fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0)
+                return fd;
+
+        return terminal_vhangup_fd(fd);
+}
+
+int vt_disallocate(const char *name) {
+        int fd, r;
+        unsigned u;
+
+        /* Deallocate the VT if possible. If not possible
+         * (i.e. because it is the active one), at least clear it
+         * entirely (including the scrollback buffer) */
+
+        if (!startswith(name, "/dev/"))
+                return -EINVAL;
+
+        if (!tty_is_vc(name)) {
+                /* So this is not a VT. I guess we cannot deallocate
+                 * it then. But let's at least clear the screen */
+
+                fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
+                if (fd < 0)
+                        return fd;
+
+                loop_write(fd,
+                           "\033[r"    /* clear scrolling region */
+                           "\033[H"    /* move home */
+                           "\033[2J",  /* clear screen */
+                           10, false);
+                safe_close(fd);
+
+                return 0;
+        }
+
+        if (!startswith(name, "/dev/tty"))
+                return -EINVAL;
+
+        r = safe_atou(name+8, &u);
+        if (r < 0)
+                return r;
+
+        if (u <= 0)
+                return -EINVAL;
+
+        /* Try to deallocate */
+        fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0)
+                return fd;
+
+        r = ioctl(fd, VT_DISALLOCATE, u);
+        safe_close(fd);
+
+        if (r >= 0)
+                return 0;
+
+        if (errno != EBUSY)
+                return -errno;
+
+        /* Couldn't deallocate, so let's clear it fully with
+         * scrollback */
+        fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0)
+                return fd;
+
+        loop_write(fd,
+                   "\033[r"   /* clear scrolling region */
+                   "\033[H"   /* move home */
+                   "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
+                   10, false);
+        safe_close(fd);
+
+        return 0;
+}
+
+void warn_melody(void) {
+        _cleanup_close_ int fd = -1;
+
+        fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
+        if (fd < 0)
+                return;
+
+        /* Yeah, this is synchronous. Kinda sucks. But well... */
+
+        ioctl(fd, KIOCSOUND, (int)(1193180/440));
+        usleep(125*USEC_PER_MSEC);
+
+        ioctl(fd, KIOCSOUND, (int)(1193180/220));
+        usleep(125*USEC_PER_MSEC);
+
+        ioctl(fd, KIOCSOUND, (int)(1193180/220));
+        usleep(125*USEC_PER_MSEC);
+
+        ioctl(fd, KIOCSOUND, 0);
+}
+
+int make_console_stdio(void) {
+        int fd, r;
+
+        /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
+
+        fd = acquire_terminal("/dev/console", false, true, true, USEC_INFINITY);
+        if (fd < 0)
+                return log_error_errno(fd, "Failed to acquire terminal: %m");
+
+        r = make_stdio(fd);
+        if (r < 0)
+                return log_error_errno(r, "Failed to duplicate terminal fd: %m");
+
+        return 0;
+}
+
+int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
+        static const char status_indent[] = "         "; /* "[" STATUS "] " */
+        _cleanup_free_ char *s = NULL;
+        _cleanup_close_ int fd = -1;
+        struct iovec iovec[6] = {};
+        int n = 0;
+        static bool prev_ephemeral;
+
+        assert(format);
+
+        /* This is independent of logging, as status messages are
+         * optional and go exclusively to the console. */
+
+        if (vasprintf(&s, format, ap) < 0)
+                return log_oom();
+
+        fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
+        if (fd < 0)
+                return fd;
+
+        if (ellipse) {
+                char *e;
+                size_t emax, sl;
+                int c;
+
+                c = fd_columns(fd);
+                if (c <= 0)
+                        c = 80;
+
+                sl = status ? sizeof(status_indent)-1 : 0;
+
+                emax = c - sl - 1;
+                if (emax < 3)
+                        emax = 3;
+
+                e = ellipsize(s, emax, 50);
+                if (e) {
+                        free(s);
+                        s = e;
+                }
+        }
+
+        if (prev_ephemeral)
+                IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
+        prev_ephemeral = ephemeral;
+
+        if (status) {
+                if (!isempty(status)) {
+                        IOVEC_SET_STRING(iovec[n++], "[");
+                        IOVEC_SET_STRING(iovec[n++], status);
+                        IOVEC_SET_STRING(iovec[n++], "] ");
+                } else
+                        IOVEC_SET_STRING(iovec[n++], status_indent);
+        }
+
+        IOVEC_SET_STRING(iovec[n++], s);
+        if (!ephemeral)
+                IOVEC_SET_STRING(iovec[n++], "\n");
+
+        if (writev(fd, iovec, n) < 0)
+                return -errno;
+
+        return 0;
+}
+
+int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) {
+        va_list ap;
+        int r;
+
+        assert(format);
+
+        va_start(ap, format);
+        r = status_vprintf(status, ellipse, ephemeral, format, ap);
+        va_end(ap);
+
+        return r;
+}
+
+bool tty_is_vc(const char *tty) {
+        assert(tty);
+
+        return vtnr_from_tty(tty) >= 0;
+}
+
+bool tty_is_console(const char *tty) {
+        assert(tty);
+
+        if (startswith(tty, "/dev/"))
+                tty += 5;
+
+        return streq(tty, "console");
+}
+
+int vtnr_from_tty(const char *tty) {
+        int i, r;
+
+        assert(tty);
+
+        if (startswith(tty, "/dev/"))
+                tty += 5;
+
+        if (!startswith(tty, "tty") )
+                return -EINVAL;
+
+        if (tty[3] < '0' || tty[3] > '9')
+                return -EINVAL;
+
+        r = safe_atoi(tty+3, &i);
+        if (r < 0)
+                return r;
+
+        if (i < 0 || i > 63)
+                return -EINVAL;
+
+        return i;
+}
+
+char *resolve_dev_console(char **active) {
+        char *tty;
+
+        /* Resolve where /dev/console is pointing to, if /sys is actually ours
+         * (i.e. not read-only-mounted which is a sign for container setups) */
+
+        if (path_is_read_only_fs("/sys") > 0)
+                return NULL;
+
+        if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
+                return NULL;
+
+        /* If multiple log outputs are configured the last one is what
+         * /dev/console points to */
+        tty = strrchr(*active, ' ');
+        if (tty)
+                tty++;
+        else
+                tty = *active;
+
+        if (streq(tty, "tty0")) {
+                char *tmp;
+
+                /* Get the active VC (e.g. tty1) */
+                if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
+                        free(*active);
+                        tty = *active = tmp;
+                }
+        }
+
+        return tty;
+}
+
+bool tty_is_vc_resolve(const char *tty) {
+        _cleanup_free_ char *active = NULL;
+
+        assert(tty);
+
+        if (startswith(tty, "/dev/"))
+                tty += 5;
+
+        if (streq(tty, "console")) {
+                tty = resolve_dev_console(&active);
+                if (!tty)
+                        return false;
+        }
+
+        return tty_is_vc(tty);
+}
+
+const char *default_term_for_tty(const char *tty) {
+        assert(tty);
+
+        return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt220";
+}
+
+int fd_columns(int fd) {
+        struct winsize ws = {};
+
+        if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
+                return -errno;
+
+        if (ws.ws_col <= 0)
+                return -EIO;
+
+        return ws.ws_col;
+}
+
+unsigned columns(void) {
+        const char *e;
+        int c;
+
+        if (_likely_(cached_columns > 0))
+                return cached_columns;
+
+        c = 0;
+        e = getenv("COLUMNS");
+        if (e)
+                (void) safe_atoi(e, &c);
+
+        if (c <= 0)
+                c = fd_columns(STDOUT_FILENO);
+
+        if (c <= 0)
+                c = 80;
+
+        cached_columns = c;
+        return cached_columns;
+}
+
+int fd_lines(int fd) {
+        struct winsize ws = {};
+
+        if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
+                return -errno;
+
+        if (ws.ws_row <= 0)
+                return -EIO;
+
+        return ws.ws_row;
+}
+
+unsigned lines(void) {
+        const char *e;
+        int l;
+
+        if (_likely_(cached_lines > 0))
+                return cached_lines;
+
+        l = 0;
+        e = getenv("LINES");
+        if (e)
+                (void) safe_atoi(e, &l);
+
+        if (l <= 0)
+                l = fd_lines(STDOUT_FILENO);
+
+        if (l <= 0)
+                l = 24;
+
+        cached_lines = l;
+        return cached_lines;
+}
+
+/* intended to be used as a SIGWINCH sighandler */
+void columns_lines_cache_reset(int signum) {
+        cached_columns = 0;
+        cached_lines = 0;
+}
+
+bool on_tty(void) {
+        static int cached_on_tty = -1;
+
+        if (_unlikely_(cached_on_tty < 0))
+                cached_on_tty = isatty(STDOUT_FILENO) > 0;
+
+        return cached_on_tty;
+}
+
+int make_stdio(int fd) {
+        int r, s, t;
+
+        assert(fd >= 0);
+
+        r = dup2(fd, STDIN_FILENO);
+        s = dup2(fd, STDOUT_FILENO);
+        t = dup2(fd, STDERR_FILENO);
+
+        if (fd >= 3)
+                safe_close(fd);
+
+        if (r < 0 || s < 0 || t < 0)
+                return -errno;
+
+        /* Explicitly unset O_CLOEXEC, since if fd was < 3, then
+         * dup2() was a NOP and the bit hence possibly set. */
+        fd_cloexec(STDIN_FILENO, false);
+        fd_cloexec(STDOUT_FILENO, false);
+        fd_cloexec(STDERR_FILENO, false);
+
+        return 0;
+}
+
+int make_null_stdio(void) {
+        int null_fd;
+
+        null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
+        if (null_fd < 0)
+                return -errno;
+
+        return make_stdio(null_fd);
+}
+
+int getttyname_malloc(int fd, char **ret) {
+        size_t l = 100;
+        int r;
+
+        assert(fd >= 0);
+        assert(ret);
+
+        for (;;) {
+                char path[l];
+
+                r = ttyname_r(fd, path, sizeof(path));
+                if (r == 0) {
+                        const char *p;
+                        char *c;
+
+                        p = startswith(path, "/dev/");
+                        c = strdup(p ?: path);
+                        if (!c)
+                                return -ENOMEM;
+
+                        *ret = c;
+                        return 0;
+                }
+
+                if (r != ERANGE)
+                        return -r;
+
+                l *= 2;
+        }
+
+        return 0;
+}
+
+int getttyname_harder(int fd, char **r) {
+        int k;
+        char *s = NULL;
+
+        k = getttyname_malloc(fd, &s);
+        if (k < 0)
+                return k;
+
+        if (streq(s, "tty")) {
+                free(s);
+                return get_ctty(0, NULL, r);
+        }
+
+        *r = s;
+        return 0;
+}
+
+int get_ctty_devnr(pid_t pid, dev_t *d) {
+        int r;
+        _cleanup_free_ char *line = NULL;
+        const char *p;
+        unsigned long ttynr;
+
+        assert(pid >= 0);
+
+        p = procfs_file_alloca(pid, "stat");
+        r = read_one_line_file(p, &line);
+        if (r < 0)
+                return r;
+
+        p = strrchr(line, ')');
+        if (!p)
+                return -EIO;
+
+        p++;
+
+        if (sscanf(p, " "
+                   "%*c "  /* state */
+                   "%*d "  /* ppid */
+                   "%*d "  /* pgrp */
+                   "%*d "  /* session */
+                   "%lu ", /* ttynr */
+                   &ttynr) != 1)
+                return -EIO;
+
+        if (major(ttynr) == 0 && minor(ttynr) == 0)
+                return -ENOENT;
+
+        if (d)
+                *d = (dev_t) ttynr;
+
+        return 0;
+}
+
+int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
+        char fn[sizeof("/dev/char/")-1 + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL;
+        _cleanup_free_ char *s = NULL;
+        const char *p;
+        dev_t devnr;
+        int k;
+
+        assert(r);
+
+        k = get_ctty_devnr(pid, &devnr);
+        if (k < 0)
+                return k;
+
+        sprintf(fn, "/dev/char/%u:%u", major(devnr), minor(devnr));
+
+        k = readlink_malloc(fn, &s);
+        if (k < 0) {
+
+                if (k != -ENOENT)
+                        return k;
+
+                /* This is an ugly hack */
+                if (major(devnr) == 136) {
+                        if (asprintf(&b, "pts/%u", minor(devnr)) < 0)
+                                return -ENOMEM;
+                } else {
+                        /* Probably something like the ptys which have no
+                         * symlink in /dev/char. Let's return something
+                         * vaguely useful. */
+
+                        b = strdup(fn + 5);
+                        if (!b)
+                                return -ENOMEM;
+                }
+        } else {
+                if (startswith(s, "/dev/"))
+                        p = s + 5;
+                else if (startswith(s, "../"))
+                        p = s + 3;
+                else
+                        p = s;
+
+                b = strdup(p);
+                if (!b)
+                        return -ENOMEM;
+        }
+
+        *r = b;
+        if (_devnr)
+                *_devnr = devnr;
+
+        return 0;
+}
diff --git a/src/shared/terminal-util.h b/src/shared/terminal-util.h
new file mode 100644
index 0000000..188714f
--- /dev/null
+++ b/src/shared/terminal-util.h
@@ -0,0 +1,109 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "macro.h"
+#include "time-util.h"
+
+#define ANSI_HIGHLIGHT_ON "\x1B[1;39m"
+#define ANSI_RED_ON "\x1B[31m"
+#define ANSI_HIGHLIGHT_RED_ON "\x1B[1;31m"
+#define ANSI_GREEN_ON "\x1B[32m"
+#define ANSI_HIGHLIGHT_GREEN_ON "\x1B[1;32m"
+#define ANSI_HIGHLIGHT_YELLOW_ON "\x1B[1;33m"
+#define ANSI_HIGHLIGHT_BLUE_ON "\x1B[1;34m"
+#define ANSI_HIGHLIGHT_OFF "\x1B[0m"
+#define ANSI_ERASE_TO_END_OF_LINE "\x1B[K"
+
+int reset_terminal_fd(int fd, bool switch_to_text);
+int reset_terminal(const char *name);
+
+int open_terminal(const char *name, int mode);
+int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm, usec_t timeout);
+int release_terminal(void);
+
+int terminal_vhangup_fd(int fd);
+int terminal_vhangup(const char *name);
+
+int chvt(int vt);
+
+int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl);
+int ask_char(char *ret, const char *replies, const char *text, ...) _printf_(3, 4);
+int ask_string(char **ret, const char *text, ...) _printf_(2, 3);
+
+int vt_disallocate(const char *name);
+
+char *resolve_dev_console(char **active);
+bool tty_is_vc(const char *tty);
+bool tty_is_vc_resolve(const char *tty);
+bool tty_is_console(const char *tty) _pure_;
+int vtnr_from_tty(const char *tty);
+const char *default_term_for_tty(const char *tty);
+
+void warn_melody(void);
+
+int make_stdio(int fd);
+int make_null_stdio(void);
+int make_console_stdio(void);
+
+int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) _printf_(4,0);
+int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) _printf_(4,5);
+
+int fd_columns(int fd);
+unsigned columns(void);
+int fd_lines(int fd);
+unsigned lines(void);
+void columns_lines_cache_reset(int _unused_ signum);
+
+bool on_tty(void);
+
+static inline const char *ansi_highlight(void) {
+        return on_tty() ? ANSI_HIGHLIGHT_ON : "";
+}
+
+static inline const char *ansi_highlight_red(void) {
+        return on_tty() ? ANSI_HIGHLIGHT_RED_ON : "";
+}
+
+static inline const char *ansi_highlight_green(void) {
+        return on_tty() ? ANSI_HIGHLIGHT_GREEN_ON : "";
+}
+
+static inline const char *ansi_highlight_yellow(void) {
+        return on_tty() ? ANSI_HIGHLIGHT_YELLOW_ON : "";
+}
+
+static inline const char *ansi_highlight_blue(void) {
+        return on_tty() ? ANSI_HIGHLIGHT_BLUE_ON : "";
+}
+
+static inline const char *ansi_highlight_off(void) {
+        return on_tty() ? ANSI_HIGHLIGHT_OFF : "";
+}
+
+int get_ctty_devnr(pid_t pid, dev_t *d);
+int get_ctty(pid_t, dev_t *_devnr, char **r);
+
+int getttyname_malloc(int fd, char **r);
+int getttyname_harder(int fd, char **r);
diff --git a/src/shared/util.c b/src/shared/util.c
index e4c4dd9..508b5d1 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -35,9 +35,6 @@
 #include <fcntl.h>
 #include <dirent.h>
 #include <sys/ioctl.h>
-#include <linux/vt.h>
-#include <linux/tiocl.h>
-#include <termios.h>
 #include <stdarg.h>
 #include <poll.h>
 #include <ctype.h>
@@ -45,7 +42,6 @@
 #include <sys/utsname.h>
 #include <pwd.h>
 #include <netinet/ip.h>
-#include <linux/kd.h>
 #include <sys/wait.h>
 #include <sys/time.h>
 #include <glob.h>
@@ -95,6 +91,7 @@
 #include "formats-util.h"
 #include "process-util.h"
 #include "random-util.h"
+#include "terminal-util.h"
 
 /* Put this test here for a lack of better place */
 assert_cc(EAGAIN == EWOULDBLOCK);
@@ -102,9 +99,6 @@ assert_cc(EAGAIN == EWOULDBLOCK);
 int saved_argc = 0;
 char **saved_argv = NULL;
 
-static volatile unsigned cached_columns = 0;
-static volatile unsigned cached_lines = 0;
-
 size_t page_size(void) {
         static thread_local size_t pgsz = 0;
         long r;
@@ -1509,301 +1503,6 @@ bool fstype_is_network(const char *fstype) {
         return nulstr_contains(table, fstype);
 }
 
-int chvt(int vt) {
-        _cleanup_close_ int fd;
-
-        fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
-        if (fd < 0)
-                return -errno;
-
-        if (vt < 0) {
-                int tiocl[2] = {
-                        TIOCL_GETKMSGREDIRECT,
-                        0
-                };
-
-                if (ioctl(fd, TIOCLINUX, tiocl) < 0)
-                        return -errno;
-
-                vt = tiocl[0] <= 0 ? 1 : tiocl[0];
-        }
-
-        if (ioctl(fd, VT_ACTIVATE, vt) < 0)
-                return -errno;
-
-        return 0;
-}
-
-int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
-        struct termios old_termios, new_termios;
-        char c, line[LINE_MAX];
-
-        assert(f);
-        assert(ret);
-
-        if (tcgetattr(fileno(f), &old_termios) >= 0) {
-                new_termios = old_termios;
-
-                new_termios.c_lflag &= ~ICANON;
-                new_termios.c_cc[VMIN] = 1;
-                new_termios.c_cc[VTIME] = 0;
-
-                if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
-                        size_t k;
-
-                        if (t != USEC_INFINITY) {
-                                if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
-                                        tcsetattr(fileno(f), TCSADRAIN, &old_termios);
-                                        return -ETIMEDOUT;
-                                }
-                        }
-
-                        k = fread(&c, 1, 1, f);
-
-                        tcsetattr(fileno(f), TCSADRAIN, &old_termios);
-
-                        if (k <= 0)
-                                return -EIO;
-
-                        if (need_nl)
-                                *need_nl = c != '\n';
-
-                        *ret = c;
-                        return 0;
-                }
-        }
-
-        if (t != USEC_INFINITY) {
-                if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
-                        return -ETIMEDOUT;
-        }
-
-        errno = 0;
-        if (!fgets(line, sizeof(line), f))
-                return errno ? -errno : -EIO;
-
-        truncate_nl(line);
-
-        if (strlen(line) != 1)
-                return -EBADMSG;
-
-        if (need_nl)
-                *need_nl = false;
-
-        *ret = line[0];
-        return 0;
-}
-
-int ask_char(char *ret, const char *replies, const char *text, ...) {
-        int r;
-
-        assert(ret);
-        assert(replies);
-        assert(text);
-
-        for (;;) {
-                va_list ap;
-                char c;
-                bool need_nl = true;
-
-                if (on_tty())
-                        fputs(ANSI_HIGHLIGHT_ON, stdout);
-
-                va_start(ap, text);
-                vprintf(text, ap);
-                va_end(ap);
-
-                if (on_tty())
-                        fputs(ANSI_HIGHLIGHT_OFF, stdout);
-
-                fflush(stdout);
-
-                r = read_one_char(stdin, &c, USEC_INFINITY, &need_nl);
-                if (r < 0) {
-
-                        if (r == -EBADMSG) {
-                                puts("Bad input, please try again.");
-                                continue;
-                        }
-
-                        putchar('\n');
-                        return r;
-                }
-
-                if (need_nl)
-                        putchar('\n');
-
-                if (strchr(replies, c)) {
-                        *ret = c;
-                        return 0;
-                }
-
-                puts("Read unexpected character, please try again.");
-        }
-}
-
-int ask_string(char **ret, const char *text, ...) {
-        assert(ret);
-        assert(text);
-
-        for (;;) {
-                char line[LINE_MAX];
-                va_list ap;
-
-                if (on_tty())
-                        fputs(ANSI_HIGHLIGHT_ON, stdout);
-
-                va_start(ap, text);
-                vprintf(text, ap);
-                va_end(ap);
-
-                if (on_tty())
-                        fputs(ANSI_HIGHLIGHT_OFF, stdout);
-
-                fflush(stdout);
-
-                errno = 0;
-                if (!fgets(line, sizeof(line), stdin))
-                        return errno ? -errno : -EIO;
-
-                if (!endswith(line, "\n"))
-                        putchar('\n');
-                else {
-                        char *s;
-
-                        if (isempty(line))
-                                continue;
-
-                        truncate_nl(line);
-                        s = strdup(line);
-                        if (!s)
-                                return -ENOMEM;
-
-                        *ret = s;
-                        return 0;
-                }
-        }
-}
-
-int reset_terminal_fd(int fd, bool switch_to_text) {
-        struct termios termios;
-        int r = 0;
-
-        /* Set terminal to some sane defaults */
-
-        assert(fd >= 0);
-
-        /* We leave locked terminal attributes untouched, so that
-         * Plymouth may set whatever it wants to set, and we don't
-         * interfere with that. */
-
-        /* Disable exclusive mode, just in case */
-        ioctl(fd, TIOCNXCL);
-
-        /* Switch to text mode */
-        if (switch_to_text)
-                ioctl(fd, KDSETMODE, KD_TEXT);
-
-        /* Enable console unicode mode */
-        ioctl(fd, KDSKBMODE, K_UNICODE);
-
-        if (tcgetattr(fd, &termios) < 0) {
-                r = -errno;
-                goto finish;
-        }
-
-        /* We only reset the stuff that matters to the software. How
-         * hardware is set up we don't touch assuming that somebody
-         * else will do that for us */
-
-        termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
-        termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
-        termios.c_oflag |= ONLCR;
-        termios.c_cflag |= CREAD;
-        termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
-
-        termios.c_cc[VINTR]    =   03;  /* ^C */
-        termios.c_cc[VQUIT]    =  034;  /* ^\ */
-        termios.c_cc[VERASE]   = 0177;
-        termios.c_cc[VKILL]    =  025;  /* ^X */
-        termios.c_cc[VEOF]     =   04;  /* ^D */
-        termios.c_cc[VSTART]   =  021;  /* ^Q */
-        termios.c_cc[VSTOP]    =  023;  /* ^S */
-        termios.c_cc[VSUSP]    =  032;  /* ^Z */
-        termios.c_cc[VLNEXT]   =  026;  /* ^V */
-        termios.c_cc[VWERASE]  =  027;  /* ^W */
-        termios.c_cc[VREPRINT] =  022;  /* ^R */
-        termios.c_cc[VEOL]     =    0;
-        termios.c_cc[VEOL2]    =    0;
-
-        termios.c_cc[VTIME]  = 0;
-        termios.c_cc[VMIN]   = 1;
-
-        if (tcsetattr(fd, TCSANOW, &termios) < 0)
-                r = -errno;
-
-finish:
-        /* Just in case, flush all crap out */
-        tcflush(fd, TCIOFLUSH);
-
-        return r;
-}
-
-int reset_terminal(const char *name) {
-        _cleanup_close_ int fd = -1;
-
-        fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
-        if (fd < 0)
-                return fd;
-
-        return reset_terminal_fd(fd, true);
-}
-
-int open_terminal(const char *name, int mode) {
-        int fd, r;
-        unsigned c = 0;
-
-        /*
-         * If a TTY is in the process of being closed opening it might
-         * cause EIO. This is horribly awful, but unlikely to be
-         * changed in the kernel. Hence we work around this problem by
-         * retrying a couple of times.
-         *
-         * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
-         */
-
-        assert(!(mode & O_CREAT));
-
-        for (;;) {
-                fd = open(name, mode, 0);
-                if (fd >= 0)
-                        break;
-
-                if (errno != EIO)
-                        return -errno;
-
-                /* Max 1s in total */
-                if (c >= 20)
-                        return -errno;
-
-                usleep(50 * USEC_PER_MSEC);
-                c++;
-        }
-
-        r = isatty(fd);
-        if (r < 0) {
-                safe_close(fd);
-                return -errno;
-        }
-
-        if (!r) {
-                safe_close(fd);
-                return -ENOTTY;
-        }
-
-        return fd;
-}
-
 int flush_fd(int fd) {
         struct pollfd pollfd = {
                 .fd = fd,
@@ -1840,185 +1539,6 @@ int flush_fd(int fd) {
         }
 }
 
-int acquire_terminal(
-                const char *name,
-                bool fail,
-                bool force,
-                bool ignore_tiocstty_eperm,
-                usec_t timeout) {
-
-        int fd = -1, notify = -1, r = 0, wd = -1;
-        usec_t ts = 0;
-
-        assert(name);
-
-        /* We use inotify to be notified when the tty is closed. We
-         * create the watch before checking if we can actually acquire
-         * it, so that we don't lose any event.
-         *
-         * Note: strictly speaking this actually watches for the
-         * device being closed, it does *not* really watch whether a
-         * tty loses its controlling process. However, unless some
-         * rogue process uses TIOCNOTTY on /dev/tty *after* closing
-         * its tty otherwise this will not become a problem. As long
-         * as the administrator makes sure not configure any service
-         * on the same tty as an untrusted user this should not be a
-         * problem. (Which he probably should not do anyway.) */
-
-        if (timeout != USEC_INFINITY)
-                ts = now(CLOCK_MONOTONIC);
-
-        if (!fail && !force) {
-                notify = inotify_init1(IN_CLOEXEC | (timeout != USEC_INFINITY ? IN_NONBLOCK : 0));
-                if (notify < 0) {
-                        r = -errno;
-                        goto fail;
-                }
-
-                wd = inotify_add_watch(notify, name, IN_CLOSE);
-                if (wd < 0) {
-                        r = -errno;
-                        goto fail;
-                }
-        }
-
-        for (;;) {
-                struct sigaction sa_old, sa_new = {
-                        .sa_handler = SIG_IGN,
-                        .sa_flags = SA_RESTART,
-                };
-
-                if (notify >= 0) {
-                        r = flush_fd(notify);
-                        if (r < 0)
-                                goto fail;
-                }
-
-                /* We pass here O_NOCTTY only so that we can check the return
-                 * value TIOCSCTTY and have a reliable way to figure out if we
-                 * successfully became the controlling process of the tty */
-                fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
-                if (fd < 0)
-                        return fd;
-
-                /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
-                 * if we already own the tty. */
-                assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
-
-                /* First, try to get the tty */
-                if (ioctl(fd, TIOCSCTTY, force) < 0)
-                        r = -errno;
-
-                assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
-
-                /* Sometimes it makes sense to ignore TIOCSCTTY
-                 * returning EPERM, i.e. when very likely we already
-                 * are have this controlling terminal. */
-                if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
-                        r = 0;
-
-                if (r < 0 && (force || fail || r != -EPERM)) {
-                        goto fail;
-                }
-
-                if (r >= 0)
-                        break;
-
-                assert(!fail);
-                assert(!force);
-                assert(notify >= 0);
-
-                for (;;) {
-                        union inotify_event_buffer buffer;
-                        struct inotify_event *e;
-                        ssize_t l;
-
-                        if (timeout != USEC_INFINITY) {
-                                usec_t n;
-
-                                n = now(CLOCK_MONOTONIC);
-                                if (ts + timeout < n) {
-                                        r = -ETIMEDOUT;
-                                        goto fail;
-                                }
-
-                                r = fd_wait_for_event(fd, POLLIN, ts + timeout - n);
-                                if (r < 0)
-                                        goto fail;
-
-                                if (r == 0) {
-                                        r = -ETIMEDOUT;
-                                        goto fail;
-                                }
-                        }
-
-                        l = read(notify, &buffer, sizeof(buffer));
-                        if (l < 0) {
-                                if (errno == EINTR || errno == EAGAIN)
-                                        continue;
-
-                                r = -errno;
-                                goto fail;
-                        }
-
-                        FOREACH_INOTIFY_EVENT(e, buffer, l) {
-                                if (e->wd != wd || !(e->mask & IN_CLOSE)) {
-                                        r = -EIO;
-                                        goto fail;
-                                }
-                        }
-
-                        break;
-                }
-
-                /* We close the tty fd here since if the old session
-                 * ended our handle will be dead. It's important that
-                 * we do this after sleeping, so that we don't enter
-                 * an endless loop. */
-                fd = safe_close(fd);
-        }
-
-        safe_close(notify);
-
-        r = reset_terminal_fd(fd, true);
-        if (r < 0)
-                log_warning_errno(r, "Failed to reset terminal: %m");
-
-        return fd;
-
-fail:
-        safe_close(fd);
-        safe_close(notify);
-
-        return r;
-}
-
-int release_terminal(void) {
-        static const struct sigaction sa_new = {
-                .sa_handler = SIG_IGN,
-                .sa_flags = SA_RESTART,
-        };
-
-        _cleanup_close_ int fd = -1;
-        struct sigaction sa_old;
-        int r = 0;
-
-        fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC);
-        if (fd < 0)
-                return -errno;
-
-        /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
-         * by our own TIOCNOTTY */
-        assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
-
-        if (ioctl(fd, TIOCNOTTY) < 0)
-                r = -errno;
-
-        assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
-
-        return r;
-}
-
 int sigaction_many(const struct sigaction *sa, ...) {
         va_list ap;
         int r = 0, sig;
@@ -2303,40 +1823,6 @@ int parse_size(const char *t, off_t base, off_t *size) {
         return 0;
 }
 
-int make_stdio(int fd) {
-        int r, s, t;
-
-        assert(fd >= 0);
-
-        r = dup2(fd, STDIN_FILENO);
-        s = dup2(fd, STDOUT_FILENO);
-        t = dup2(fd, STDERR_FILENO);
-
-        if (fd >= 3)
-                safe_close(fd);
-
-        if (r < 0 || s < 0 || t < 0)
-                return -errno;
-
-        /* Explicitly unset O_CLOEXEC, since if fd was < 3, then
-         * dup2() was a NOP and the bit hence possibly set. */
-        fd_cloexec(STDIN_FILENO, false);
-        fd_cloexec(STDOUT_FILENO, false);
-        fd_cloexec(STDERR_FILENO, false);
-
-        return 0;
-}
-
-int make_null_stdio(void) {
-        int null_fd;
-
-        null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
-        if (null_fd < 0)
-                return -errno;
-
-        return make_stdio(null_fd);
-}
-
 bool is_device_path(const char *path) {
 
         /* Returns true on paths that refer to a device, either in
@@ -2460,202 +1946,61 @@ char* gethostname_malloc(void) {
         return strdup(u.sysname);
 }
 
-bool hostname_is_set(void) {
-        struct utsname u;
-
-        assert_se(uname(&u) >= 0);
-
-        return !isempty(u.nodename) && !streq(u.nodename, "(none)");
-}
-
-char *lookup_uid(uid_t uid) {
-        long bufsize;
-        char *name;
-        _cleanup_free_ char *buf = NULL;
-        struct passwd pwbuf, *pw = NULL;
-
-        /* Shortcut things to avoid NSS lookups */
-        if (uid == 0)
-                return strdup("root");
-
-        bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
-        if (bufsize <= 0)
-                bufsize = 4096;
-
-        buf = malloc(bufsize);
-        if (!buf)
-                return NULL;
-
-        if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
-                return strdup(pw->pw_name);
-
-        if (asprintf(&name, UID_FMT, uid) < 0)
-                return NULL;
-
-        return name;
-}
-
-char* getlogname_malloc(void) {
-        uid_t uid;
-        struct stat st;
-
-        if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
-                uid = st.st_uid;
-        else
-                uid = getuid();
-
-        return lookup_uid(uid);
-}
-
-char *getusername_malloc(void) {
-        const char *e;
-
-        e = getenv("USER");
-        if (e)
-                return strdup(e);
-
-        return lookup_uid(getuid());
-}
-
-int getttyname_malloc(int fd, char **ret) {
-        size_t l = 100;
-        int r;
-
-        assert(fd >= 0);
-        assert(ret);
-
-        for (;;) {
-                char path[l];
-
-                r = ttyname_r(fd, path, sizeof(path));
-                if (r == 0) {
-                        const char *p;
-                        char *c;
-
-                        p = startswith(path, "/dev/");
-                        c = strdup(p ?: path);
-                        if (!c)
-                                return -ENOMEM;
-
-                        *ret = c;
-                        return 0;
-                }
-
-                if (r != ERANGE)
-                        return -r;
-
-                l *= 2;
-        }
-
-        return 0;
-}
-
-int getttyname_harder(int fd, char **r) {
-        int k;
-        char *s = NULL;
-
-        k = getttyname_malloc(fd, &s);
-        if (k < 0)
-                return k;
-
-        if (streq(s, "tty")) {
-                free(s);
-                return get_ctty(0, NULL, r);
-        }
-
-        *r = s;
-        return 0;
-}
-
-int get_ctty_devnr(pid_t pid, dev_t *d) {
-        int r;
-        _cleanup_free_ char *line = NULL;
-        const char *p;
-        unsigned long ttynr;
-
-        assert(pid >= 0);
-
-        p = procfs_file_alloca(pid, "stat");
-        r = read_one_line_file(p, &line);
-        if (r < 0)
-                return r;
-
-        p = strrchr(line, ')');
-        if (!p)
-                return -EIO;
-
-        p++;
+bool hostname_is_set(void) {
+        struct utsname u;
 
-        if (sscanf(p, " "
-                   "%*c "  /* state */
-                   "%*d "  /* ppid */
-                   "%*d "  /* pgrp */
-                   "%*d "  /* session */
-                   "%lu ", /* ttynr */
-                   &ttynr) != 1)
-                return -EIO;
+        assert_se(uname(&u) >= 0);
 
-        if (major(ttynr) == 0 && minor(ttynr) == 0)
-                return -ENOENT;
+        return !isempty(u.nodename) && !streq(u.nodename, "(none)");
+}
 
-        if (d)
-                *d = (dev_t) ttynr;
+char *lookup_uid(uid_t uid) {
+        long bufsize;
+        char *name;
+        _cleanup_free_ char *buf = NULL;
+        struct passwd pwbuf, *pw = NULL;
 
-        return 0;
-}
+        /* Shortcut things to avoid NSS lookups */
+        if (uid == 0)
+                return strdup("root");
 
-int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
-        char fn[sizeof("/dev/char/")-1 + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL;
-        _cleanup_free_ char *s = NULL;
-        const char *p;
-        dev_t devnr;
-        int k;
+        bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+        if (bufsize <= 0)
+                bufsize = 4096;
 
-        assert(r);
+        buf = malloc(bufsize);
+        if (!buf)
+                return NULL;
 
-        k = get_ctty_devnr(pid, &devnr);
-        if (k < 0)
-                return k;
+        if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
+                return strdup(pw->pw_name);
 
-        sprintf(fn, "/dev/char/%u:%u", major(devnr), minor(devnr));
+        if (asprintf(&name, UID_FMT, uid) < 0)
+                return NULL;
 
-        k = readlink_malloc(fn, &s);
-        if (k < 0) {
+        return name;
+}
 
-                if (k != -ENOENT)
-                        return k;
+char* getlogname_malloc(void) {
+        uid_t uid;
+        struct stat st;
 
-                /* This is an ugly hack */
-                if (major(devnr) == 136) {
-                        if (asprintf(&b, "pts/%u", minor(devnr)) < 0)
-                                return -ENOMEM;
-                } else {
-                        /* Probably something like the ptys which have no
-                         * symlink in /dev/char. Let's return something
-                         * vaguely useful. */
+        if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
+                uid = st.st_uid;
+        else
+                uid = getuid();
 
-                        b = strdup(fn + 5);
-                        if (!b)
-                                return -ENOMEM;
-                }
-        } else {
-                if (startswith(s, "/dev/"))
-                        p = s + 5;
-                else if (startswith(s, "../"))
-                        p = s + 3;
-                else
-                        p = s;
+        return lookup_uid(uid);
+}
 
-                b = strdup(p);
-                if (!b)
-                        return -ENOMEM;
-        }
+char *getusername_malloc(void) {
+        const char *e;
 
-        *r = b;
-        if (_devnr)
-                *_devnr = devnr;
+        e = getenv("USER");
+        if (e)
+                return strdup(e);
 
-        return 0;
+        return lookup_uid(getuid());
 }
 
 bool is_temporary_fs(const struct statfs *s) {
@@ -2738,84 +2083,6 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
         }
 }
 
-int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
-        static const char status_indent[] = "         "; /* "[" STATUS "] " */
-        _cleanup_free_ char *s = NULL;
-        _cleanup_close_ int fd = -1;
-        struct iovec iovec[6] = {};
-        int n = 0;
-        static bool prev_ephemeral;
-
-        assert(format);
-
-        /* This is independent of logging, as status messages are
-         * optional and go exclusively to the console. */
-
-        if (vasprintf(&s, format, ap) < 0)
-                return log_oom();
-
-        fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
-        if (fd < 0)
-                return fd;
-
-        if (ellipse) {
-                char *e;
-                size_t emax, sl;
-                int c;
-
-                c = fd_columns(fd);
-                if (c <= 0)
-                        c = 80;
-
-                sl = status ? sizeof(status_indent)-1 : 0;
-
-                emax = c - sl - 1;
-                if (emax < 3)
-                        emax = 3;
-
-                e = ellipsize(s, emax, 50);
-                if (e) {
-                        free(s);
-                        s = e;
-                }
-        }
-
-        if (prev_ephemeral)
-                IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
-        prev_ephemeral = ephemeral;
-
-        if (status) {
-                if (!isempty(status)) {
-                        IOVEC_SET_STRING(iovec[n++], "[");
-                        IOVEC_SET_STRING(iovec[n++], status);
-                        IOVEC_SET_STRING(iovec[n++], "] ");
-                } else
-                        IOVEC_SET_STRING(iovec[n++], status_indent);
-        }
-
-        IOVEC_SET_STRING(iovec[n++], s);
-        if (!ephemeral)
-                IOVEC_SET_STRING(iovec[n++], "\n");
-
-        if (writev(fd, iovec, n) < 0)
-                return -errno;
-
-        return 0;
-}
-
-int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) {
-        va_list ap;
-        int r;
-
-        assert(format);
-
-        va_start(ap, format);
-        r = status_vprintf(status, ellipse, ephemeral, format, ap);
-        va_end(ap);
-
-        return r;
-}
-
 char *replace_env(const char *format, char **env) {
         enum {
                 WORD,
@@ -2960,89 +2227,6 @@ char **replace_env_argv(char **argv, char **env) {
         return ret;
 }
 
-int fd_columns(int fd) {
-        struct winsize ws = {};
-
-        if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
-                return -errno;
-
-        if (ws.ws_col <= 0)
-                return -EIO;
-
-        return ws.ws_col;
-}
-
-unsigned columns(void) {
-        const char *e;
-        int c;
-
-        if (_likely_(cached_columns > 0))
-                return cached_columns;
-
-        c = 0;
-        e = getenv("COLUMNS");
-        if (e)
-                (void) safe_atoi(e, &c);
-
-        if (c <= 0)
-                c = fd_columns(STDOUT_FILENO);
-
-        if (c <= 0)
-                c = 80;
-
-        cached_columns = c;
-        return cached_columns;
-}
-
-int fd_lines(int fd) {
-        struct winsize ws = {};
-
-        if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
-                return -errno;
-
-        if (ws.ws_row <= 0)
-                return -EIO;
-
-        return ws.ws_row;
-}
-
-unsigned lines(void) {
-        const char *e;
-        int l;
-
-        if (_likely_(cached_lines > 0))
-                return cached_lines;
-
-        l = 0;
-        e = getenv("LINES");
-        if (e)
-                (void) safe_atoi(e, &l);
-
-        if (l <= 0)
-                l = fd_lines(STDOUT_FILENO);
-
-        if (l <= 0)
-                l = 24;
-
-        cached_lines = l;
-        return cached_lines;
-}
-
-/* intended to be used as a SIGWINCH sighandler */
-void columns_lines_cache_reset(int signum) {
-        cached_columns = 0;
-        cached_lines = 0;
-}
-
-bool on_tty(void) {
-        static int cached_on_tty = -1;
-
-        if (_unlikely_(cached_on_tty < 0))
-                cached_on_tty = isatty(STDOUT_FILENO) > 0;
-
-        return cached_on_tty;
-}
-
 int files_same(const char *filea, const char *fileb) {
         struct stat a, b;
 
@@ -3351,101 +2535,6 @@ char *fstab_node_to_udev_node(const char *p) {
         return strdup(p);
 }
 
-bool tty_is_vc(const char *tty) {
-        assert(tty);
-
-        return vtnr_from_tty(tty) >= 0;
-}
-
-bool tty_is_console(const char *tty) {
-        assert(tty);
-
-        if (startswith(tty, "/dev/"))
-                tty += 5;
-
-        return streq(tty, "console");
-}
-
-int vtnr_from_tty(const char *tty) {
-        int i, r;
-
-        assert(tty);
-
-        if (startswith(tty, "/dev/"))
-                tty += 5;
-
-        if (!startswith(tty, "tty") )
-                return -EINVAL;
-
-        if (tty[3] < '0' || tty[3] > '9')
-                return -EINVAL;
-
-        r = safe_atoi(tty+3, &i);
-        if (r < 0)
-                return r;
-
-        if (i < 0 || i > 63)
-                return -EINVAL;
-
-        return i;
-}
-
-char *resolve_dev_console(char **active) {
-        char *tty;
-
-        /* Resolve where /dev/console is pointing to, if /sys is actually ours
-         * (i.e. not read-only-mounted which is a sign for container setups) */
-
-        if (path_is_read_only_fs("/sys") > 0)
-                return NULL;
-
-        if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
-                return NULL;
-
-        /* If multiple log outputs are configured the last one is what
-         * /dev/console points to */
-        tty = strrchr(*active, ' ');
-        if (tty)
-                tty++;
-        else
-                tty = *active;
-
-        if (streq(tty, "tty0")) {
-                char *tmp;
-
-                /* Get the active VC (e.g. tty1) */
-                if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
-                        free(*active);
-                        tty = *active = tmp;
-                }
-        }
-
-        return tty;
-}
-
-bool tty_is_vc_resolve(const char *tty) {
-        _cleanup_free_ char *active = NULL;
-
-        assert(tty);
-
-        if (startswith(tty, "/dev/"))
-                tty += 5;
-
-        if (streq(tty, "console")) {
-                tty = resolve_dev_console(&active);
-                if (!tty)
-                        return false;
-        }
-
-        return tty_is_vc(tty);
-}
-
-const char *default_term_for_tty(const char *tty) {
-        assert(tty);
-
-        return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt220";
-}
-
 bool dirent_is_file(const struct dirent *de) {
         assert(de);
 
@@ -3798,94 +2887,6 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
         return 0;
 }
 
-int terminal_vhangup_fd(int fd) {
-        assert(fd >= 0);
-
-        if (ioctl(fd, TIOCVHANGUP) < 0)
-                return -errno;
-
-        return 0;
-}
-
-int terminal_vhangup(const char *name) {
-        _cleanup_close_ int fd;
-
-        fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
-        if (fd < 0)
-                return fd;
-
-        return terminal_vhangup_fd(fd);
-}
-
-int vt_disallocate(const char *name) {
-        int fd, r;
-        unsigned u;
-
-        /* Deallocate the VT if possible. If not possible
-         * (i.e. because it is the active one), at least clear it
-         * entirely (including the scrollback buffer) */
-
-        if (!startswith(name, "/dev/"))
-                return -EINVAL;
-
-        if (!tty_is_vc(name)) {
-                /* So this is not a VT. I guess we cannot deallocate
-                 * it then. But let's at least clear the screen */
-
-                fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
-                if (fd < 0)
-                        return fd;
-
-                loop_write(fd,
-                           "\033[r"    /* clear scrolling region */
-                           "\033[H"    /* move home */
-                           "\033[2J",  /* clear screen */
-                           10, false);
-                safe_close(fd);
-
-                return 0;
-        }
-
-        if (!startswith(name, "/dev/tty"))
-                return -EINVAL;
-
-        r = safe_atou(name+8, &u);
-        if (r < 0)
-                return r;
-
-        if (u <= 0)
-                return -EINVAL;
-
-        /* Try to deallocate */
-        fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
-        if (fd < 0)
-                return fd;
-
-        r = ioctl(fd, VT_DISALLOCATE, u);
-        safe_close(fd);
-
-        if (r >= 0)
-                return 0;
-
-        if (errno != EBUSY)
-                return -errno;
-
-        /* Couldn't deallocate, so let's clear it fully with
-         * scrollback */
-        fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
-        if (fd < 0)
-                return fd;
-
-        loop_write(fd,
-                   "\033[r"   /* clear scrolling region */
-                   "\033[H"   /* move home */
-                   "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
-                   10, false);
-        safe_close(fd);
-
-        return 0;
-}
-
 int symlink_atomic(const char *from, const char *to) {
         _cleanup_free_ char *t = NULL;
         int r;
@@ -4898,43 +3899,6 @@ bool in_initrd(void) {
         return saved;
 }
 
-void warn_melody(void) {
-        _cleanup_close_ int fd = -1;
-
-        fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
-        if (fd < 0)
-                return;
-
-        /* Yeah, this is synchronous. Kinda sucks. But well... */
-
-        ioctl(fd, KIOCSOUND, (int)(1193180/440));
-        usleep(125*USEC_PER_MSEC);
-
-        ioctl(fd, KIOCSOUND, (int)(1193180/220));
-        usleep(125*USEC_PER_MSEC);
-
-        ioctl(fd, KIOCSOUND, (int)(1193180/220));
-        usleep(125*USEC_PER_MSEC);
-
-        ioctl(fd, KIOCSOUND, 0);
-}
-
-int make_console_stdio(void) {
-        int fd, r;
-
-        /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
-
-        fd = acquire_terminal("/dev/console", false, true, true, USEC_INFINITY);
-        if (fd < 0)
-                return log_error_errno(fd, "Failed to acquire terminal: %m");
-
-        r = make_stdio(fd);
-        if (r < 0)
-                return log_error_errno(r, "Failed to duplicate terminal fd: %m");
-
-        return 0;
-}
-
 int get_home_dir(char **_h) {
         struct passwd *p;
         const char *e;
diff --git a/src/shared/util.h b/src/shared/util.h
index 4d5162f..f54722f 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -63,16 +63,6 @@
 
 #define FORMAT_BYTES_MAX 8
 
-#define ANSI_HIGHLIGHT_ON "\x1B[1;39m"
-#define ANSI_RED_ON "\x1B[31m"
-#define ANSI_HIGHLIGHT_RED_ON "\x1B[1;31m"
-#define ANSI_GREEN_ON "\x1B[32m"
-#define ANSI_HIGHLIGHT_GREEN_ON "\x1B[1;32m"
-#define ANSI_HIGHLIGHT_YELLOW_ON "\x1B[1;33m"
-#define ANSI_HIGHLIGHT_BLUE_ON "\x1B[1;34m"
-#define ANSI_HIGHLIGHT_OFF "\x1B[0m"
-#define ANSI_ERASE_TO_END_OF_LINE "\x1B[K"
-
 size_t page_size(void) _pure_;
 #define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
 
@@ -279,10 +269,6 @@ bool hidden_file(const char *filename) _pure_;
 
 bool chars_intersect(const char *a, const char *b) _pure_;
 
-int make_stdio(int fd);
-int make_null_stdio(void);
-int make_console_stdio(void);
-
 /* For basic lookup tables with strictly enumerated entries */
 #define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
         scope const char *name##_to_string(type i) {                    \
@@ -348,19 +334,6 @@ int close_all_fds(const int except[], unsigned n_except);
 
 bool fstype_is_network(const char *fstype);
 
-int chvt(int vt);
-
-int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl);
-int ask_char(char *ret, const char *replies, const char *text, ...) _printf_(3, 4);
-int ask_string(char **ret, const char *text, ...) _printf_(2, 3);
-
-int reset_terminal_fd(int fd, bool switch_to_text);
-int reset_terminal(const char *name);
-
-int open_terminal(const char *name, int mode);
-int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm, usec_t timeout);
-int release_terminal(void);
-
 int flush_fd(int fd);
 
 int ignore_signals(int sig, ...);
@@ -388,12 +361,6 @@ char* gethostname_malloc(void);
 char* getlogname_malloc(void);
 char* getusername_malloc(void);
 
-int getttyname_malloc(int fd, char **r);
-int getttyname_harder(int fd, char **r);
-
-int get_ctty_devnr(pid_t pid, dev_t *d);
-int get_ctty(pid_t, dev_t *_devnr, char **r);
-
 int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
 int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
 
@@ -404,43 +371,8 @@ int pipe_eof(int fd);
 
 cpu_set_t* cpu_set_malloc(unsigned *ncpus);
 
-int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) _printf_(4,0);
-int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) _printf_(4,5);
-
 #define xsprintf(buf, fmt, ...) assert_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf))
 
-int fd_columns(int fd);
-unsigned columns(void);
-int fd_lines(int fd);
-unsigned lines(void);
-void columns_lines_cache_reset(int _unused_ signum);
-
-bool on_tty(void);
-
-static inline const char *ansi_highlight(void) {
-        return on_tty() ? ANSI_HIGHLIGHT_ON : "";
-}
-
-static inline const char *ansi_highlight_red(void) {
-        return on_tty() ? ANSI_HIGHLIGHT_RED_ON : "";
-}
-
-static inline const char *ansi_highlight_green(void) {
-        return on_tty() ? ANSI_HIGHLIGHT_GREEN_ON : "";
-}
-
-static inline const char *ansi_highlight_yellow(void) {
-        return on_tty() ? ANSI_HIGHLIGHT_YELLOW_ON : "";
-}
-
-static inline const char *ansi_highlight_blue(void) {
-        return on_tty() ? ANSI_HIGHLIGHT_BLUE_ON : "";
-}
-
-static inline const char *ansi_highlight_off(void) {
-        return on_tty() ? ANSI_HIGHLIGHT_OFF : "";
-}
-
 int files_same(const char *filea, const char *fileb);
 
 int running_in_chroot(void);
@@ -462,13 +394,6 @@ DIR *xopendirat(int dirfd, const char *name, int flags);
 
 char *fstab_node_to_udev_node(const char *p);
 
-char *resolve_dev_console(char **active);
-bool tty_is_vc(const char *tty);
-bool tty_is_vc_resolve(const char *tty);
-bool tty_is_console(const char *tty) _pure_;
-int vtnr_from_tty(const char *tty);
-const char *default_term_for_tty(const char *tty);
-
 void execute_directories(const char* const* directories, usec_t timeout, char *argv[]);
 
 bool nulstr_contains(const char*nulstr, const char *needle);
@@ -482,10 +407,6 @@ bool machine_name_is_valid(const char *s) _pure_;
 
 char* strshorten(char *s, size_t l);
 
-int terminal_vhangup_fd(int fd);
-int terminal_vhangup(const char *name);
-
-int vt_disallocate(const char *name);
 
 int symlink_atomic(const char *from, const char *to);
 int mknod_atomic(const char *path, mode_t mode, dev_t dev);
@@ -583,8 +504,6 @@ bool http_etag_is_valid(const char *etag);
 
 bool in_initrd(void);
 
-void warn_melody(void);
-
 int get_home_dir(char **ret);
 int get_shell(char **_ret);
 
diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c
index 7fb6fe3..d6c4cc8 100644
--- a/src/shared/utmp-wtmp.c
+++ b/src/shared/utmp-wtmp.c
@@ -30,6 +30,7 @@
 #include "macro.h"
 #include "path-util.h"
 #include "utmp-wtmp.h"
+#include "terminal-util.h"
 
 int utmp_get_runlevel(int *runlevel, int *previous) {
         struct utmpx *found, lookup = { .ut_type = RUN_LVL };
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 04b7e7b..75d709d 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -71,6 +71,7 @@
 #include "efivars.h"
 #include "formats-util.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 static char **arg_types = NULL;
 static char **arg_states = NULL;
diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c
index 6a2f9aa..27df908 100644
--- a/src/test/test-ellipsize.c
+++ b/src/test/test-ellipsize.c
@@ -22,6 +22,7 @@
 #include <stdio.h>
 
 #include "util.h"
+#include "terminal-util.h"
 #include "def.h"
 
 static void test_one(const char *p) {
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index a17ef14..1de100c 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -28,6 +28,7 @@
 #include "util.h"
 #include "macro.h"
 #include "virt.h"
+#include "terminal-util.h"
 
 static void test_get_process_comm(void) {
         struct stat st;
diff --git a/src/test/test-strip-tab-ansi.c b/src/test/test-strip-tab-ansi.c
index 5016906..3584548 100644
--- a/src/test/test-strip-tab-ansi.c
+++ b/src/test/test-strip-tab-ansi.c
@@ -22,6 +22,7 @@
 #include <stdio.h>
 
 #include "util.h"
+#include "terminal-util.h"
 
 int main(int argc, char *argv[]) {
         char *p;
diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c
new file mode 100644
index 0000000..d81fdb9
--- /dev/null
+++ b/src/test/test-terminal-util.c
@@ -0,0 +1,84 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+  Copyright 2013 Thomas H.P. Andersen
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "terminal-util.h"
+#include "macro.h"
+#include "util.h"
+#include "log.h"
+
+static void test_default_term_for_tty(void) {
+        puts(default_term_for_tty("/dev/tty23"));
+        puts(default_term_for_tty("/dev/ttyS23"));
+        puts(default_term_for_tty("/dev/tty0"));
+        puts(default_term_for_tty("/dev/pty0"));
+        puts(default_term_for_tty("/dev/pts/0"));
+        puts(default_term_for_tty("/dev/console"));
+        puts(default_term_for_tty("tty23"));
+        puts(default_term_for_tty("ttyS23"));
+        puts(default_term_for_tty("tty0"));
+        puts(default_term_for_tty("pty0"));
+        puts(default_term_for_tty("pts/0"));
+        puts(default_term_for_tty("console"));
+}
+
+static void test_read_one_char(void) {
+        _cleanup_fclose_ FILE *file = NULL;
+        char r;
+        bool need_nl;
+        char name[] = "/tmp/test-read_one_char.XXXXXX";
+        int fd;
+
+        fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+        assert_se(fd >= 0);
+        file = fdopen(fd, "r+");
+        assert_se(file);
+        assert_se(fputs("c\n", file) >= 0);
+        rewind(file);
+
+        assert_se(read_one_char(file, &r, 1000000, &need_nl) >= 0);
+        assert_se(!need_nl);
+        assert_se(r == 'c');
+        assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0);
+
+        rewind(file);
+        assert_se(fputs("foobar\n", file) >= 0);
+        rewind(file);
+        assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0);
+
+        rewind(file);
+        assert_se(fputs("\n", file) >= 0);
+        rewind(file);
+        assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0);
+
+        unlink(name);
+}
+
+int main(int argc, char *argv[]) {
+        log_parse_environment();
+        log_open();
+
+        test_default_term_for_tty();
+        test_read_one_char();
+
+        return 0;
+}
diff --git a/src/test/test-util.c b/src/test/test-util.c
index bfd4df9..fdb772d 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -522,21 +522,6 @@ static void test_foreach_word_quoted(void) {
               true);
 }
 
-static void test_default_term_for_tty(void) {
-        puts(default_term_for_tty("/dev/tty23"));
-        puts(default_term_for_tty("/dev/ttyS23"));
-        puts(default_term_for_tty("/dev/tty0"));
-        puts(default_term_for_tty("/dev/pty0"));
-        puts(default_term_for_tty("/dev/pts/0"));
-        puts(default_term_for_tty("/dev/console"));
-        puts(default_term_for_tty("tty23"));
-        puts(default_term_for_tty("ttyS23"));
-        puts(default_term_for_tty("tty0"));
-        puts(default_term_for_tty("pty0"));
-        puts(default_term_for_tty("pts/0"));
-        puts(default_term_for_tty("console"));
-}
-
 static void test_memdup_multiply(void) {
         int org[] = {1, 2, 3};
         int *dup;
@@ -981,38 +966,6 @@ static void test_readlink_and_make_absolute(void) {
         assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
 }
 
-static void test_read_one_char(void) {
-        _cleanup_fclose_ FILE *file = NULL;
-        char r;
-        bool need_nl;
-        char name[] = "/tmp/test-read_one_char.XXXXXX";
-        int fd;
-
-        fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
-        assert_se(fd >= 0);
-        file = fdopen(fd, "r+");
-        assert_se(file);
-        assert_se(fputs("c\n", file) >= 0);
-        rewind(file);
-
-        assert_se(read_one_char(file, &r, 1000000, &need_nl) >= 0);
-        assert_se(!need_nl);
-        assert_se(r == 'c');
-        assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0);
-
-        rewind(file);
-        assert_se(fputs("foobar\n", file) >= 0);
-        rewind(file);
-        assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0);
-
-        rewind(file);
-        assert_se(fputs("\n", file) >= 0);
-        rewind(file);
-        assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0);
-
-        unlink(name);
-}
-
 static void test_ignore_signals(void) {
         assert_se(ignore_signals(SIGINT, -1) >= 0);
         assert_se(kill(getpid(), SIGINT) >= 0);
@@ -1525,7 +1478,6 @@ int main(int argc, char *argv[]) {
         test_cunescape();
         test_foreach_word();
         test_foreach_word_quoted();
-        test_default_term_for_tty();
         test_memdup_multiply();
         test_hostname_is_valid();
         test_u64log2();
@@ -1552,7 +1504,6 @@ int main(int argc, char *argv[]) {
         test_close_nointr();
         test_unlink_noerrno();
         test_readlink_and_make_absolute();
-        test_read_one_char();
         test_ignore_signals();
         test_strshorten();
         test_strjoina();
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index 0a41f05..61b6e76 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -33,6 +33,7 @@
 #include "build.h"
 #include "strv.h"
 #include "pager.h"
+#include "terminal-util.h"
 
 static bool arg_no_pager = false;
 static bool arg_ask_password = true;
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
index 8f4031a..8cd6cab 100644
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -43,6 +43,7 @@
 #include "build.h"
 #include "def.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 static enum {
         ACTION_LIST,
diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c
index 3f93524..6c782b3 100644
--- a/src/vconsole/vconsole-setup.c
+++ b/src/vconsole/vconsole-setup.c
@@ -36,6 +36,7 @@
 #include "virt.h"
 #include "fileio.h"
 #include "process-util.h"
+#include "terminal-util.h"
 
 static bool is_vconsole(int fd) {
         unsigned char data[1];

commit 3df3e884ae1237ef0d4d23b0e80f4ffda95ac135
Author: Ronny Chevalier <chevalier.ronny at gmail.com>
Date:   Fri Apr 10 22:27:10 2015 +0200

    shared: add random-util.[ch]

diff --git a/Makefile.am b/Makefile.am
index ceb1d7d..f348ef9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -901,6 +901,8 @@ libsystemd_shared_la_SOURCES = \
 	src/shared/memfd-util.h \
 	src/shared/process-util.c \
 	src/shared/process-util.h \
+	src/shared/random-util.c \
+	src/shared/random-util.h \
 	src/shared/uid-range.c \
 	src/shared/uid-range.h \
 	src/shared/nss-util.h \
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index a37ca17..c92f379 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -32,6 +32,7 @@
 #include "mkdir.h"
 #include "time-util.h"
 #include "path-util.h"
+#include "random-util.h"
 #include "locale-util.h"
 #include "ask-password-api.h"
 
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 6bbcc6d..a432eb0 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -34,6 +34,7 @@
 #include "journal-authenticate.h"
 #include "lookup3.h"
 #include "compress.h"
+#include "random-util.h"
 
 #define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem))
 #define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem))
diff --git a/src/journal/journald-rate-limit.c b/src/journal/journald-rate-limit.c
index 6d779d2..6f83035 100644
--- a/src/journal/journald-rate-limit.c
+++ b/src/journal/journald-rate-limit.c
@@ -26,6 +26,7 @@
 #include "list.h"
 #include "util.h"
 #include "hashmap.h"
+#include "random-util.h"
 
 #define POOLS_MAX 5
 #define BUCKETS_MAX 127
diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c
index ae41c0c..41a566d 100644
--- a/src/journal/test-compress.c
+++ b/src/journal/test-compress.c
@@ -20,6 +20,7 @@
 #include "compress.h"
 #include "util.h"
 #include "macro.h"
+#include "random-util.h"
 
 #ifdef HAVE_XZ
 # define XZ_OK 0
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 4224e01..c44392e 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -28,6 +28,7 @@
 
 #include "util.h"
 #include "refcnt.h"
+#include "random-util.h"
 #include "async.h"
 
 #include "dhcp-protocol.h"
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 3db1cb0..9d88d46 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -28,6 +28,7 @@
 #include "udev-util.h"
 #include "util.h"
 #include "refcnt.h"
+#include "random-util.h"
 
 #include "network-internal.h"
 #include "sd-dhcp6-client.h"
diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c
index 02f2f9e..9e04db9 100644
--- a/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/libsystemd-network/sd-ipv4ll.c
@@ -27,6 +27,7 @@
 #include "siphash24.h"
 #include "list.h"
 #include "refcnt.h"
+#include "random-util.h"
 
 #include "ipv4ll-internal.h"
 #include "sd-ipv4ll.h"
diff --git a/src/libsystemd-network/sd-pppoe.c b/src/libsystemd-network/sd-pppoe.c
index 601f3bd..1de8a5e 100644
--- a/src/libsystemd-network/sd-pppoe.c
+++ b/src/libsystemd-network/sd-pppoe.c
@@ -33,6 +33,7 @@
 #include "event-util.h"
 
 #include "util.h"
+#include "random-util.h"
 #include "socket-util.h"
 #include "async.h"
 #include "refcnt.h"
diff --git a/src/libsystemd-terminal/modeset.c b/src/libsystemd-terminal/modeset.c
index cccaaba..621d6c4 100644
--- a/src/libsystemd-terminal/modeset.c
+++ b/src/libsystemd-terminal/modeset.c
@@ -40,11 +40,13 @@
 #include <systemd/sd-login.h>
 #include <termios.h>
 #include <unistd.h>
+
 #include "build.h"
 #include "grdev.h"
 #include "macro.h"
 #include "sysview.h"
 #include "util.h"
+#include "random-util.h"
 
 typedef struct Modeset Modeset;
 
diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c
index f0ffedc..46f2181 100644
--- a/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/libsystemd/sd-id128/sd-id128.c
@@ -26,6 +26,7 @@
 #include "util.h"
 #include "macro.h"
 #include "sd-id128.h"
+#include "random-util.h"
 
 _public_ char *sd_id128_to_string(sd_id128_t id, char s[33]) {
         unsigned n;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 9607532..6417a8c 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -52,6 +52,7 @@
 #include <blkid/blkid.h>
 #endif
 
+#include "random-util.h"
 #include "sd-daemon.h"
 #include "sd-bus.h"
 #include "sd-id128.h"
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index ba116de..b2bc092 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -27,6 +27,7 @@
 #include "af-list.h"
 #include "resolved-dns-domain.h"
 #include "resolved-dns-scope.h"
+#include "random-util.h"
 
 #define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC)
 #define MULTICAST_RATELIMIT_BURST 1000
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index bc1a90d..2149389 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -22,6 +22,7 @@
 #include "af-list.h"
 
 #include "resolved-dns-transaction.h"
+#include "random-util.h"
 
 DnsTransaction* dns_transaction_free(DnsTransaction *t) {
         DnsQuery *q;
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index adaa6c6..a10a327 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -31,6 +31,7 @@
 #include "utf8.h"
 #include "fileio-label.h"
 #include "ordered-set.h"
+#include "random-util.h"
 
 #include "resolved-dns-domain.h"
 #include "resolved-conf.h"
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
index dfc89d2..ad1a773 100644
--- a/src/shared/ask-password-api.c
+++ b/src/shared/ask-password-api.c
@@ -35,6 +35,7 @@
 #include "formats-util.h"
 #include "mkdir.h"
 #include "strv.h"
+#include "random-util.h"
 
 #include "ask-password-api.h"
 
diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c
index 48d7502..d8ea9d5 100644
--- a/src/shared/hashmap.c
+++ b/src/shared/hashmap.c
@@ -30,6 +30,7 @@
 #include "siphash24.h"
 #include "strv.h"
 #include "mempool.h"
+#include "random-util.h"
 
 #ifdef ENABLE_DEBUG_HASHMAP
 #include "list.h"
diff --git a/src/shared/random-util.c b/src/shared/random-util.c
new file mode 100644
index 0000000..88f5182
--- /dev/null
+++ b/src/shared/random-util.c
@@ -0,0 +1,127 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/auxv.h>
+#include <linux/random.h>
+
+#include "random-util.h"
+#include "time-util.h"
+#include "missing.h"
+#include "util.h"
+
+int dev_urandom(void *p, size_t n) {
+        static int have_syscall = -1;
+
+        _cleanup_close_ int fd = -1;
+        int r;
+
+        /* Gathers some randomness from the kernel. This call will
+         * never block, and will always return some data from the
+         * kernel, regardless if the random pool is fully initialized
+         * or not. It thus makes no guarantee for the quality of the
+         * returned entropy, but is good enough for or usual usecases
+         * of seeding the hash functions for hashtable */
+
+        /* Use the getrandom() syscall unless we know we don't have
+         * it, or when the requested size is too large for it. */
+        if (have_syscall != 0 || (size_t) (int) n != n) {
+                r = getrandom(p, n, GRND_NONBLOCK);
+                if (r == (int) n) {
+                        have_syscall = true;
+                        return 0;
+                }
+
+                if (r < 0) {
+                        if (errno == ENOSYS)
+                                /* we lack the syscall, continue with
+                                 * reading from /dev/urandom */
+                                have_syscall = false;
+                        else if (errno == EAGAIN)
+                                /* not enough entropy for now. Let's
+                                 * remember to use the syscall the
+                                 * next time, again, but also read
+                                 * from /dev/urandom for now, which
+                                 * doesn't care about the current
+                                 * amount of entropy.  */
+                                have_syscall = true;
+                        else
+                                return -errno;
+                } else
+                        /* too short read? */
+                        return -ENODATA;
+        }
+
+        fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
+        if (fd < 0)
+                return errno == ENOENT ? -ENOSYS : -errno;
+
+        return loop_read_exact(fd, p, n, true);
+}
+
+void initialize_srand(void) {
+        static bool srand_called = false;
+        unsigned x;
+#ifdef HAVE_SYS_AUXV_H
+        void *auxv;
+#endif
+
+        if (srand_called)
+                return;
+
+        x = 0;
+
+#ifdef HAVE_SYS_AUXV_H
+        /* The kernel provides us with a bit of entropy in auxv, so
+         * let's try to make use of that to seed the pseudo-random
+         * generator. It's better than nothing... */
+
+        auxv = (void*) getauxval(AT_RANDOM);
+        if (auxv)
+                x ^= *(unsigned*) auxv;
+#endif
+
+        x ^= (unsigned) now(CLOCK_REALTIME);
+        x ^= (unsigned) gettid();
+
+        srand(x);
+        srand_called = true;
+}
+
+void random_bytes(void *p, size_t n) {
+        uint8_t *q;
+        int r;
+
+        r = dev_urandom(p, n);
+        if (r >= 0)
+                return;
+
+        /* If some idiot made /dev/urandom unavailable to us, he'll
+         * get a PRNG instead. */
+
+        initialize_srand();
+
+        for (q = p; q < (uint8_t*) p + n; q ++)
+                *q = rand();
+}
diff --git a/src/shared/random-util.h b/src/shared/random-util.h
new file mode 100644
index 0000000..f7862c8
--- /dev/null
+++ b/src/shared/random-util.h
@@ -0,0 +1,38 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdint.h>
+
+int dev_urandom(void *p, size_t n);
+void random_bytes(void *p, size_t n);
+void initialize_srand(void);
+
+static inline uint64_t random_u64(void) {
+        uint64_t u;
+        random_bytes(&u, sizeof(u));
+        return u;
+}
+
+static inline uint32_t random_u32(void) {
+        uint32_t u;
+        random_bytes(&u, sizeof(u));
+        return u;
+}
diff --git a/src/shared/util.c b/src/shared/util.c
index d4753f1..e4c4dd9 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -94,6 +94,7 @@
 #include "sparse-endian.h"
 #include "formats-util.h"
 #include "process-util.h"
+#include "random-util.h"
 
 /* Put this test here for a lack of better place */
 assert_cc(EAGAIN == EWOULDBLOCK);
@@ -2387,101 +2388,6 @@ char* dirname_malloc(const char *path) {
         return dir;
 }
 
-int dev_urandom(void *p, size_t n) {
-        static int have_syscall = -1;
-
-        _cleanup_close_ int fd = -1;
-        int r;
-
-        /* Gathers some randomness from the kernel. This call will
-         * never block, and will always return some data from the
-         * kernel, regardless if the random pool is fully initialized
-         * or not. It thus makes no guarantee for the quality of the
-         * returned entropy, but is good enough for or usual usecases
-         * of seeding the hash functions for hashtable */
-
-        /* Use the getrandom() syscall unless we know we don't have
-         * it, or when the requested size is too large for it. */
-        if (have_syscall != 0 || (size_t) (int) n != n) {
-                r = getrandom(p, n, GRND_NONBLOCK);
-                if (r == (int) n) {
-                        have_syscall = true;
-                        return 0;
-                }
-
-                if (r < 0) {
-                        if (errno == ENOSYS)
-                                /* we lack the syscall, continue with
-                                 * reading from /dev/urandom */
-                                have_syscall = false;
-                        else if (errno == EAGAIN)
-                                /* not enough entropy for now. Let's
-                                 * remember to use the syscall the
-                                 * next time, again, but also read
-                                 * from /dev/urandom for now, which
-                                 * doesn't care about the current
-                                 * amount of entropy.  */
-                                have_syscall = true;
-                        else
-                                return -errno;
-                } else
-                        /* too short read? */
-                        return -ENODATA;
-        }
-
-        fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
-        if (fd < 0)
-                return errno == ENOENT ? -ENOSYS : -errno;
-
-        return loop_read_exact(fd, p, n, true);
-}
-
-void initialize_srand(void) {
-        static bool srand_called = false;
-        unsigned x;
-#ifdef HAVE_SYS_AUXV_H
-        void *auxv;
-#endif
-
-        if (srand_called)
-                return;
-
-        x = 0;
-
-#ifdef HAVE_SYS_AUXV_H
-        /* The kernel provides us with a bit of entropy in auxv, so
-         * let's try to make use of that to seed the pseudo-random
-         * generator. It's better than nothing... */
-
-        auxv = (void*) getauxval(AT_RANDOM);
-        if (auxv)
-                x ^= *(unsigned*) auxv;
-#endif
-
-        x ^= (unsigned) now(CLOCK_REALTIME);
-        x ^= (unsigned) gettid();
-
-        srand(x);
-        srand_called = true;
-}
-
-void random_bytes(void *p, size_t n) {
-        uint8_t *q;
-        int r;
-
-        r = dev_urandom(p, n);
-        if (r >= 0)
-                return;
-
-        /* If some idiot made /dev/urandom unavailable to us, he'll
-         * get a PRNG instead. */
-
-        initialize_srand();
-
-        for (q = p; q < (uint8_t*) p + n; q ++)
-                *q = rand();
-}
-
 void rename_process(const char name[8]) {
         assert(name);
 
diff --git a/src/shared/util.h b/src/shared/util.h
index b939d7f..4d5162f 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -283,22 +283,6 @@ int make_stdio(int fd);
 int make_null_stdio(void);
 int make_console_stdio(void);
 
-int dev_urandom(void *p, size_t n);
-void random_bytes(void *p, size_t n);
-void initialize_srand(void);
-
-static inline uint64_t random_u64(void) {
-        uint64_t u;
-        random_bytes(&u, sizeof(u));
-        return u;
-}
-
-static inline uint32_t random_u32(void) {
-        uint32_t u;
-        random_bytes(&u, sizeof(u));
-        return u;
-}
-
 /* For basic lookup tables with strictly enumerated entries */
 #define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
         scope const char *name##_to_string(type i) {                    \
diff --git a/src/udev/cdrom_id/cdrom_id.c b/src/udev/cdrom_id/cdrom_id.c
index 54a5075..3d74ae5 100644
--- a/src/udev/cdrom_id/cdrom_id.c
+++ b/src/udev/cdrom_id/cdrom_id.c
@@ -36,6 +36,7 @@
 
 #include "libudev.h"
 #include "libudev-private.h"
+#include "random-util.h"
 
 /* device info */
 static unsigned int cd_cd_rom;
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index 86d09bb..00052dd 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -37,6 +37,7 @@
 #include "conf-files.h"
 #include "rtnl-util.h"
 #include "network-internal.h"
+#include "random-util.h"
 
 struct link_config_ctx {
         LIST_HEAD(link_config, links);
diff --git a/src/udev/scsi_id/scsi_serial.c b/src/udev/scsi_id/scsi_serial.c
index dcfff1d..3691a69 100644
--- a/src/udev/scsi_id/scsi_serial.c
+++ b/src/udev/scsi_id/scsi_serial.c
@@ -37,6 +37,7 @@
 #include "libudev-private.h"
 #include "scsi.h"
 #include "scsi_id.h"
+#include "random-util.h"
 
 /*
  * A priority based list of id, naa, and binary/ascii for the identifier

commit 0b452006de98294d1690f045f6ea2f7f6630ec3b
Author: Ronny Chevalier <chevalier.ronny at gmail.com>
Date:   Fri Apr 10 19:10:00 2015 +0200

    shared: add process-util.[ch]

diff --git a/.gitignore b/.gitignore
index 875ada5..7330c80 100644
--- a/.gitignore
+++ b/.gitignore
@@ -234,6 +234,7 @@
 /test-path-util
 /test-pppoe
 /test-prioq
+/test-process-util
 /test-pty
 /test-qcow2
 /test-ratelimit
diff --git a/Makefile.am b/Makefile.am
index 0a57389..ceb1d7d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -899,6 +899,8 @@ libsystemd_shared_la_SOURCES = \
 	src/shared/base-filesystem.h \
 	src/shared/memfd-util.c \
 	src/shared/memfd-util.h \
+	src/shared/process-util.c \
+	src/shared/process-util.h \
 	src/shared/uid-range.c \
 	src/shared/uid-range.h \
 	src/shared/nss-util.h \
@@ -1389,6 +1391,7 @@ tests += \
 	test-utf8 \
 	test-ellipsize \
 	test-util \
+	test-process-util \
 	test-path-lookup \
 	test-ring \
 	test-barrier \
@@ -1664,6 +1667,12 @@ test_util_LDADD = \
 	libsystemd-label.la \
 	libsystemd-shared.la
 
+test_process_util_SOURCES = \
+	src/test/test-process-util.c
+
+test_process_util_LDADD = \
+	libsystemd-shared.la
+
 test_path_lookup_SOURCES = \
 	src/test/test-path-lookup.c
 
diff --git a/src/core/automount.c b/src/core/automount.c
index e1ca2a4..ce484ff 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -41,6 +41,7 @@
 #include "bus-util.h"
 #include "bus-error.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
         [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 6b8abb4..e337c0f 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -22,6 +22,7 @@
 #include <fcntl.h>
 #include <fnmatch.h>
 
+#include "process-util.h"
 #include "path-util.h"
 #include "special.h"
 #include "cgroup-util.h"
diff --git a/src/core/execute.c b/src/core/execute.c
index c87e900..b00d510 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -77,6 +77,7 @@
 #include "bus-endpoint.h"
 #include "cap-list.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 #ifdef HAVE_APPARMOR
 #include "apparmor-util.h"
diff --git a/src/core/killall.c b/src/core/killall.c
index 5040514..31bec01 100644
--- a/src/core/killall.c
+++ b/src/core/killall.c
@@ -28,6 +28,7 @@
 #include "killall.h"
 #include "set.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 #define TIMEOUT_USEC (10 * USEC_PER_SEC)
 
diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
index 2ffb2a7..e083c5b 100644
--- a/src/core/machine-id-setup.c
+++ b/src/core/machine-id-setup.c
@@ -36,6 +36,7 @@
 #include "virt.h"
 #include "fileio.h"
 #include "path-util.h"
+#include "process-util.h"
 
 static int shorten_uuid(char destination[34], const char source[36]) {
         unsigned i, j;
diff --git a/src/core/main.c b/src/core/main.c
index 5d1aed8..80a51ee 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -73,6 +73,7 @@
 #include "smack-setup.h"
 #include "kmod-setup.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 static enum {
         ACTION_RUN,
diff --git a/src/core/manager.c b/src/core/manager.c
index 1c912fc..6d1729b 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -71,6 +71,7 @@
 #include "dbus-manager.h"
 #include "bus-kernel.h"
 #include "time-util.h"
+#include "process-util.h"
 
 /* Initial delay and the interval for printing status messages about running jobs */
 #define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC)
diff --git a/src/core/service.c b/src/core/service.c
index c6ea655..fa818fc 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -46,6 +46,7 @@
 #include "bus-util.h"
 #include "bus-kernel.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
         [SERVICE_DEAD] = UNIT_INACTIVE,
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index 70a461e..f037a38 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -42,6 +42,7 @@
 #include "cgroup-util.h"
 #include "def.h"
 #include "switch-root.h"
+#include "process-util.h"
 
 #define FINALIZE_ATTEMPTS 50
 
diff --git a/src/core/unit.c b/src/core/unit.c
index 4b9c406..3aa1bf2 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -47,6 +47,7 @@
 #include "execute.h"
 #include "dropin.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
         [UNIT_SERVICE] = &service_vtable,
diff --git a/src/delta/delta.c b/src/delta/delta.c
index 9f1f8f3..106c036 100644
--- a/src/delta/delta.c
+++ b/src/delta/delta.c
@@ -32,6 +32,7 @@
 #include "pager.h"
 #include "build.h"
 #include "strv.h"
+#include "process-util.h"
 
 static const char prefixes[] =
         "/etc\0"
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 7eaf902..6a0f67f 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -32,6 +32,7 @@
 #include "sd-device.h"
 
 #include "util.h"
+#include "process-util.h"
 #include "special.h"
 #include "bus-util.h"
 #include "bus-error.h"
diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c
index f8f5fb3..0f59f5a 100644
--- a/src/getty-generator/getty-generator.c
+++ b/src/getty-generator/getty-generator.c
@@ -31,6 +31,7 @@
 #include "virt.h"
 #include "fileio.h"
 #include "path-util.h"
+#include "process-util.h"
 
 static const char *arg_dest = "/tmp";
 
diff --git a/src/import/export-tar.c b/src/import/export-tar.c
index 9bd0251..73e1fae 100644
--- a/src/import/export-tar.c
+++ b/src/import/export-tar.c
@@ -27,6 +27,7 @@
 #include "btrfs-util.h"
 #include "import-common.h"
 #include "export-tar.h"
+#include "process-util.h"
 
 #define COPY_BUFFER_SIZE (16*1024)
 
diff --git a/src/import/import-tar.c b/src/import/import-tar.c
index 6ec5504..12701bf 100644
--- a/src/import/import-tar.c
+++ b/src/import/import-tar.c
@@ -35,6 +35,7 @@
 #include "import-compress.h"
 #include "import-common.h"
 #include "import-tar.h"
+#include "process-util.h"
 
 struct TarImport {
         sd_event *event;
diff --git a/src/import/importd.c b/src/import/importd.c
index 998e960..d4da4b2 100644
--- a/src/import/importd.c
+++ b/src/import/importd.c
@@ -33,6 +33,7 @@
 #include "machine-pool.h"
 #include "path-util.h"
 #include "import-util.h"
+#include "process-util.h"
 
 typedef struct Transfer Transfer;
 typedef struct Manager Manager;
diff --git a/src/import/pull-common.c b/src/import/pull-common.c
index 5732353..59091ba 100644
--- a/src/import/pull-common.c
+++ b/src/import/pull-common.c
@@ -29,6 +29,7 @@
 #include "capability.h"
 #include "pull-job.h"
 #include "pull-common.h"
+#include "process-util.h"
 
 #define FILENAME_ESCAPE "/.#\"\'"
 
diff --git a/src/import/pull-dkr.c b/src/import/pull-dkr.c
index c922bac..0eefec5 100644
--- a/src/import/pull-dkr.c
+++ b/src/import/pull-dkr.c
@@ -37,6 +37,7 @@
 #include "pull-common.h"
 #include "import-common.h"
 #include "pull-dkr.h"
+#include "process-util.h"
 
 typedef enum DkrProgress {
         DKR_SEARCHING,
diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c
index 0efa07d..27a9af8 100644
--- a/src/import/pull-tar.c
+++ b/src/import/pull-tar.c
@@ -38,6 +38,7 @@
 #include "pull-job.h"
 #include "pull-common.h"
 #include "pull-tar.h"
+#include "process-util.h"
 
 typedef enum TarProgress {
         TAR_DOWNLOADING,
diff --git a/src/journal/coredump.c b/src/journal/coredump.c
index 4e23e48..1c747aa 100644
--- a/src/journal/coredump.c
+++ b/src/journal/coredump.c
@@ -48,6 +48,7 @@
 #include "capability.h"
 #include "journald-native.h"
 #include "coredump-vacuum.h"
+#include "process-util.h"
 
 /* The maximum size up to which we process coredumps */
 #define PROCESS_SIZE_MAX ((off_t) (2LLU*1024LLU*1024LLU*1024LLU))
diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c
index 4026a1c..4f6ddfa 100644
--- a/src/journal/coredumpctl.c
+++ b/src/journal/coredumpctl.c
@@ -37,6 +37,7 @@
 #include "journal-internal.h"
 #include "compress.h"
 #include "sigbus.h"
+#include "process-util.h"
 
 static enum {
         ACTION_NONE,
diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c
index 4ccacd7..6c15530 100644
--- a/src/journal/journald-console.c
+++ b/src/journal/journald-console.c
@@ -27,6 +27,7 @@
 #include "journald-server.h"
 #include "journald-console.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 static bool prefix_timestamp(void) {
 
diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c
index cb4bc38..e5be7f7 100644
--- a/src/journal/journald-kmsg.c
+++ b/src/journal/journald-kmsg.c
@@ -32,6 +32,7 @@
 #include "journald-kmsg.h"
 #include "journald-syslog.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 void server_forward_kmsg(
         Server *s,
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 7e20b96..5e07ce3 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -51,6 +51,7 @@
 #include "journald-server.h"
 #include "acl-util.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 #ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c
index 6c46a30..26fdf62 100644
--- a/src/journal/journald-syslog.c
+++ b/src/journal/journald-syslog.c
@@ -32,6 +32,7 @@
 #include "journald-console.h"
 #include "journald-wall.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 /* Warn once every 30s if we missed syslog message */
 #define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC)
diff --git a/src/journal/journald-wall.c b/src/journal/journald-wall.c
index b4e0717..5298e45 100644
--- a/src/journal/journald-wall.c
+++ b/src/journal/journald-wall.c
@@ -23,6 +23,7 @@
 #include "journald-server.h"
 #include "journald-wall.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 void server_forward_wall(
                 Server *s,
diff --git a/src/libsystemd-network/test-pppoe.c b/src/libsystemd-network/test-pppoe.c
index 40d04fd..9c8d6f7 100644
--- a/src/libsystemd-network/test-pppoe.c
+++ b/src/libsystemd-network/test-pppoe.c
@@ -31,6 +31,7 @@
 #include "event-util.h"
 #include "sd-rtnl.h"
 #include "sd-pppoe.h"
+#include "process-util.h"
 
 static void pppoe_handler(sd_pppoe *ppp, int event, void *userdata) {
         static int pppoe_state = -1;
diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c
index 3b3a5d3..f157c25 100644
--- a/src/libsystemd/sd-bus/bus-container.c
+++ b/src/libsystemd/sd-bus/bus-container.c
@@ -23,6 +23,7 @@
 #include <fcntl.h>
 
 #include "util.h"
+#include "process-util.h"
 #include "bus-internal.h"
 #include "bus-socket.h"
 #include "bus-container.h"
diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c
index 4141cc3..a5d3574 100644
--- a/src/libsystemd/sd-bus/bus-creds.c
+++ b/src/libsystemd/sd-bus/bus-creds.c
@@ -24,6 +24,7 @@
 
 #include "util.h"
 #include "formats-util.h"
+#include "process-util.h"
 #include "capability.h"
 #include "cgroup-util.h"
 #include "fileio.h"
diff --git a/src/login/inhibit.c b/src/login/inhibit.c
index 1f78e4b..57cfb5d 100644
--- a/src/login/inhibit.c
+++ b/src/login/inhibit.c
@@ -32,6 +32,7 @@
 #include "build.h"
 #include "strv.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 static const char* arg_what = "idle:sleep:shutdown";
 static const char* arg_who = NULL;
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index ec102ae..7393eb3 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -41,6 +41,7 @@
 #include "cgroup-util.h"
 #include "spawn-polkit-agent.h"
 #include "verbs.h"
+#include "process-util.h"
 
 static char **arg_property = NULL;
 static bool arg_all = false;
diff --git a/src/login/logind-action.c b/src/login/logind-action.c
index d7ae175..29e7ed0 100644
--- a/src/login/logind-action.c
+++ b/src/login/logind-action.c
@@ -28,6 +28,7 @@
 #include "bus-error.h"
 #include "logind-action.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 int manager_handle_action(
                 Manager *m,
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 45aedad..6bf9205 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -41,6 +41,7 @@
 #include "efivars.h"
 #include "logind.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 6cc46af..2d710a9 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -43,6 +43,7 @@
 #include "machine.h"
 #include "machine-dbus.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 static int property_get_id(
                 sd_bus *bus,
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 688c510..87e15d7 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -52,6 +52,7 @@
 #include "copy.h"
 #include "verbs.h"
 #include "import-util.h"
+#include "process-util.h"
 
 static char **arg_property = NULL;
 static bool arg_all = false;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 8ec6743..9607532 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -92,6 +92,7 @@
 #include "fw-util.h"
 #include "local-addresses.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 #ifdef HAVE_SECCOMP
 #include "seccomp-util.h"
diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c
index 819706a..a729f59 100644
--- a/src/quotacheck/quotacheck.c
+++ b/src/quotacheck/quotacheck.c
@@ -25,6 +25,7 @@
 #include <unistd.h>
 
 #include "util.h"
+#include "process-util.h"
 
 static bool arg_skip = false;
 static bool arg_force = false;
diff --git a/src/shared/audit.c b/src/shared/audit.c
index 4c1496f..84181d3 100644
--- a/src/shared/audit.c
+++ b/src/shared/audit.c
@@ -25,6 +25,7 @@
 #include "macro.h"
 #include "audit.h"
 #include "util.h"
+#include "process-util.h"
 #include "fileio.h"
 
 int audit_session_from_pid(pid_t pid, uint32_t *id) {
diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c
index fed72ac..0f263e9 100644
--- a/src/shared/cgroup-show.c
+++ b/src/shared/cgroup-show.c
@@ -26,6 +26,7 @@
 
 #include "util.h"
 #include "formats-util.h"
+#include "process-util.h"
 #include "macro.h"
 #include "path-util.h"
 #include "cgroup-util.h"
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index 481708f..5b04702 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -34,6 +34,7 @@
 #include "macro.h"
 #include "util.h"
 #include "formats-util.h"
+#include "process-util.h"
 #include "path-util.h"
 #include "unit-name.h"
 #include "fileio.h"
diff --git a/src/shared/log.c b/src/shared/log.c
index 32ec581..7edcf1f 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -35,6 +35,7 @@
 #include "macro.h"
 #include "socket-util.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 #define SNDBUF_SIZE (8*1024*1024)
 
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index e179b8a..7a7a1e9 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -32,6 +32,7 @@
 #include "hashmap.h"
 #include "journal-internal.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 /* up to three lines (each up to 100 characters),
    or 300 characters, whichever is less */
diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c
index 0fae623..41aa1b7 100644
--- a/src/shared/machine-pool.c
+++ b/src/shared/machine-pool.c
@@ -25,6 +25,7 @@
 #include <sys/mount.h>
 
 #include "util.h"
+#include "process-util.h"
 #include "mkdir.h"
 #include "btrfs-util.h"
 #include "path-util.h"
diff --git a/src/shared/pager.c b/src/shared/pager.c
index f12bfb3..b5a584b 100644
--- a/src/shared/pager.c
+++ b/src/shared/pager.c
@@ -27,6 +27,7 @@
 
 #include "pager.h"
 #include "util.h"
+#include "process-util.h"
 #include "macro.h"
 
 static pid_t pager_pid = 0;
diff --git a/src/shared/process-util.c b/src/shared/process-util.c
new file mode 100644
index 0000000..92a69f5
--- /dev/null
+++ b/src/shared/process-util.c
@@ -0,0 +1,538 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <ctype.h>
+
+#include "process-util.h"
+#include "fileio.h"
+#include "util.h"
+#include "log.h"
+
+int get_process_state(pid_t pid) {
+        const char *p;
+        char state;
+        int r;
+        _cleanup_free_ char *line = NULL;
+
+        assert(pid >= 0);
+
+        p = procfs_file_alloca(pid, "stat");
+        r = read_one_line_file(p, &line);
+        if (r < 0)
+                return r;
+
+        p = strrchr(line, ')');
+        if (!p)
+                return -EIO;
+
+        p++;
+
+        if (sscanf(p, " %c", &state) != 1)
+                return -EIO;
+
+        return (unsigned char) state;
+}
+
+int get_process_comm(pid_t pid, char **name) {
+        const char *p;
+        int r;
+
+        assert(name);
+        assert(pid >= 0);
+
+        p = procfs_file_alloca(pid, "comm");
+
+        r = read_one_line_file(p, name);
+        if (r == -ENOENT)
+                return -ESRCH;
+
+        return r;
+}
+
+int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
+        _cleanup_fclose_ FILE *f = NULL;
+        char *r = NULL, *k;
+        const char *p;
+        int c;
+
+        assert(line);
+        assert(pid >= 0);
+
+        p = procfs_file_alloca(pid, "cmdline");
+
+        f = fopen(p, "re");
+        if (!f)
+                return -errno;
+
+        if (max_length == 0) {
+                size_t len = 0, allocated = 0;
+
+                while ((c = getc(f)) != EOF) {
+
+                        if (!GREEDY_REALLOC(r, allocated, len+2)) {
+                                free(r);
+                                return -ENOMEM;
+                        }
+
+                        r[len++] = isprint(c) ? c : ' ';
+                }
+
+                if (len > 0)
+                        r[len-1] = 0;
+
+        } else {
+                bool space = false;
+                size_t left;
+
+                r = new(char, max_length);
+                if (!r)
+                        return -ENOMEM;
+
+                k = r;
+                left = max_length;
+                while ((c = getc(f)) != EOF) {
+
+                        if (isprint(c)) {
+                                if (space) {
+                                        if (left <= 4)
+                                                break;
+
+                                        *(k++) = ' ';
+                                        left--;
+                                        space = false;
+                                }
+
+                                if (left <= 4)
+                                        break;
+
+                                *(k++) = (char) c;
+                                left--;
+                        }  else
+                                space = true;
+                }
+
+                if (left <= 4) {
+                        size_t n = MIN(left-1, 3U);
+                        memcpy(k, "...", n);
+                        k[n] = 0;
+                } else
+                        *k = 0;
+        }
+
+        /* Kernel threads have no argv[] */
+        if (isempty(r)) {
+                _cleanup_free_ char *t = NULL;
+                int h;
+
+                free(r);
+
+                if (!comm_fallback)
+                        return -ENOENT;
+
+                h = get_process_comm(pid, &t);
+                if (h < 0)
+                        return h;
+
+                r = strjoin("[", t, "]", NULL);
+                if (!r)
+                        return -ENOMEM;
+        }
+
+        *line = r;
+        return 0;
+}
+
+int is_kernel_thread(pid_t pid) {
+        const char *p;
+        size_t count;
+        char c;
+        bool eof;
+        FILE *f;
+
+        if (pid == 0)
+                return 0;
+
+        assert(pid > 0);
+
+        p = procfs_file_alloca(pid, "cmdline");
+        f = fopen(p, "re");
+        if (!f)
+                return -errno;
+
+        count = fread(&c, 1, 1, f);
+        eof = feof(f);
+        fclose(f);
+
+        /* Kernel threads have an empty cmdline */
+
+        if (count <= 0)
+                return eof ? 1 : -errno;
+
+        return 0;
+}
+
+int get_process_capeff(pid_t pid, char **capeff) {
+        const char *p;
+
+        assert(capeff);
+        assert(pid >= 0);
+
+        p = procfs_file_alloca(pid, "status");
+
+        return get_status_field(p, "\nCapEff:", capeff);
+}
+
+static int get_process_link_contents(const char *proc_file, char **name) {
+        int r;
+
+        assert(proc_file);
+        assert(name);
+
+        r = readlink_malloc(proc_file, name);
+        if (r < 0)
+                return r == -ENOENT ? -ESRCH : r;
+
+        return 0;
+}
+
+int get_process_exe(pid_t pid, char **name) {
+        const char *p;
+        char *d;
+        int r;
+
+        assert(pid >= 0);
+
+        p = procfs_file_alloca(pid, "exe");
+        r = get_process_link_contents(p, name);
+        if (r < 0)
+                return r;
+
+        d = endswith(*name, " (deleted)");
+        if (d)
+                *d = '\0';
+
+        return 0;
+}
+
+static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
+        _cleanup_fclose_ FILE *f = NULL;
+        char line[LINE_MAX];
+        const char *p;
+
+        assert(field);
+        assert(uid);
+
+        if (pid == 0)
+                return getuid();
+
+        p = procfs_file_alloca(pid, "status");
+        f = fopen(p, "re");
+        if (!f)
+                return -errno;
+
+        FOREACH_LINE(line, f, return -errno) {
+                char *l;
+
+                l = strstrip(line);
+
+                if (startswith(l, field)) {
+                        l += strlen(field);
+                        l += strspn(l, WHITESPACE);
+
+                        l[strcspn(l, WHITESPACE)] = 0;
+
+                        return parse_uid(l, uid);
+                }
+        }
+
+        return -EIO;
+}
+
+int get_process_uid(pid_t pid, uid_t *uid) {
+        return get_process_id(pid, "Uid:", uid);
+}
+
+int get_process_gid(pid_t pid, gid_t *gid) {
+        assert_cc(sizeof(uid_t) == sizeof(gid_t));
+        return get_process_id(pid, "Gid:", gid);
+}
+
+int get_process_cwd(pid_t pid, char **cwd) {
+        const char *p;
+
+        assert(pid >= 0);
+
+        p = procfs_file_alloca(pid, "cwd");
+
+        return get_process_link_contents(p, cwd);
+}
+
+int get_process_root(pid_t pid, char **root) {
+        const char *p;
+
+        assert(pid >= 0);
+
+        p = procfs_file_alloca(pid, "root");
+
+        return get_process_link_contents(p, root);
+}
+
+int get_process_environ(pid_t pid, char **env) {
+        _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_free_ char *outcome = NULL;
+        int c;
+        const char *p;
+        size_t allocated = 0, sz = 0;
+
+        assert(pid >= 0);
+        assert(env);
+
+        p = procfs_file_alloca(pid, "environ");
+
+        f = fopen(p, "re");
+        if (!f)
+                return -errno;
+
+        while ((c = fgetc(f)) != EOF) {
+                if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
+                        return -ENOMEM;
+
+                if (c == '\0')
+                        outcome[sz++] = '\n';
+                else
+                        sz += cescape_char(c, outcome + sz);
+        }
+
+        outcome[sz] = '\0';
+        *env = outcome;
+        outcome = NULL;
+
+        return 0;
+}
+
+int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
+        int r;
+        _cleanup_free_ char *line = NULL;
+        long unsigned ppid;
+        const char *p;
+
+        assert(pid >= 0);
+        assert(_ppid);
+
+        if (pid == 0) {
+                *_ppid = getppid();
+                return 0;
+        }
+
+        p = procfs_file_alloca(pid, "stat");
+        r = read_one_line_file(p, &line);
+        if (r < 0)
+                return r;
+
+        /* Let's skip the pid and comm fields. The latter is enclosed
+         * in () but does not escape any () in its value, so let's
+         * skip over it manually */
+
+        p = strrchr(line, ')');
+        if (!p)
+                return -EIO;
+
+        p++;
+
+        if (sscanf(p, " "
+                   "%*c "  /* state */
+                   "%lu ", /* ppid */
+                   &ppid) != 1)
+                return -EIO;
+
+        if ((long unsigned) (pid_t) ppid != ppid)
+                return -ERANGE;
+
+        *_ppid = (pid_t) ppid;
+
+        return 0;
+}
+
+int wait_for_terminate(pid_t pid, siginfo_t *status) {
+        siginfo_t dummy;
+
+        assert(pid >= 1);
+
+        if (!status)
+                status = &dummy;
+
+        for (;;) {
+                zero(*status);
+
+                if (waitid(P_PID, pid, status, WEXITED) < 0) {
+
+                        if (errno == EINTR)
+                                continue;
+
+                        return -errno;
+                }
+
+                return 0;
+        }
+}
+
+/*
+ * Return values:
+ * < 0 : wait_for_terminate() failed to get the state of the
+ *       process, the process was terminated by a signal, or
+ *       failed for an unknown reason.
+ * >=0 : The process terminated normally, and its exit code is
+ *       returned.
+ *
+ * That is, success is indicated by a return value of zero, and an
+ * error is indicated by a non-zero value.
+ *
+ * A warning is emitted if the process terminates abnormally,
+ * and also if it returns non-zero unless check_exit_code is true.
+ */
+int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code) {
+        int r;
+        siginfo_t status;
+
+        assert(name);
+        assert(pid > 1);
+
+        r = wait_for_terminate(pid, &status);
+        if (r < 0)
+                return log_warning_errno(r, "Failed to wait for %s: %m", name);
+
+        if (status.si_code == CLD_EXITED) {
+                if (status.si_status != 0)
+                        log_full(check_exit_code ? LOG_WARNING : LOG_DEBUG,
+                                 "%s failed with error code %i.", name, status.si_status);
+                else
+                        log_debug("%s succeeded.", name);
+
+                return status.si_status;
+        } else if (status.si_code == CLD_KILLED ||
+                   status.si_code == CLD_DUMPED) {
+
+                log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
+                return -EPROTO;
+        }
+
+        log_warning("%s failed due to unknown reason.", name);
+        return -EPROTO;
+}
+
+int kill_and_sigcont(pid_t pid, int sig) {
+        int r;
+
+        r = kill(pid, sig) < 0 ? -errno : 0;
+
+        if (r >= 0)
+                kill(pid, SIGCONT);
+
+        return r;
+}
+
+int getenv_for_pid(pid_t pid, const char *field, char **_value) {
+        _cleanup_fclose_ FILE *f = NULL;
+        char *value = NULL;
+        int r;
+        bool done = false;
+        size_t l;
+        const char *path;
+
+        assert(pid >= 0);
+        assert(field);
+        assert(_value);
+
+        path = procfs_file_alloca(pid, "environ");
+
+        f = fopen(path, "re");
+        if (!f)
+                return -errno;
+
+        l = strlen(field);
+        r = 0;
+
+        do {
+                char line[LINE_MAX];
+                unsigned i;
+
+                for (i = 0; i < sizeof(line)-1; i++) {
+                        int c;
+
+                        c = getc(f);
+                        if (_unlikely_(c == EOF)) {
+                                done = true;
+                                break;
+                        } else if (c == 0)
+                                break;
+
+                        line[i] = c;
+                }
+                line[i] = 0;
+
+                if (memcmp(line, field, l) == 0 && line[l] == '=') {
+                        value = strdup(line + l + 1);
+                        if (!value)
+                                return -ENOMEM;
+
+                        r = 1;
+                        break;
+                }
+
+        } while (!done);
+
+        *_value = value;
+        return r;
+}
+
+bool pid_is_unwaited(pid_t pid) {
+        /* Checks whether a PID is still valid at all, including a zombie */
+
+        if (pid <= 0)
+                return false;
+
+        if (kill(pid, 0) >= 0)
+                return true;
+
+        return errno != ESRCH;
+}
+
+bool pid_is_alive(pid_t pid) {
+        int r;
+
+        /* Checks whether a PID is still valid and not a zombie */
+
+        if (pid <= 0)
+                return false;
+
+        r = get_process_state(pid);
+        if (r == -ENOENT || r == 'Z')
+                return false;
+
+        return true;
+}
diff --git a/src/shared/process-util.h b/src/shared/process-util.h
new file mode 100644
index 0000000..07431d0
--- /dev/null
+++ b/src/shared/process-util.h
@@ -0,0 +1,65 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+#include <sys/types.h>
+#include <alloca.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include "formats-util.h"
+
+#define procfs_file_alloca(pid, field)                                  \
+        ({                                                              \
+                pid_t _pid_ = (pid);                                    \
+                const char *_r_;                                        \
+                if (_pid_ == 0) {                                       \
+                        _r_ = ("/proc/self/" field);                    \
+                } else {                                                \
+                        _r_ = alloca(strlen("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
+                        sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_);                       \
+                }                                                       \
+                _r_;                                                    \
+        })
+
+int get_process_state(pid_t pid);
+int get_process_comm(pid_t pid, char **name);
+int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line);
+int get_process_exe(pid_t pid, char **name);
+int get_process_uid(pid_t pid, uid_t *uid);
+int get_process_gid(pid_t pid, gid_t *gid);
+int get_process_capeff(pid_t pid, char **capeff);
+int get_process_cwd(pid_t pid, char **cwd);
+int get_process_root(pid_t pid, char **root);
+int get_process_environ(pid_t pid, char **environ);
+
+int wait_for_terminate(pid_t pid, siginfo_t *status);
+int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
+
+int kill_and_sigcont(pid_t pid, int sig);
+pid_t get_parent_of_pid(pid_t pid, pid_t *ppid);
+void rename_process(const char name[8]);
+int is_kernel_thread(pid_t pid);
+int getenv_for_pid(pid_t pid, const char *field, char **_value);
+
+bool pid_is_alive(pid_t pid);
+bool pid_is_unwaited(pid_t pid);
diff --git a/src/shared/smack-util.c b/src/shared/smack-util.c
index a73a996..2e24b1e 100644
--- a/src/shared/smack-util.c
+++ b/src/shared/smack-util.c
@@ -24,6 +24,7 @@
 #include <sys/xattr.h>
 
 #include "util.h"
+#include "process-util.h"
 #include "path-util.h"
 #include "fileio.h"
 #include "smack-util.h"
diff --git a/src/shared/spawn-ask-password-agent.c b/src/shared/spawn-ask-password-agent.c
index 0d74588..70466d1 100644
--- a/src/shared/spawn-ask-password-agent.c
+++ b/src/shared/spawn-ask-password-agent.c
@@ -25,6 +25,7 @@
 
 #include "log.h"
 #include "util.h"
+#include "process-util.h"
 #include "spawn-ask-password-agent.h"
 
 static pid_t agent_pid = 0;
diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c
index bc1810d..4db249e 100644
--- a/src/shared/spawn-polkit-agent.c
+++ b/src/shared/spawn-polkit-agent.c
@@ -27,6 +27,7 @@
 
 #include "log.h"
 #include "util.h"
+#include "process-util.h"
 #include "spawn-polkit-agent.h"
 
 #ifdef ENABLE_POLKIT
diff --git a/src/shared/util.c b/src/shared/util.c
index 7321f1b..d4753f1 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -93,6 +93,7 @@
 #include "def.h"
 #include "sparse-endian.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 /* Put this test here for a lack of better place */
 assert_cc(EAGAIN == EWOULDBLOCK);
@@ -185,7 +186,7 @@ char* first_word(const char *s, const char *word) {
         return (char*) p;
 }
 
-static size_t cescape_char(char c, char *buf) {
+size_t cescape_char(char c, char *buf) {
         char * buf_old = buf;
 
         switch (c) {
@@ -598,49 +599,6 @@ const char* split(const char **state, size_t *l, const char *separator, bool quo
         return current;
 }
 
-int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
-        int r;
-        _cleanup_free_ char *line = NULL;
-        long unsigned ppid;
-        const char *p;
-
-        assert(pid >= 0);
-        assert(_ppid);
-
-        if (pid == 0) {
-                *_ppid = getppid();
-                return 0;
-        }
-
-        p = procfs_file_alloca(pid, "stat");
-        r = read_one_line_file(p, &line);
-        if (r < 0)
-                return r;
-
-        /* Let's skip the pid and comm fields. The latter is enclosed
-         * in () but does not escape any () in its value, so let's
-         * skip over it manually */
-
-        p = strrchr(line, ')');
-        if (!p)
-                return -EIO;
-
-        p++;
-
-        if (sscanf(p, " "
-                   "%*c "  /* state */
-                   "%lu ", /* ppid */
-                   &ppid) != 1)
-                return -EIO;
-
-        if ((long unsigned) (pid_t) ppid != ppid)
-                return -ERANGE;
-
-        *_ppid = (pid_t) ppid;
-
-        return 0;
-}
-
 int fchmod_umask(int fd, mode_t m) {
         mode_t u;
         int r;
@@ -659,308 +617,6 @@ char *truncate_nl(char *s) {
         return s;
 }
 
-int get_process_state(pid_t pid) {
-        const char *p;
-        char state;
-        int r;
-        _cleanup_free_ char *line = NULL;
-
-        assert(pid >= 0);
-
-        p = procfs_file_alloca(pid, "stat");
-        r = read_one_line_file(p, &line);
-        if (r < 0)
-                return r;
-
-        p = strrchr(line, ')');
-        if (!p)
-                return -EIO;
-
-        p++;
-
-        if (sscanf(p, " %c", &state) != 1)
-                return -EIO;
-
-        return (unsigned char) state;
-}
-
-int get_process_comm(pid_t pid, char **name) {
-        const char *p;
-        int r;
-
-        assert(name);
-        assert(pid >= 0);
-
-        p = procfs_file_alloca(pid, "comm");
-
-        r = read_one_line_file(p, name);
-        if (r == -ENOENT)
-                return -ESRCH;
-
-        return r;
-}
-
-int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
-        _cleanup_fclose_ FILE *f = NULL;
-        char *r = NULL, *k;
-        const char *p;
-        int c;
-
-        assert(line);
-        assert(pid >= 0);
-
-        p = procfs_file_alloca(pid, "cmdline");
-
-        f = fopen(p, "re");
-        if (!f)
-                return -errno;
-
-        if (max_length == 0) {
-                size_t len = 0, allocated = 0;
-
-                while ((c = getc(f)) != EOF) {
-
-                        if (!GREEDY_REALLOC(r, allocated, len+2)) {
-                                free(r);
-                                return -ENOMEM;
-                        }
-
-                        r[len++] = isprint(c) ? c : ' ';
-                }
-
-                if (len > 0)
-                        r[len-1] = 0;
-
-        } else {
-                bool space = false;
-                size_t left;
-
-                r = new(char, max_length);
-                if (!r)
-                        return -ENOMEM;
-
-                k = r;
-                left = max_length;
-                while ((c = getc(f)) != EOF) {
-
-                        if (isprint(c)) {
-                                if (space) {
-                                        if (left <= 4)
-                                                break;
-
-                                        *(k++) = ' ';
-                                        left--;
-                                        space = false;
-                                }
-
-                                if (left <= 4)
-                                        break;
-
-                                *(k++) = (char) c;
-                                left--;
-                        }  else
-                                space = true;
-                }
-
-                if (left <= 4) {
-                        size_t n = MIN(left-1, 3U);
-                        memcpy(k, "...", n);
-                        k[n] = 0;
-                } else
-                        *k = 0;
-        }
-
-        /* Kernel threads have no argv[] */
-        if (isempty(r)) {
-                _cleanup_free_ char *t = NULL;
-                int h;
-
-                free(r);
-
-                if (!comm_fallback)
-                        return -ENOENT;
-
-                h = get_process_comm(pid, &t);
-                if (h < 0)
-                        return h;
-
-                r = strjoin("[", t, "]", NULL);
-                if (!r)
-                        return -ENOMEM;
-        }
-
-        *line = r;
-        return 0;
-}
-
-int is_kernel_thread(pid_t pid) {
-        const char *p;
-        size_t count;
-        char c;
-        bool eof;
-        FILE *f;
-
-        if (pid == 0)
-                return 0;
-
-        assert(pid > 0);
-
-        p = procfs_file_alloca(pid, "cmdline");
-        f = fopen(p, "re");
-        if (!f)
-                return -errno;
-
-        count = fread(&c, 1, 1, f);
-        eof = feof(f);
-        fclose(f);
-
-        /* Kernel threads have an empty cmdline */
-
-        if (count <= 0)
-                return eof ? 1 : -errno;
-
-        return 0;
-}
-
-int get_process_capeff(pid_t pid, char **capeff) {
-        const char *p;
-
-        assert(capeff);
-        assert(pid >= 0);
-
-        p = procfs_file_alloca(pid, "status");
-
-        return get_status_field(p, "\nCapEff:", capeff);
-}
-
-static int get_process_link_contents(const char *proc_file, char **name) {
-        int r;
-
-        assert(proc_file);
-        assert(name);
-
-        r = readlink_malloc(proc_file, name);
-        if (r < 0)
-                return r == -ENOENT ? -ESRCH : r;
-
-        return 0;
-}
-
-int get_process_exe(pid_t pid, char **name) {
-        const char *p;
-        char *d;
-        int r;
-
-        assert(pid >= 0);
-
-        p = procfs_file_alloca(pid, "exe");
-        r = get_process_link_contents(p, name);
-        if (r < 0)
-                return r;
-
-        d = endswith(*name, " (deleted)");
-        if (d)
-                *d = '\0';
-
-        return 0;
-}
-
-static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
-        _cleanup_fclose_ FILE *f = NULL;
-        char line[LINE_MAX];
-        const char *p;
-
-        assert(field);
-        assert(uid);
-
-        if (pid == 0)
-                return getuid();
-
-        p = procfs_file_alloca(pid, "status");
-        f = fopen(p, "re");
-        if (!f)
-                return -errno;
-
-        FOREACH_LINE(line, f, return -errno) {
-                char *l;
-
-                l = strstrip(line);
-
-                if (startswith(l, field)) {
-                        l += strlen(field);
-                        l += strspn(l, WHITESPACE);
-
-                        l[strcspn(l, WHITESPACE)] = 0;
-
-                        return parse_uid(l, uid);
-                }
-        }
-
-        return -EIO;
-}
-
-int get_process_uid(pid_t pid, uid_t *uid) {
-        return get_process_id(pid, "Uid:", uid);
-}
-
-int get_process_gid(pid_t pid, gid_t *gid) {
-        assert_cc(sizeof(uid_t) == sizeof(gid_t));
-        return get_process_id(pid, "Gid:", gid);
-}
-
-int get_process_cwd(pid_t pid, char **cwd) {
-        const char *p;
-
-        assert(pid >= 0);
-
-        p = procfs_file_alloca(pid, "cwd");
-
-        return get_process_link_contents(p, cwd);
-}
-
-int get_process_root(pid_t pid, char **root) {
-        const char *p;
-
-        assert(pid >= 0);
-
-        p = procfs_file_alloca(pid, "root");
-
-        return get_process_link_contents(p, root);
-}
-
-int get_process_environ(pid_t pid, char **env) {
-        _cleanup_fclose_ FILE *f = NULL;
-        _cleanup_free_ char *outcome = NULL;
-        int c;
-        const char *p;
-        size_t allocated = 0, sz = 0;
-
-        assert(pid >= 0);
-        assert(env);
-
-        p = procfs_file_alloca(pid, "environ");
-
-        f = fopen(p, "re");
-        if (!f)
-                return -errno;
-
-        while ((c = fgetc(f)) != EOF) {
-                if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
-                        return -ENOMEM;
-
-                if (c == '\0')
-                        outcome[sz++] = '\n';
-                else
-                        sz += cescape_char(c, outcome + sz);
-        }
-
-        outcome[sz] = '\0';
-        *env = outcome;
-        outcome = NULL;
-
-        return 0;
-}
-
 char *strnappend(const char *s, const char *suffix, size_t b) {
         size_t a;
         char *r;
@@ -3676,73 +3332,6 @@ static char *unquote(const char *s, const char* quotes) {
         return strdup(s);
 }
 
-int wait_for_terminate(pid_t pid, siginfo_t *status) {
-        siginfo_t dummy;
-
-        assert(pid >= 1);
-
-        if (!status)
-                status = &dummy;
-
-        for (;;) {
-                zero(*status);
-
-                if (waitid(P_PID, pid, status, WEXITED) < 0) {
-
-                        if (errno == EINTR)
-                                continue;
-
-                        return -errno;
-                }
-
-                return 0;
-        }
-}
-
-/*
- * Return values:
- * < 0 : wait_for_terminate() failed to get the state of the
- *       process, the process was terminated by a signal, or
- *       failed for an unknown reason.
- * >=0 : The process terminated normally, and its exit code is
- *       returned.
- *
- * That is, success is indicated by a return value of zero, and an
- * error is indicated by a non-zero value.
- *
- * A warning is emitted if the process terminates abnormally,
- * and also if it returns non-zero unless check_exit_code is true.
- */
-int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code) {
-        int r;
-        siginfo_t status;
-
-        assert(name);
-        assert(pid > 1);
-
-        r = wait_for_terminate(pid, &status);
-        if (r < 0)
-                return log_warning_errno(r, "Failed to wait for %s: %m", name);
-
-        if (status.si_code == CLD_EXITED) {
-                if (status.si_status != 0)
-                        log_full(check_exit_code ? LOG_WARNING : LOG_DEBUG,
-                                 "%s failed with error code %i.", name, status.si_status);
-                else
-                        log_debug("%s succeeded.", name);
-
-                return status.si_status;
-        } else if (status.si_code == CLD_KILLED ||
-                   status.si_code == CLD_DUMPED) {
-
-                log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
-                return -EPROTO;
-        }
-
-        log_warning("%s failed due to unknown reason.", name);
-        return -EPROTO;
-}
-
 noreturn void freeze(void) {
 
         /* Make sure nobody waits for us on a socket anymore */
@@ -4119,17 +3708,6 @@ void execute_directories(const char* const* directories, usec_t timeout, char *a
         wait_for_terminate_and_warn(name, executor_pid, true);
 }
 
-int kill_and_sigcont(pid_t pid, int sig) {
-        int r;
-
-        r = kill(pid, sig) < 0 ? -errno : 0;
-
-        if (r >= 0)
-                kill(pid, SIGCONT);
-
-        return r;
-}
-
 bool nulstr_contains(const char*nulstr, const char *needle) {
         const char *i;
 
@@ -5338,60 +4916,6 @@ int setrlimit_closest(int resource, const struct rlimit *rlim) {
         return 0;
 }
 
-int getenv_for_pid(pid_t pid, const char *field, char **_value) {
-        _cleanup_fclose_ FILE *f = NULL;
-        char *value = NULL;
-        int r;
-        bool done = false;
-        size_t l;
-        const char *path;
-
-        assert(pid >= 0);
-        assert(field);
-        assert(_value);
-
-        path = procfs_file_alloca(pid, "environ");
-
-        f = fopen(path, "re");
-        if (!f)
-                return -errno;
-
-        l = strlen(field);
-        r = 0;
-
-        do {
-                char line[LINE_MAX];
-                unsigned i;
-
-                for (i = 0; i < sizeof(line)-1; i++) {
-                        int c;
-
-                        c = getc(f);
-                        if (_unlikely_(c == EOF)) {
-                                done = true;
-                                break;
-                        } else if (c == 0)
-                                break;
-
-                        line[i] = c;
-                }
-                line[i] = 0;
-
-                if (memcmp(line, field, l) == 0 && line[l] == '=') {
-                        value = strdup(line + l + 1);
-                        if (!value)
-                                return -ENOMEM;
-
-                        r = 1;
-                        break;
-                }
-
-        } while (!done);
-
-        *_value = value;
-        return r;
-}
-
 bool http_etag_is_valid(const char *etag) {
         if (isempty(etag))
                 return false;
@@ -6497,33 +6021,6 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
         return 0;
 }
 
-bool pid_is_unwaited(pid_t pid) {
-        /* Checks whether a PID is still valid at all, including a zombie */
-
-        if (pid <= 0)
-                return false;
-
-        if (kill(pid, 0) >= 0)
-                return true;
-
-        return errno != ESRCH;
-}
-
-bool pid_is_alive(pid_t pid) {
-        int r;
-
-        /* Checks whether a PID is still valid and not a zombie */
-
-        if (pid <= 0)
-                return false;
-
-        r = get_process_state(pid);
-        if (r == -ENOENT || r == 'Z')
-                return false;
-
-        return true;
-}
-
 int getpeercred(int fd, struct ucred *ucred) {
         socklen_t n = sizeof(struct ucred);
         struct ucred u;
diff --git a/src/shared/util.h b/src/shared/util.h
index d17b987..b939d7f 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -227,8 +227,6 @@ const char* split(const char **state, size_t *l, const char *separator, bool quo
 #define _FOREACH_WORD(word, length, s, separator, quoted, state)        \
         for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted)))
 
-pid_t get_parent_of_pid(pid_t pid, pid_t *ppid);
-
 char *strappend(const char *s, const char *suffix);
 char *strnappend(const char *s, const char *suffix, size_t length);
 
@@ -252,17 +250,6 @@ char *file_in_same_dir(const char *path, const char *filename);
 
 int rmdir_parents(const char *path, const char *stop);
 
-int get_process_state(pid_t pid);
-int get_process_comm(pid_t pid, char **name);
-int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line);
-int get_process_exe(pid_t pid, char **name);
-int get_process_uid(pid_t pid, uid_t *uid);
-int get_process_gid(pid_t pid, gid_t *gid);
-int get_process_capeff(pid_t pid, char **capeff);
-int get_process_cwd(pid_t pid, char **cwd);
-int get_process_root(pid_t pid, char **root);
-int get_process_environ(pid_t pid, char **environ);
-
 char hexchar(int x) _const_;
 int unhexchar(char c) _const_;
 char octchar(int x) _const_;
@@ -271,6 +258,7 @@ char decchar(int x) _const_;
 int undecchar(char c) _const_;
 
 char *cescape(const char *s);
+size_t cescape_char(char c, char *buf);
 
 typedef enum UnescapeFlags {
         UNESCAPE_RELAX = 1,
@@ -406,8 +394,6 @@ bool is_device_path(const char *path);
 int dir_is_empty(const char *path);
 char* dirname_malloc(const char *path);
 
-void rename_process(const char name[8]);
-
 void sigset_add_many(sigset_t *ss, ...);
 int sigprocmask_many(int how, ...);
 
@@ -482,9 +468,6 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
 int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode);
 int touch(const char *path);
 
-int wait_for_terminate(pid_t pid, siginfo_t *status);
-int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
-
 noreturn void freeze(void);
 
 bool null_or_empty(struct stat *st) _pure_;
@@ -504,8 +487,6 @@ const char *default_term_for_tty(const char *tty);
 
 void execute_directories(const char* const* directories, usec_t timeout, char *argv[]);
 
-int kill_and_sigcont(pid_t pid, int sig);
-
 bool nulstr_contains(const char*nulstr, const char *needle);
 
 bool plymouth_running(void);
@@ -604,8 +585,6 @@ int fd_wait_for_event(int fd, int event, usec_t timeout);
 
 void* memdup(const void *p, size_t l) _alloc_(2);
 
-int is_kernel_thread(pid_t pid);
-
 int fd_inc_sndbuf(int fd, size_t n);
 int fd_inc_rcvbuf(int fd, size_t n);
 
@@ -613,8 +592,6 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
 
 int setrlimit_closest(int resource, const struct rlimit *rlim);
 
-int getenv_for_pid(pid_t pid, const char *field, char **_value);
-
 bool http_url_is_valid(const char *url) _pure_;
 bool documentation_url_is_valid(const char *url) _pure_;
 
@@ -891,19 +868,6 @@ int unlink_noerrno(const char *path);
                 _d_;                                                    \
         })
 
-#define procfs_file_alloca(pid, field)                                  \
-        ({                                                              \
-                pid_t _pid_ = (pid);                                    \
-                const char *_r_;                                        \
-                if (_pid_ == 0) {                                       \
-                        _r_ = ("/proc/self/" field);                    \
-                } else {                                                \
-                        _r_ = alloca(strlen("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
-                        sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_);                       \
-                }                                                       \
-                _r_;                                                    \
-        })
-
 bool id128_is_valid(const char *s) _pure_;
 
 int split_pair(const char *s, const char *sep, char **l, char **r);
@@ -931,9 +895,6 @@ int container_get_leader(const char *machine, pid_t *pid);
 int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd);
 int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd);
 
-bool pid_is_alive(pid_t pid);
-bool pid_is_unwaited(pid_t pid);
-
 int getpeercred(int fd, struct ucred *ucred);
 int getpeersec(int fd, char **ret);
 
diff --git a/src/shared/virt.c b/src/shared/virt.c
index 54c4655..1299a75 100644
--- a/src/shared/virt.c
+++ b/src/shared/virt.c
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include "util.h"
+#include "process-util.h"
 #include "virt.h"
 #include "fileio.h"
 
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 915482f..04b7e7b 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -70,6 +70,7 @@
 #include "dropin.h"
 #include "efivars.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 static char **arg_types = NULL;
 static char **arg_states = NULL;
diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c
index c0f4abe..aca4f86 100644
--- a/src/test/test-cgroup-util.c
+++ b/src/test/test-cgroup-util.c
@@ -24,6 +24,7 @@
 #include "cgroup-util.h"
 #include "test-helper.h"
 #include "formats-util.h"
+#include "process-util.h"
 
 static void check_p_d_u(const char *path, int code, const char *result) {
         _cleanup_free_ char *unit = NULL;
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 63e4a19..4c31b77 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include "util.h"
+#include "process-util.h"
 #include "fileio.h"
 #include "strv.h"
 #include "env-util.h"
diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c
index 2397db5..7d7e08d 100644
--- a/src/test/test-namespace.c
+++ b/src/test/test-namespace.c
@@ -23,6 +23,7 @@
 
 #include "namespace.h"
 #include "util.h"
+#include "process-util.h"
 
 static void test_tmpdir(const char *id, const char *A, const char *B) {
         _cleanup_free_ char *a, *b;
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
new file mode 100644
index 0000000..a17ef14
--- /dev/null
+++ b/src/test/test-process-util.c
@@ -0,0 +1,138 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+  Copyright 2013 Thomas H.P. Andersen
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "process-util.h"
+#include "log.h"
+#include "util.h"
+#include "macro.h"
+#include "virt.h"
+
+static void test_get_process_comm(void) {
+        struct stat st;
+        _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL, *cwd = NULL, *root = NULL;
+        _cleanup_free_ char *env = NULL;
+        pid_t e;
+        uid_t u;
+        gid_t g;
+        dev_t h;
+        int r;
+        pid_t me;
+
+        if (stat("/proc/1/comm", &st) == 0) {
+                assert_se(get_process_comm(1, &a) >= 0);
+                log_info("pid1 comm: '%s'", a);
+        } else {
+                log_warning("/proc/1/comm does not exist.");
+        }
+
+        assert_se(get_process_cmdline(1, 0, true, &c) >= 0);
+        log_info("pid1 cmdline: '%s'", c);
+
+        assert_se(get_process_cmdline(1, 8, false, &d) >= 0);
+        log_info("pid1 cmdline truncated: '%s'", d);
+
+        assert_se(get_parent_of_pid(1, &e) >= 0);
+        log_info("pid1 ppid: "PID_FMT, e);
+        assert_se(e == 0);
+
+        assert_se(is_kernel_thread(1) == 0);
+
+        r = get_process_exe(1, &f);
+        assert_se(r >= 0 || r == -EACCES);
+        log_info("pid1 exe: '%s'", strna(f));
+
+        assert_se(get_process_uid(1, &u) == 0);
+        log_info("pid1 uid: "UID_FMT, u);
+        assert_se(u == 0);
+
+        assert_se(get_process_gid(1, &g) == 0);
+        log_info("pid1 gid: "GID_FMT, g);
+        assert_se(g == 0);
+
+        me = getpid();
+
+        r = get_process_cwd(me, &cwd);
+        assert_se(r >= 0 || r == -EACCES);
+        log_info("pid1 cwd: '%s'", cwd);
+
+        r = get_process_root(me, &root);
+        assert_se(r >= 0 || r == -EACCES);
+        log_info("pid1 root: '%s'", root);
+
+        r = get_process_environ(me, &env);
+        assert_se(r >= 0 || r == -EACCES);
+        log_info("self strlen(environ): '%zu'", strlen(env));
+
+        if (!detect_container(NULL))
+                assert_se(get_ctty_devnr(1, &h) == -ENOENT);
+
+        getenv_for_pid(1, "PATH", &i);
+        log_info("pid1 $PATH: '%s'", strna(i));
+}
+
+static void test_pid_is_unwaited(void) {
+        pid_t pid;
+
+        pid = fork();
+        assert_se(pid >= 0);
+        if (pid == 0) {
+                _exit(EXIT_SUCCESS);
+        } else {
+                int status;
+
+                waitpid(pid, &status, 0);
+                assert_se(!pid_is_unwaited(pid));
+        }
+        assert_se(pid_is_unwaited(getpid()));
+        assert_se(!pid_is_unwaited(-1));
+}
+
+static void test_pid_is_alive(void) {
+        pid_t pid;
+
+        pid = fork();
+        assert_se(pid >= 0);
+        if (pid == 0) {
+                _exit(EXIT_SUCCESS);
+        } else {
+                int status;
+
+                waitpid(pid, &status, 0);
+                assert_se(!pid_is_alive(pid));
+        }
+        assert_se(pid_is_alive(getpid()));
+        assert_se(!pid_is_alive(-1));
+}
+
+int main(int argc, char *argv[]) {
+        log_parse_environment();
+        log_open();
+
+        test_get_process_comm();
+        test_pid_is_unwaited();
+        test_pid_is_alive();
+
+        return 0;
+}
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 4d36eb2..bfd4df9 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -37,6 +37,7 @@
 #include "fileio.h"
 #include "conf-parser.h"
 #include "virt.h"
+#include "process-util.h"
 
 static void test_streq_ptr(void) {
         assert_se(streq_ptr(NULL, NULL));
@@ -572,69 +573,6 @@ static void test_u64log2(void) {
         assert_se(u64log2(1024*1024+5) == 20);
 }
 
-static void test_get_process_comm(void) {
-        struct stat st;
-        _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL, *cwd = NULL, *root = NULL;
-        _cleanup_free_ char *env = NULL;
-        pid_t e;
-        uid_t u;
-        gid_t g;
-        dev_t h;
-        int r;
-        pid_t me;
-
-        if (stat("/proc/1/comm", &st) == 0) {
-                assert_se(get_process_comm(1, &a) >= 0);
-                log_info("pid1 comm: '%s'", a);
-        } else {
-                log_warning("/proc/1/comm does not exist.");
-        }
-
-        assert_se(get_process_cmdline(1, 0, true, &c) >= 0);
-        log_info("pid1 cmdline: '%s'", c);
-
-        assert_se(get_process_cmdline(1, 8, false, &d) >= 0);
-        log_info("pid1 cmdline truncated: '%s'", d);
-
-        assert_se(get_parent_of_pid(1, &e) >= 0);
-        log_info("pid1 ppid: "PID_FMT, e);
-        assert_se(e == 0);
-
-        assert_se(is_kernel_thread(1) == 0);
-
-        r = get_process_exe(1, &f);
-        assert_se(r >= 0 || r == -EACCES);
-        log_info("pid1 exe: '%s'", strna(f));
-
-        assert_se(get_process_uid(1, &u) == 0);
-        log_info("pid1 uid: "UID_FMT, u);
-        assert_se(u == 0);
-
-        assert_se(get_process_gid(1, &g) == 0);
-        log_info("pid1 gid: "GID_FMT, g);
-        assert_se(g == 0);
-
-        me = getpid();
-
-        r = get_process_cwd(me, &cwd);
-        assert_se(r >= 0 || r == -EACCES);
-        log_info("pid1 cwd: '%s'", cwd);
-
-        r = get_process_root(me, &root);
-        assert_se(r >= 0 || r == -EACCES);
-        log_info("pid1 root: '%s'", root);
-
-        r = get_process_environ(me, &env);
-        assert_se(r >= 0 || r == -EACCES);
-        log_info("self strlen(environ): '%zu'", strlen(env));
-
-        if (!detect_container(NULL))
-                assert_se(get_ctty_devnr(1, &h) == -ENOENT);
-
-        getenv_for_pid(1, "PATH", &i);
-        log_info("pid1 $PATH: '%s'", strna(i));
-}
-
 static void test_protect_errno(void) {
         errno = 12;
         {
@@ -1138,40 +1076,6 @@ static void test_is_symlink(void) {
         unlink(name_link);
 }
 
-static void test_pid_is_unwaited(void) {
-        pid_t pid;
-
-        pid = fork();
-        assert_se(pid >= 0);
-        if (pid == 0) {
-                _exit(EXIT_SUCCESS);
-        } else {
-                int status;
-
-                waitpid(pid, &status, 0);
-                assert_se(!pid_is_unwaited(pid));
-        }
-        assert_se(pid_is_unwaited(getpid()));
-        assert_se(!pid_is_unwaited(-1));
-}
-
-static void test_pid_is_alive(void) {
-        pid_t pid;
-
-        pid = fork();
-        assert_se(pid >= 0);
-        if (pid == 0) {
-                _exit(EXIT_SUCCESS);
-        } else {
-                int status;
-
-                waitpid(pid, &status, 0);
-                assert_se(!pid_is_alive(pid));
-        }
-        assert_se(pid_is_alive(getpid()));
-        assert_se(!pid_is_alive(-1));
-}
-
 static void test_search_and_fopen(void) {
         const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
         char name[] = "/tmp/test-search_and_fopen.XXXXXX";
@@ -1625,7 +1529,6 @@ int main(int argc, char *argv[]) {
         test_memdup_multiply();
         test_hostname_is_valid();
         test_u64log2();
-        test_get_process_comm();
         test_protect_errno();
         test_parse_size();
         test_config_parse_iec_off();
@@ -1654,8 +1557,6 @@ int main(int argc, char *argv[]) {
         test_strshorten();
         test_strjoina();
         test_is_symlink();
-        test_pid_is_unwaited();
-        test_pid_is_alive();
         test_search_and_fopen();
         test_search_and_fopen_nulstr();
         test_glob_exists();
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
index 47093b8..8f4031a 100644
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -42,6 +42,7 @@
 #include "strv.h"
 #include "build.h"
 #include "def.h"
+#include "process-util.h"
 
 static enum {
         ACTION_LIST,
diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c
index 243e51d..3f93524 100644
--- a/src/vconsole/vconsole-setup.c
+++ b/src/vconsole/vconsole-setup.c
@@ -35,6 +35,7 @@
 #include "log.h"
 #include "virt.h"
 #include "fileio.h"
+#include "process-util.h"
 
 static bool is_vconsole(int fd) {
         unsigned char data[1];

commit 6482f6269c87d2249e52e889a63adbdd50f2d691
Author: Ronny Chevalier <chevalier.ronny at gmail.com>
Date:   Fri Apr 10 20:43:52 2015 +0200

    shared: add formats-util.h

diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c
index d612816..3e398b5 100644
--- a/src/bus-proxyd/bus-proxyd.c
+++ b/src/bus-proxyd/bus-proxyd.c
@@ -41,6 +41,7 @@
 #include "capability.h"
 #include "bus-xml-policy.h"
 #include "proxy.h"
+#include "formats-util.h"
 
 static char *arg_address = NULL;
 static char **arg_configuration = NULL;
diff --git a/src/bus-proxyd/bus-xml-policy.c b/src/bus-proxyd/bus-xml-policy.c
index 497bce7..675d244 100644
--- a/src/bus-proxyd/bus-xml-policy.c
+++ b/src/bus-proxyd/bus-xml-policy.c
@@ -27,6 +27,7 @@
 #include "bus-internal.h"
 #include "bus-xml-policy.h"
 #include "sd-login.h"
+#include "formats-util.h"
 
 static void policy_item_free(PolicyItem *i) {
         assert(i);
diff --git a/src/bus-proxyd/proxy.c b/src/bus-proxyd/proxy.c
index c689618..aa5010c 100644
--- a/src/bus-proxyd/proxy.c
+++ b/src/bus-proxyd/proxy.c
@@ -42,6 +42,7 @@
 #include "driver.h"
 #include "proxy.h"
 #include "synthesize.h"
+#include "formats-util.h"
 
 static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
         _cleanup_bus_close_unref_ sd_bus *b = NULL;
diff --git a/src/bus-proxyd/stdio-bridge.c b/src/bus-proxyd/stdio-bridge.c
index 35e69a5..61bc08a 100644
--- a/src/bus-proxyd/stdio-bridge.c
+++ b/src/bus-proxyd/stdio-bridge.c
@@ -37,6 +37,7 @@
 #include "strv.h"
 #include "def.h"
 #include "proxy.h"
+#include "formats-util.h"
 
 static char *arg_address = NULL;
 static char *arg_command_line_buffer = NULL;
diff --git a/src/core/automount.c b/src/core/automount.c
index f6a6ad5..e1ca2a4 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -40,6 +40,7 @@
 #include "dbus-automount.h"
 #include "bus-util.h"
 #include "bus-error.h"
+#include "formats-util.h"
 
 static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
         [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
diff --git a/src/core/busname.c b/src/core/busname.c
index 0ca9678..b1b953a 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -30,6 +30,7 @@
 #include "bus-policy.h"
 #include "dbus-busname.h"
 #include "busname.h"
+#include "formats-util.h"
 
 static const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
         [BUSNAME_DEAD] = UNIT_INACTIVE,
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 1b26e55..8821cc7 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -40,6 +40,7 @@
 #include "dbus-snapshot.h"
 #include "dbus-execute.h"
 #include "bus-common-errors.h"
+#include "formats-util.h"
 
 static int property_get_version(
                 sd_bus *bus,
diff --git a/src/core/execute.c b/src/core/execute.c
index 768a32b..c87e900 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -76,6 +76,7 @@
 #include "smack-util.h"
 #include "bus-endpoint.h"
 #include "cap-list.h"
+#include "formats-util.h"
 
 #ifdef HAVE_APPARMOR
 #include "apparmor-util.h"
diff --git a/src/core/killall.c b/src/core/killall.c
index c6f1ddf..5040514 100644
--- a/src/core/killall.c
+++ b/src/core/killall.c
@@ -27,6 +27,7 @@
 #include "util.h"
 #include "killall.h"
 #include "set.h"
+#include "formats-util.h"
 
 #define TIMEOUT_USEC (10 * USEC_PER_SEC)
 
diff --git a/src/core/main.c b/src/core/main.c
index dd8b650..5d1aed8 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -72,6 +72,7 @@
 #include "ima-setup.h"
 #include "smack-setup.h"
 #include "kmod-setup.h"
+#include "formats-util.h"
 
 static enum {
         ACTION_RUN,
diff --git a/src/core/mount.c b/src/core/mount.c
index c4aa810..8bfbbed 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -40,6 +40,7 @@
 #include "special.h"
 #include "exit-status.h"
 #include "fstab-util.h"
+#include "formats-util.h"
 
 #define RETRY_UMOUNT_MAX 32
 
diff --git a/src/core/service.c b/src/core/service.c
index d938550..c6ea655 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -45,6 +45,7 @@
 #include "bus-error.h"
 #include "bus-util.h"
 #include "bus-kernel.h"
+#include "formats-util.h"
 
 static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
         [SERVICE_DEAD] = UNIT_INACTIVE,
diff --git a/src/core/socket.c b/src/core/socket.c
index c81fd66..dd805d5 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -48,6 +48,7 @@
 #include "dbus-socket.h"
 #include "unit.h"
 #include "socket.h"
+#include "formats-util.h"
 
 static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
         [SOCKET_DEAD] = UNIT_INACTIVE,
diff --git a/src/core/swap.c b/src/core/swap.c
index 53f1274..76660cc 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -35,6 +35,7 @@
 #include "virt.h"
 #include "udev-util.h"
 #include "fstab-util.h"
+#include "formats-util.h"
 
 static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
         [SWAP_DEAD] = UNIT_INACTIVE,
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index 90cb504..bb4aa21 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -26,6 +26,7 @@
 #include "unit-printf.h"
 #include "macro.h"
 #include "cgroup-util.h"
+#include "formats-util.h"
 
 static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) {
         Unit *u = userdata;
diff --git a/src/core/unit.c b/src/core/unit.c
index 7660d6b..4b9c406 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -46,6 +46,7 @@
 #include "dbus.h"
 #include "execute.h"
 #include "dropin.h"
+#include "formats-util.h"
 
 const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
         [UNIT_SERVICE] = &service_vtable,
diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c
index ecec7a1..19d6468 100644
--- a/src/initctl/initctl.c
+++ b/src/initctl/initctl.c
@@ -36,6 +36,7 @@
 #include "bus-util.h"
 #include "bus-error.h"
 #include "def.h"
+#include "formats-util.h"
 
 #define SERVER_FD_MAX 16
 #define TIMEOUT_MSEC ((int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC))
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
index 75bb434..ddbb873 100644
--- a/src/journal-remote/journal-upload.c
+++ b/src/journal-remote/journal-upload.c
@@ -34,6 +34,7 @@
 #include "conf-parser.h"
 #include "sigbus.h"
 #include "journal-upload.h"
+#include "formats-util.h"
 
 #define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-upload.pem"
 #define CERT_FILE     CERTIFICATE_ROOT "/certs/journal-upload.pem"
diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c
index f7ea779..4ccacd7 100644
--- a/src/journal/journald-console.c
+++ b/src/journal/journald-console.c
@@ -26,6 +26,7 @@
 #include "fileio.h"
 #include "journald-server.h"
 #include "journald-console.h"
+#include "formats-util.h"
 
 static bool prefix_timestamp(void) {
 
diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c
index 80bd9cd..cb4bc38 100644
--- a/src/journal/journald-kmsg.c
+++ b/src/journal/journald-kmsg.c
@@ -31,6 +31,7 @@
 #include "journald-server.h"
 #include "journald-kmsg.h"
 #include "journald-syslog.h"
+#include "formats-util.h"
 
 void server_forward_kmsg(
         Server *s,
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 78d5b22..7e20b96 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -50,6 +50,7 @@
 #include "journald-audit.h"
 #include "journald-server.h"
 #include "acl-util.h"
+#include "formats-util.h"
 
 #ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c
index 7d545ca..6c46a30 100644
--- a/src/journal/journald-syslog.c
+++ b/src/journal/journald-syslog.c
@@ -31,6 +31,7 @@
 #include "journald-kmsg.h"
 #include "journald-console.h"
 #include "journald-wall.h"
+#include "formats-util.h"
 
 /* Warn once every 30s if we missed syslog message */
 #define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC)
diff --git a/src/journal/journald-wall.c b/src/journal/journald-wall.c
index e320167..b4e0717 100644
--- a/src/journal/journald-wall.c
+++ b/src/journal/journald-wall.c
@@ -22,6 +22,7 @@
 #include "utmp-wtmp.h"
 #include "journald-server.h"
 #include "journald-wall.h"
+#include "formats-util.h"
 
 void server_forward_wall(
                 Server *s,
diff --git a/src/journal/journald.c b/src/journal/journald.c
index 28a4233..b2624c6 100644
--- a/src/journal/journald.c
+++ b/src/journal/journald.c
@@ -30,6 +30,7 @@
 #include "journald-syslog.h"
 
 #include "sigbus.h"
+#include "formats-util.h"
 
 int main(int argc, char *argv[]) {
         Server server;
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index 9b9e8ac..9f0f71a 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -42,6 +42,7 @@
 #include "catalog.h"
 #include "replace-var.h"
 #include "fileio.h"
+#include "formats-util.h"
 
 #define JOURNAL_FILES_MAX 7168
 
diff --git a/src/journal/stacktrace.c b/src/journal/stacktrace.c
index 6b9d272..706c08e 100644
--- a/src/journal/stacktrace.c
+++ b/src/journal/stacktrace.c
@@ -25,6 +25,7 @@
 #include "util.h"
 #include "macro.h"
 #include "stacktrace.h"
+#include "formats-util.h"
 
 #define FRAMES_MAX 64
 #define THREADS_MAX 64
diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c
index cd1c5e2..4141cc3 100644
--- a/src/libsystemd/sd-bus/bus-creds.c
+++ b/src/libsystemd/sd-bus/bus-creds.c
@@ -23,6 +23,7 @@
 #include <linux/capability.h>
 
 #include "util.h"
+#include "formats-util.h"
 #include "capability.h"
 #include "cgroup-util.h"
 #include "fileio.h"
diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c
index 4bc8965..d722680 100644
--- a/src/libsystemd/sd-bus/bus-dump.c
+++ b/src/libsystemd/sd-bus/bus-dump.c
@@ -24,6 +24,7 @@
 #include "strv.h"
 #include "macro.h"
 #include "cap-list.h"
+#include "formats-util.h"
 
 #include "bus-message.h"
 #include "bus-internal.h"
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index 35c2aa6..0062e66 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -39,6 +39,7 @@
 #include "memfd-util.h"
 #include "capability.h"
 #include "fileio.h"
+#include "formats-util.h"
 
 #include "bus-internal.h"
 #include "bus-message.h"
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 873aede..f97e15d 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -29,6 +29,7 @@
 #include "missing.h"
 #include "utf8.h"
 #include "sd-daemon.h"
+#include "formats-util.h"
 
 #include "sd-bus.h"
 #include "bus-socket.h"
diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c
index 7f49fe9..ab2ec27 100644
--- a/src/libsystemd/sd-bus/test-bus-chat.c
+++ b/src/libsystemd/sd-bus/test-bus-chat.c
@@ -27,6 +27,7 @@
 #include "log.h"
 #include "util.h"
 #include "macro.h"
+#include "formats-util.h"
 
 #include "sd-bus.h"
 #include "bus-error.h"
diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c
index 072191e..7b8f063 100644
--- a/src/libsystemd/sd-login/sd-login.c
+++ b/src/libsystemd/sd-login/sd-login.c
@@ -31,6 +31,7 @@
 #include "strv.h"
 #include "fileio.h"
 #include "login-shared.h"
+#include "formats-util.h"
 #include "sd-login.h"
 
 _public_ int sd_pid_get_session(pid_t pid, char **session) {
diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c
index 2802e82..05affa4 100644
--- a/src/libsystemd/sd-login/test-login.c
+++ b/src/libsystemd/sd-login/test-login.c
@@ -26,6 +26,7 @@
 
 #include "util.h"
 #include "strv.h"
+#include "formats-util.h"
 
 static void test_login(void) {
         _cleanup_close_pair_ int pair[2] = { -1, -1 };
diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index c938471..4f994a1 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include "util.h"
+#include "formats-util.h"
 #include "refcnt.h"
 #include "missing.h"
 
diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c
index c48ac78..e9d403c 100644
--- a/src/libudev/libudev-monitor.c
+++ b/src/libudev/libudev-monitor.c
@@ -32,6 +32,7 @@
 #include "libudev-private.h"
 #include "socket-util.h"
 #include "missing.h"
+#include "formats-util.h"
 
 /**
  * SECTION:libudev-monitor
diff --git a/src/login/inhibit.c b/src/login/inhibit.c
index 9f349b7..1f78e4b 100644
--- a/src/login/inhibit.c
+++ b/src/login/inhibit.c
@@ -31,6 +31,7 @@
 #include "util.h"
 #include "build.h"
 #include "strv.h"
+#include "formats-util.h"
 
 static const char* arg_what = "idle:sleep:shutdown";
 static const char* arg_who = NULL;
diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c
index d2b3337..466225d 100644
--- a/src/login/logind-acl.c
+++ b/src/login/logind-acl.c
@@ -23,6 +23,7 @@
 #include <string.h>
 
 #include "util.h"
+#include "formats-util.h"
 #include "acl-util.h"
 #include "set.h"
 #include "logind-acl.h"
diff --git a/src/login/logind-action.c b/src/login/logind-action.c
index 281e3c7..d7ae175 100644
--- a/src/login/logind-action.c
+++ b/src/login/logind-action.c
@@ -27,6 +27,7 @@
 #include "bus-util.h"
 #include "bus-error.h"
 #include "logind-action.h"
+#include "formats-util.h"
 
 int manager_handle_action(
                 Manager *m,
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 9ba85d8..45aedad 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -40,6 +40,7 @@
 #include "selinux-util.h"
 #include "efivars.h"
 #include "logind.h"
+#include "formats-util.h"
 
 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
index 5eb1a2e..68304a1 100644
--- a/src/login/logind-inhibit.c
+++ b/src/login/logind-inhibit.c
@@ -28,6 +28,7 @@
 #include "mkdir.h"
 #include "logind-inhibit.h"
 #include "fileio.h"
+#include "formats-util.h"
 
 Inhibitor* inhibitor_new(Manager *m, const char* id) {
         Inhibitor *i;
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index 49808c9..4c0bebd 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -29,6 +29,7 @@
 #include "logind-acl.h"
 #include "util.h"
 #include "mkdir.h"
+#include "formats-util.h"
 
 Seat *seat_new(Manager *m, const char *id) {
         Seat *s;
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 59f7657..cebc90c 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -37,6 +37,7 @@
 #include "bus-util.h"
 #include "bus-error.h"
 #include "logind-session.h"
+#include "formats-util.h"
 
 #define RELEASE_USEC (20*USEC_PER_SEC)
 
diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
index f7af8ff..03c3370 100644
--- a/src/login/logind-user-dbus.c
+++ b/src/login/logind-user-dbus.c
@@ -26,6 +26,7 @@
 #include "bus-util.h"
 #include "logind.h"
 #include "logind-user.h"
+#include "formats-util.h"
 
 static int property_get_display(
                 sd_bus *bus,
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index cba9cb6..b00e9b1 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -38,6 +38,7 @@
 #include "clean-ipc.h"
 #include "logind-user.h"
 #include "smack-util.h"
+#include "formats-util.h"
 
 User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
         User *u;
diff --git a/src/login/logind.c b/src/login/logind.c
index e788074..707d528 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -32,6 +32,7 @@
 #include "bus-error.h"
 #include "logind.h"
 #include "udev-util.h"
+#include "formats-util.h"
 
 Manager *manager_new(void) {
         Manager *m;
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index d7a708f..a0fabfe 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -40,6 +40,7 @@
 #include "socket-util.h"
 #include "fileio.h"
 #include "bus-error.h"
+#include "formats-util.h"
 
 static int parse_argv(
                 pam_handle_t *handle,
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index d6b8c90..6cc46af 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -42,6 +42,7 @@
 #include "bus-internal.h"
 #include "machine.h"
 #include "machine-dbus.h"
+#include "formats-util.h"
 
 static int property_get_id(
                 sd_bus *bus,
diff --git a/src/machine/machine.c b/src/machine/machine.c
index 048607f..dd073ad 100644
--- a/src/machine/machine.c
+++ b/src/machine/machine.c
@@ -35,6 +35,7 @@
 #include "bus-error.h"
 #include "machine.h"
 #include "machine-dbus.h"
+#include "formats-util.h"
 
 Machine* machine_new(Manager *manager, const char *name) {
         Machine *m;
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index 4d74093..066a8da 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -35,6 +35,7 @@
 #include "image-dbus.h"
 #include "machined.h"
 #include "machine-dbus.h"
+#include "formats-util.h"
 
 static int property_get_pool_path(
                 sd_bus *bus,
diff --git a/src/machine/machined.c b/src/machine/machined.c
index f91f067..7980293 100644
--- a/src/machine/machined.c
+++ b/src/machine/machined.c
@@ -30,6 +30,7 @@
 #include "label.h"
 #include "machine-image.h"
 #include "machined.h"
+#include "formats-util.h"
 
 Manager *manager_new(void) {
         Manager *m;
diff --git a/src/notify/notify.c b/src/notify/notify.c
index 00db753..c920b29 100644
--- a/src/notify/notify.c
+++ b/src/notify/notify.c
@@ -32,6 +32,7 @@
 #include "log.h"
 #include "build.h"
 #include "env-util.h"
+#include "formats-util.h"
 
 static bool arg_ready = false;
 static pid_t arg_pid = 0;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 6789281..8ec6743 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -91,6 +91,7 @@
 #include "in-addr-util.h"
 #include "fw-util.h"
 #include "local-addresses.h"
+#include "formats-util.h"
 
 #ifdef HAVE_SECCOMP
 #include "seccomp-util.h"
diff --git a/src/run/run.c b/src/run/run.c
index 3ded2c7..156824e 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -34,6 +34,7 @@
 #include "bus-error.h"
 #include "calendarspec.h"
 #include "ptyfwd.h"
+#include "formats-util.h"
 
 static bool arg_scope = false;
 static bool arg_remain_after_exit = false;
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
index 44ebc58..dfc89d2 100644
--- a/src/shared/ask-password-api.c
+++ b/src/shared/ask-password-api.c
@@ -32,6 +32,7 @@
 #include <sys/signalfd.h>
 
 #include "util.h"
+#include "formats-util.h"
 #include "mkdir.h"
 #include "strv.h"
 
diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c
index cbd94e8..fed72ac 100644
--- a/src/shared/cgroup-show.c
+++ b/src/shared/cgroup-show.c
@@ -25,6 +25,7 @@
 #include <errno.h>
 
 #include "util.h"
+#include "formats-util.h"
 #include "macro.h"
 #include "path-util.h"
 #include "cgroup-util.h"
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index b6fa386..481708f 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -33,6 +33,7 @@
 #include "set.h"
 #include "macro.h"
 #include "util.h"
+#include "formats-util.h"
 #include "path-util.h"
 #include "unit-name.h"
 #include "fileio.h"
diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c
index ea781f5..48b1086 100644
--- a/src/shared/clean-ipc.c
+++ b/src/shared/clean-ipc.c
@@ -29,6 +29,7 @@
 #include <mqueue.h>
 
 #include "util.h"
+#include "formats-util.h"
 #include "strv.h"
 #include "clean-ipc.h"
 
diff --git a/src/shared/formats-util.h b/src/shared/formats-util.h
new file mode 100644
index 0000000..ce516b1
--- /dev/null
+++ b/src/shared/formats-util.h
@@ -0,0 +1,63 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Ronny Chevalier
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <inttypes.h>
+
+#if SIZEOF_PID_T == 4
+#  define PID_PRI PRIi32
+#elif SIZEOF_PID_T == 2
+#  define PID_PRI PRIi16
+#else
+#  error Unknown pid_t size
+#endif
+#define PID_FMT "%" PID_PRI
+
+#if SIZEOF_UID_T == 4
+#  define UID_FMT "%" PRIu32
+#elif SIZEOF_UID_T == 2
+#  define UID_FMT "%" PRIu16
+#else
+#  error Unknown uid_t size
+#endif
+
+#if SIZEOF_GID_T == 4
+#  define GID_FMT "%" PRIu32
+#elif SIZEOF_GID_T == 2
+#  define GID_FMT "%" PRIu16
+#else
+#  error Unknown gid_t size
+#endif
+
+#if SIZEOF_TIME_T == 8
+#  define PRI_TIME PRIi64
+#elif SIZEOF_TIME_T == 4
+#  define PRI_TIME PRIu32
+#else
+#  error Unknown time_t size
+#endif
+
+#if SIZEOF_RLIM_T == 8
+#  define RLIM_FMT "%" PRIu64
+#elif SIZEOF_RLIM_T == 4
+#  define RLIM_FMT "%" PRIu32
+#else
+#  error Unknown rlim_t size
+#endif
diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c
index f62a032..9996649 100644
--- a/src/shared/install-printf.c
+++ b/src/shared/install-printf.c
@@ -25,6 +25,7 @@
 #include "unit-name.h"
 #include "util.h"
 #include "install-printf.h"
+#include "formats-util.h"
 
 static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) {
         InstallInfo *i = userdata;
diff --git a/src/shared/log.c b/src/shared/log.c
index 646a1d6..32ec581 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -34,6 +34,7 @@
 #include "missing.h"
 #include "macro.h"
 #include "socket-util.h"
+#include "formats-util.h"
 
 #define SNDBUF_SIZE (8*1024*1024)
 
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index 4e1b878..e179b8a 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -31,6 +31,7 @@
 #include "utf8.h"
 #include "hashmap.h"
 #include "journal-internal.h"
+#include "formats-util.h"
 
 /* up to three lines (each up to 100 characters),
    or 300 characters, whichever is less */
diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
index 4a6bf50..94a0663 100644
--- a/src/shared/socket-util.c
+++ b/src/shared/socket-util.c
@@ -35,6 +35,7 @@
 #include "socket-util.h"
 #include "missing.h"
 #include "fileio.h"
+#include "formats-util.h"
 
 int socket_address_parse(SocketAddress *a, const char *s) {
         char *e, *n;
diff --git a/src/shared/util.c b/src/shared/util.c
index df5f8d1..7321f1b 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -92,6 +92,7 @@
 #include "virt.h"
 #include "def.h"
 #include "sparse-endian.h"
+#include "formats-util.h"
 
 /* Put this test here for a lack of better place */
 assert_cc(EAGAIN == EWOULDBLOCK);
diff --git a/src/shared/util.h b/src/shared/util.h
index 56e11c7..d17b987 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -43,50 +43,10 @@
 #include <sys/inotify.h>
 #include <sys/statfs.h>
 
-#if SIZEOF_PID_T == 4
-#  define PID_PRI PRIi32
-#elif SIZEOF_PID_T == 2
-#  define PID_PRI PRIi16
-#else
-#  error Unknown pid_t size
-#endif
-#define PID_FMT "%" PID_PRI
-
-#if SIZEOF_UID_T == 4
-#  define UID_FMT "%" PRIu32
-#elif SIZEOF_UID_T == 2
-#  define UID_FMT "%" PRIu16
-#else
-#  error Unknown uid_t size
-#endif
-
-#if SIZEOF_GID_T == 4
-#  define GID_FMT "%" PRIu32
-#elif SIZEOF_GID_T == 2
-#  define GID_FMT "%" PRIu16
-#else
-#  error Unknown gid_t size
-#endif
-
-#if SIZEOF_TIME_T == 8
-#  define PRI_TIME PRIi64
-#elif SIZEOF_TIME_T == 4
-#  define PRI_TIME PRIu32
-#else
-#  error Unknown time_t size
-#endif
-
-#if SIZEOF_RLIM_T == 8
-#  define RLIM_FMT "%" PRIu64
-#elif SIZEOF_RLIM_T == 4
-#  define RLIM_FMT "%" PRIu32
-#else
-#  error Unknown rlim_t size
-#endif
-
 #include "macro.h"
 #include "missing.h"
 #include "time-util.h"
+#include "formats-util.h"
 
 /* What is interpreted as whitespace? */
 #define WHITESPACE " \t\n\r"
diff --git a/src/shutdownd/shutdownd.c b/src/shutdownd/shutdownd.c
index 6e4511e..a05cddc 100644
--- a/src/shutdownd/shutdownd.c
+++ b/src/shutdownd/shutdownd.c
@@ -35,6 +35,7 @@
 #include "utmp-wtmp.h"
 #include "mkdir.h"
 #include "fileio.h"
+#include "formats-util.h"
 
 union shutdown_buffer {
         struct sd_shutdown_command command;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 9cb351d..915482f 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -69,6 +69,7 @@
 #include "mkdir.h"
 #include "dropin.h"
 #include "efivars.h"
+#include "formats-util.h"
 
 static char **arg_types = NULL;
 static char **arg_states = NULL;
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index e549df6..cc4c7ef 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -38,6 +38,7 @@
 #include "fileio-label.h"
 #include "uid-range.h"
 #include "selinux-util.h"
+#include "formats-util.h"
 
 typedef enum ItemType {
         ADD_USER = 'u',
diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c
index 9834a6a..c0f4abe 100644
--- a/src/test/test-cgroup-util.c
+++ b/src/test/test-cgroup-util.c
@@ -23,6 +23,7 @@
 #include "util.h"
 #include "cgroup-util.h"
 #include "test-helper.h"
+#include "formats-util.h"
 
 static void check_p_d_u(const char *path, int code, const char *result) {
         _cleanup_free_ char *unit = NULL;
diff --git a/src/test/test-log.c b/src/test/test-log.c
index ca64004..9dcfa2f 100644
--- a/src/test/test-log.c
+++ b/src/test/test-log.c
@@ -24,6 +24,7 @@
 
 #include "log.h"
 #include "util.h"
+#include "formats-util.h"
 
 int main(int argc, char* argv[]) {
 
diff --git a/src/test/test-tmpfiles.c b/src/test/test-tmpfiles.c
index 90e49d4..221dd67 100644
--- a/src/test/test-tmpfiles.c
+++ b/src/test/test-tmpfiles.c
@@ -25,6 +25,7 @@
 #include <stdio.h>
 
 #include "util.h"
+#include "formats-util.h"
 
 int main(int argc, char** argv) {
         const char *p = argv[1] ?: "/tmp";
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index ad5f3f6..ef13dcb 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -56,6 +56,7 @@
 #include "selinux-util.h"
 #include "btrfs-util.h"
 #include "acl-util.h"
+#include "formats-util.h"
 
 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
  * them in the file system. This is intended to be used to create
diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c
index 61d3c5b..0f357ba 100644
--- a/src/udev/udev-ctrl.c
+++ b/src/udev/udev-ctrl.c
@@ -19,6 +19,7 @@
 #include <sys/un.h>
 
 #include "socket-util.h"
+#include "formats-util.h"
 #include "udev.h"
 
 /* wire protocol magic must match */
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 3a165b0..bda0638 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -32,6 +32,7 @@
 
 #include "udev.h"
 #include "rtnl-util.h"
+#include "formats-util.h"
 
 struct udev_event *udev_event_new(struct udev_device *dev) {
         struct udev *udev = udev_device_get_udev(dev);
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index debf9ea..d824172 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -28,6 +28,7 @@
 #include "udev.h"
 #include "smack-util.h"
 #include "selinux-util.h"
+#include "formats-util.h"
 
 static int node_symlink(struct udev_device *dev, const char *node, const char *slink) {
         struct stat stats;
diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c
index 7ef2e68..5e93955 100644
--- a/src/udev/udevadm-monitor.c
+++ b/src/udev/udevadm-monitor.c
@@ -27,6 +27,7 @@
 
 #include "udev.h"
 #include "udev-util.h"
+#include "formats-util.h"
 
 static bool udev_exit;
 
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 830aedd..a3f17c4 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -48,6 +48,7 @@
 #include "selinux-util.h"
 #include "udev.h"
 #include "udev-util.h"
+#include "formats-util.h"
 
 static struct udev_rules *rules;
 static struct udev_ctrl *udev_ctrl;
diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c
index 33535eb..ea9b0c9 100644
--- a/src/update-utmp/update-utmp.c
+++ b/src/update-utmp/update-utmp.c
@@ -37,6 +37,7 @@
 #include "bus-util.h"
 #include "bus-error.h"
 #include "unit-name.h"
+#include "formats-util.h"
 
 typedef struct Context {
         sd_bus *bus;



More information about the systemd-commits mailing list