]>
Commit | Line | Data |
---|---|---|
726f6388 | 1 | This file is jobs.def, from which is created jobs.c. |
ccc6cda3 | 2 | It implements the builtins "jobs" and "disown" in Bash. |
726f6388 | 3 | |
8868edaf | 4 | Copyright (C) 1987-2020 Free Software Foundation, Inc. |
726f6388 JA |
5 | |
6 | This file is part of GNU Bash, the Bourne Again SHell. | |
7 | ||
3185942a JA |
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. | |
726f6388 | 12 | |
3185942a JA |
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. | |
726f6388 | 17 | |
3185942a JA |
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/>. | |
726f6388 JA |
20 | |
21 | $PRODUCES jobs.c | |
22 | ||
23 | $BUILTIN jobs | |
24 | $FUNCTION jobs_builtin | |
25 | $DEPENDS_ON JOB_CONTROL | |
ccc6cda3 | 26 | $SHORT_DOC jobs [-lnprs] [jobspec ...] or jobs -x command [args] |
3185942a JA |
27 | Display status of jobs. |
28 | ||
29 | Lists the active jobs. JOBSPEC restricts output to that job. | |
30 | Without options, the status of all active jobs is displayed. | |
31 | ||
32 | Options: | |
33 | -l lists process IDs in addition to the normal information | |
ac50fbac | 34 | -n lists only processes that have changed status since the last |
a0c0a00f | 35 | notification |
3185942a JA |
36 | -p lists process IDs only |
37 | -r restrict output to running jobs | |
38 | -s restrict output to stopped jobs | |
39 | ||
40 | If -x is supplied, COMMAND is run after all job specifications that | |
41 | appear in ARGS have been replaced with the process ID of that job's | |
ccc6cda3 | 42 | process group leader. |
3185942a JA |
43 | |
44 | Exit Status: | |
45 | Returns success unless an invalid option is given or an error occurs. | |
46 | If -x is used, returns the exit status of COMMAND. | |
726f6388 JA |
47 | $END |
48 | ||
ccc6cda3 | 49 | #include <config.h> |
726f6388 JA |
50 | |
51 | #if defined (JOB_CONTROL) | |
ccc6cda3 | 52 | #include "../bashtypes.h" |
726f6388 | 53 | #include <signal.h> |
ccc6cda3 JA |
54 | #if defined (HAVE_UNISTD_H) |
55 | # include <unistd.h> | |
56 | #endif | |
57 | ||
58 | #include "../bashansi.h" | |
b80f6443 | 59 | #include "../bashintl.h" |
726f6388 | 60 | |
ccc6cda3 JA |
61 | #include "../shell.h" |
62 | #include "../jobs.h" | |
63 | #include "../execute_cmd.h" | |
726f6388 | 64 | #include "bashgetopt.h" |
ccc6cda3 JA |
65 | #include "common.h" |
66 | ||
67 | #define JSTATE_ANY 0x0 | |
68 | #define JSTATE_RUNNING 0x1 | |
69 | #define JSTATE_STOPPED 0x2 | |
726f6388 | 70 | |
8868edaf | 71 | static int execute_list_with_replacements PARAMS((WORD_LIST *)); |
726f6388 JA |
72 | |
73 | /* The `jobs' command. Prints outs a list of active jobs. If the | |
74 | argument `-l' is given, then the process id's are printed also. | |
75 | If the argument `-p' is given, print the process group leader's | |
76 | pid only. If `-n' is given, only processes that have changed | |
77 | status since the last notification are printed. If -x is given, | |
78 | replace all job specs with the pid of the appropriate process | |
ccc6cda3 JA |
79 | group leader and execute the command. The -r and -s options mean |
80 | to print info about running and stopped jobs only, respectively. */ | |
726f6388 JA |
81 | int |
82 | jobs_builtin (list) | |
83 | WORD_LIST *list; | |
84 | { | |
ccc6cda3 JA |
85 | int form, execute, state, opt, any_failed, job; |
86 | sigset_t set, oset; | |
726f6388 | 87 | |
ccc6cda3 JA |
88 | execute = any_failed = 0; |
89 | form = JLIST_STANDARD; | |
90 | state = JSTATE_ANY; | |
91 | ||
726f6388 | 92 | reset_internal_getopt (); |
ccc6cda3 | 93 | while ((opt = internal_getopt (list, "lpnxrs")) != -1) |
726f6388 JA |
94 | { |
95 | switch (opt) | |
96 | { | |
97 | case 'l': | |
98 | form = JLIST_LONG; | |
99 | break; | |
100 | case 'p': | |
101 | form = JLIST_PID_ONLY; | |
102 | break; | |
103 | case 'n': | |
104 | form = JLIST_CHANGED_ONLY; | |
105 | break; | |
106 | case 'x': | |
107 | if (form != JLIST_STANDARD) | |
108 | { | |
b80f6443 | 109 | builtin_error (_("no other options allowed with `-x'")); |
726f6388 JA |
110 | return (EXECUTION_FAILURE); |
111 | } | |
112 | execute++; | |
113 | break; | |
ccc6cda3 JA |
114 | case 'r': |
115 | state = JSTATE_RUNNING; | |
116 | break; | |
117 | case 's': | |
118 | state = JSTATE_STOPPED; | |
119 | break; | |
726f6388 | 120 | |
a0c0a00f | 121 | CASE_HELPOPT; |
726f6388 | 122 | default: |
ccc6cda3 | 123 | builtin_usage (); |
726f6388 JA |
124 | return (EX_USAGE); |
125 | } | |
126 | } | |
127 | ||
128 | list = loptend; | |
129 | ||
130 | if (execute) | |
131 | return (execute_list_with_replacements (list)); | |
132 | ||
133 | if (!list) | |
134 | { | |
ccc6cda3 JA |
135 | switch (state) |
136 | { | |
137 | case JSTATE_ANY: | |
138 | list_all_jobs (form); | |
139 | break; | |
140 | case JSTATE_RUNNING: | |
141 | list_running_jobs (form); | |
142 | break; | |
143 | case JSTATE_STOPPED: | |
144 | list_stopped_jobs (form); | |
145 | break; | |
146 | } | |
726f6388 JA |
147 | return (EXECUTION_SUCCESS); |
148 | } | |
149 | ||
150 | while (list) | |
151 | { | |
726f6388 JA |
152 | BLOCK_CHILD (set, oset); |
153 | job = get_job_spec (list); | |
154 | ||
95732b49 | 155 | if ((job == NO_JOB) || jobs == 0 || get_job_by_jid (job) == 0) |
726f6388 | 156 | { |
7117c2d2 | 157 | sh_badjob (list->word->word); |
726f6388 JA |
158 | any_failed++; |
159 | } | |
160 | else if (job != DUP_JOB) | |
161 | list_one_job ((JOB *)NULL, form, 0, job); | |
162 | ||
163 | UNBLOCK_CHILD (oset); | |
164 | list = list->next; | |
165 | } | |
166 | return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS); | |
167 | } | |
168 | ||
169 | static int | |
170 | execute_list_with_replacements (list) | |
171 | WORD_LIST *list; | |
172 | { | |
173 | register WORD_LIST *l; | |
174 | int job, result; | |
b80f6443 | 175 | COMMAND *command; |
95732b49 | 176 | JOB *j; |
726f6388 JA |
177 | |
178 | /* First do the replacement of job specifications with pids. */ | |
179 | for (l = list; l; l = l->next) | |
180 | { | |
181 | if (l->word->word[0] == '%') /* we have a winner */ | |
182 | { | |
183 | job = get_job_spec (l); | |
184 | ||
185 | /* A bad job spec is not really a job spec! Pass it through. */ | |
95732b49 | 186 | if (INVALID_JOB (job)) |
726f6388 JA |
187 | continue; |
188 | ||
95732b49 | 189 | j = get_job_by_jid (job); |
726f6388 | 190 | free (l->word->word); |
95732b49 | 191 | l->word->word = itos (j->pgrp); |
726f6388 JA |
192 | } |
193 | } | |
194 | ||
195 | /* Next make a new simple command and execute it. */ | |
196 | begin_unwind_frame ("jobs_builtin"); | |
726f6388 | 197 | |
b80f6443 JA |
198 | command = make_bare_simple_command (); |
199 | command->value.Simple->words = copy_word_list (list); | |
200 | command->value.Simple->redirects = (REDIRECT *)NULL; | |
201 | command->flags |= CMD_INHIBIT_EXPANSION; | |
202 | command->value.Simple->flags |= CMD_INHIBIT_EXPANSION; | |
726f6388 | 203 | |
b80f6443 JA |
204 | add_unwind_protect (dispose_command, command); |
205 | result = execute_command (command); | |
206 | dispose_command (command); | |
726f6388 | 207 | |
b80f6443 | 208 | discard_unwind_frame ("jobs_builtin"); |
726f6388 JA |
209 | return (result); |
210 | } | |
211 | #endif /* JOB_CONTROL */ | |
ccc6cda3 JA |
212 | |
213 | $BUILTIN disown | |
214 | $FUNCTION disown_builtin | |
215 | $DEPENDS_ON JOB_CONTROL | |
a0c0a00f | 216 | $SHORT_DOC disown [-h] [-ar] [jobspec ... | pid ...] |
3185942a JA |
217 | Remove jobs from current shell. |
218 | ||
219 | Removes each JOBSPEC argument from the table of active jobs. Without | |
220 | any JOBSPECs, the shell uses its notion of the current job. | |
221 | ||
222 | Options: | |
223 | -a remove all jobs if JOBSPEC is not supplied | |
224 | -h mark each JOBSPEC so that SIGHUP is not sent to the job if the | |
a0c0a00f | 225 | shell receives a SIGHUP |
3185942a JA |
226 | -r remove only running jobs |
227 | ||
228 | Exit Status: | |
229 | Returns success unless an invalid option or JOBSPEC is given. | |
ccc6cda3 JA |
230 | $END |
231 | ||
232 | #if defined (JOB_CONTROL) | |
233 | int | |
234 | disown_builtin (list) | |
235 | WORD_LIST *list; | |
236 | { | |
cce855bc | 237 | int opt, job, retval, nohup_only, running_jobs, all_jobs; |
ccc6cda3 | 238 | sigset_t set, oset; |
7117c2d2 | 239 | intmax_t pid_value; |
ccc6cda3 | 240 | |
cce855bc | 241 | nohup_only = running_jobs = all_jobs = 0; |
ccc6cda3 | 242 | reset_internal_getopt (); |
cce855bc | 243 | while ((opt = internal_getopt (list, "ahr")) != -1) |
ccc6cda3 JA |
244 | { |
245 | switch (opt) | |
246 | { | |
cce855bc JA |
247 | case 'a': |
248 | all_jobs = 1; | |
249 | break; | |
ccc6cda3 JA |
250 | case 'h': |
251 | nohup_only = 1; | |
252 | break; | |
cce855bc JA |
253 | case 'r': |
254 | running_jobs = 1; | |
255 | break; | |
a0c0a00f | 256 | CASE_HELPOPT; |
ccc6cda3 JA |
257 | default: |
258 | builtin_usage (); | |
259 | return (EX_USAGE); | |
260 | } | |
261 | } | |
262 | list = loptend; | |
263 | retval = EXECUTION_SUCCESS; | |
264 | ||
cce855bc JA |
265 | /* `disown -a' or `disown -r' */ |
266 | if (list == 0 && (all_jobs || running_jobs)) | |
d166f048 JA |
267 | { |
268 | if (nohup_only) | |
cce855bc | 269 | nohup_all_jobs (running_jobs); |
d166f048 | 270 | else |
cce855bc | 271 | delete_all_jobs (running_jobs); |
d166f048 JA |
272 | return (EXECUTION_SUCCESS); |
273 | } | |
d166f048 | 274 | |
ccc6cda3 JA |
275 | do |
276 | { | |
277 | BLOCK_CHILD (set, oset); | |
f73dda09 | 278 | job = (list && legal_number (list->word->word, &pid_value) && pid_value == (pid_t) pid_value) |
8868edaf | 279 | ? get_job_by_pid ((pid_t) pid_value, 0, 0) |
d166f048 | 280 | : get_job_spec (list); |
ccc6cda3 | 281 | |
95732b49 | 282 | if (job == NO_JOB || jobs == 0 || INVALID_JOB (job)) |
ccc6cda3 | 283 | { |
3185942a | 284 | sh_badjob (list ? list->word->word : _("current")); |
ccc6cda3 JA |
285 | retval = EXECUTION_FAILURE; |
286 | } | |
287 | else if (nohup_only) | |
288 | nohup_job (job); | |
289 | else | |
cce855bc | 290 | delete_job (job, 1); |
ccc6cda3 JA |
291 | UNBLOCK_CHILD (oset); |
292 | ||
293 | if (list) | |
294 | list = list->next; | |
295 | } | |
296 | while (list); | |
d166f048 | 297 | |
ccc6cda3 JA |
298 | return (retval); |
299 | } | |
300 | #endif /* JOB_CONTROL */ |