| This file is wait.def, from which is created wait.c. |
| It implements the builtin "wait" in Bash. |
| |
| Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc. |
| |
| This file is part of GNU Bash, the Bourne Again SHell. |
| |
| Bash is free software; you can redistribute it and/or modify it under |
| the terms of the GNU General Public License as published by the Free |
| Software Foundation; either version 1, or (at your option) any later |
| version. |
| |
| Bash is distributed in the hope that it will be useful, but WITHOUT ANY |
| WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| for more details. |
| |
| You should have received a copy of the GNU General Public License along |
| with Bash; see the file COPYING. If not, write to the Free Software |
| Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
| |
| $BUILTIN wait |
| $FUNCTION wait_builtin |
| $DEPENDS_ON JOB_CONTROL |
| $PRODUCES wait.c |
| $SHORT_DOC wait [n] |
| Wait for the specified process and report its termination status. If |
| N is not given, all currently active child processes are waited for, |
| and the return code is zero. N may be a process ID or a job |
| specification; if a job spec is given, all processes in the job's |
| pipeline are waited for. |
| $END |
| |
| $BUILTIN wait |
| $FUNCTION wait_builtin |
| $DEPENDS_ON !JOB_CONTROL |
| $SHORT_DOC wait [n] |
| Wait for the specified process and report its termination status. If |
| N is not given, all currently active child processes are waited for, |
| and the return code is zero. N is a process ID; if it is not given, |
| all child processes of the shell are waited for. |
| $END |
| |
| #include <config.h> |
| |
| #include "../bashtypes.h" |
| #include <signal.h> |
| |
| #if defined (HAVE_UNISTD_H) |
| # include <unistd.h> |
| #endif |
| |
| #include "../bashansi.h" |
| |
| #include "../shell.h" |
| #include "../jobs.h" |
| #include "common.h" |
| #include "bashgetopt.h" |
| |
| extern int interrupt_immediately; |
| |
| /* Wait for the pid in LIST to stop or die. If no arguments are given, then |
| wait for all of the active background processes of the shell and return |
| 0. If a list of pids or job specs are given, return the exit status of |
| the last one waited for. */ |
| |
| #define WAIT_RETURN(s) do { run_unwind_frame ("wait_builtin"); return (s); } while (0) |
| |
| int |
| wait_builtin (list) |
| WORD_LIST *list; |
| { |
| int status; |
| |
| if (no_options (list)) |
| return (EX_USAGE); |
| if (list != loptend) |
| list = loptend; |
| |
| begin_unwind_frame ("wait_builtin"); |
| unwind_protect_int (interrupt_immediately); |
| interrupt_immediately++; |
| |
| /* We support jobs or pids. |
| wait <pid-or-job> [pid-or-job ...] */ |
| |
| /* But wait without any arguments means to wait for all of the shell's |
| currently active background processes. */ |
| if (list == 0) |
| { |
| wait_for_background_pids (); |
| WAIT_RETURN (EXECUTION_SUCCESS); |
| } |
| |
| status = EXECUTION_SUCCESS; |
| while (list) |
| { |
| pid_t pid; |
| char *w; |
| |
| w = list->word->word; |
| if (digit (*w)) |
| { |
| if (all_digits (w + 1)) |
| { |
| pid = (pid_t)atoi (w); |
| status = wait_for_single_pid (pid); |
| } |
| else |
| { |
| builtin_error ("`%s' is not a pid or valid job spec", w); |
| WAIT_RETURN (EXECUTION_FAILURE); |
| } |
| } |
| #if defined (JOB_CONTROL) |
| else if (job_control && *w) |
| /* Must be a job spec. Check it out. */ |
| { |
| int job; |
| sigset_t set, oset; |
| |
| BLOCK_CHILD (set, oset); |
| job = get_job_spec (list); |
| |
| if (job < 0 || job >= job_slots || !jobs[job]) |
| { |
| if (job != DUP_JOB) |
| builtin_error ("%s: no such job", list->word->word); |
| UNBLOCK_CHILD (oset); |
| status = 127; /* As per Posix.2, section 4.70.2 */ |
| list = list->next; |
| continue; |
| } |
| |
| /* Job spec used. Wait for the last pid in the pipeline. */ |
| UNBLOCK_CHILD (oset); |
| status = wait_for_job (job); |
| } |
| else if (job_control == 0 && *w == '%') |
| { |
| /* can't use jobspecs as arguments if job control is not active. */ |
| builtin_error ("job control not enabled"); |
| status = EXECUTION_FAILURE; |
| } |
| #endif /* JOB_CONTROL */ |
| else |
| { |
| builtin_error ("`%s' is not a pid or valid job spec", w); |
| status = EXECUTION_FAILURE; |
| } |
| list = list->next; |
| } |
| |
| WAIT_RETURN (status); |
| } |