It turns out job control in both hush and lash was broken by the
authorEric Andersen <andersen@codepoet.org>
Thu, 17 May 2001 00:14:27 +0000 (00:14 -0000)
committerEric Andersen <andersen@codepoet.org>
Thu, 17 May 2001 00:14:27 +0000 (00:14 -0000)
signal handling in cmdedit.c.  Disabling it makes the shells behave
themselves again.  hush isn't quite there, but is getting close...
 -Erik

cmdedit.c
hush.c
shell/cmdedit.c
shell/hush.c

index ec9939312a6ce57df86fd0cbe33496c53f5d15d3..cc39e562ae611583184c9f3ccf80e3880ffa9e85 100644 (file)
--- a/cmdedit.c
+++ b/cmdedit.c
@@ -571,6 +571,7 @@ extern void cmdedit_init(void)
                atexit(cmdedit_reset_term);     /* be sure to do this only once */
        }
 
+#if 0
        if ((handlers_sets & SET_TERM_HANDLERS) == 0) {
                signal(SIGKILL, clean_up_and_die);
                signal(SIGINT, clean_up_and_die);
@@ -578,6 +579,7 @@ extern void cmdedit_init(void)
                signal(SIGTERM, clean_up_and_die);
                handlers_sets |= SET_TERM_HANDLERS;
        }
+#endif 
 
 }
 
@@ -1487,6 +1489,7 @@ prepare_to_die:
 extern void cmdedit_terminate(void)
 {
        cmdedit_reset_term();
+#if 0
        if ((handlers_sets & SET_TERM_HANDLERS) != 0) {
                signal(SIGKILL, SIG_DFL);
                signal(SIGINT, SIG_DFL);
@@ -1495,6 +1498,7 @@ extern void cmdedit_terminate(void)
                signal(SIGWINCH, SIG_DFL);
                handlers_sets &= ~SET_TERM_HANDLERS;
        }
+#endif 
 }
 
 #endif /* BB_FEATURE_COMMAND_EDITING */
diff --git a/hush.c b/hush.c
index c938fb1e398491ba06caefe184a0bffd5ce93308..59568189fe2038a855685fe810a563d81afbee24 100644 (file)
--- a/hush.c
+++ b/hush.c
@@ -1160,6 +1160,7 @@ static void insert_bg_job(struct pipe *pi)
        /* physically copy the struct job */
        memcpy(thejob, pi, sizeof(struct pipe));
        thejob->next = NULL;
+       //thejob->num_progs = 0;
        thejob->running_progs = thejob->num_progs;
        thejob->stopped_progs = 0;
        thejob->text = xmalloc(MAX_LINE);
@@ -1184,7 +1185,6 @@ static void remove_bg_job(struct pipe *pi)
 {
        struct pipe *prev_pipe;
 
-       free_pipe(pi);
        if (pi == job_list->head) {
                job_list->head = pi->next;
        } else {
@@ -1194,6 +1194,7 @@ static void remove_bg_job(struct pipe *pi)
                prev_pipe->next = pi->next;
        }
 
+       free_pipe(pi);
        free(pi);
 }
 
@@ -1393,13 +1394,11 @@ static int run_pipe_real(struct pipe *pi)
                        setup_redirects(child,NULL);
                        
                        if (pi->followup!=PIPE_BG) {
-                               /* Put our child in the process group whose leader is the
-                                * first process in this pipe. */
+                               /* If we (the child) win the race, put ourselves in the process
+                                * group whose leader is the first process in this pipe. */
                                if (pi->pgrp < 0) {
                                        pi->pgrp = child->pid;
                                }
-                               /* Don't check for errors.  The child may be dead already,
-                                * in which case setpgid returns error code EACCES. */
                                if (setpgid(0, pi->pgrp) == 0) {
                                        signal(SIGTTOU, SIG_IGN);
                                        tcsetpgrp(ctty, pi->pgrp);
@@ -1460,15 +1459,11 @@ static int run_list_real(struct pipe *pi)
                        if (interactive) {
                                /* move the new process group into the foreground */
                                /* suppress messages when run from /linuxrc mag@sysgo.de */
-                               //signal(SIGTTIN, SIG_IGN);
-                               //signal(SIGTTOU, SIG_IGN);
                                if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY)
                                        perror_msg("tcsetpgrp");
                                rcode = pipe_wait(pi);
                                if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY)
                                        perror_msg("tcsetpgrp");
-                               //signal(SIGTTIN, SIG_DFL);
-                               //signal(SIGTTOU, SIG_DFL);
                        } else {
                                rcode = pipe_wait(pi);
                        }
@@ -1479,7 +1474,6 @@ static int run_list_real(struct pipe *pi)
                if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) ||
                     (rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) )
                        skip_more_in_this_rmode=rmode;
-                       /* return rcode; */ /* XXX broken if list is part of if/then/else */
        }
        checkjobs();
        return rcode;
@@ -2528,9 +2522,27 @@ int shell_main(int argc, char **argv)
        global_argc = argc;
        global_argv = argv;
 
+       /* If we get started under a job aware app (like bash 
+        * for example), make sure we are now in charge so we 
+        * don't fight over who gets the foreground */
+       do { 
+               pid_t initialpgrp;
+               initialpgrp = tcgetpgrp(fileno(stderr));
+               if (initialpgrp < 0) {
+                       error_msg_and_die("sh: can't access tty; job control disabled\n");
+               }
+               if (initialpgrp == -1)
+                       initialpgrp = getpgrp();
+               else if (initialpgrp != getpgrp()) {
+                       killpg(initialpgrp, SIGTTIN);
+                       continue;
+               }
+       } while (0);
        /* don't pay any attention to this signal; it just confuses 
           things and isn't really meant for shells anyway */
        signal(SIGTTOU, SIG_IGN);
+       setpgid(0, getpid());
+       tcsetpgrp(fileno(stderr), getpid());
 
        if (argv[0] && argv[0][0] == '-') {
                debug_printf("\nsourcing /etc/profile\n");
index ec9939312a6ce57df86fd0cbe33496c53f5d15d3..cc39e562ae611583184c9f3ccf80e3880ffa9e85 100644 (file)
@@ -571,6 +571,7 @@ extern void cmdedit_init(void)
                atexit(cmdedit_reset_term);     /* be sure to do this only once */
        }
 
+#if 0
        if ((handlers_sets & SET_TERM_HANDLERS) == 0) {
                signal(SIGKILL, clean_up_and_die);
                signal(SIGINT, clean_up_and_die);
@@ -578,6 +579,7 @@ extern void cmdedit_init(void)
                signal(SIGTERM, clean_up_and_die);
                handlers_sets |= SET_TERM_HANDLERS;
        }
+#endif 
 
 }
 
@@ -1487,6 +1489,7 @@ prepare_to_die:
 extern void cmdedit_terminate(void)
 {
        cmdedit_reset_term();
+#if 0
        if ((handlers_sets & SET_TERM_HANDLERS) != 0) {
                signal(SIGKILL, SIG_DFL);
                signal(SIGINT, SIG_DFL);
@@ -1495,6 +1498,7 @@ extern void cmdedit_terminate(void)
                signal(SIGWINCH, SIG_DFL);
                handlers_sets &= ~SET_TERM_HANDLERS;
        }
+#endif 
 }
 
 #endif /* BB_FEATURE_COMMAND_EDITING */
index c938fb1e398491ba06caefe184a0bffd5ce93308..59568189fe2038a855685fe810a563d81afbee24 100644 (file)
@@ -1160,6 +1160,7 @@ static void insert_bg_job(struct pipe *pi)
        /* physically copy the struct job */
        memcpy(thejob, pi, sizeof(struct pipe));
        thejob->next = NULL;
+       //thejob->num_progs = 0;
        thejob->running_progs = thejob->num_progs;
        thejob->stopped_progs = 0;
        thejob->text = xmalloc(MAX_LINE);
@@ -1184,7 +1185,6 @@ static void remove_bg_job(struct pipe *pi)
 {
        struct pipe *prev_pipe;
 
-       free_pipe(pi);
        if (pi == job_list->head) {
                job_list->head = pi->next;
        } else {
@@ -1194,6 +1194,7 @@ static void remove_bg_job(struct pipe *pi)
                prev_pipe->next = pi->next;
        }
 
+       free_pipe(pi);
        free(pi);
 }
 
@@ -1393,13 +1394,11 @@ static int run_pipe_real(struct pipe *pi)
                        setup_redirects(child,NULL);
                        
                        if (pi->followup!=PIPE_BG) {
-                               /* Put our child in the process group whose leader is the
-                                * first process in this pipe. */
+                               /* If we (the child) win the race, put ourselves in the process
+                                * group whose leader is the first process in this pipe. */
                                if (pi->pgrp < 0) {
                                        pi->pgrp = child->pid;
                                }
-                               /* Don't check for errors.  The child may be dead already,
-                                * in which case setpgid returns error code EACCES. */
                                if (setpgid(0, pi->pgrp) == 0) {
                                        signal(SIGTTOU, SIG_IGN);
                                        tcsetpgrp(ctty, pi->pgrp);
@@ -1460,15 +1459,11 @@ static int run_list_real(struct pipe *pi)
                        if (interactive) {
                                /* move the new process group into the foreground */
                                /* suppress messages when run from /linuxrc mag@sysgo.de */
-                               //signal(SIGTTIN, SIG_IGN);
-                               //signal(SIGTTOU, SIG_IGN);
                                if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY)
                                        perror_msg("tcsetpgrp");
                                rcode = pipe_wait(pi);
                                if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY)
                                        perror_msg("tcsetpgrp");
-                               //signal(SIGTTIN, SIG_DFL);
-                               //signal(SIGTTOU, SIG_DFL);
                        } else {
                                rcode = pipe_wait(pi);
                        }
@@ -1479,7 +1474,6 @@ static int run_list_real(struct pipe *pi)
                if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) ||
                     (rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) )
                        skip_more_in_this_rmode=rmode;
-                       /* return rcode; */ /* XXX broken if list is part of if/then/else */
        }
        checkjobs();
        return rcode;
@@ -2528,9 +2522,27 @@ int shell_main(int argc, char **argv)
        global_argc = argc;
        global_argv = argv;
 
+       /* If we get started under a job aware app (like bash 
+        * for example), make sure we are now in charge so we 
+        * don't fight over who gets the foreground */
+       do { 
+               pid_t initialpgrp;
+               initialpgrp = tcgetpgrp(fileno(stderr));
+               if (initialpgrp < 0) {
+                       error_msg_and_die("sh: can't access tty; job control disabled\n");
+               }
+               if (initialpgrp == -1)
+                       initialpgrp = getpgrp();
+               else if (initialpgrp != getpgrp()) {
+                       killpg(initialpgrp, SIGTTIN);
+                       continue;
+               }
+       } while (0);
        /* don't pay any attention to this signal; it just confuses 
           things and isn't really meant for shells anyway */
        signal(SIGTTOU, SIG_IGN);
+       setpgid(0, getpid());
+       tcsetpgrp(fileno(stderr), getpid());
 
        if (argv[0] && argv[0][0] == '-') {
                debug_printf("\nsourcing /etc/profile\n");