chiark / gitweb /
dbus: automatically send out changed events for properties written to
[elogind.git] / src / shared / util.c
index 563853fad611337947878bee1e002566b0bb167a..0b4d4d6746ecda587c6a55cd0f45db36ae075352 100644 (file)
@@ -6,16 +6,16 @@
   Copyright 2010 Lennart Poettering
 
   systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
+  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
-  General Public License for more details.
+  Lesser General Public License for more details.
 
-  You should have received a copy of the GNU General Public License
+  You should have received a copy of the GNU Lesser General Public License
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
@@ -1591,74 +1591,6 @@ char *file_in_same_dir(const char *path, const char *filename) {
         return r;
 }
 
-int safe_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) {
-        struct stat st;
-
-        if (label_mkdir(path, mode) >= 0)
-                if (chmod_and_chown(path, mode, uid, gid) < 0)
-                        return -errno;
-
-        if (lstat(path, &st) < 0)
-                return -errno;
-
-        if ((st.st_mode & 0777) != mode ||
-            st.st_uid != uid ||
-            st.st_gid != gid ||
-            !S_ISDIR(st.st_mode)) {
-                errno = EEXIST;
-                return -errno;
-        }
-
-        return 0;
-}
-
-
-int mkdir_parents(const char *path, mode_t mode) {
-        const char *p, *e;
-
-        assert(path);
-
-        /* Creates every parent directory in the path except the last
-         * component. */
-
-        p = path + strspn(path, "/");
-        for (;;) {
-                int r;
-                char *t;
-
-                e = p + strcspn(p, "/");
-                p = e + strspn(e, "/");
-
-                /* Is this the last component? If so, then we're
-                 * done */
-                if (*p == 0)
-                        return 0;
-
-                if (!(t = strndup(path, e - path)))
-                        return -ENOMEM;
-
-                r = label_mkdir(t, mode);
-                free(t);
-
-                if (r < 0 && errno != EEXIST)
-                        return -errno;
-        }
-}
-
-int mkdir_p(const char *path, mode_t mode) {
-        int r;
-
-        /* Like mkdir -p */
-
-        if ((r = mkdir_parents(path, mode)) < 0)
-                return r;
-
-        if (label_mkdir(path, mode) < 0 && errno != EEXIST)
-                return -errno;
-
-        return 0;
-}
-
 int rmdir_parents(const char *path, const char *stop) {
         size_t l;
         int r = 0;
@@ -4344,24 +4276,6 @@ char *fstab_node_to_udev_node(const char *p) {
         return strdup(p);
 }
 
-void filter_environ(const char *prefix) {
-        int i, j;
-        assert(prefix);
-
-        if (!environ)
-                return;
-
-        for (i = 0, j = 0; environ[i]; i++) {
-
-                if (startswith(environ[i], prefix))
-                        continue;
-
-                environ[j++] = environ[i];
-        }
-
-        environ[j] = NULL;
-}
-
 bool tty_is_vc(const char *tty) {
         assert(tty);
 
@@ -6121,3 +6035,112 @@ int fd_inc_rcvbuf(int fd, size_t n) {
 
         return 1;
 }
+
+int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
+        pid_t parent_pid, agent_pid;
+        int fd;
+        bool stdout_is_tty, stderr_is_tty;
+        unsigned n, i;
+        va_list ap;
+        char **l;
+
+        assert(pid);
+        assert(path);
+
+        parent_pid = getpid();
+
+        /* Spawns a temporary TTY agent, making sure it goes away when
+         * we go away */
+
+        agent_pid = fork();
+        if (agent_pid < 0)
+                return -errno;
+
+        if (agent_pid != 0) {
+                *pid = agent_pid;
+                return 0;
+        }
+
+        /* In the child:
+         *
+         * Make sure the agent goes away when the parent dies */
+        if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
+                _exit(EXIT_FAILURE);
+
+        /* Check whether our parent died before we were able
+         * to set the death signal */
+        if (getppid() != parent_pid)
+                _exit(EXIT_SUCCESS);
+
+        /* Don't leak fds to the agent */
+        close_all_fds(except, n_except);
+
+        stdout_is_tty = isatty(STDOUT_FILENO);
+        stderr_is_tty = isatty(STDERR_FILENO);
+
+        if (!stdout_is_tty || !stderr_is_tty) {
+                /* Detach from stdout/stderr. and reopen
+                 * /dev/tty for them. This is important to
+                 * ensure that when systemctl is started via
+                 * popen() or a similar call that expects to
+                 * read EOF we actually do generate EOF and
+                 * not delay this indefinitely by because we
+                 * keep an unused copy of stdin around. */
+                fd = open("/dev/tty", O_WRONLY);
+                if (fd < 0) {
+                        log_error("Failed to open /dev/tty: %m");
+                        _exit(EXIT_FAILURE);
+                }
+
+                if (!stdout_is_tty)
+                        dup2(fd, STDOUT_FILENO);
+
+                if (!stderr_is_tty)
+                        dup2(fd, STDERR_FILENO);
+
+                if (fd > 2)
+                        close(fd);
+        }
+
+        /* Count arguments */
+        va_start(ap, path);
+        for (n = 0; va_arg(ap, char*); n++)
+                ;
+        va_end(ap);
+
+        /* Allocate strv */
+        l = alloca(sizeof(char *) * (n + 1));
+
+        /* Fill in arguments */
+        va_start(ap, path);
+        for (i = 0; i <= n; i++)
+                l[i] = va_arg(ap, char*);
+        va_end(ap);
+
+        execv(path, l);
+        _exit(EXIT_FAILURE);
+}
+
+int setrlimit_closest(int resource, const struct rlimit *rlim) {
+        struct rlimit highest, fixed;
+
+        assert(rlim);
+
+        if (setrlimit(resource, rlim) >= 0)
+                return 0;
+
+        if (errno != EPERM)
+                return -errno;
+
+        /* So we failed to set the desired setrlimit, then let's try
+         * to get as close as we can */
+        assert_se(getrlimit(resource, &highest) == 0);
+
+        fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
+        fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
+
+        if (setrlimit(resource, &fixed) < 0)
+                return -errno;
+
+        return 0;
+}