2e3fac5776241fd1c000be822b221d000b4f99a8
[platform/upstream/bash.git] / builtins / wait.def
1 This file is wait.def, from which is created wait.c.
2 It implements the builtin "wait" in Bash.
3
4 Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING.  If not, write to the Free Software
20 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
21
22 $BUILTIN wait
23 $FUNCTION wait_builtin
24 $DEPENDS_ON JOB_CONTROL
25 $PRODUCES wait.c
26 $SHORT_DOC wait [n]
27 Wait for the specified process and report its termination status.  If
28 N is not given, all currently active child processes are waited for,
29 and the return code is zero.  N may be a process ID or a job
30 specification; if a job spec is given, all processes in the job's
31 pipeline are waited for.
32 $END
33
34 $BUILTIN wait
35 $FUNCTION wait_builtin
36 $DEPENDS_ON !JOB_CONTROL
37 $SHORT_DOC wait [n]
38 Wait for the specified process and report its termination status.  If
39 N is not given, all currently active child processes are waited for,
40 and the return code is zero.  N is a process ID; if it is not given,
41 all child processes of the shell are waited for.
42 $END
43
44 #include <config.h>
45
46 #include "../bashtypes.h"
47 #include <signal.h>
48
49 #if defined (HAVE_UNISTD_H)
50 #  include <unistd.h>
51 #endif
52
53 #include "../bashansi.h"
54
55 #include "../shell.h"
56 #include "../jobs.h"
57 #include "common.h"
58 #include "bashgetopt.h"
59
60 extern int interrupt_immediately;
61
62 procenv_t wait_intr_buf;
63
64 /* Wait for the pid in LIST to stop or die.  If no arguments are given, then
65    wait for all of the active background processes of the shell and return
66    0.  If a list of pids or job specs are given, return the exit status of
67    the last one waited for. */
68
69 #define WAIT_RETURN(s) do { run_unwind_frame ("wait_builtin"); return (s); } while (0)
70
71 int
72 wait_builtin (list)
73      WORD_LIST *list;
74 {
75   int status, code;
76
77   if (no_options (list))
78     return (EX_USAGE);
79   if (list != loptend)
80     list = loptend;
81
82   begin_unwind_frame ("wait_builtin");
83   unwind_protect_int (interrupt_immediately);
84   interrupt_immediately++;
85
86   /* POSIX.2 says:  When the shell is waiting (by means of the wait utility)
87      for asynchronous commands to complete, the reception of a signal for
88      which a trap has been set shall cause the wait utility to return
89      immediately with an exit status greater than 128, after which the trap
90      associated with the signal shall be taken.
91
92      We handle SIGINT here; it's the only one that needs to be treated
93      specially (I think), since it's handled specially in {no,}jobs.c. */
94   code = setjmp (wait_intr_buf);
95   if (code)
96     {
97       status = 128 + SIGINT;
98       WAIT_RETURN (status);
99     }
100
101   /* We support jobs or pids.
102      wait <pid-or-job> [pid-or-job ...] */
103
104   /* But wait without any arguments means to wait for all of the shell's
105      currently active background processes. */
106   if (list == 0)
107     {
108       wait_for_background_pids ();
109       WAIT_RETURN (EXECUTION_SUCCESS);
110     }
111
112   status = EXECUTION_SUCCESS;
113   while (list)
114     {
115       pid_t pid;
116       char *w;
117
118       w = list->word->word;
119       if (digit (*w))
120         {
121           if (all_digits (w + 1))
122             {
123               pid = (pid_t)atoi (w);
124               status = wait_for_single_pid (pid);
125             }
126           else
127             {
128               builtin_error ("`%s' is not a pid or valid job spec", w);
129               WAIT_RETURN (EXECUTION_FAILURE);
130             }
131         }
132 #if defined (JOB_CONTROL)
133       else if (job_control && *w)
134         /* Must be a job spec.  Check it out. */
135         {
136           int job;
137           sigset_t set, oset;
138
139           BLOCK_CHILD (set, oset);
140           job = get_job_spec (list);
141
142           if (job < 0 || job >= job_slots || !jobs[job])
143             {
144               if (job != DUP_JOB)
145                 builtin_error ("%s: no such job", list->word->word);
146               UNBLOCK_CHILD (oset);
147               status = 127;     /* As per Posix.2, section 4.70.2 */
148               list = list->next;
149               continue;
150             }
151
152           /* Job spec used.  Wait for the last pid in the pipeline. */
153           UNBLOCK_CHILD (oset);
154           status = wait_for_job (job);
155         }
156       else if (job_control == 0 && *w == '%')
157         {
158           /* can't use jobspecs as arguments if job control is not active. */
159           builtin_error ("job control not enabled");
160           status = EXECUTION_FAILURE;
161         }
162 #endif /* JOB_CONTROL */
163       else
164         {
165           builtin_error ("`%s' is not a pid or valid job spec", w);
166           status = EXECUTION_FAILURE;
167         }
168       list = list->next;
169     }
170
171   WAIT_RETURN (status);
172 }