chiark / gitweb /
logind: fix introspection typo
[elogind.git] / src / util.c
index a0c04e3204f81b259e4f84d0884338c6c30645be..a0fbdc517e7167a7f85cfe4ecccdfb9afa22175f 100644 (file)
@@ -53,6 +53,7 @@
 #include <sys/capability.h>
 #include <sys/time.h>
 #include <linux/rtc.h>
+#include <glob.h>
 
 #include "macro.h"
 #include "util.h"
@@ -64,6 +65,9 @@
 #include "exit-status.h"
 #include "hashmap.h"
 
+int saved_argc = 0;
+char **saved_argv = NULL;
+
 size_t page_size(void) {
         static __thread size_t pgsz = 0;
         long r;
@@ -487,7 +491,7 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
         assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
         char_array_0(fn);
 
-        if (!(f = fopen(fn, "r")))
+        if (!(f = fopen(fn, "re")))
                 return -errno;
 
         if (!(fgets(line, sizeof(line), f))) {
@@ -532,7 +536,7 @@ int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
         assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
         char_array_0(fn);
 
-        if (!(f = fopen(fn, "r")))
+        if (!(f = fopen(fn, "re")))
                 return -errno;
 
         if (!(fgets(line, sizeof(line), f))) {
@@ -1007,7 +1011,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, char **line) {
         if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
                 return -ENOMEM;
 
-        f = fopen(p, "r");
+        f = fopen(p, "re");
         free(p);
 
         if (!f)
@@ -2653,7 +2657,7 @@ int release_terminal(void) {
         int r = 0, fd;
         struct sigaction sa_old, sa_new;
 
-        if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY)) < 0)
+        if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC)) < 0)
                 return -errno;
 
         /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
@@ -2944,6 +2948,10 @@ int make_stdio(int fd) {
         if (r < 0 || s < 0 || t < 0)
                 return -errno;
 
+        fd_cloexec(STDIN_FILENO, false);
+        fd_cloexec(STDOUT_FILENO, false);
+        fd_cloexec(STDERR_FILENO, false);
+
         return 0;
 }
 
@@ -3026,6 +3034,20 @@ void rename_process(const char name[8]) {
 
         if (program_invocation_name)
                 strncpy(program_invocation_name, name, strlen(program_invocation_name));
+
+        if (saved_argc > 0) {
+                int i;
+
+                if (saved_argv[0])
+                        strncpy(saved_argv[0], name, strlen(saved_argv[0]));
+
+                for (i = 1; i < saved_argc; i++) {
+                        if (!saved_argv[i])
+                                break;
+
+                        memset(saved_argv[i], 0, strlen(saved_argv[i]));
+                }
+        }
 }
 
 void sigset_add_many(sigset_t *ss, ...) {
@@ -3844,8 +3866,12 @@ char *normalize_env_assignment(const char *s) {
 }
 
 int wait_for_terminate(pid_t pid, siginfo_t *status) {
+        siginfo_t dummy;
+
         assert(pid >= 1);
-        assert(status);
+
+        if (!status)
+                status = &dummy;
 
         for (;;) {
                 zero(*status);
@@ -4255,7 +4281,7 @@ int detect_container(const char **id) {
                 return 1;
         }
 
-        if ((f = fopen("/proc/self/cgroup", "r"))) {
+        if ((f = fopen("/proc/self/cgroup", "re"))) {
 
                 for (;;) {
                         char line[LINE_MAX], *p;
@@ -5171,6 +5197,76 @@ int socket_from_display(const char *display, char **path) {
         return 0;
 }
 
+int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home) {
+        struct passwd *p;
+        unsigned long lu;
+
+        assert(username);
+        assert(*username);
+        assert(uid);
+        assert(gid);
+        assert(home);
+
+        /* We enforce some special rules for uid=0: in order to avoid
+         * NSS lookups for root we hardcode its data. */
+
+        if (streq(*username, "root") || streq(*username, "0")) {
+                *username = "root";
+                *uid = 0;
+                *gid = 0;
+                *home = "/root";
+                return 0;
+        }
+
+        if (safe_atolu(*username, &lu) >= 0) {
+                errno = 0;
+                p = getpwuid((uid_t) lu);
+
+                /* If there are multiple users with the same id, make
+                 * sure to leave $USER to the configured value instead
+                 * of the first occurrence in the database. However if
+                 * the uid was configured by a numeric uid, then let's
+                 * pick the real username from /etc/passwd. */
+                if (p)
+                        *username = p->pw_name;
+        } else {
+                errno = 0;
+                p = getpwnam(*username);
+        }
+
+        if (!p)
+                return errno != 0 ? -errno : -ESRCH;
+
+        *uid = p->pw_uid;
+        *gid = p->pw_gid;
+        *home = p->pw_dir;
+        return 0;
+}
+
+int glob_exists(const char *path) {
+        glob_t g;
+        int r, k;
+
+        assert(path);
+
+        zero(g);
+        errno = 0;
+        k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
+
+        if (k == GLOB_NOMATCH)
+                r = 0;
+        else if (k == GLOB_NOSPACE)
+                r = -ENOMEM;
+        else if (k == 0)
+                r = !strv_isempty(g.gl_pathv);
+        else
+                r = errno ? -errno : -EIO;
+
+        globfree(&g);
+
+        return r;
+}
+
 static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_NONE] = "none",
         [IOPRIO_CLASS_RT] = "realtime",