Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 1 | This file is wait.def, from which is created wait.c. |
| 2 | It implements the builtin "wait" in Bash. |
| 3 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 4 | Copyright (C) 1987-2013 Free Software Foundation, Inc. |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 5 | |
| 6 | This file is part of GNU Bash, the Bourne Again SHell. |
| 7 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 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. |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 12 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 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. |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 17 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 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/>. |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 20 | |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 21 | $BUILTIN wait |
| 22 | $FUNCTION wait_builtin |
| 23 | $DEPENDS_ON JOB_CONTROL |
| 24 | $PRODUCES wait.c |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 25 | $SHORT_DOC wait [-n] [id ...] |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 26 | Wait for job completion and return exit status. |
| 27 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 28 | Waits for each process identified by an ID, which may be a process ID or a |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 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 |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 32 | in that job's pipeline. |
| 33 | |
| 34 | If the -n option is supplied, waits for the next job to terminate and |
| 35 | returns its exit status. |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 36 | |
| 37 | Exit Status: |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 38 | Returns the status of the last ID; fails if ID is invalid or an invalid |
| 39 | option is given. |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 40 | $END |
| 41 | |
| 42 | $BUILTIN wait |
| 43 | $FUNCTION wait_builtin |
| 44 | $DEPENDS_ON !JOB_CONTROL |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 45 | $SHORT_DOC wait [pid ...] |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 46 | Wait for process completion and return exit status. |
| 47 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 48 | Waits for each process specified by a PID and reports its termination status. |
| 49 | If PID is not given, waits for all currently active child processes, |
| 50 | and the return status is zero. PID must be a process ID. |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 51 | |
| 52 | Exit Status: |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 53 | Returns the status of the last PID; fails if PID is invalid or an invalid |
| 54 | option is given. |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 55 | $END |
| 56 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 57 | #include <config.h> |
| 58 | |
| 59 | #include "../bashtypes.h" |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 60 | #include <signal.h> |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 61 | |
| 62 | #if defined (HAVE_UNISTD_H) |
| 63 | # include <unistd.h> |
| 64 | #endif |
| 65 | |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 66 | #include <chartypes.h> |
| 67 | |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 68 | #include "../bashansi.h" |
| 69 | |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 70 | #include "../shell.h" |
| 71 | #include "../jobs.h" |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 72 | #include "common.h" |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 73 | #include "bashgetopt.h" |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 74 | |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 75 | extern int wait_signal_received; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 76 | |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 77 | procenv_t wait_intr_buf; |
| 78 | |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 79 | /* Wait for the pid in LIST to stop or die. If no arguments are given, then |
| 80 | wait for all of the active background processes of the shell and return |
| 81 | 0. If a list of pids or job specs are given, return the exit status of |
| 82 | the last one waited for. */ |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 83 | |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 84 | #define WAIT_RETURN(s) \ |
| 85 | do \ |
| 86 | { \ |
| 87 | interrupt_immediately = old_interrupt_immediately;\ |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 88 | wait_signal_received = 0; \ |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 89 | return (s);\ |
| 90 | } \ |
| 91 | while (0) |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 92 | |
| 93 | int |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 94 | wait_builtin (list) |
| 95 | WORD_LIST *list; |
| 96 | { |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 97 | int status, code, opt, nflag; |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 98 | volatile int old_interrupt_immediately; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 99 | |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 100 | USE_VAR(list); |
| 101 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 102 | nflag = 0; |
| 103 | reset_internal_getopt (); |
| 104 | while ((opt = internal_getopt (list, "n")) != -1) |
| 105 | { |
| 106 | switch (opt) |
| 107 | { |
| 108 | #if defined (JOB_CONTROL) |
| 109 | case 'n': |
| 110 | nflag = 1; |
| 111 | break; |
| 112 | #endif |
| 113 | default: |
| 114 | builtin_usage (); |
| 115 | return (EX_USAGE); |
| 116 | } |
| 117 | } |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 118 | list = loptend; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 119 | |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 120 | old_interrupt_immediately = interrupt_immediately; |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 121 | #if 0 |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 122 | interrupt_immediately++; |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 123 | #endif |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 124 | |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 125 | /* POSIX.2 says: When the shell is waiting (by means of the wait utility) |
| 126 | for asynchronous commands to complete, the reception of a signal for |
| 127 | which a trap has been set shall cause the wait utility to return |
| 128 | immediately with an exit status greater than 128, after which the trap |
| 129 | associated with the signal shall be taken. |
| 130 | |
| 131 | We handle SIGINT here; it's the only one that needs to be treated |
| 132 | specially (I think), since it's handled specially in {no,}jobs.c. */ |
| 133 | code = setjmp (wait_intr_buf); |
| 134 | if (code) |
| 135 | { |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 136 | status = 128 + wait_signal_received; |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 137 | WAIT_RETURN (status); |
| 138 | } |
| 139 | |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 140 | /* We support jobs or pids. |
| 141 | wait <pid-or-job> [pid-or-job ...] */ |
| 142 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 143 | #if defined (JOB_CONTROL) |
| 144 | if (nflag) |
| 145 | { |
| 146 | status = wait_for_any_job (); |
| 147 | if (status < 0) |
| 148 | status = 127; |
| 149 | WAIT_RETURN (status); |
| 150 | } |
| 151 | #endif |
| 152 | |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 153 | /* But wait without any arguments means to wait for all of the shell's |
| 154 | currently active background processes. */ |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 155 | if (list == 0) |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 156 | { |
| 157 | wait_for_background_pids (); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 158 | WAIT_RETURN (EXECUTION_SUCCESS); |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 159 | } |
| 160 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 161 | status = EXECUTION_SUCCESS; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 162 | while (list) |
| 163 | { |
| 164 | pid_t pid; |
| 165 | char *w; |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 166 | intmax_t pid_value; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 167 | |
| 168 | w = list->word->word; |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 169 | if (DIGIT (*w)) |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 170 | { |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 171 | if (legal_number (w, &pid_value) && pid_value == (pid_t)pid_value) |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 172 | { |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 173 | pid = (pid_t)pid_value; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 174 | status = wait_for_single_pid (pid); |
| 175 | } |
| 176 | else |
| 177 | { |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 178 | sh_badpid (w); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 179 | WAIT_RETURN (EXECUTION_FAILURE); |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 180 | } |
| 181 | } |
| 182 | #if defined (JOB_CONTROL) |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 183 | else if (*w && *w == '%') |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 184 | /* Must be a job spec. Check it out. */ |
| 185 | { |
| 186 | int job; |
| 187 | sigset_t set, oset; |
| 188 | |
| 189 | BLOCK_CHILD (set, oset); |
| 190 | job = get_job_spec (list); |
| 191 | |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 192 | if (INVALID_JOB (job)) |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 193 | { |
| 194 | if (job != DUP_JOB) |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 195 | sh_badjob (list->word->word); |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 196 | UNBLOCK_CHILD (oset); |
| 197 | status = 127; /* As per Posix.2, section 4.70.2 */ |
| 198 | list = list->next; |
| 199 | continue; |
| 200 | } |
| 201 | |
| 202 | /* Job spec used. Wait for the last pid in the pipeline. */ |
| 203 | UNBLOCK_CHILD (oset); |
| 204 | status = wait_for_job (job); |
| 205 | } |
| 206 | #endif /* JOB_CONTROL */ |
| 207 | else |
| 208 | { |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 209 | sh_badpid (w); |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 210 | status = EXECUTION_FAILURE; |
| 211 | } |
| 212 | list = list->next; |
| 213 | } |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 214 | |
| 215 | WAIT_RETURN (status); |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 216 | } |