chiark / gitweb /
remove GTK pieces
[elogind.git] / src / util.c
index ce7f1c9f84052718e623c4d0cdddec9b618bb6b1..dfc1dc6b85a94a7dec0bf01cc2b74dfc08938c9f 100644 (file)
@@ -705,15 +705,22 @@ int read_one_line_file(const char *fn, char **line) {
         assert(fn);
         assert(line);
 
-        if (!(f = fopen(fn, "re")))
+        f = fopen(fn, "re");
+        if (!f)
                 return -errno;
 
-        if (!(fgets(t, sizeof(t), f))) {
-                r = feof(f) ? -EIO : -errno;
-                goto finish;
+        if (!fgets(t, sizeof(t), f)) {
+
+                if (ferror(f)) {
+                        r = -errno;
+                        goto finish;
+                }
+
+                t[0] = 0;
         }
 
-        if (!(c = strdup(t))) {
+        c = strdup(t);
+        if (!c) {
                 r = -ENOMEM;
                 goto finish;
         }
@@ -885,7 +892,7 @@ int load_env_file(
                 char ***rl) {
 
         FILE *f;
-        char **m = 0;
+        char **m = NULL;
         int r;
 
         assert(fname);
@@ -1826,7 +1833,8 @@ char *cunescape_length(const char *s, size_t length) {
 
         /* Undoes C style string escaping */
 
-        if (!(r = new(char, length+1)))
+        r = new(char, length+1);
+        if (!r)
                 return r;
 
         for (f = s, t = r; f < s + length; f++) {
@@ -1880,8 +1888,10 @@ char *cunescape_length(const char *s, size_t length) {
                         /* hexadecimal encoding */
                         int a, b;
 
-                        if ((a = unhexchar(f[1])) < 0 ||
-                            (b = unhexchar(f[2])) < 0) {
+                        a = unhexchar(f[1]);
+                        b = unhexchar(f[2]);
+
+                        if (a < 0 || b < 0) {
                                 /* Invalid escape code, let's take it literal then */
                                 *(t++) = '\\';
                                 *(t++) = 'x';
@@ -1904,9 +1914,11 @@ char *cunescape_length(const char *s, size_t length) {
                         /* octal encoding */
                         int a, b, c;
 
-                        if ((a = unoctchar(f[0])) < 0 ||
-                            (b = unoctchar(f[1])) < 0 ||
-                            (c = unoctchar(f[2])) < 0) {
+                        a = unoctchar(f[0]);
+                        b = unoctchar(f[1]);
+                        c = unoctchar(f[2]);
+
+                        if (a < 0 || b < 0 || c < 0) {
                                 /* Invalid escape code, let's take it literal then */
                                 *(t++) = '\\';
                                 *(t++) = f[0];
@@ -2195,13 +2207,47 @@ int fd_cloexec(int fd, bool cloexec) {
         return 0;
 }
 
+static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
+        unsigned i;
+
+        assert(n_fdset == 0 || fdset);
+
+        for (i = 0; i < n_fdset; i++)
+                if (fdset[i] == fd)
+                        return true;
+
+        return false;
+}
+
 int close_all_fds(const int except[], unsigned n_except) {
         DIR *d;
         struct dirent *de;
         int r = 0;
 
-        if (!(d = opendir("/proc/self/fd")))
-                return -errno;
+        assert(n_except == 0 || except);
+
+        d = opendir("/proc/self/fd");
+        if (!d) {
+                int fd;
+                struct rlimit rl;
+
+                /* When /proc isn't available (for example in chroots)
+                 * the fallback is brute forcing through the fd
+                 * table */
+
+                assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
+                for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
+
+                        if (fd_in_set(fd, except, n_except))
+                                continue;
+
+                        if (close_nointr(fd) < 0)
+                                if (errno != EBADF && r == 0)
+                                        r = -errno;
+                }
+
+                return r;
+        }
 
         while ((de = readdir(d))) {
                 int fd = -1;
@@ -2219,20 +2265,8 @@ int close_all_fds(const int except[], unsigned n_except) {
                 if (fd == dirfd(d))
                         continue;
 
-                if (except) {
-                        bool found;
-                        unsigned i;
-
-                        found = false;
-                        for (i = 0; i < n_except; i++)
-                                if (except[i] == fd) {
-                                        found = true;
-                                        break;
-                                }
-
-                        if (found)
-                                continue;
-                }
+                if (fd_in_set(fd, except, n_except))
+                        continue;
 
                 if (close_nointr(fd) < 0) {
                         /* Valgrind has its own FD and doesn't want to have it closed */
@@ -3263,11 +3297,15 @@ fallback:
 void rename_process(const char name[8]) {
         assert(name);
 
-        prctl(PR_SET_NAME, name);
+        /* This is a like a poor man's setproctitle(). It changes the
+         * comm field, argv[0], and also the glibc's internally used
+         * name of the process. For the first one a limit of 16 chars
+         * applies, to the second one usually one of 10 (i.e. length
+         * of "/sbin/init"), to the third one one of 7 (i.e. length of
+         * "systemd"). If you pass a longer string it will be
+         * truncated */
 
-        /* This is a like a poor man's setproctitle(). The string
-         * passed should fit in 7 chars (i.e. the length of
-         * "systemd") */
+        prctl(PR_SET_NAME, name);
 
         if (program_invocation_name)
                 strncpy(program_invocation_name, name, strlen(program_invocation_name));
@@ -3555,7 +3593,8 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) {
                 if (is_dir) {
                         int subdir_fd;
 
-                        if ((subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)) < 0) {
+                        subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
+                        if (subdir_fd < 0) {
                                 if (ret == 0 && errno != ENOENT)
                                         ret = -errno;
                                 continue;
@@ -3777,139 +3816,6 @@ void status_welcome(void) {
                         log_warning("Failed to read /etc/os-release: %s", strerror(-r));
         }
 
-#if defined(TARGET_FEDORA)
-        if (!pretty_name) {
-                if ((r = read_one_line_file("/etc/system-release", &pretty_name)) < 0) {
-
-                        if (r != -ENOENT)
-                                log_warning("Failed to read /etc/system-release: %s", strerror(-r));
-                }
-        }
-
-        if (!ansi_color && pretty_name) {
-
-                /* This tries to mimic the color magic the old Red Hat sysinit
-                 * script did. */
-
-                if (startswith(pretty_name, "Red Hat"))
-                        const_color = "0;31"; /* Red for RHEL */
-                else if (startswith(pretty_name, "Fedora"))
-                        const_color = "0;34"; /* Blue for Fedora */
-        }
-
-#elif defined(TARGET_SUSE)
-
-        if (!pretty_name) {
-                if ((r = read_one_line_file("/etc/SuSE-release", &pretty_name)) < 0) {
-
-                        if (r != -ENOENT)
-                                log_warning("Failed to read /etc/SuSE-release: %s", strerror(-r));
-                }
-        }
-
-        if (!ansi_color)
-                const_color = "0;32"; /* Green for openSUSE */
-
-#elif defined(TARGET_GENTOO)
-
-        if (!pretty_name) {
-                if ((r = read_one_line_file("/etc/gentoo-release", &pretty_name)) < 0) {
-
-                        if (r != -ENOENT)
-                                log_warning("Failed to read /etc/gentoo-release: %s", strerror(-r));
-                }
-        }
-
-        if (!ansi_color)
-                const_color = "1;34"; /* Light Blue for Gentoo */
-
-#elif defined(TARGET_ALTLINUX)
-
-        if (!pretty_name) {
-                if ((r = read_one_line_file("/etc/altlinux-release", &pretty_name)) < 0) {
-
-                        if (r != -ENOENT)
-                                log_warning("Failed to read /etc/altlinux-release: %s", strerror(-r));
-                }
-        }
-
-        if (!ansi_color)
-                const_color = "0;36"; /* Cyan for ALTLinux */
-
-
-#elif defined(TARGET_DEBIAN)
-
-        if (!pretty_name) {
-                char *version;
-
-                if ((r = read_one_line_file("/etc/debian_version", &version)) < 0) {
-
-                        if (r != -ENOENT)
-                                log_warning("Failed to read /etc/debian_version: %s", strerror(-r));
-                } else {
-                        pretty_name = strappend("Debian ", version);
-                        free(version);
-
-                        if (!pretty_name)
-                                log_warning("Failed to allocate Debian version string.");
-                }
-        }
-
-        if (!ansi_color)
-                const_color = "1;31"; /* Light Red for Debian */
-
-#elif defined(TARGET_UBUNTU)
-
-        if ((r = parse_env_file("/etc/lsb-release", NEWLINE,
-                                "DISTRIB_DESCRIPTION", &pretty_name,
-                                NULL)) < 0) {
-
-                if (r != -ENOENT)
-                        log_warning("Failed to read /etc/lsb-release: %s", strerror(-r));
-        }
-
-        if (!ansi_color)
-                const_color = "0;33"; /* Orange/Brown for Ubuntu */
-
-#elif defined(TARGET_MANDRIVA)
-
-        if (!pretty_name) {
-                char *s, *p;
-
-                if ((r = read_one_line_file("/etc/mandriva-release", &s) < 0)) {
-                        if (r != -ENOENT)
-                                log_warning("Failed to read /etc/mandriva-release: %s", strerror(-r));
-                } else {
-                        p = strstr(s, " release ");
-                        if (p) {
-                                *p = '\0';
-                                p += 9;
-                                p[strcspn(p, " ")] = '\0';
-
-                                /* This corresponds to standard rc.sysinit */
-                                if (asprintf(&pretty_name, "%s\x1B[0;39m %s", s, p) > 0)
-                                        const_color = "1;36";
-                                else
-                                        log_warning("Failed to allocate Mandriva version string.");
-                        } else
-                                log_warning("Failed to parse /etc/mandriva-release");
-                        free(s);
-                }
-        }
-#elif defined(TARGET_MEEGO)
-
-        if (!pretty_name) {
-                if ((r = read_one_line_file("/etc/meego-release", &pretty_name)) < 0) {
-
-                        if (r != -ENOENT)
-                                log_warning("Failed to read /etc/meego-release: %s", strerror(-r));
-                }
-        }
-
-       if (!ansi_color)
-               const_color = "1;35"; /* Bright Magenta for MeeGo */
-#endif
-
         if (!pretty_name && !const_pretty)
                 const_pretty = "Linux";
 
@@ -4299,7 +4205,7 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid) {
 
 }
 
-void freeze(void) {
+_noreturn_ void freeze(void) {
 
         /* Make sure nobody waits for us on a socket anymore */
         close_all_fds(NULL, 0);
@@ -4619,11 +4525,12 @@ void execute_directory(const char *directory, DIR *d, char *argv[]) {
         }
 
         while (!hashmap_isempty(pids)) {
+                pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
                 siginfo_t si;
                 char *path;
 
                 zero(si);
-                if (waitid(P_ALL, 0, &si, WEXITED) < 0) {
+                if (waitid(P_PID, pid, &si, WEXITED) < 0) {
 
                         if (errno == EINTR)
                                 continue;
@@ -5702,6 +5609,36 @@ int get_group_creds(const char **groupname, gid_t *gid) {
         return 0;
 }
 
+int in_group(const char *name) {
+        gid_t gid, *gids;
+        int ngroups_max, r, i;
+
+        r = get_group_creds(&name, &gid);
+        if (r < 0)
+                return r;
+
+        if (getgid() == gid)
+                return 1;
+
+        if (getegid() == gid)
+                return 1;
+
+        ngroups_max = sysconf(_SC_NGROUPS_MAX);
+        assert(ngroups_max > 0);
+
+        gids = alloca(sizeof(gid_t) * ngroups_max);
+
+        r = getgroups(ngroups_max, gids);
+        if (r < 0)
+                return -errno;
+
+        for (i = 0; i < r; i++)
+                if (gids[i] == gid)
+                        return 1;
+
+        return 0;
+}
+
 int glob_exists(const char *path) {
         glob_t g;
         int r, k;