No need to use pseudo-cbreak mode now that we use pipes when stdout is
not a tty. Instead, check whether stdin is a tty and if not, delay setting the tty to raw mode until the command tries to access it itself (and receives SIGTTIN or SIGTTOU).
This commit is contained in:
@@ -150,7 +150,7 @@ static int stack_top;
|
|||||||
|
|
||||||
extern time_t get_date(char *);
|
extern time_t get_date(char *);
|
||||||
extern char *get_timestr(time_t, int);
|
extern char *get_timestr(time_t, int);
|
||||||
extern int term_raw(int, int, int);
|
extern int term_raw(int, int);
|
||||||
extern int term_restore(int, int);
|
extern int term_restore(int, int);
|
||||||
extern void zero_bytes(volatile void *, size_t);
|
extern void zero_bytes(volatile void *, size_t);
|
||||||
void cleanup(int);
|
void cleanup(int);
|
||||||
@@ -297,7 +297,7 @@ main(int argc, char *argv[])
|
|||||||
ch = fcntl(STDIN_FILENO, F_GETFL, 0);
|
ch = fcntl(STDIN_FILENO, F_GETFL, 0);
|
||||||
if (ch != -1)
|
if (ch != -1)
|
||||||
(void) fcntl(STDIN_FILENO, F_SETFL, ch | O_NONBLOCK);
|
(void) fcntl(STDIN_FILENO, F_SETFL, ch | O_NONBLOCK);
|
||||||
if (!term_raw(STDIN_FILENO, 0, 1))
|
if (!term_raw(STDIN_FILENO, 1))
|
||||||
error(1, "cannot set tty to raw mode");
|
error(1, "cannot set tty to raw mode");
|
||||||
}
|
}
|
||||||
fdsr = (fd_set *)emalloc2(howmany(STDOUT_FILENO + 1, NFDBITS),
|
fdsr = (fd_set *)emalloc2(howmany(STDOUT_FILENO + 1, NFDBITS),
|
||||||
|
42
src/script.c
42
src/script.c
@@ -87,8 +87,7 @@
|
|||||||
#define SFD_USERTTY 5
|
#define SFD_USERTTY 5
|
||||||
|
|
||||||
#define TERM_COOKED 0
|
#define TERM_COOKED 0
|
||||||
#define TERM_CBREAK 1
|
#define TERM_RAW 1
|
||||||
#define TERM_RAW 2
|
|
||||||
|
|
||||||
#if !defined(TIOCGSIZE) && defined(TIOCGWINSZ)
|
#if !defined(TIOCGSIZE) && defined(TIOCGWINSZ)
|
||||||
# define TIOCGSIZE TIOCGWINSZ
|
# define TIOCGSIZE TIOCGWINSZ
|
||||||
@@ -108,7 +107,7 @@ struct io_buffer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int script_fds[6] = { -1, -1, -1, -1, -1, -1};
|
static int script_fds[6] = { -1, -1, -1, -1, -1, -1};
|
||||||
static int ttyout = TRUE;
|
static int ttyin = TRUE;
|
||||||
|
|
||||||
static sig_atomic_t recvsig[NSIG];
|
static sig_atomic_t recvsig[NSIG];
|
||||||
static sig_atomic_t ttymode = TERM_COOKED;
|
static sig_atomic_t ttymode = TERM_COOKED;
|
||||||
@@ -296,7 +295,7 @@ suspend_parent(int signo, int fd, struct io_buffer *iobufs)
|
|||||||
if (foreground) {
|
if (foreground) {
|
||||||
if (ttymode != TERM_RAW) {
|
if (ttymode != TERM_RAW) {
|
||||||
do {
|
do {
|
||||||
n = term_raw(script_fds[SFD_USERTTY], !ttyout, 0);
|
n = term_raw(script_fds[SFD_USERTTY], 0);
|
||||||
} while (!n && errno == EINTR);
|
} while (!n && errno == EINTR);
|
||||||
ttymode = TERM_RAW;
|
ttymode = TERM_RAW;
|
||||||
}
|
}
|
||||||
@@ -335,10 +334,9 @@ suspend_parent(int signo, int fd, struct io_buffer *iobufs)
|
|||||||
|
|
||||||
if (ttymode != TERM_COOKED) {
|
if (ttymode != TERM_COOKED) {
|
||||||
if (foreground) {
|
if (foreground) {
|
||||||
/* Set raw/cbreak mode. */
|
/* Set raw mode. */
|
||||||
do {
|
do {
|
||||||
n = term_raw(script_fds[SFD_USERTTY], !ttyout,
|
n = term_raw(script_fds[SFD_USERTTY], 0);
|
||||||
ttymode == TERM_CBREAK);
|
|
||||||
} while (!n && errno == EINTR);
|
} while (!n && errno == EINTR);
|
||||||
} else {
|
} else {
|
||||||
/* Background process, no access to tty. */
|
/* Background process, no access to tty. */
|
||||||
@@ -565,6 +563,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
*/
|
*/
|
||||||
memset(io_pipe, 0, sizeof(io_pipe));
|
memset(io_pipe, 0, sizeof(io_pipe));
|
||||||
if (!isatty(STDIN_FILENO)) {
|
if (!isatty(STDIN_FILENO)) {
|
||||||
|
ttyin = FALSE;
|
||||||
if (pipe(io_pipe[STDIN_FILENO]) != 0)
|
if (pipe(io_pipe[STDIN_FILENO]) != 0)
|
||||||
error(1, "unable to create pipe");
|
error(1, "unable to create pipe");
|
||||||
iobufs = io_buf_new(STDIN_FILENO, io_pipe[STDIN_FILENO][1],
|
iobufs = io_buf_new(STDIN_FILENO, io_pipe[STDIN_FILENO][1],
|
||||||
@@ -572,7 +571,6 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
script_fds[SFD_STDIN] = io_pipe[STDIN_FILENO][0];
|
script_fds[SFD_STDIN] = io_pipe[STDIN_FILENO][0];
|
||||||
}
|
}
|
||||||
if (!isatty(STDOUT_FILENO)) {
|
if (!isatty(STDOUT_FILENO)) {
|
||||||
ttyout = FALSE;
|
|
||||||
if (pipe(io_pipe[STDOUT_FILENO]) != 0)
|
if (pipe(io_pipe[STDOUT_FILENO]) != 0)
|
||||||
error(1, "unable to create pipe");
|
error(1, "unable to create pipe");
|
||||||
iobufs = io_buf_new(io_pipe[STDOUT_FILENO][0], STDOUT_FILENO,
|
iobufs = io_buf_new(io_pipe[STDOUT_FILENO][0], STDOUT_FILENO,
|
||||||
@@ -603,14 +601,15 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
sync_ttysize(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE]);
|
sync_ttysize(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start out in raw mode is stdout is a tty. */
|
/* Start out in raw mode is stdin is a tty. */
|
||||||
ttymode = ttyout ? TERM_RAW : TERM_CBREAK;
|
if (ttyin) {
|
||||||
do {
|
ttymode = TERM_RAW;
|
||||||
n = term_raw(script_fds[SFD_USERTTY], !ttyout,
|
do {
|
||||||
ttymode == TERM_CBREAK);
|
n = term_raw(script_fds[SFD_USERTTY], 0);
|
||||||
} while (!n && errno == EINTR);
|
} while (!n && errno == EINTR);
|
||||||
if (!n)
|
if (!n)
|
||||||
error(1, "Can't set terminal to raw mode");
|
error(1, "Can't set terminal to raw mode");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -738,7 +737,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
FD_SET(iob->rfd, fdsr);
|
FD_SET(iob->rfd, fdsr);
|
||||||
}
|
}
|
||||||
if (iob->wfd != -1 &&
|
if (iob->wfd != -1 &&
|
||||||
(ttymode == TERM_RAW || iob->wfd != script_fds[SFD_USERTTY])) {
|
(foreground || iob->wfd != script_fds[SFD_USERTTY])) {
|
||||||
if (iob->len > iob->off)
|
if (iob->len > iob->off)
|
||||||
FD_SET(iob->wfd, fdsw);
|
FD_SET(iob->wfd, fdsw);
|
||||||
}
|
}
|
||||||
@@ -971,7 +970,13 @@ script_child(const char *path, char *argv[], char *envp[], int backchannel, int
|
|||||||
close(n);
|
close(n);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (foreground && !ttyout)
|
/*
|
||||||
|
* If stdin is not a tty, start command in the background since
|
||||||
|
* it might be part of a pipeline that reads from /dev/tty.
|
||||||
|
* In this case, we rely on the command receiving SIGTTOU or SIGTTIN
|
||||||
|
* when it needs access to the controlling tty.
|
||||||
|
*/
|
||||||
|
if (foreground && !ttyin)
|
||||||
foreground = 0;
|
foreground = 0;
|
||||||
|
|
||||||
/* Start command and wait for it to stop or exit */
|
/* Start command and wait for it to stop or exit */
|
||||||
@@ -1012,7 +1017,6 @@ script_child(const char *path, char *argv[], char *envp[], int backchannel, int
|
|||||||
close(errpipe[1]);
|
close(errpipe[1]);
|
||||||
|
|
||||||
/* If any of stdin/stdout/stderr are pipes, close them in parent. */
|
/* If any of stdin/stdout/stderr are pipes, close them in parent. */
|
||||||
/* XXX - close other end too */
|
|
||||||
if (script_fds[SFD_STDIN] != script_fds[SFD_SLAVE])
|
if (script_fds[SFD_STDIN] != script_fds[SFD_SLAVE])
|
||||||
close(script_fds[SFD_STDIN]);
|
close(script_fds[SFD_STDIN]);
|
||||||
if (script_fds[SFD_STDOUT] != script_fds[SFD_SLAVE])
|
if (script_fds[SFD_STDOUT] != script_fds[SFD_SLAVE])
|
||||||
|
@@ -178,7 +178,7 @@ void script_setup(uid_t);
|
|||||||
int term_cbreak(int);
|
int term_cbreak(int);
|
||||||
int term_copy(int, int);
|
int term_copy(int, int);
|
||||||
int term_noecho(int);
|
int term_noecho(int);
|
||||||
int term_raw(int, int, int);
|
int term_raw(int, int);
|
||||||
int term_restore(int, int);
|
int term_restore(int, int);
|
||||||
|
|
||||||
/* fmt_string.h */
|
/* fmt_string.h */
|
||||||
|
@@ -116,7 +116,7 @@ term_noecho(int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
term_raw(int fd, int opost, int isig)
|
term_raw(int fd, int isig)
|
||||||
{
|
{
|
||||||
struct termios term;
|
struct termios term;
|
||||||
|
|
||||||
@@ -130,9 +130,6 @@ term_raw(int fd, int opost, int isig)
|
|||||||
if (isig)
|
if (isig)
|
||||||
SET(term.c_lflag, ISIG);
|
SET(term.c_lflag, ISIG);
|
||||||
CLR(term.c_iflag, ICRNL | IGNCR | INLCR | IUCLC | IXON);
|
CLR(term.c_iflag, ICRNL | IGNCR | INLCR | IUCLC | IXON);
|
||||||
/* Only retain output post-processing opost flag set. */
|
|
||||||
if (!opost)
|
|
||||||
CLR(term.c_oflag, OPOST);
|
|
||||||
if (tcsetattr(fd, TCSADRAIN|TCSASOFT, &term) == 0) {
|
if (tcsetattr(fd, TCSADRAIN|TCSASOFT, &term) == 0) {
|
||||||
changed = 1;
|
changed = 1;
|
||||||
return(1);
|
return(1);
|
||||||
|
Reference in New Issue
Block a user