5154a776d3221389e8bd55e5233fdcb305bff0fb
[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) \
70   do \
71     { \
72       interrupt_immediately = old_interrupt_immediately;\
73       return (s);\
74     } \
75   while (0)
76
77 int
78 wait_builtin (list)
79      WORD_LIST *list;
80 {
81   int status, code;
82   volatile int old_interrupt_immediately;
83
84   if (no_options (list))
85     return (EX_USAGE);
86   if (list != loptend)
87     list = loptend;
88
89   old_interrupt_immediately = interrupt_immediately;
90   interrupt_immediately++;
91
92   /* POSIX.2 says:  When the shell is waiting (by means of the wait utility)
93      for asynchronous commands to complete, the reception of a signal for
94      which a trap has been set shall cause the wait utility to return
95      immediately with an exit status greater than 128, after which the trap
96      associated with the signal shall be taken.
97
98      We handle SIGINT here; it's the only one that needs to be treated
99      specially (I think), since it's handled specially in {no,}jobs.c. */
100   code = setjmp (wait_intr_buf);
101   if (code)
102     {
103       status = 128 + SIGINT;
104       WAIT_RETURN (status);
105     }
106
107   /* We support jobs or pids.
108      wait <pid-or-job> [pid-or-job ...] */
109
110   /* But wait without any arguments means to wait for all of the shell's
111      currently active background processes. */
112   if (list == 0)
113     {
114       wait_for_background_pids ();
115       WAIT_RETURN (EXECUTION_SUCCESS);
116     }
117
118   status = EXECUTION_SUCCESS;
119   while (list)
120     {
121       pid_t pid;
122       char *w;
123
124       w = list->word->word;
125       if (digit (*w))
126         {
127           if (all_digits (w + 1))
128             {
129               pid = (pid_t)atoi (w);
130               status = wait_for_single_pid (pid);
131             }
132           else
133             {
134               builtin_error ("`%s' is not a pid or valid job spec", w);
135               WAIT_RETURN (EXECUTION_FAILURE);
136             }
137         }
138 #if defined (JOB_CONTROL)
139       else if (job_control && *w)
140         /* Must be a job spec.  Check it out. */
141         {
142           int job;
143           sigset_t set, oset;
144
145           BLOCK_CHILD (set, oset);
146           job = get_job_spec (list);
147
148           if (job < 0 || job >= job_slots || !jobs[job])
149             {
150               if (job != DUP_JOB)
151                 builtin_error ("%s: no such job", list->word->word);
152               UNBLOCK_CHILD (oset);
153               status = 127;     /* As per Posix.2, section 4.70.2 */
154               list = list->next;
155               continue;
156             }
157
158           /* Job spec used.  Wait for the last pid in the pipeline. */
159           UNBLOCK_CHILD (oset);
160           status = wait_for_job (job);
161         }
162       else if (job_control == 0 && *w == '%')
163         {
164           /* can't use jobspecs as arguments if job control is not active. */
165           builtin_error ("job control not enabled");
166           status = EXECUTION_FAILURE;
167         }
168 #endif /* JOB_CONTROL */
169       else
170         {
171           builtin_error ("`%s' is not a pid or valid job spec", w);
172           status = EXECUTION_FAILURE;
173         }
174       list = list->next;
175     }
176
177   WAIT_RETURN (status);
178 }