]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/jobs.def
Bash-4.3 patch 11
[thirdparty/bash.git] / builtins / jobs.def
CommitLineData
726f6388 1This file is jobs.def, from which is created jobs.c.
ccc6cda3 2It implements the builtins "jobs" and "disown" in Bash.
726f6388 3
3185942a 4Copyright (C) 1987-2009 Free Software Foundation, Inc.
726f6388
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
3185942a
JA
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
726f6388 12
3185942a
JA
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
726f6388 17
3185942a
JA
18You should have received a copy of the GNU General Public License
19along 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
27Display status of jobs.
28
29Lists the active jobs. JOBSPEC restricts output to that job.
30Without options, the status of all active jobs is displayed.
31
32Options:
33 -l lists process IDs in addition to the normal information
ac50fbac 34 -n lists only processes that have changed status since the last
3185942a
JA
35 notification
36 -p lists process IDs only
37 -r restrict output to running jobs
38 -s restrict output to stopped jobs
39
40If -x is supplied, COMMAND is run after all job specifications that
41appear in ARGS have been replaced with the process ID of that job's
ccc6cda3 42process group leader.
3185942a
JA
43
44Exit Status:
45Returns success unless an invalid option is given or an error occurs.
46If -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
f73dda09 71static int execute_list_with_replacements __P((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
81int
82jobs_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
JA
120
121 default:
ccc6cda3 122 builtin_usage ();
726f6388
JA
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 {
ccc6cda3
JA
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 }
726f6388
JA
146 return (EXECUTION_SUCCESS);
147 }
148
149 while (list)
150 {
726f6388
JA
151 BLOCK_CHILD (set, oset);
152 job = get_job_spec (list);
153
95732b49 154 if ((job == NO_JOB) || jobs == 0 || get_job_by_jid (job) == 0)
726f6388 155 {
7117c2d2 156 sh_badjob (list->word->word);
726f6388
JA
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
168static int
169execute_list_with_replacements (list)
170 WORD_LIST *list;
171{
172 register WORD_LIST *l;
173 int job, result;
b80f6443 174 COMMAND *command;
95732b49 175 JOB *j;
726f6388
JA
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. */
95732b49 185 if (INVALID_JOB (job))
726f6388
JA
186 continue;
187
95732b49 188 j = get_job_by_jid (job);
726f6388 189 free (l->word->word);
95732b49 190 l->word->word = itos (j->pgrp);
726f6388
JA
191 }
192 }
193
194 /* Next make a new simple command and execute it. */
195 begin_unwind_frame ("jobs_builtin");
726f6388 196
b80f6443
JA
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;
726f6388 202
b80f6443
JA
203 add_unwind_protect (dispose_command, command);
204 result = execute_command (command);
205 dispose_command (command);
726f6388 206
b80f6443 207 discard_unwind_frame ("jobs_builtin");
726f6388
JA
208 return (result);
209}
210#endif /* JOB_CONTROL */
ccc6cda3
JA
211
212$BUILTIN disown
213$FUNCTION disown_builtin
214$DEPENDS_ON JOB_CONTROL
cce855bc 215$SHORT_DOC disown [-h] [-ar] [jobspec ...]
3185942a
JA
216Remove jobs from current shell.
217
218Removes each JOBSPEC argument from the table of active jobs. Without
219any JOBSPECs, the shell uses its notion of the current job.
220
221Options:
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
227Exit Status:
228Returns success unless an invalid option or JOBSPEC is given.
ccc6cda3
JA
229$END
230
231#if defined (JOB_CONTROL)
232int
233disown_builtin (list)
234 WORD_LIST *list;
235{
cce855bc 236 int opt, job, retval, nohup_only, running_jobs, all_jobs;
ccc6cda3 237 sigset_t set, oset;
7117c2d2 238 intmax_t pid_value;
ccc6cda3 239
cce855bc 240 nohup_only = running_jobs = all_jobs = 0;
ccc6cda3 241 reset_internal_getopt ();
cce855bc 242 while ((opt = internal_getopt (list, "ahr")) != -1)
ccc6cda3
JA
243 {
244 switch (opt)
245 {
cce855bc
JA
246 case 'a':
247 all_jobs = 1;
248 break;
ccc6cda3
JA
249 case 'h':
250 nohup_only = 1;
251 break;
cce855bc
JA
252 case 'r':
253 running_jobs = 1;
254 break;
ccc6cda3
JA
255 default:
256 builtin_usage ();
257 return (EX_USAGE);
258 }
259 }
260 list = loptend;
261 retval = EXECUTION_SUCCESS;
262
cce855bc
JA
263 /* `disown -a' or `disown -r' */
264 if (list == 0 && (all_jobs || running_jobs))
d166f048
JA
265 {
266 if (nohup_only)
cce855bc 267 nohup_all_jobs (running_jobs);
d166f048 268 else
cce855bc 269 delete_all_jobs (running_jobs);
d166f048
JA
270 return (EXECUTION_SUCCESS);
271 }
d166f048 272
ccc6cda3
JA
273 do
274 {
275 BLOCK_CHILD (set, oset);
f73dda09
JA
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)
d166f048 278 : get_job_spec (list);
ccc6cda3 279
95732b49 280 if (job == NO_JOB || jobs == 0 || INVALID_JOB (job))
ccc6cda3 281 {
3185942a 282 sh_badjob (list ? list->word->word : _("current"));
ccc6cda3
JA
283 retval = EXECUTION_FAILURE;
284 }
285 else if (nohup_only)
286 nohup_job (job);
287 else
cce855bc 288 delete_job (job, 1);
ccc6cda3
JA
289 UNBLOCK_CHILD (oset);
290
291 if (list)
292 list = list->next;
293 }
294 while (list);
d166f048 295
ccc6cda3
JA
296 return (retval);
297}
298#endif /* JOB_CONTROL */