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.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* Copyright (c) 2009-2012 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* 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)
|
||||
|
Reference in New Issue
Block a user