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