From 592f6fefb0282e0519e05fb03075c808e3b44fc1 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 25 Sep 2012 13:49:51 -0400 Subject: [PATCH] Start commands in the background when I/O logging is enabled. We can't do this on Mac OS X due to a kernel bug in tc[gs]etattr(2) which returns EINTR on signal instead of restarting automatically. --- src/exec_pty.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/exec_pty.c b/src/exec_pty.c index ddfd67be7..30b4ea044 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2011 Todd C. Miller + * Copyright (c) 2009-2012 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -79,6 +79,18 @@ # define winsize ttysize #endif +/* + * Mac OS X has a bug wrt tc[gs]etpgrp where it returns EINTR if interrupted + * by a signal (usually SIGTTOU or SIGTTIN) instead of being restarted + * automatically (via ERESTART in the kernel). On other systems we can start + * the command in the background which prevents sudo from stealing /dev/tty + * input when it doesn't need to. When the command receives SIGTTOU or SIGTTIN, + * sudo will continue it in the foreground (assuming sudo is in the foreground). + */ +#ifdef __APPLE__ +# define TCSETATTR_NO_RESTART +#endif + struct io_buffer { struct io_buffer *next; int len; /* buffer length (how much produced) */ @@ -659,6 +671,7 @@ fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask) sync_ttysize(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE]); } +#ifdef TCSETATTR_NO_RESTART /* Start out in raw mode if we are not part of a pipeline. */ if (!pipeline) { ttymode = TERM_RAW; @@ -668,6 +681,7 @@ fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask) if (!n) error(1, _("unable to set terminal to raw mode")); } +#endif } /* @@ -1089,17 +1103,17 @@ exec_monitor(struct command_details *details, int backchannel) if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE]) close(io_fds[SFD_STDERR]); - /* - * Put command in its own process group. If we are starting the command - * in the foreground, assign its pgrp to the tty. - */ + /* Put command in its own process group. */ cmnd_pgrp = cmnd_pid; setpgid(cmnd_pid, cmnd_pgrp); +#ifdef TCSETATTR_NO_RESTART + /* Make the command the foreground process for the pty slave. */ if (foreground) { do { n = tcsetpgrp(io_fds[SFD_SLAVE], cmnd_pgrp); } while (n == -1 && errno == EINTR); } +#endif /* Wait for errno on pipe, signal on backchannel or for SIGCHLD */ maxfd = MAX(MAX(errpipe[0], signal_pipe[0]), backchannel); @@ -1289,11 +1303,13 @@ exec_pty(struct command_details *details, int *errfd) dup2(io_fds[SFD_STDERR], STDERR_FILENO) == -1) error(1, "dup2"); +#ifdef TCSETATTR_NO_RESTART /* Wait for parent to grant us the tty if we are foreground. */ if (foreground) { while (tcgetpgrp(io_fds[SFD_SLAVE]) != self) ; /* spin */ } +#endif /* We have guaranteed that the slave fd is > 2 */ if (io_fds[SFD_SLAVE] != -1) -- 2.40.0