chiark / gitweb /
shared: add formats-util.h
authorRonny Chevalier <chevalier.ronny@gmail.com>
Fri, 10 Apr 2015 18:43:52 +0000 (20:43 +0200)
committerSven Eden <yamakuzure@gmx.net>
Tue, 14 Mar 2017 07:02:36 +0000 (08:02 +0100)
31 files changed:
src/libelogind/sd-bus/bus-creds.c
src/libelogind/sd-bus/bus-dump.c
src/libelogind/sd-bus/bus-kernel.c
src/libelogind/sd-bus/bus-socket.c
src/libelogind/sd-bus/test-bus-chat.c
src/libelogind/sd-login/sd-login.c
src/libelogind/sd-login/test-login.c
src/libelogind/sd-rtnl/rtnl-message.c
src/login/inhibit.c
src/login/logind-acl.c
src/login/logind-action.c
src/login/logind-dbus.c
src/login/logind-inhibit.c
src/login/logind-seat.c
src/login/logind-session.c
src/login/logind-user-dbus.c
src/login/logind-user.c
src/login/logind.c
src/login/pam_elogind.c
src/shared/ask-password-api.c
src/shared/cgroup-show.c
src/shared/cgroup-util.c
src/shared/clean-ipc.c
src/shared/formats-util.h [new file with mode: 0644]
src/shared/install-printf.c
src/shared/log.c
src/shared/logs-show.c
src/shared/mkdir-label.c
src/shared/socket-util.c
src/shared/util.c
src/shared/util.h

index 603bc73..39cbdba 100644 (file)
@@ -24,7 +24,6 @@
 
 #include "util.h"
 #include "formats-util.h"
-#include "process-util.h"
 #include "capability.h"
 #include "cgroup-util.h"
 #include "fileio.h"
index 4bc8965..d722680 100644 (file)
@@ -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"
index 35c2aa6..0062e66 100644 (file)
@@ -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"
index 873aede..f97e15d 100644 (file)
@@ -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"
index 7f49fe9..ab2ec27 100644 (file)
@@ -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"
index c548991..5cc6d69 100644 (file)
@@ -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) {
index 2802e82..05affa4 100644 (file)
@@ -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 };
index c938471..4f994a1 100644 (file)
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include "util.h"
+#include "formats-util.h"
 #include "refcnt.h"
 #include "missing.h"
 
index 57cfb5d..1f78e4b 100644 (file)
@@ -32,7 +32,6 @@
 #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;
index d2b3337..466225d 100644 (file)
@@ -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"
index c83d51d..61dddae 100644 (file)
@@ -36,7 +36,6 @@
 #include "bus-util.h"
 #include "logind-action.h"
 #include "formats-util.h"
-#include "process-util.h"
 
 int manager_handle_action(
                 Manager *m,
index 7245ee7..39b552e 100644 (file)
@@ -41,7 +41,6 @@
 #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;
index 5eb1a2e..68304a1 100644 (file)
@@ -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;
index ead6498..e208112 100644 (file)
@@ -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;
index f03c2e5..f1c08c0 100644 (file)
@@ -39,6 +39,7 @@
 #include "cgroup-util.h"
 #include "def.h"
 #include "logind-session.h"
+#include "formats-util.h"
 
 static void session_remove_fifo(Session *s);
 
index f7af8ff..03c3370 100644 (file)
@@ -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,
index 1f6ffff..3e1c75e 100644 (file)
@@ -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;
index 8e8fe19..534f783 100644 (file)
@@ -34,6 +34,7 @@
 #include "bus-error.h"
 #include "logind.h"
 #include "udev-util.h"
+#include "formats-util.h"
 
 Manager *manager_new(void) {
         Manager *m;
index b0bc471..226d380 100644 (file)
@@ -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,
index 44ebc58..dfc89d2 100644 (file)
@@ -32,6 +32,7 @@
 #include <sys/signalfd.h>
 
 #include "util.h"
+#include "formats-util.h"
 #include "mkdir.h"
 #include "strv.h"
 
index 0f263e9..fed72ac 100644 (file)
@@ -26,7 +26,6 @@
 
 #include "util.h"
 #include "formats-util.h"
-#include "process-util.h"
 #include "macro.h"
 #include "path-util.h"
 #include "cgroup-util.h"
index 63166a3..c746d60 100644 (file)
@@ -34,7 +34,6 @@
 #include "macro.h"
 #include "util.h"
 #include "formats-util.h"
-#include "process-util.h"
 #include "path-util.h"
 #include "fileio.h"
 #include "special.h"
index ea781f5..48b1086 100644 (file)
@@ -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 (file)
index 0000000..ce516b1
--- /dev/null
@@ -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
index f62a032..9996649 100644 (file)
@@ -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;
index 7edcf1f..32ec581 100644 (file)
@@ -35,7 +35,6 @@
 #include "macro.h"
 #include "socket-util.h"
 #include "formats-util.h"
-#include "process-util.h"
 
 #define SNDBUF_SIZE (8*1024*1024)
 
index 7a7a1e9..e179b8a 100644 (file)
@@ -32,7 +32,6 @@
 #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 */
index 76bbc1e..221dd67 100644 (file)
@@ -3,8 +3,7 @@
 /***
   This file is part of systemd.
 
-  Copyright 2010 Lennart Poettering
-  Copyright 2013 Kay Sievers
+  Copyright 2014 Zbigniew JÄ™drzejewski-Szmek
 
   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
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <fcntl.h>
 #include <unistd.h>
+#include <stdlib.h>
 #include <stdio.h>
 
-#include "label.h"
-#include "mkdir.h"
+#include "util.h"
+#include "formats-util.h"
 
-int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid) {
-        return mkdir_safe_internal(path, mode, uid, gid, mkdir_label);
-}
+int main(int argc, char** argv) {
+        const char *p = argv[1] ?: "/tmp";
+        char *pattern = strjoina(p, "/systemd-test-XXXXXX");
+        _cleanup_close_ int fd, fd2;
+        _cleanup_free_ char *cmd, *cmd2;
 
-int mkdir_parents_label(const char *path, mode_t mode) {
-        return mkdir_parents_internal(NULL, path, mode, mkdir_label);
-}
+        fd = open_tmpfile(p, O_RDWR|O_CLOEXEC);
+        assert_se(fd >= 0);
+
+        assert_se(asprintf(&cmd, "ls -l /proc/"PID_FMT"/fd/%d", getpid(), fd) > 0);
+        system(cmd);
+
+        fd2 = mkostemp_safe(pattern, O_RDWR|O_CLOEXEC);
+        assert_se(fd >= 0);
+        assert_se(unlink(pattern) == 0);
+
+        assert_se(asprintf(&cmd2, "ls -l /proc/"PID_FMT"/fd/%d", getpid(), fd2) > 0);
+        system(cmd2);
 
-int mkdir_p_label(const char *path, mode_t mode) {
-        return mkdir_p_internal(NULL, path, mode, mkdir_label);
+        return 0;
 }
index 4a6bf50..94a0663 100644 (file)
@@ -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;
index 863371c..b1f4e30 100644 (file)
@@ -93,7 +93,6 @@
 #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);
@@ -186,7 +185,7 @@ char* first_word(const char *s, const char *word) {
         return (char*) p;
 }
 
-size_t cescape_char(char c, char *buf) {
+static size_t cescape_char(char c, char *buf) {
         char * buf_old = buf;
 
         switch (c) {
@@ -599,6 +598,49 @@ 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;
@@ -617,6 +659,308 @@ 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;
@@ -3332,6 +3676,73 @@ 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 */
@@ -3708,6 +4119,17 @@ 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;
 
@@ -4916,6 +5338,60 @@ 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;
@@ -6021,6 +6497,33 @@ 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;
index 9271578..f9f96ce 100644 (file)
 #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"