X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fsystemctl.c;h=dfa952ed46d5a31bbdd9af3861266ff7457c2eb3;hp=8cdc01aa49566f2bf5275f1fc49e6fdb74e223ba;hb=7fc01d33196f329c24766795b7af66e598c3e65b;hpb=bd40a2d830265cdd36eb19576bdbe8e41dd527ee diff --git a/src/systemctl.c b/src/systemctl.c index 8cdc01aa4..dfa952ed4 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -121,7 +121,7 @@ static bool on_tty(void) { /* Note that this is invoked relatively early, before we start * the pager. That means the value we return reflects whether * we originally were started on a tty, not if we currently - * are. But this is intended, since we want color, and so on + * are. But this is intended, since we want colour and so on * when run in our own pager. */ if (_unlikely_(t < 0)) @@ -141,6 +141,9 @@ static void spawn_ask_password_agent(void) { if (!arg_ask_password) return; + if (arg_user) + return; + parent = getpid(); /* Spawns a temporary TTY agent, making sure it goes away when @@ -151,13 +154,16 @@ static void spawn_ask_password_agent(void) { if (child == 0) { /* In the child */ - const char * const args[] = { SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, "--watch", NULL }; + int fd; + bool stdout_is_tty, stderr_is_tty; + + /* Make sure the agent goes away when the parent dies */ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) _exit(EXIT_FAILURE); @@ -166,6 +172,35 @@ static void spawn_ask_password_agent(void) { if (getppid() != parent) _exit(EXIT_SUCCESS); + /* Don't leak fds to the agent */ + close_all_fds(NULL, 0); + + 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. */ + if ((fd = open("/dev/tty", O_WRONLY)) < 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); + } + execv(args[0], (char **) args); _exit(EXIT_FAILURE); }