]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/jobs.def
Bash-4.3 patch 39
[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-2009 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 default:
122 builtin_usage ();
123 return (EX_USAGE);
124 }
125 }
126
127 list = loptend;
128
129 if (execute)
130 return (execute_list_with_replacements (list));
131
132 if (!list)
133 {
134 switch (state)
135 {
136 case JSTATE_ANY:
137 list_all_jobs (form);
138 break;
139 case JSTATE_RUNNING:
140 list_running_jobs (form);
141 break;
142 case JSTATE_STOPPED:
143 list_stopped_jobs (form);
144 break;
145 }
146 return (EXECUTION_SUCCESS);
147 }
148
149 while (list)
150 {
151 BLOCK_CHILD (set, oset);
152 job = get_job_spec (list);
153
154 if ((job == NO_JOB) || jobs == 0 || get_job_by_jid (job) == 0)
155 {
156 sh_badjob (list->word->word);
157 any_failed++;
158 }
159 else if (job != DUP_JOB)
160 list_one_job ((JOB *)NULL, form, 0, job);
161
162 UNBLOCK_CHILD (oset);
163 list = list->next;
164 }
165 return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
166 }
167
168 static int
169 execute_list_with_replacements (list)
170 WORD_LIST *list;
171 {
172 register WORD_LIST *l;
173 int job, result;
174 COMMAND *command;
175 JOB *j;
176
177 /* First do the replacement of job specifications with pids. */
178 for (l = list; l; l = l->next)
179 {
180 if (l->word->word[0] == '%') /* we have a winner */
181 {
182 job = get_job_spec (l);
183
184 /* A bad job spec is not really a job spec! Pass it through. */
185 if (INVALID_JOB (job))
186 continue;
187
188 j = get_job_by_jid (job);
189 free (l->word->word);
190 l->word->word = itos (j->pgrp);
191 }
192 }
193
194 /* Next make a new simple command and execute it. */
195 begin_unwind_frame ("jobs_builtin");
196
197 command = make_bare_simple_command ();
198 command->value.Simple->words = copy_word_list (list);
199 command->value.Simple->redirects = (REDIRECT *)NULL;
200 command->flags |= CMD_INHIBIT_EXPANSION;
201 command->value.Simple->flags |= CMD_INHIBIT_EXPANSION;
202
203 add_unwind_protect (dispose_command, command);
204 result = execute_command (command);
205 dispose_command (command);
206
207 discard_unwind_frame ("jobs_builtin");
208 return (result);
209 }
210 #endif /* JOB_CONTROL */
211
212 $BUILTIN disown
213 $FUNCTION disown_builtin
214 $DEPENDS_ON JOB_CONTROL
215 $SHORT_DOC disown [-h] [-ar] [jobspec ...]
216 Remove jobs from current shell.
217
218 Removes each JOBSPEC argument from the table of active jobs. Without
219 any JOBSPECs, the shell uses its notion of the current job.
220
221 Options:
222 -a remove all jobs if JOBSPEC is not supplied
223 -h mark each JOBSPEC so that SIGHUP is not sent to the job if the
224 shell receives a SIGHUP
225 -r remove only running jobs
226
227 Exit Status:
228 Returns success unless an invalid option or JOBSPEC is given.
229 $END
230
231 #if defined (JOB_CONTROL)
232 int
233 disown_builtin (list)
234 WORD_LIST *list;
235 {
236 int opt, job, retval, nohup_only, running_jobs, all_jobs;
237 sigset_t set, oset;
238 intmax_t pid_value;
239
240 nohup_only = running_jobs = all_jobs = 0;
241 reset_internal_getopt ();
242 while ((opt = internal_getopt (list, "ahr")) != -1)
243 {
244 switch (opt)
245 {
246 case 'a':
247 all_jobs = 1;
248 break;
249 case 'h':
250 nohup_only = 1;
251 break;
252 case 'r':
253 running_jobs = 1;
254 break;
255 default:
256 builtin_usage ();
257 return (EX_USAGE);
258 }
259 }
260 list = loptend;
261 retval = EXECUTION_SUCCESS;
262
263 /* `disown -a' or `disown -r' */
264 if (list == 0 && (all_jobs || running_jobs))
265 {
266 if (nohup_only)
267 nohup_all_jobs (running_jobs);
268 else
269 delete_all_jobs (running_jobs);
270 return (EXECUTION_SUCCESS);
271 }
272
273 do
274 {
275 BLOCK_CHILD (set, oset);
276 job = (list && legal_number (list->word->word, &pid_value) && pid_value == (pid_t) pid_value)
277 ? get_job_by_pid ((pid_t) pid_value, 0)
278 : get_job_spec (list);
279
280 if (job == NO_JOB || jobs == 0 || INVALID_JOB (job))
281 {
282 sh_badjob (list ? list->word->word : _("current"));
283 retval = EXECUTION_FAILURE;
284 }
285 else if (nohup_only)
286 nohup_job (job);
287 else
288 delete_job (job, 1);
289 UNBLOCK_CHILD (oset);
290
291 if (list)
292 list = list->next;
293 }
294 while (list);
295
296 return (retval);
297 }
298 #endif /* JOB_CONTROL */