aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c83
1 files changed, 79 insertions, 4 deletions
diff --git a/shell/ash.c b/shell/ash.c
index bfdd94047..d8f41327b 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -3579,6 +3579,72 @@ static struct job *curjob; //lots
3579/* number of presumed living untracked jobs */ 3579/* number of presumed living untracked jobs */
3580static int jobless; //4 3580static int jobless; //4
3581 3581
3582#if 0
3583/* Bash has a feature: it restores termios after a successful wait for
3584 * a foreground job which had at least one stopped or sigkilled member.
3585 * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3586 * properly restoring tty state. Should we do this too?
3587 * A reproducer: ^Z an interactive python:
3588 *
3589 * # python
3590 * Python 2.7.12 (...)
3591 * >>> ^Z
3592 * { python leaves tty in -icanon -echo state. We do survive that... }
3593 * [1]+ Stopped python
3594 * { ...however, next program (python #2) does not survive it well: }
3595 * # python
3596 * Python 2.7.12 (...)
3597 * >>> Traceback (most recent call last):
3598 * { above, I typed "qwerty<CR>", but -echo state is still in effect }
3599 * File "<stdin>", line 1, in <module>
3600 * NameError: name 'qwerty' is not defined
3601 *
3602 * The implementation below is modeled on bash code and seems to work.
3603 * However, I'm not sure we should do this. For one: what if I'd fg
3604 * the stopped python instead? It'll be confused by "restored" tty state.
3605 */
3606static struct termios shell_tty_info;
3607static void
3608get_tty_state(void)
3609{
3610 if (rootshell && ttyfd >= 0)
3611 tcgetattr(ttyfd, &shell_tty_info);
3612}
3613static void
3614set_tty_state(void)
3615{
3616 /* if (rootshell) - caller ensures this */
3617 if (ttyfd >= 0)
3618 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3619}
3620static int
3621job_signal_status(struct job *jp)
3622{
3623 int status;
3624 unsigned i;
3625 struct procstat *ps = jp->ps;
3626 for (i = 0; i < jp->nprocs; i++) {
3627 status = ps[i].ps_status;
3628 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3629 return status;
3630 }
3631 return 0;
3632}
3633static void
3634restore_tty_if_stopped_or_signaled(struct job *jp)
3635{
3636//TODO: check what happens if we come from waitforjob() in expbackq()
3637 if (rootshell) {
3638 int s = job_signal_status(jp);
3639 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3640 set_tty_state();
3641 }
3642}
3643#else
3644# define get_tty_state() ((void)0)
3645# define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3646#endif
3647
3582static void 3648static void
3583set_curjob(struct job *jp, unsigned mode) 3649set_curjob(struct job *jp, unsigned mode)
3584{ 3650{
@@ -3910,8 +3976,10 @@ restartjob(struct job *jp, int mode)
3910 goto out; 3976 goto out;
3911 jp->state = JOBRUNNING; 3977 jp->state = JOBRUNNING;
3912 pgid = jp->ps[0].ps_pid; 3978 pgid = jp->ps[0].ps_pid;
3913 if (mode == FORK_FG) 3979 if (mode == FORK_FG) {
3980 get_tty_state();
3914 xtcsetpgrp(ttyfd, pgid); 3981 xtcsetpgrp(ttyfd, pgid);
3982 }
3915 killpg(pgid, SIGCONT); 3983 killpg(pgid, SIGCONT);
3916 ps = jp->ps; 3984 ps = jp->ps;
3917 i = jp->nprocs; 3985 i = jp->nprocs;
@@ -4445,7 +4513,7 @@ makejob(/*union node *node,*/ int nprocs)
4445 memset(jp, 0, sizeof(*jp)); 4513 memset(jp, 0, sizeof(*jp));
4446#if JOBS 4514#if JOBS
4447 /* jp->jobctl is a bitfield. 4515 /* jp->jobctl is a bitfield.
4448 * "jp->jobctl |= jobctl" likely to give awful code */ 4516 * "jp->jobctl |= doing_jobctl" likely to give awful code */
4449 if (doing_jobctl) 4517 if (doing_jobctl)
4450 jp->jobctl = 1; 4518 jp->jobctl = 1;
4451#endif 4519#endif
@@ -5040,6 +5108,8 @@ waitforjob(struct job *jp)
5040#if JOBS 5108#if JOBS
5041 if (jp->jobctl) { 5109 if (jp->jobctl) {
5042 xtcsetpgrp(ttyfd, rootpid); 5110 xtcsetpgrp(ttyfd, rootpid);
5111 restore_tty_if_stopped_or_signaled(jp);
5112
5043 /* 5113 /*
5044 * This is truly gross. 5114 * This is truly gross.
5045 * If we're doing job control, then we did a TIOCSPGRP which 5115 * If we're doing job control, then we did a TIOCSPGRP which
@@ -8852,13 +8922,15 @@ static int
8852evalsubshell(union node *n, int flags) 8922evalsubshell(union node *n, int flags)
8853{ 8923{
8854 struct job *jp; 8924 struct job *jp;
8855 int backgnd = (n->type == NBACKGND); 8925 int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8856 int status; 8926 int status;
8857 8927
8858 expredir(n->nredir.redirect); 8928 expredir(n->nredir.redirect);
8859 if (!backgnd && (flags & EV_EXIT) && !may_have_traps) 8929 if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8860 goto nofork; 8930 goto nofork;
8861 INT_OFF; 8931 INT_OFF;
8932 if (backgnd == FORK_FG)
8933 get_tty_state();
8862 jp = makejob(/*n,*/ 1); 8934 jp = makejob(/*n,*/ 1);
8863 if (forkshell(jp, n, backgnd) == 0) { 8935 if (forkshell(jp, n, backgnd) == 0) {
8864 /* child */ 8936 /* child */
@@ -8873,7 +8945,7 @@ evalsubshell(union node *n, int flags)
8873 } 8945 }
8874 /* parent */ 8946 /* parent */
8875 status = 0; 8947 status = 0;
8876 if (!backgnd) 8948 if (backgnd == FORK_FG)
8877 status = waitforjob(jp); 8949 status = waitforjob(jp);
8878 INT_ON; 8950 INT_ON;
8879 return status; 8951 return status;
@@ -8965,6 +9037,8 @@ evalpipe(union node *n, int flags)
8965 pipelen++; 9037 pipelen++;
8966 flags |= EV_EXIT; 9038 flags |= EV_EXIT;
8967 INT_OFF; 9039 INT_OFF;
9040 if (n->npipe.pipe_backgnd == 0)
9041 get_tty_state();
8968 jp = makejob(/*n,*/ pipelen); 9042 jp = makejob(/*n,*/ pipelen);
8969 prevfd = -1; 9043 prevfd = -1;
8970 for (lp = n->npipe.cmdlist; lp; lp = lp->next) { 9044 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
@@ -9647,6 +9721,7 @@ evalcommand(union node *cmd, int flags)
9647 if (!(flags & EV_EXIT) || may_have_traps) { 9721 if (!(flags & EV_EXIT) || may_have_traps) {
9648 /* No, forking off a child is necessary */ 9722 /* No, forking off a child is necessary */
9649 INT_OFF; 9723 INT_OFF;
9724 get_tty_state();
9650 jp = makejob(/*cmd,*/ 1); 9725 jp = makejob(/*cmd,*/ 1);
9651 if (forkshell(jp, cmd, FORK_FG) != 0) { 9726 if (forkshell(jp, cmd, FORK_FG) != 0) {
9652 /* parent */ 9727 /* parent */