Bash-4.2 distribution sources and documentation
[platform/upstream/bash.git] / jobs.c
diff --git a/jobs.c b/jobs.c
index df13ad9..d63c5dd 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -3,7 +3,7 @@
 /* This file works with both POSIX and BSD systems.  It implements job
    control. */
 
-/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2010 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 extern int errno;
 #endif /* !errno */
 
+#if !defined (HAVE_KILLPG)
+extern int killpg __P((pid_t, int));
+#endif
+
 #define DEFAULT_CHILD_MAX 32
 #if !defined (DEBUG)
 #define MAX_JOBS_IN_ARRAY 4096         /* production */
@@ -246,8 +250,6 @@ static int find_job __P((pid_t, int, PROCESS **));
 static int print_job __P((JOB *, int, int, int));
 static int process_exit_status __P((WAIT));
 static int process_exit_signal __P((WAIT));
-static int job_exit_status __P((int));
-static int job_exit_signal __P((int));
 static int set_job_status_and_cleanup __P((int));
 
 static WAIT job_signal_status __P((int));
@@ -645,7 +647,7 @@ stop_pipeline (async, deferred)
 
   stop_making_children ();
   UNBLOCK_CHILD (oset);
-  return (js.j_current);
+  return (newjob ? i : js.j_current);
 }
 
 /* Functions to manage the list of exited background pids whose status has
@@ -1134,6 +1136,33 @@ add_process (name, pid)
     }
 }
 
+/* Create a (dummy) PROCESS with NAME, PID, and STATUS, and make it the last
+   process in jobs[JID]->pipe.  Used by the lastpipe code. */
+void
+append_process (name, pid, status, jid)
+     char *name;
+     pid_t pid;
+     int status;
+     int jid;
+{
+  PROCESS *t, *p;
+
+  t = (PROCESS *)xmalloc (sizeof (PROCESS));
+  t->next = (PROCESS *)NULL;
+  t->pid = pid;
+  /* set process exit status using offset discovered by configure */
+  t->status = (status & 0xff) << WEXITSTATUS_OFFSET;
+  t->running = PS_DONE;
+  t->command = name;
+
+  js.c_reaped++;       /* XXX */
+
+  for (p = jobs[jid]->pipe; p->next != jobs[jid]->pipe; p = p->next)
+    ;
+  p->next = t;
+  t->next = jobs[jid]->pipe;
+}
+
 #if 0
 /* Take the last job and make it the first job.  Must be called with
    SIGCHLD blocked. */
@@ -1708,10 +1737,10 @@ make_child (command, async_p)
   /* Create the child, handle severe errors.  Retry on EAGAIN. */
   while ((pid = fork ()) < 0 && errno == EAGAIN && forksleep < FORKSLEEP_MAX)
     {
-#if 0          /* for bash-4.2 */
+      /* bash-4.2 */
       /* If we can't create any children, try to reap some dead ones. */
       waitchld (-1, 0);
-#endif
+
       sys_error ("fork: retry");
       if (sleep (forksleep) != 0)
        break;
@@ -2125,7 +2154,7 @@ wait_for_single_pid (pid)
   return r;
 }
 
-/* Wait for all of the backgrounds of this shell to finish. */
+/* Wait for all of the background processes started by this shell to finish. */
 void
 wait_for_background_pids ()
 {
@@ -2306,14 +2335,14 @@ raw_job_exit_status (job)
 /* Return the exit status of job JOB.  This is the exit status of the last
    (rightmost) process in the job's pipeline, modified if the job was killed
    by a signal or stopped. */
-static int
+int
 job_exit_status (job)
      int job;
 {
   return (process_exit_status (raw_job_exit_status (job)));
 }
 
-static int
+int
 job_exit_signal (job)
      int job;
 {
@@ -2347,7 +2376,6 @@ wait_for (pid)
   WAIT s;
   register PROCESS *child;
   sigset_t set, oset;
-  register PROCESS *p;
 
   /* In the case that this code is interrupted, and we longjmp () out of it,
      we are relying on the code in throw_to_top_level () to restore the
@@ -2549,11 +2577,13 @@ if (job == NO_JOB)
                }
            }
        }
-      else if ((subshell_environment & SUBSHELL_COMSUB) && wait_sigint_received)
+      else if ((subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PIPE)) && wait_sigint_received)
        {
          /* If waiting for a job in a subshell started to do command
-            substitution, simulate getting and being killed by the SIGINT to
-            pass the status back to our parent. */
+            substitution or to run a pipeline element that consists of
+            something like a while loop or a for loop, simulate getting
+            and being killed by the SIGINT to pass the status back to our
+            parent. */
          s = job_signal_status (job);
        
          if (WIFSIGNALED (s) && WTERMSIG (s) == SIGINT && signal_is_trapped (SIGINT) == 0)
@@ -4114,7 +4144,13 @@ itrace("mark_dead_jobs_as_notified: child_max = %d ndead = %d ndeadproc = %d", j
 }
 
 /* Here to allow other parts of the shell (like the trap stuff) to
-   unfreeze the jobs list. */
+   freeze and unfreeze the jobs list. */
+void
+freeze_jobs_list ()
+{
+  jobs_list_frozen = 1;
+}
+
 void
 unfreeze_jobs_list ()
 {