blob: 47da58e495a0dcc7b6f13a3371b4f4e42f9c51ca [file] [log] [blame]
Jari Aalto726f6381996-08-26 18:22:31 +00001This file is jobs.def, from which is created jobs.c.
Jari Aaltoccc6cda1996-12-23 17:02:34 +00002It implements the builtins "jobs" and "disown" in Bash.
Jari Aalto726f6381996-08-26 18:22:31 +00003
Jari Aalto31859422009-01-12 13:36:28 +00004Copyright (C) 1987-2009 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00005
6This file is part of GNU Bash, the Bourne Again SHell.
7
Jari Aalto31859422009-01-12 13:36:28 +00008Bash 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.
Jari Aalto726f6381996-08-26 18:22:31 +000012
Jari Aalto31859422009-01-12 13:36:28 +000013Bash 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.
Jari Aalto726f6381996-08-26 18:22:31 +000017
Jari Aalto31859422009-01-12 13:36:28 +000018You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
Jari Aalto726f6381996-08-26 18:22:31 +000020
21$PRODUCES jobs.c
22
23$BUILTIN jobs
24$FUNCTION jobs_builtin
25$DEPENDS_ON JOB_CONTROL
Jari Aaltoccc6cda1996-12-23 17:02:34 +000026$SHORT_DOC jobs [-lnprs] [jobspec ...] or jobs -x command [args]
Jari Aalto31859422009-01-12 13:36:28 +000027Display 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
Chet Rameyac50fba2014-02-26 09:36:43 -050034 -n lists only processes that have changed status since the last
Jari Aalto31859422009-01-12 13:36:28 +000035 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
Jari Aaltoccc6cda1996-12-23 17:02:34 +000042process group leader.
Jari Aalto31859422009-01-12 13:36:28 +000043
44Exit Status:
45Returns success unless an invalid option is given or an error occurs.
46If -x is used, returns the exit status of COMMAND.
Jari Aalto726f6381996-08-26 18:22:31 +000047$END
48
Jari Aaltoccc6cda1996-12-23 17:02:34 +000049#include <config.h>
Jari Aalto726f6381996-08-26 18:22:31 +000050
51#if defined (JOB_CONTROL)
Jari Aaltoccc6cda1996-12-23 17:02:34 +000052#include "../bashtypes.h"
Jari Aalto726f6381996-08-26 18:22:31 +000053#include <signal.h>
Jari Aaltoccc6cda1996-12-23 17:02:34 +000054#if defined (HAVE_UNISTD_H)
55# include <unistd.h>
56#endif
Jari Aalto726f6381996-08-26 18:22:31 +000057
Jari Aaltoccc6cda1996-12-23 17:02:34 +000058#include "../bashansi.h"
Jari Aaltob80f6442004-07-27 13:29:18 +000059#include "../bashintl.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000060
61#include "../shell.h"
62#include "../jobs.h"
63#include "../execute_cmd.h"
Jari Aalto726f6381996-08-26 18:22:31 +000064#include "bashgetopt.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000065#include "common.h"
66
67#define JSTATE_ANY 0x0
68#define JSTATE_RUNNING 0x1
69#define JSTATE_STOPPED 0x2
Jari Aalto726f6381996-08-26 18:22:31 +000070
Jari Aaltof73dda02001-11-13 17:56:06 +000071static int execute_list_with_replacements __P((WORD_LIST *));
Jari Aalto726f6381996-08-26 18:22:31 +000072
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
Jari Aaltoccc6cda1996-12-23 17:02:34 +000079 group leader and execute the command. The -r and -s options mean
80 to print info about running and stopped jobs only, respectively. */
Jari Aalto726f6381996-08-26 18:22:31 +000081int
82jobs_builtin (list)
83 WORD_LIST *list;
84{
Jari Aaltoccc6cda1996-12-23 17:02:34 +000085 int form, execute, state, opt, any_failed, job;
86 sigset_t set, oset;
Jari Aalto726f6381996-08-26 18:22:31 +000087
Jari Aaltoccc6cda1996-12-23 17:02:34 +000088 execute = any_failed = 0;
89 form = JLIST_STANDARD;
90 state = JSTATE_ANY;
91
Jari Aalto726f6381996-08-26 18:22:31 +000092 reset_internal_getopt ();
Jari Aaltoccc6cda1996-12-23 17:02:34 +000093 while ((opt = internal_getopt (list, "lpnxrs")) != -1)
Jari Aalto726f6381996-08-26 18:22:31 +000094 {
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 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000109 builtin_error (_("no other options allowed with `-x'"));
Jari Aalto726f6381996-08-26 18:22:31 +0000110 return (EXECUTION_FAILURE);
111 }
112 execute++;
113 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000114 case 'r':
115 state = JSTATE_RUNNING;
116 break;
117 case 's':
118 state = JSTATE_STOPPED;
119 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000120
121 default:
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000122 builtin_usage ();
Jari Aalto726f6381996-08-26 18:22:31 +0000123 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 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000134 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 }
Jari Aalto726f6381996-08-26 18:22:31 +0000146 return (EXECUTION_SUCCESS);
147 }
148
149 while (list)
150 {
Jari Aalto726f6381996-08-26 18:22:31 +0000151 BLOCK_CHILD (set, oset);
152 job = get_job_spec (list);
153
Jari Aalto95732b42005-12-07 14:08:12 +0000154 if ((job == NO_JOB) || jobs == 0 || get_job_by_jid (job) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000155 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000156 sh_badjob (list->word->word);
Jari Aalto726f6381996-08-26 18:22:31 +0000157 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;
Jari Aaltob80f6442004-07-27 13:29:18 +0000174 COMMAND *command;
Jari Aalto95732b42005-12-07 14:08:12 +0000175 JOB *j;
Jari Aalto726f6381996-08-26 18:22:31 +0000176
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. */
Jari Aalto95732b42005-12-07 14:08:12 +0000185 if (INVALID_JOB (job))
Jari Aalto726f6381996-08-26 18:22:31 +0000186 continue;
187
Jari Aalto95732b42005-12-07 14:08:12 +0000188 j = get_job_by_jid (job);
Jari Aalto726f6381996-08-26 18:22:31 +0000189 free (l->word->word);
Jari Aalto95732b42005-12-07 14:08:12 +0000190 l->word->word = itos (j->pgrp);
Jari Aalto726f6381996-08-26 18:22:31 +0000191 }
192 }
193
194 /* Next make a new simple command and execute it. */
195 begin_unwind_frame ("jobs_builtin");
Jari Aalto726f6381996-08-26 18:22:31 +0000196
Jari Aaltob80f6442004-07-27 13:29:18 +0000197 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;
Jari Aalto726f6381996-08-26 18:22:31 +0000202
Jari Aaltob80f6442004-07-27 13:29:18 +0000203 add_unwind_protect (dispose_command, command);
204 result = execute_command (command);
205 dispose_command (command);
Jari Aalto726f6381996-08-26 18:22:31 +0000206
Jari Aaltob80f6442004-07-27 13:29:18 +0000207 discard_unwind_frame ("jobs_builtin");
Jari Aalto726f6381996-08-26 18:22:31 +0000208 return (result);
209}
210#endif /* JOB_CONTROL */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000211
212$BUILTIN disown
213$FUNCTION disown_builtin
214$DEPENDS_ON JOB_CONTROL
Jari Aaltocce855b1998-04-17 19:52:44 +0000215$SHORT_DOC disown [-h] [-ar] [jobspec ...]
Jari Aalto31859422009-01-12 13:36:28 +0000216Remove 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.
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000229$END
230
231#if defined (JOB_CONTROL)
232int
233disown_builtin (list)
234 WORD_LIST *list;
235{
Jari Aaltocce855b1998-04-17 19:52:44 +0000236 int opt, job, retval, nohup_only, running_jobs, all_jobs;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000237 sigset_t set, oset;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000238 intmax_t pid_value;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000239
Jari Aaltocce855b1998-04-17 19:52:44 +0000240 nohup_only = running_jobs = all_jobs = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000241 reset_internal_getopt ();
Jari Aaltocce855b1998-04-17 19:52:44 +0000242 while ((opt = internal_getopt (list, "ahr")) != -1)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000243 {
244 switch (opt)
245 {
Jari Aaltocce855b1998-04-17 19:52:44 +0000246 case 'a':
247 all_jobs = 1;
248 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000249 case 'h':
250 nohup_only = 1;
251 break;
Jari Aaltocce855b1998-04-17 19:52:44 +0000252 case 'r':
253 running_jobs = 1;
254 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000255 default:
256 builtin_usage ();
257 return (EX_USAGE);
258 }
259 }
260 list = loptend;
261 retval = EXECUTION_SUCCESS;
262
Jari Aaltocce855b1998-04-17 19:52:44 +0000263 /* `disown -a' or `disown -r' */
264 if (list == 0 && (all_jobs || running_jobs))
Jari Aaltod166f041997-06-05 14:59:13 +0000265 {
266 if (nohup_only)
Jari Aaltocce855b1998-04-17 19:52:44 +0000267 nohup_all_jobs (running_jobs);
Jari Aaltod166f041997-06-05 14:59:13 +0000268 else
Jari Aaltocce855b1998-04-17 19:52:44 +0000269 delete_all_jobs (running_jobs);
Jari Aaltod166f041997-06-05 14:59:13 +0000270 return (EXECUTION_SUCCESS);
271 }
Jari Aaltod166f041997-06-05 14:59:13 +0000272
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000273 do
274 {
275 BLOCK_CHILD (set, oset);
Jari Aaltof73dda02001-11-13 17:56:06 +0000276 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)
Jari Aaltod166f041997-06-05 14:59:13 +0000278 : get_job_spec (list);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000279
Jari Aalto95732b42005-12-07 14:08:12 +0000280 if (job == NO_JOB || jobs == 0 || INVALID_JOB (job))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000281 {
Jari Aalto31859422009-01-12 13:36:28 +0000282 sh_badjob (list ? list->word->word : _("current"));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000283 retval = EXECUTION_FAILURE;
284 }
285 else if (nohup_only)
286 nohup_job (job);
287 else
Jari Aaltocce855b1998-04-17 19:52:44 +0000288 delete_job (job, 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000289 UNBLOCK_CHILD (oset);
290
291 if (list)
292 list = list->next;
293 }
294 while (list);
Jari Aaltod166f041997-06-05 14:59:13 +0000295
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000296 return (retval);
297}
298#endif /* JOB_CONTROL */