diff --git a/src/basic/process-util.c b/src/basic/process-util.c index a78e8141b4..e325820584 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1514,82 +1514,6 @@ int namespace_fork( return 1; } -int fork_agent(const char *name, int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) { - bool stdout_is_tty, stderr_is_tty; - size_t n, i; - va_list ap; - char **l; - int r; - - assert(path); - - /* Spawns a temporary TTY agent, making sure it goes away when we go away */ - - r = safe_fork_full(name, - except, - n_except, - FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG, - ret_pid); - if (r < 0) - return r; - if (r > 0) - return 0; - - /* In the child: */ - - stdout_is_tty = isatty(STDOUT_FILENO); - stderr_is_tty = isatty(STDERR_FILENO); - - if (!stdout_is_tty || !stderr_is_tty) { - int fd; - - /* 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_errno(errno, "Failed to open /dev/tty: %m"); - _exit(EXIT_FAILURE); - } - - if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) { - log_error_errno(errno, "Failed to dup2 /dev/tty: %m"); - _exit(EXIT_FAILURE); - } - - if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) { - log_error_errno(errno, "Failed to dup2 /dev/tty: %m"); - _exit(EXIT_FAILURE); - } - - safe_close_above_stdio(fd); - } - - (void) rlimit_nofile_safe(); - - /* Count arguments */ - va_start(ap, path); - for (n = 0; va_arg(ap, char*); n++) - ; - va_end(ap); - - /* Allocate strv */ - l = newa(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 set_oom_score_adjust(int value) { char t[DECIMAL_STR_MAX(int)]; diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 58a3ebd577..b130c5ae02 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -174,8 +174,6 @@ static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) { int namespace_fork(const char *outer_name, const char *inner_name, int except_fds[], size_t n_except_fds, ForkFlags flags, int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd, pid_t *ret_pid); -int fork_agent(const char *name, int except[], size_t n_except, pid_t *pid, const char *path, ...) _sentinel_; - int set_oom_score_adjust(int value); /* The highest possibly (theoretic) pid_t value on this architecture. */ diff --git a/src/shared/exec-util.c b/src/shared/exec-util.c index 031ca4cb4c..68e896a8fa 100644 --- a/src/shared/exec-util.c +++ b/src/shared/exec-util.c @@ -470,3 +470,76 @@ int fexecve_or_execve(int executable_fd, const char *executable, char *const arg execve(executable, argv, envp); return -errno; } + +int fork_agent(const char *name, int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) { + bool stdout_is_tty, stderr_is_tty; + size_t n, i; + va_list ap; + char **l; + int r; + + assert(path); + + /* Spawns a temporary TTY agent, making sure it goes away when we go away */ + + r = safe_fork_full(name, + except, + n_except, + FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG, + ret_pid); + if (r < 0) + return r; + if (r > 0) + return 0; + + /* In the child: */ + + stdout_is_tty = isatty(STDOUT_FILENO); + stderr_is_tty = isatty(STDERR_FILENO); + + if (!stdout_is_tty || !stderr_is_tty) { + int fd; + + /* 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 keeping an unused copy of + * stdin around. */ + fd = open("/dev/tty", O_WRONLY); + if (fd < 0) { + log_error_errno(errno, "Failed to open /dev/tty: %m"); + _exit(EXIT_FAILURE); + } + + if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) { + log_error_errno(errno, "Failed to dup2 /dev/tty: %m"); + _exit(EXIT_FAILURE); + } + + if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) { + log_error_errno(errno, "Failed to dup2 /dev/tty: %m"); + _exit(EXIT_FAILURE); + } + + safe_close_above_stdio(fd); + } + + (void) rlimit_nofile_safe(); + + /* Count arguments */ + va_start(ap, path); + for (n = 0; va_arg(ap, char*); n++) + ; + va_end(ap); + + /* Allocate strv */ + l = newa(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); +} diff --git a/src/shared/exec-util.h b/src/shared/exec-util.h index 9ce5324de9..21d28608f9 100644 --- a/src/shared/exec-util.h +++ b/src/shared/exec-util.h @@ -48,3 +48,5 @@ const char* exec_command_flags_to_string(ExecCommandFlags i); ExecCommandFlags exec_command_flags_from_string(const char *s); int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]); + +int fork_agent(const char *name, int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) _sentinel_; diff --git a/src/shared/spawn-ask-password-agent.c b/src/shared/spawn-ask-password-agent.c index 1f07b198fa..38fab21203 100644 --- a/src/shared/spawn-ask-password-agent.c +++ b/src/shared/spawn-ask-password-agent.c @@ -4,6 +4,7 @@ #include #include +#include "exec-util.h" #include "log.h" #include "process-util.h" #include "spawn-ask-password-agent.h" diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c index a0024eb2ea..cd0b4601da 100644 --- a/src/shared/spawn-polkit-agent.c +++ b/src/shared/spawn-polkit-agent.c @@ -6,6 +6,7 @@ #include #include +#include "exec-util.h" #include "fd-util.h" #include "io-util.h" #include "log.h"