Remove debugging statement.
[oweals/busybox.git] / hush.c
diff --git a/hush.c b/hush.c
index a9d3a16accc069503223fc51448d27fe6f52c43f..b74b9d159b8da9cb2ff478227f8e3726b64f9a90 100644 (file)
--- a/hush.c
+++ b/hush.c
@@ -251,12 +251,13 @@ static const char *cwd;
 static struct pipe *job_list;
 static unsigned int last_bg_pid;
 static unsigned int last_jobid;
-static unsigned int ctty;
+static unsigned int shell_terminal;
 static char *PS1;
 static char *PS2;
 struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
 struct variables *top_vars = &shell_ver;
 
+
 #define B_CHUNK (100)
 #define B_NOSPAC 1
 
@@ -395,7 +396,6 @@ static char *get_local_var(const char *var);
 static void  unset_local_var(const char *name);
 static int set_local_var(const char *s, int flg_export);
 
-
 /* Table of built-in functions.  They can be forked or not, depending on
  * context: within pipes, they fork.  As simple commands, they do not.
  * When used in non-forking context, they can change global variables
@@ -556,7 +556,6 @@ static int builtin_fg_bg(struct child_prog *child)
                        error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]);
                        return EXIT_FAILURE;
                }
-
                for (pi = job_list; pi; pi = pi->next) {
                        if (pi->jobid == jobnum) {
                                break;
@@ -567,20 +566,23 @@ static int builtin_fg_bg(struct child_prog *child)
                        return EXIT_FAILURE;
                }
        }
+
        if (*child->argv[0] == 'f') {
-               /* Make this job the foreground job */
-               signal(SIGTTOU, SIG_IGN);
-               /* suppress messages when run from /linuxrc mag@sysgo.de */
-               if (tcsetpgrp(ctty, pi->pgrp) && errno != ENOTTY)
-                       perror_msg("tcsetpgrp-1"); 
-               signal(SIGTTOU, SIG_DFL);
+               /* Put the job into the foreground.  */
+               tcsetpgrp(shell_terminal, pi->pgrp);
        }
 
        /* Restart the processes in the job */
        for (i = 0; i < pi->num_progs; i++)
                pi->progs[i].is_stopped = 0;
 
-       kill(-pi->pgrp, SIGCONT);
+       if ( (i=kill(- pi->pgrp, SIGCONT)) < 0) {
+               if (i == ESRCH) {
+                       remove_bg_job(pi);
+               } else {
+                       perror_msg("kill (SIGCONT)");
+               }
+       }
 
        pi->stopped_progs = 0;
        return EXIT_SUCCESS;
@@ -613,6 +615,7 @@ static int builtin_jobs(struct child_prog *child)
                        status_string = "Stopped";
                else
                        status_string = "Running";
+
                printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
        }
        return EXIT_SUCCESS;
@@ -861,7 +864,7 @@ static inline void setup_prompt_string(int promptmode, char **prompt_str)
                *prompt_str = PS2;
        }
 #else
-       *prompt_str = (promptmode==0)? PS1 : PS2;
+       *prompt_str = (promptmode==1)? PS1 : PS2;
 #endif
        debug_printf("result %s\n",*prompt_str);
 }
@@ -1142,7 +1145,7 @@ static void insert_bg_job(struct pipe *pi)
 
        /* add thejob to the list of running jobs */
        if (!job_list) {
-               thejob = job_list= xmalloc(sizeof(*thejob));
+               thejob = job_list = xmalloc(sizeof(*thejob));
        } else {
                for (thejob = job_list; thejob->next; thejob = thejob->next) /* nothing */;
                thejob->next = xmalloc(sizeof(*thejob));
@@ -1178,14 +1181,19 @@ static void remove_bg_job(struct pipe *pi)
        struct pipe *prev_pipe;
 
        if (pi == job_list) {
-               job_list= pi->next;
+               job_list = pi->next;
        } else {
                prev_pipe = job_list;
                while (prev_pipe->next != pi)
                        prev_pipe = prev_pipe->next;
                prev_pipe->next = pi->next;
        }
+       if (job_list)
+               last_jobid = job_list->jobid;
+       else
+               last_jobid = 0;
 
+       pi->stopped_progs = 0;
        free_pipe(pi, 0);
        free(pi);
 }
@@ -1210,7 +1218,7 @@ static int checkjobs(struct pipe* fg_pipe)
                        int i, rcode = 0;
                        for (i=0; i < fg_pipe->num_progs; i++) {
                                if (fg_pipe->progs[i].pid == childpid) {
-                                       if (i==fg_pipe->num_progs-1)
+                                       if (i==fg_pipe->num_progs-1) 
                                                rcode=WEXITSTATUS(status);
                                        (fg_pipe->num_progs)--;
                                        return(rcode);
@@ -1220,8 +1228,9 @@ static int checkjobs(struct pipe* fg_pipe)
 
                for (pi = job_list; pi; pi = pi->next) {
                        prognum = 0;
-                       while (prognum < pi->num_progs &&
-                                  pi->progs[prognum].pid != childpid) prognum++;
+                       while (prognum < pi->num_progs && pi->progs[prognum].pid != childpid) {
+                               prognum++;
+                       }
                        if (prognum < pi->num_progs)
                                break;
                }
@@ -1245,9 +1254,14 @@ static int checkjobs(struct pipe* fg_pipe)
                        pi->stopped_progs++;
                        pi->progs[prognum].is_stopped = 1;
 
+#if 0
+                       /* Printing this stuff is a pain, since it tends to
+                        * overwrite the prompt an inconveinient moments.  So
+                        * don't do that.  */
                        if (pi->stopped_progs == pi->num_progs) {
-                               printf(JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text);
+                               printf("\n"JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text);
                        }
+#endif 
                }
        }
 
@@ -1255,32 +1269,32 @@ static int checkjobs(struct pipe* fg_pipe)
                perror_msg("waitpid");
 
        /* move the shell to the foreground */
-       if (interactive && tcsetpgrp(ctty, getpgid(0)))
-               perror_msg("tcsetpgrp-2");
+       //if (interactive && tcsetpgrp(shell_terminal, getpgid(0)))
+       //      perror_msg("tcsetpgrp-2");
        return -1;
 }
 
 /* Figure out our controlling tty, checking in order stderr,
  * stdin, and stdout.  If check_pgrp is set, also check that
  * we belong to the foreground process group associated with
- * that tty.  The value of ctty is needed in order to call
- * tcsetpgrp(ctty, ...); */
+ * that tty.  The value of shell_terminal is needed in order to call
+ * tcsetpgrp(shell_terminal, ...); */
 void controlling_tty(int check_pgrp)
 {
        pid_t curpgrp;
 
-       if ((curpgrp = tcgetpgrp(ctty = 2)) < 0
-                       && (curpgrp = tcgetpgrp(ctty = 0)) < 0
-                       && (curpgrp = tcgetpgrp(ctty = 1)) < 0)
-               goto ctty_error;
+       if ((curpgrp = tcgetpgrp(shell_terminal = 2)) < 0
+                       && (curpgrp = tcgetpgrp(shell_terminal = 0)) < 0
+                       && (curpgrp = tcgetpgrp(shell_terminal = 1)) < 0)
+               goto shell_terminal_error;
 
        if (check_pgrp && curpgrp != getpgid(0))
-               goto ctty_error;
+               goto shell_terminal_error;
 
        return;
 
-ctty_error:
-               ctty = -1;
+shell_terminal_error:
+               shell_terminal = -1;
                return;
 }
 
@@ -1394,8 +1408,13 @@ static int run_pipe_real(struct pipe *pi)
 
                /* XXX test for failed fork()? */
                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();
 
@@ -1414,7 +1433,7 @@ static int run_pipe_real(struct pipe *pi)
                        /* Like bash, explicit redirects override pipes,
                         * and the pipe fd is available for dup'ing. */
                        setup_redirects(child,NULL);
-                       
+
                        if (interactive && pi->followup!=PIPE_BG) {
                                /* If we (the child) win the race, put ourselves in the process
                                 * group whose leader is the first process in this pipe. */
@@ -1422,16 +1441,16 @@ static int run_pipe_real(struct pipe *pi)
                                        pi->pgrp = getpid();
                                }
                                if (setpgid(0, pi->pgrp) == 0) {
-                                       signal(SIGTTOU, SIG_IGN);
-                                       tcsetpgrp(ctty, pi->pgrp);
-                                       signal(SIGTTOU, SIG_DFL);
+                                       tcsetpgrp(2, pi->pgrp);
                                }
                        }
 
                        pseudo_exec(child);
                }
-               /* Put our child in the process group whose leader is the
-                * first process in this pipe. */
+               
+
+               /* put our child in the process group whose leader is the
+                  first process in this pipe */
                if (pi->pgrp < 0) {
                        pi->pgrp = child->pid;
                }
@@ -1478,18 +1497,18 @@ static int run_list_real(struct pipe *pi)
                        insert_bg_job(pi);
                        rcode = EXIT_SUCCESS;
                } else {
-
                        if (interactive) {
                                /* move the new process group into the foreground */
-                               if (tcsetpgrp(ctty, pi->pgrp) && errno != ENOTTY)
+                               if (tcsetpgrp(shell_terminal, pi->pgrp) && errno != ENOTTY)
                                        perror_msg("tcsetpgrp-3");
                                rcode = checkjobs(pi);
-                               if (tcsetpgrp(ctty, getpgid(0)) && errno != ENOTTY)
+                               /* move the shell to the foreground */
+                               if (tcsetpgrp(shell_terminal, getpgid(0)) && errno != ENOTTY)
                                        perror_msg("tcsetpgrp-4");
                        } else {
                                rcode = checkjobs(pi);
                        }
-                       debug_printf("pipe_wait returned %d\n",rcode);
+                       debug_printf("checkjobs returned %d\n",rcode);
                }
                last_return_code=rcode;
                if ( rmode == RES_IF || rmode == RES_ELIF )
@@ -1497,8 +1516,8 @@ 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;
+               checkjobs(NULL);
        }
-       checkjobs(NULL);
        return rcode;
 }
 
@@ -1517,6 +1536,9 @@ static int free_pipe(struct pipe *pi, int indent)
        struct redir_struct *r, *rnext;
        int a, i, ret_code=0;
        char *ind = indenter(indent);
+
+       if (pi->stopped_progs > 0)
+               return ret_code;
        final_printf("%s run pipe: (pid %d)\n",ind,getpid());
        for (i=0; i<pi->num_progs; i++) {
                child = &pi->progs[i];
@@ -2516,6 +2538,32 @@ static int parse_file_outer(FILE *f)
        return rcode;
 }
 
+/* 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()
+{
+       static pid_t shell_pgrp;
+       /* 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.  */
+       setsid();
+       shell_pgrp = getpid ();
+       setpgid (shell_pgrp, shell_pgrp);
+
+       /* Grab control of the terminal.  */
+       tcsetpgrp(shell_terminal, shell_pgrp);
+}
 
 int shell_main(int argc, char **argv)
 {
@@ -2536,11 +2584,11 @@ int shell_main(int argc, char **argv)
        interactive = 0;
        close_me_head = NULL;
        last_bg_pid = 0;
+       job_list = NULL;
        last_jobid = 0;
 
        /* Initialize some more globals to non-zero values */
        set_cwd();
-       job_list = NULL;
 #ifdef BB_FEATURE_COMMAND_EDITING
        cmdedit_set_initial_prompt();
 #else
@@ -2558,23 +2606,14 @@ int shell_main(int argc, char **argv)
        last_return_code=EXIT_SUCCESS;
 
 
-       /* 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 */
-       /* don't pay any attention to this signal; it just confuses 
-          things and isn't really meant for shells anyway */
-       controlling_tty(0);
-       signal(SIGTTOU, SIG_IGN);
-       setpgid(0, getpid());
-       tcsetpgrp(ctty, getpid());
-
        if (argv[0] && argv[0][0] == '-') {
                debug_printf("\nsourcing /etc/profile\n");
-               input = xfopen("/etc/profile", "r");
-               mark_open(fileno(input));
-               parse_file_outer(input);
-               mark_closed(fileno(input));
-               fclose(input);
+               if ((input = fopen("/etc/profile", "r")) != NULL) {
+                       mark_open(fileno(input));
+                       parse_file_outer(input);
+                       mark_closed(fileno(input));
+                       fclose(input);
+               }
        }
        input=stdin;
        
@@ -2620,7 +2659,9 @@ int shell_main(int argc, char **argv)
        if (interactive) {
                /* Looks like they want an interactive shell */
                fprintf(stdout, "\nhush -- the humble shell v0.01 (testing)\n\n");
+               setup_job_control();
        }
+       
        if (argv[optind]==NULL) {
                opt=parse_file_outer(stdin);
                goto final_return;