This should finish off the job control issues with lash. Make certain
authorEric Andersen <andersen@codepoet.org>
Mon, 25 Jun 2001 17:11:54 +0000 (17:11 -0000)
committerEric Andersen <andersen@codepoet.org>
Mon, 25 Jun 2001 17:11:54 +0000 (17:11 -0000)
we have a controlling terminal...
 -Erik

lash.c
shell/lash.c

diff --git a/lash.c b/lash.c
index 689c720f60ff61d84af1a2fdd247b907c069fc6d..68f67353967a265491bd2ca7ddba845c7fb0057e 100644 (file)
--- a/lash.c
+++ b/lash.c
@@ -44,6 +44,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 #include <getopt.h>
+#include <termios.h>
 #include "busybox.h"
 #include "cmdedit.h"
 
@@ -181,7 +182,8 @@ static int argc;
 static char **argv;
 static struct close_me *close_me_head;
 static unsigned int last_jobid;
-
+static int shell_terminal;
+static pid_t shell_pgrp;
 static char *PS1;
 static char *PS2 = "> ";
 
@@ -299,10 +301,9 @@ static int builtin_fg_bg(struct child_prog *child)
        }
 
        if (*child->argv[0] == 'f') {
-               /* Make this job the foreground job */
-               /* suppress messages when run from /linuxrc mag@sysgo.de */
-               if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY)
-                       perror_msg("tcsetpgrp"); 
+               /* Put the job into the foreground.  */
+               tcsetpgrp(shell_terminal, job->pgrp);
+
                child->family->job_list->fg = job;
        }
 
@@ -310,10 +311,11 @@ static int builtin_fg_bg(struct child_prog *child)
        for (i = 0; i < job->num_progs; i++)
                job->progs[i].is_stopped = 0;
 
-       kill(-job->pgrp, SIGCONT);
-
        job->stopped_progs = 0;
 
+       if (kill(- job->pgrp, SIGCONT) < 0)
+               perror_msg("kill (SIGCONT)");
+
        return EXIT_SUCCESS;
 }
 
@@ -1081,7 +1083,7 @@ static void insert_job(struct job *newjob, int inbg)
 
                /* move the new process group into the foreground */
                /* suppress messages when run from /linuxrc mag@sysgo.de */
-               if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY)
+               if (tcsetpgrp(shell_terminal, newjob->pgrp) && errno != ENOTTY)
                        perror_msg("tcsetpgrp");
        }
 }
@@ -1131,7 +1133,13 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
                }
 
                if (!(child->pid = fork())) {
+                       /* Set the handling for job control signals back to the default.  */
+                       signal(SIGINT, SIG_DFL);
+                       signal(SIGQUIT, SIG_DFL);
+                       signal(SIGTSTP, SIG_DFL);
+                       signal(SIGTTIN, SIG_DFL);
                        signal(SIGTTOU, SIG_DFL);
+                       signal(SIGCHLD, SIG_DFL);
 
                        close_all();
 
@@ -1192,14 +1200,10 @@ static int busy_loop(FILE * input)
        newjob.job_context = DEFAULT_CONTEXT;
 
        /* save current owner of TTY so we can restore it on exit */
-       parent_pgrp = tcgetpgrp(0);
+       parent_pgrp = tcgetpgrp(shell_terminal);
 
        command = (char *) xcalloc(BUFSIZ, sizeof(char));
 
-       /* don't pay any attention to this signal; it just confuses 
-          things and isn't really meant for shells anyway */
-       signal(SIGTTOU, SIG_IGN);
-
        while (1) {
                if (!job_list.fg) {
                        /* no job is in the foreground */
@@ -1266,7 +1270,7 @@ static int busy_loop(FILE * input)
                        if (!job_list.fg) {
                                /* move the shell to the foreground */
                                /* suppress messages when run from /linuxrc mag@sysgo.de */
-                               if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY)
+                               if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY)
                                        perror_msg("tcsetpgrp"); 
                        }
                }
@@ -1274,7 +1278,7 @@ static int busy_loop(FILE * input)
        free(command);
 
        /* return controlling TTY back to parent process group before exiting */
-       if (tcsetpgrp(0, parent_pgrp))
+       if (tcsetpgrp(shell_terminal, parent_pgrp))
                perror_msg("tcsetpgrp");
 
        /* return exit status if called with "-c" */
@@ -1300,6 +1304,32 @@ void free_memory(void)
 }
 #endif
 
+/* Make sure we have a controlling tty.  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 */
+static void setup_job_control()
+{
+       /* Loop until we are in the foreground.  */
+       while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ()))
+               kill (- shell_pgrp, SIGTTIN);
+
+       /* Ignore interactive and job-control signals.  */
+       signal(SIGINT, SIG_IGN);
+       signal(SIGQUIT, SIG_IGN);
+       signal(SIGTSTP, SIG_IGN);
+       signal(SIGTTIN, SIG_IGN);
+       signal(SIGTTOU, SIG_IGN);
+       signal(SIGCHLD, SIG_IGN);
+
+       /* Put ourselves in our own process group.  */
+       shell_pgrp = getpid ();
+       if (setpgid (shell_pgrp, shell_pgrp) < 0) {
+               perror_msg_and_die("Couldn't put the shell in its own process group");
+       }
+
+       /* Grab control of the terminal.  */
+       tcsetpgrp(shell_terminal, shell_pgrp);
+}
 
 int shell_main(int argc_l, char **argv_l)
 {
@@ -1359,6 +1389,7 @@ int shell_main(int argc_l, char **argv_l)
                        isatty(fileno(stdin)) && isatty(fileno(stdout))) {
                interactive=TRUE;
        }
+       setup_job_control();
        if (interactive==TRUE) {
                //printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
                /* Looks like they want an interactive shell */
index 689c720f60ff61d84af1a2fdd247b907c069fc6d..68f67353967a265491bd2ca7ddba845c7fb0057e 100644 (file)
@@ -44,6 +44,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 #include <getopt.h>
+#include <termios.h>
 #include "busybox.h"
 #include "cmdedit.h"
 
@@ -181,7 +182,8 @@ static int argc;
 static char **argv;
 static struct close_me *close_me_head;
 static unsigned int last_jobid;
-
+static int shell_terminal;
+static pid_t shell_pgrp;
 static char *PS1;
 static char *PS2 = "> ";
 
@@ -299,10 +301,9 @@ static int builtin_fg_bg(struct child_prog *child)
        }
 
        if (*child->argv[0] == 'f') {
-               /* Make this job the foreground job */
-               /* suppress messages when run from /linuxrc mag@sysgo.de */
-               if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY)
-                       perror_msg("tcsetpgrp"); 
+               /* Put the job into the foreground.  */
+               tcsetpgrp(shell_terminal, job->pgrp);
+
                child->family->job_list->fg = job;
        }
 
@@ -310,10 +311,11 @@ static int builtin_fg_bg(struct child_prog *child)
        for (i = 0; i < job->num_progs; i++)
                job->progs[i].is_stopped = 0;
 
-       kill(-job->pgrp, SIGCONT);
-
        job->stopped_progs = 0;
 
+       if (kill(- job->pgrp, SIGCONT) < 0)
+               perror_msg("kill (SIGCONT)");
+
        return EXIT_SUCCESS;
 }
 
@@ -1081,7 +1083,7 @@ static void insert_job(struct job *newjob, int inbg)
 
                /* move the new process group into the foreground */
                /* suppress messages when run from /linuxrc mag@sysgo.de */
-               if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY)
+               if (tcsetpgrp(shell_terminal, newjob->pgrp) && errno != ENOTTY)
                        perror_msg("tcsetpgrp");
        }
 }
@@ -1131,7 +1133,13 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
                }
 
                if (!(child->pid = fork())) {
+                       /* Set the handling for job control signals back to the default.  */
+                       signal(SIGINT, SIG_DFL);
+                       signal(SIGQUIT, SIG_DFL);
+                       signal(SIGTSTP, SIG_DFL);
+                       signal(SIGTTIN, SIG_DFL);
                        signal(SIGTTOU, SIG_DFL);
+                       signal(SIGCHLD, SIG_DFL);
 
                        close_all();
 
@@ -1192,14 +1200,10 @@ static int busy_loop(FILE * input)
        newjob.job_context = DEFAULT_CONTEXT;
 
        /* save current owner of TTY so we can restore it on exit */
-       parent_pgrp = tcgetpgrp(0);
+       parent_pgrp = tcgetpgrp(shell_terminal);
 
        command = (char *) xcalloc(BUFSIZ, sizeof(char));
 
-       /* don't pay any attention to this signal; it just confuses 
-          things and isn't really meant for shells anyway */
-       signal(SIGTTOU, SIG_IGN);
-
        while (1) {
                if (!job_list.fg) {
                        /* no job is in the foreground */
@@ -1266,7 +1270,7 @@ static int busy_loop(FILE * input)
                        if (!job_list.fg) {
                                /* move the shell to the foreground */
                                /* suppress messages when run from /linuxrc mag@sysgo.de */
-                               if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY)
+                               if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY)
                                        perror_msg("tcsetpgrp"); 
                        }
                }
@@ -1274,7 +1278,7 @@ static int busy_loop(FILE * input)
        free(command);
 
        /* return controlling TTY back to parent process group before exiting */
-       if (tcsetpgrp(0, parent_pgrp))
+       if (tcsetpgrp(shell_terminal, parent_pgrp))
                perror_msg("tcsetpgrp");
 
        /* return exit status if called with "-c" */
@@ -1300,6 +1304,32 @@ void free_memory(void)
 }
 #endif
 
+/* Make sure we have a controlling tty.  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 */
+static void setup_job_control()
+{
+       /* Loop until we are in the foreground.  */
+       while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ()))
+               kill (- shell_pgrp, SIGTTIN);
+
+       /* Ignore interactive and job-control signals.  */
+       signal(SIGINT, SIG_IGN);
+       signal(SIGQUIT, SIG_IGN);
+       signal(SIGTSTP, SIG_IGN);
+       signal(SIGTTIN, SIG_IGN);
+       signal(SIGTTOU, SIG_IGN);
+       signal(SIGCHLD, SIG_IGN);
+
+       /* Put ourselves in our own process group.  */
+       shell_pgrp = getpid ();
+       if (setpgid (shell_pgrp, shell_pgrp) < 0) {
+               perror_msg_and_die("Couldn't put the shell in its own process group");
+       }
+
+       /* Grab control of the terminal.  */
+       tcsetpgrp(shell_terminal, shell_pgrp);
+}
 
 int shell_main(int argc_l, char **argv_l)
 {
@@ -1359,6 +1389,7 @@ int shell_main(int argc_l, char **argv_l)
                        isatty(fileno(stdin)) && isatty(fileno(stdout))) {
                interactive=TRUE;
        }
+       setup_job_control();
        if (interactive==TRUE) {
                //printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
                /* Looks like they want an interactive shell */