]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/jobs.def
Bash-4.4 patch 19
[thirdparty/bash.git] / builtins / jobs.def
1 This file is jobs.def, from which is created jobs.c.
2 It implements the builtins "jobs" and "disown" in Bash.
3
4 Copyright (C) 1987-2015 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
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.
12
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.
17
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/>.
20
21 $PRODUCES jobs.c
22
23 $BUILTIN jobs
24 $FUNCTION jobs_builtin
25 $DEPENDS_ON JOB_CONTROL
26 $SHORT_DOC jobs [-lnprs] [jobspec ...] or jobs -x command [args]
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
34 -n lists only processes that have changed status since the last
35 notification
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
42 process group leader.
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.
47 $END
48
49 #include <config.h>
50
51 #if defined (JOB_CONTROL)
52 #include "../bashtypes.h"
53 #include <signal.h>
54 #if defined (HAVE_UNISTD_H)
55 # include <unistd.h>
56 #endif
57
58 #include "../bashansi.h"
59 #include "../bashintl.h"
60
61 #include "../shell.h"
62 #include "../jobs.h"
63 #include "../execute_cmd.h"
64 #include "bashgetopt.h"
65 #include "common.h"
66
67 #define JSTATE_ANY 0x0
68 #define JSTATE_RUNNING 0x1
69 #define JSTATE_STOPPED 0x2
70
71 static int execute_list_with_replacements __P((WORD_LIST *));
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
79 group leader and execute the command. The -r and -s options mean
80 to print info about running and stopped jobs only, respectively. */
81 int
82 jobs_builtin (list)
83 WORD_LIST *list;
84 {
85 int form, execute, state, opt, any_failed, job;
86 sigset_t set, oset;
87
88 execute = any_failed = 0;
89 form = JLIST_STANDARD;
90 state = JSTATE_ANY;
91
92 reset_internal_getopt ();
93 while ((opt = internal_getopt (list, "lpnxrs")) != -1)
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 {
109 builtin_error (_("no other options allowed with `-x'"));
110 return (EXECUTION_FAILURE);
111 }
112 execute++;
113 break;
114 case 'r':
115 state = JSTATE_RUNNING;
116 break;
117 case 's':
118 state = JSTATE_STOPPED;
119 break;
120
121 CASE_HELPOPT;
122 default:
123 builtin_usage ();
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 {
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 }
147 return (EXECUTION_SUCCESS);
148 }
149
150 while (list)
151 {
152 BLOCK_CHILD (set, oset);
153 job = get_job_spec (list);
154
155 if ((job == NO_JOB) || jobs == 0 || get_job_by_jid (job) == 0)
156 {
157 sh_badjob (list->word->word);
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;
175 COMMAND *command;
176 JOB *j;
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. */
186 if (INVALID_JOB (job))
187 continue;
188
189 j = get_job_by_jid (job);
190 free (l->word->word);
191 l->word->word = itos (j->pgrp);
192 }
193 }
194
195 /* Next make a new simple command and execute it. */
196 begin_unwind_frame ("jobs_builtin");
197
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;
203
204 add_unwind_protect (dispose_command, command);
205 result = execute_command (command);
206 dispose_command (command);
207
208 discard_unwind_frame ("jobs_builtin");
209 return (result);
210 }
211 #endif /* JOB_CONTROL */
212
213 $BUILTIN disown
214 $FUNCTION disown_builtin
215 $DEPENDS_ON JOB_CONTROL
216 $SHORT_DOC disown [-h] [-ar] [jobspec ... | pid ...]
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
225 shell receives a SIGHUP
226 -r remove only running jobs
227
228 Exit Status:
229 Returns success unless an invalid option or JOBSPEC is given.
230 $END
231
232 #if defined (JOB_CONTROL)
233 int
234 disown_builtin (list)
235 WORD_LIST *list;
236 {
237 int opt, job, retval, nohup_only, running_jobs, all_jobs;
238 sigset_t set, oset;
239 intmax_t pid_value;
240
241 nohup_only = running_jobs = all_jobs = 0;
242 reset_internal_getopt ();
243 while ((opt = internal_getopt (list, "ahr")) != -1)
244 {
245 switch (opt)
246 {
247 case 'a':
248 all_jobs = 1;
249 break;
250 case 'h':
251 nohup_only = 1;
252 break;
253 case 'r':
254 running_jobs = 1;
255 break;
256 CASE_HELPOPT;
257 default:
258 builtin_usage ();
259 return (EX_USAGE);
260 }
261 }
262 list = loptend;
263 retval = EXECUTION_SUCCESS;
264
265 /* `disown -a' or `disown -r' */
266 if (list == 0 && (all_jobs || running_jobs))
267 {
268 if (nohup_only)
269 nohup_all_jobs (running_jobs);
270 else
271 delete_all_jobs (running_jobs);
272 return (EXECUTION_SUCCESS);
273 }
274
275 do
276 {
277 BLOCK_CHILD (set, oset);
278 job = (list && legal_number (list->word->word, &pid_value) && pid_value == (pid_t) pid_value)
279 ? get_job_by_pid ((pid_t) pid_value, 0)
280 : get_job_spec (list);
281
282 if (job == NO_JOB || jobs == 0 || INVALID_JOB (job))
283 {
284 sh_badjob (list ? list->word->word : _("current"));
285 retval = EXECUTION_FAILURE;
286 }
287 else if (nohup_only)
288 nohup_job (job);
289 else
290 delete_job (job, 1);
291 UNBLOCK_CHILD (oset);
292
293 if (list)
294 list = list->next;
295 }
296 while (list);
297
298 return (retval);
299 }
300 #endif /* JOB_CONTROL */