]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/wait.def
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / builtins / wait.def
CommitLineData
726f6388
JA
1This file is wait.def, from which is created wait.c.
2It implements the builtin "wait" in Bash.
3
4Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
bb70624e 10Software Foundation; either version 2, or (at your option) any later
726f6388
JA
11version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING. If not, write to the Free Software
bb70624e 20Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
726f6388 21
726f6388
JA
22$BUILTIN wait
23$FUNCTION wait_builtin
24$DEPENDS_ON JOB_CONTROL
25$PRODUCES wait.c
26$SHORT_DOC wait [n]
27Wait for the specified process and report its termination status. If
28N is not given, all currently active child processes are waited for,
29and the return code is zero. N may be a process ID or a job
30specification; if a job spec is given, all processes in the job's
31pipeline are waited for.
32$END
33
34$BUILTIN wait
35$FUNCTION wait_builtin
36$DEPENDS_ON !JOB_CONTROL
37$SHORT_DOC wait [n]
38Wait for the specified process and report its termination status. If
39N is not given, all currently active child processes are waited for,
40and the return code is zero. N is a process ID; if it is not given,
41all child processes of the shell are waited for.
42$END
43
ccc6cda3
JA
44#include <config.h>
45
46#include "../bashtypes.h"
726f6388 47#include <signal.h>
ccc6cda3
JA
48
49#if defined (HAVE_UNISTD_H)
50# include <unistd.h>
51#endif
52
d166f048
JA
53#include "../bashansi.h"
54
726f6388
JA
55#include "../shell.h"
56#include "../jobs.h"
ccc6cda3 57#include "common.h"
d166f048 58#include "bashgetopt.h"
726f6388
JA
59
60extern int interrupt_immediately;
61
bb70624e
JA
62procenv_t wait_intr_buf;
63
726f6388
JA
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. */
ccc6cda3 68
28ef6c31
JA
69#define WAIT_RETURN(s) \
70 do \
71 { \
72 interrupt_immediately = old_interrupt_immediately;\
73 return (s);\
74 } \
75 while (0)
ccc6cda3
JA
76
77int
726f6388
JA
78wait_builtin (list)
79 WORD_LIST *list;
80{
bb70624e 81 int status, code;
28ef6c31 82 volatile int old_interrupt_immediately;
ccc6cda3
JA
83
84 if (no_options (list))
85 return (EX_USAGE);
d166f048
JA
86 if (list != loptend)
87 list = loptend;
726f6388 88
28ef6c31 89 old_interrupt_immediately = interrupt_immediately;
726f6388
JA
90 interrupt_immediately++;
91
bb70624e
JA
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
726f6388
JA
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. */
ccc6cda3 112 if (list == 0)
726f6388
JA
113 {
114 wait_for_background_pids ();
ccc6cda3 115 WAIT_RETURN (EXECUTION_SUCCESS);
726f6388
JA
116 }
117
ccc6cda3 118 status = EXECUTION_SUCCESS;
726f6388
JA
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 {
ccc6cda3
JA
134 builtin_error ("`%s' is not a pid or valid job spec", w);
135 WAIT_RETURN (EXECUTION_FAILURE);
726f6388
JA
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)
ccc6cda3 151 builtin_error ("%s: no such job", list->word->word);
726f6388
JA
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 }
cce855bc
JA
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 }
726f6388
JA
168#endif /* JOB_CONTROL */
169 else
170 {
ccc6cda3 171 builtin_error ("`%s' is not a pid or valid job spec", w);
726f6388
JA
172 status = EXECUTION_FAILURE;
173 }
174 list = list->next;
175 }
ccc6cda3
JA
176
177 WAIT_RETURN (status);
726f6388 178}