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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -79,6 +79,18 @@
|
|||||||
# define winsize ttysize
|
# define winsize ttysize
|
||||||
#endif
|
#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 {
|
||||||
struct io_buffer *next;
|
struct io_buffer *next;
|
||||||
int len; /* buffer length (how much produced) */
|
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]);
|
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. */
|
/* Start out in raw mode if we are not part of a pipeline. */
|
||||||
if (!pipeline) {
|
if (!pipeline) {
|
||||||
ttymode = TERM_RAW;
|
ttymode = TERM_RAW;
|
||||||
@@ -668,6 +681,7 @@ fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask)
|
|||||||
if (!n)
|
if (!n)
|
||||||
error(1, _("unable to set terminal to raw mode"));
|
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])
|
if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE])
|
||||||
close(io_fds[SFD_STDERR]);
|
close(io_fds[SFD_STDERR]);
|
||||||
|
|
||||||
/*
|
/* Put command in its own process group. */
|
||||||
* Put command in its own process group. If we are starting the command
|
|
||||||
* in the foreground, assign its pgrp to the tty.
|
|
||||||
*/
|
|
||||||
cmnd_pgrp = cmnd_pid;
|
cmnd_pgrp = cmnd_pid;
|
||||||
setpgid(cmnd_pid, cmnd_pgrp);
|
setpgid(cmnd_pid, cmnd_pgrp);
|
||||||
|
#ifdef TCSETATTR_NO_RESTART
|
||||||
|
/* Make the command the foreground process for the pty slave. */
|
||||||
if (foreground) {
|
if (foreground) {
|
||||||
do {
|
do {
|
||||||
n = tcsetpgrp(io_fds[SFD_SLAVE], cmnd_pgrp);
|
n = tcsetpgrp(io_fds[SFD_SLAVE], cmnd_pgrp);
|
||||||
} while (n == -1 && errno == EINTR);
|
} while (n == -1 && errno == EINTR);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Wait for errno on pipe, signal on backchannel or for SIGCHLD */
|
/* Wait for errno on pipe, signal on backchannel or for SIGCHLD */
|
||||||
maxfd = MAX(MAX(errpipe[0], signal_pipe[0]), backchannel);
|
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)
|
dup2(io_fds[SFD_STDERR], STDERR_FILENO) == -1)
|
||||||
error(1, "dup2");
|
error(1, "dup2");
|
||||||
|
|
||||||
|
#ifdef TCSETATTR_NO_RESTART
|
||||||
/* Wait for parent to grant us the tty if we are foreground. */
|
/* Wait for parent to grant us the tty if we are foreground. */
|
||||||
if (foreground) {
|
if (foreground) {
|
||||||
while (tcgetpgrp(io_fds[SFD_SLAVE]) != self)
|
while (tcgetpgrp(io_fds[SFD_SLAVE]) != self)
|
||||||
; /* spin */
|
; /* spin */
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* We have guaranteed that the slave fd is > 2 */
|
/* We have guaranteed that the slave fd is > 2 */
|
||||||
if (io_fds[SFD_SLAVE] != -1)
|
if (io_fds[SFD_SLAVE] != -1)
|
||||||
|
Reference in New Issue
Block a user