0206926f3f9fe48e9609de38d6ccda7265fbb898
[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-2009 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
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Bash is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Bash.  If not, see <http://www.gnu.org/licenses/>.
20
21 $BUILTIN wait
22 $FUNCTION wait_builtin
23 $DEPENDS_ON JOB_CONTROL
24 $PRODUCES wait.c
25 $SHORT_DOC wait [id]
26 Wait for job completion and return exit status.
27
28 Waits for the process identified by ID, which may be a process ID or a
29 job specification, and reports its termination status.  If ID is not
30 given, waits for all currently active child processes, and the return
31 status is zero.  If ID is a a job specification, waits for all processes
32 in the job's pipeline.
33
34 Exit Status:
35 Returns the status of ID; fails if ID is invalid or an invalid option is
36 given.
37 $END
38
39 $BUILTIN wait
40 $FUNCTION wait_builtin
41 $DEPENDS_ON !JOB_CONTROL
42 $SHORT_DOC wait [pid]
43 Wait for process completion and return exit status.
44
45 Waits for the specified process and reports its termination status.  If
46 PID is not given, all currently active child processes are waited for,
47 and the return code is zero.  PID must be a process ID.
48
49 Exit Status:
50 Returns the status of ID; fails if ID is invalid or an invalid option is
51 given.
52 $END
53
54 #include <config.h>
55
56 #include "../bashtypes.h"
57 #include <signal.h>
58
59 #if defined (HAVE_UNISTD_H)
60 #  include <unistd.h>
61 #endif
62
63 #include <chartypes.h>
64
65 #include "../bashansi.h"
66
67 #include "../shell.h"
68 #include "../jobs.h"
69 #include "common.h"
70 #include "bashgetopt.h"
71
72 extern int wait_signal_received;
73
74 procenv_t wait_intr_buf;
75
76 /* Wait for the pid in LIST to stop or die.  If no arguments are given, then
77    wait for all of the active background processes of the shell and return
78    0.  If a list of pids or job specs are given, return the exit status of
79    the last one waited for. */
80
81 #define WAIT_RETURN(s) \
82   do \
83     { \
84       interrupt_immediately = old_interrupt_immediately;\
85       return (s);\
86     } \
87   while (0)
88
89 int
90 wait_builtin (list)
91      WORD_LIST *list;
92 {
93   int status, code;
94   volatile int old_interrupt_immediately;
95
96   USE_VAR(list);
97
98   if (no_options (list))
99     return (EX_USAGE);
100   list = loptend;
101
102   old_interrupt_immediately = interrupt_immediately;
103   interrupt_immediately++;
104
105   /* POSIX.2 says:  When the shell is waiting (by means of the wait utility)
106      for asynchronous commands to complete, the reception of a signal for
107      which a trap has been set shall cause the wait utility to return
108      immediately with an exit status greater than 128, after which the trap
109      associated with the signal shall be taken.
110
111      We handle SIGINT here; it's the only one that needs to be treated
112      specially (I think), since it's handled specially in {no,}jobs.c. */
113   code = setjmp (wait_intr_buf);
114   if (code)
115     {
116       status = 128 + wait_signal_received;
117       WAIT_RETURN (status);
118     }
119
120   /* We support jobs or pids.
121      wait <pid-or-job> [pid-or-job ...] */
122
123   /* But wait without any arguments means to wait for all of the shell's
124      currently active background processes. */
125   if (list == 0)
126     {
127       wait_for_background_pids ();
128       WAIT_RETURN (EXECUTION_SUCCESS);
129     }
130
131   status = EXECUTION_SUCCESS;
132   while (list)
133     {
134       pid_t pid;
135       char *w;
136       intmax_t pid_value;
137
138       w = list->word->word;
139       if (DIGIT (*w))
140         {
141           if (legal_number (w, &pid_value) && pid_value == (pid_t)pid_value)
142             {
143               pid = (pid_t)pid_value;
144               status = wait_for_single_pid (pid);
145             }
146           else
147             {
148               sh_badpid (w);
149               WAIT_RETURN (EXECUTION_FAILURE);
150             }
151         }
152 #if defined (JOB_CONTROL)
153       else if (*w && *w == '%')
154         /* Must be a job spec.  Check it out. */
155         {
156           int job;
157           sigset_t set, oset;
158
159           BLOCK_CHILD (set, oset);
160           job = get_job_spec (list);
161
162           if (INVALID_JOB (job))
163             {
164               if (job != DUP_JOB)
165                 sh_badjob (list->word->word);
166               UNBLOCK_CHILD (oset);
167               status = 127;     /* As per Posix.2, section 4.70.2 */
168               list = list->next;
169               continue;
170             }
171
172           /* Job spec used.  Wait for the last pid in the pipeline. */
173           UNBLOCK_CHILD (oset);
174           status = wait_for_job (job);
175         }
176 #endif /* JOB_CONTROL */
177       else
178         {
179           sh_badpid (w);
180           status = EXECUTION_FAILURE;
181         }
182       list = list->next;
183     }
184
185   WAIT_RETURN (status);
186 }