]>
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 | |
b80f6443 | 4 | Copyright (C) 1987-2004 Free Software Foundation, Inc. |
726f6388 JA |
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 it under | |
9 | the terms of the GNU General Public License as published by the Free | |
bb70624e | 10 | Software Foundation; either version 2, or (at your option) any later |
726f6388 JA |
11 | version. |
12 | ||
13 | Bash is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License along | |
19 | with Bash; see the file COPYING. If not, write to the Free Software | |
bb70624e | 20 | Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. |
726f6388 JA |
21 | |
22 | $PRODUCES jobs.c | |
23 | ||
24 | $BUILTIN jobs | |
25 | $FUNCTION jobs_builtin | |
26 | $DEPENDS_ON JOB_CONTROL | |
ccc6cda3 | 27 | $SHORT_DOC jobs [-lnprs] [jobspec ...] or jobs -x command [args] |
726f6388 JA |
28 | Lists the active jobs. The -l option lists process id's in addition |
29 | to the normal information; the -p option lists process id's only. | |
30 | If -n is given, only processes that have changed status since the last | |
ccc6cda3 JA |
31 | notification are printed. JOBSPEC restricts output to that job. The |
32 | -r and -s options restrict output to running and stopped jobs only, | |
33 | respectively. Without options, the status of all active jobs is | |
34 | printed. If -x is given, COMMAND is run after all job specifications | |
35 | that appear in ARGS have been replaced with the process ID of that job's | |
36 | process group leader. | |
726f6388 JA |
37 | $END |
38 | ||
ccc6cda3 | 39 | #include <config.h> |
726f6388 JA |
40 | |
41 | #if defined (JOB_CONTROL) | |
ccc6cda3 | 42 | #include "../bashtypes.h" |
726f6388 | 43 | #include <signal.h> |
ccc6cda3 JA |
44 | #if defined (HAVE_UNISTD_H) |
45 | # include <unistd.h> | |
46 | #endif | |
47 | ||
48 | #include "../bashansi.h" | |
b80f6443 | 49 | #include "../bashintl.h" |
726f6388 | 50 | |
ccc6cda3 JA |
51 | #include "../shell.h" |
52 | #include "../jobs.h" | |
53 | #include "../execute_cmd.h" | |
726f6388 | 54 | #include "bashgetopt.h" |
ccc6cda3 JA |
55 | #include "common.h" |
56 | ||
57 | #define JSTATE_ANY 0x0 | |
58 | #define JSTATE_RUNNING 0x1 | |
59 | #define JSTATE_STOPPED 0x2 | |
726f6388 | 60 | |
f73dda09 | 61 | static int execute_list_with_replacements __P((WORD_LIST *)); |
726f6388 JA |
62 | |
63 | /* The `jobs' command. Prints outs a list of active jobs. If the | |
64 | argument `-l' is given, then the process id's are printed also. | |
65 | If the argument `-p' is given, print the process group leader's | |
66 | pid only. If `-n' is given, only processes that have changed | |
67 | status since the last notification are printed. If -x is given, | |
68 | replace all job specs with the pid of the appropriate process | |
ccc6cda3 JA |
69 | group leader and execute the command. The -r and -s options mean |
70 | to print info about running and stopped jobs only, respectively. */ | |
726f6388 JA |
71 | int |
72 | jobs_builtin (list) | |
73 | WORD_LIST *list; | |
74 | { | |
ccc6cda3 JA |
75 | int form, execute, state, opt, any_failed, job; |
76 | sigset_t set, oset; | |
726f6388 | 77 | |
ccc6cda3 JA |
78 | execute = any_failed = 0; |
79 | form = JLIST_STANDARD; | |
80 | state = JSTATE_ANY; | |
81 | ||
726f6388 | 82 | reset_internal_getopt (); |
ccc6cda3 | 83 | while ((opt = internal_getopt (list, "lpnxrs")) != -1) |
726f6388 JA |
84 | { |
85 | switch (opt) | |
86 | { | |
87 | case 'l': | |
88 | form = JLIST_LONG; | |
89 | break; | |
90 | case 'p': | |
91 | form = JLIST_PID_ONLY; | |
92 | break; | |
93 | case 'n': | |
94 | form = JLIST_CHANGED_ONLY; | |
95 | break; | |
96 | case 'x': | |
97 | if (form != JLIST_STANDARD) | |
98 | { | |
b80f6443 | 99 | builtin_error (_("no other options allowed with `-x'")); |
726f6388 JA |
100 | return (EXECUTION_FAILURE); |
101 | } | |
102 | execute++; | |
103 | break; | |
ccc6cda3 JA |
104 | case 'r': |
105 | state = JSTATE_RUNNING; | |
106 | break; | |
107 | case 's': | |
108 | state = JSTATE_STOPPED; | |
109 | break; | |
726f6388 JA |
110 | |
111 | default: | |
ccc6cda3 | 112 | builtin_usage (); |
726f6388 JA |
113 | return (EX_USAGE); |
114 | } | |
115 | } | |
116 | ||
117 | list = loptend; | |
118 | ||
119 | if (execute) | |
120 | return (execute_list_with_replacements (list)); | |
121 | ||
122 | if (!list) | |
123 | { | |
ccc6cda3 JA |
124 | switch (state) |
125 | { | |
126 | case JSTATE_ANY: | |
127 | list_all_jobs (form); | |
128 | break; | |
129 | case JSTATE_RUNNING: | |
130 | list_running_jobs (form); | |
131 | break; | |
132 | case JSTATE_STOPPED: | |
133 | list_stopped_jobs (form); | |
134 | break; | |
135 | } | |
726f6388 JA |
136 | return (EXECUTION_SUCCESS); |
137 | } | |
138 | ||
139 | while (list) | |
140 | { | |
726f6388 JA |
141 | BLOCK_CHILD (set, oset); |
142 | job = get_job_spec (list); | |
143 | ||
144 | if ((job == NO_JOB) || !jobs || !jobs[job]) | |
145 | { | |
7117c2d2 | 146 | sh_badjob (list->word->word); |
726f6388 JA |
147 | any_failed++; |
148 | } | |
149 | else if (job != DUP_JOB) | |
150 | list_one_job ((JOB *)NULL, form, 0, job); | |
151 | ||
152 | UNBLOCK_CHILD (oset); | |
153 | list = list->next; | |
154 | } | |
155 | return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS); | |
156 | } | |
157 | ||
158 | static int | |
159 | execute_list_with_replacements (list) | |
160 | WORD_LIST *list; | |
161 | { | |
162 | register WORD_LIST *l; | |
163 | int job, result; | |
b80f6443 | 164 | COMMAND *command; |
726f6388 JA |
165 | |
166 | /* First do the replacement of job specifications with pids. */ | |
167 | for (l = list; l; l = l->next) | |
168 | { | |
169 | if (l->word->word[0] == '%') /* we have a winner */ | |
170 | { | |
171 | job = get_job_spec (l); | |
172 | ||
173 | /* A bad job spec is not really a job spec! Pass it through. */ | |
174 | if (job < 0 || job >= job_slots || !jobs[job]) | |
175 | continue; | |
176 | ||
177 | free (l->word->word); | |
178 | l->word->word = itos (jobs[job]->pgrp); | |
179 | } | |
180 | } | |
181 | ||
182 | /* Next make a new simple command and execute it. */ | |
183 | begin_unwind_frame ("jobs_builtin"); | |
726f6388 | 184 | |
b80f6443 JA |
185 | command = make_bare_simple_command (); |
186 | command->value.Simple->words = copy_word_list (list); | |
187 | command->value.Simple->redirects = (REDIRECT *)NULL; | |
188 | command->flags |= CMD_INHIBIT_EXPANSION; | |
189 | command->value.Simple->flags |= CMD_INHIBIT_EXPANSION; | |
726f6388 | 190 | |
b80f6443 JA |
191 | add_unwind_protect (dispose_command, command); |
192 | result = execute_command (command); | |
193 | dispose_command (command); | |
726f6388 | 194 | |
b80f6443 | 195 | discard_unwind_frame ("jobs_builtin"); |
726f6388 JA |
196 | return (result); |
197 | } | |
198 | #endif /* JOB_CONTROL */ | |
ccc6cda3 JA |
199 | |
200 | $BUILTIN disown | |
201 | $FUNCTION disown_builtin | |
202 | $DEPENDS_ON JOB_CONTROL | |
cce855bc | 203 | $SHORT_DOC disown [-h] [-ar] [jobspec ...] |
ccc6cda3 JA |
204 | By default, removes each JOBSPEC argument from the table of active jobs. |
205 | If the -h option is given, the job is not removed from the table, but is | |
206 | marked so that SIGHUP is not sent to the job if the shell receives a | |
cce855bc JA |
207 | SIGHUP. The -a option, when JOBSPEC is not supplied, means to remove all |
208 | jobs from the job table; the -r option means to remove only running jobs. | |
ccc6cda3 JA |
209 | $END |
210 | ||
211 | #if defined (JOB_CONTROL) | |
212 | int | |
213 | disown_builtin (list) | |
214 | WORD_LIST *list; | |
215 | { | |
cce855bc | 216 | int opt, job, retval, nohup_only, running_jobs, all_jobs; |
ccc6cda3 | 217 | sigset_t set, oset; |
7117c2d2 | 218 | intmax_t pid_value; |
ccc6cda3 | 219 | |
cce855bc | 220 | nohup_only = running_jobs = all_jobs = 0; |
ccc6cda3 | 221 | reset_internal_getopt (); |
cce855bc | 222 | while ((opt = internal_getopt (list, "ahr")) != -1) |
ccc6cda3 JA |
223 | { |
224 | switch (opt) | |
225 | { | |
cce855bc JA |
226 | case 'a': |
227 | all_jobs = 1; | |
228 | break; | |
ccc6cda3 JA |
229 | case 'h': |
230 | nohup_only = 1; | |
231 | break; | |
cce855bc JA |
232 | case 'r': |
233 | running_jobs = 1; | |
234 | break; | |
ccc6cda3 JA |
235 | default: |
236 | builtin_usage (); | |
237 | return (EX_USAGE); | |
238 | } | |
239 | } | |
240 | list = loptend; | |
241 | retval = EXECUTION_SUCCESS; | |
242 | ||
cce855bc JA |
243 | /* `disown -a' or `disown -r' */ |
244 | if (list == 0 && (all_jobs || running_jobs)) | |
d166f048 JA |
245 | { |
246 | if (nohup_only) | |
cce855bc | 247 | nohup_all_jobs (running_jobs); |
d166f048 | 248 | else |
cce855bc | 249 | delete_all_jobs (running_jobs); |
d166f048 JA |
250 | return (EXECUTION_SUCCESS); |
251 | } | |
d166f048 | 252 | |
ccc6cda3 JA |
253 | do |
254 | { | |
255 | BLOCK_CHILD (set, oset); | |
f73dda09 JA |
256 | job = (list && legal_number (list->word->word, &pid_value) && pid_value == (pid_t) pid_value) |
257 | ? get_job_by_pid ((pid_t) pid_value, 0) | |
d166f048 | 258 | : get_job_spec (list); |
ccc6cda3 | 259 | |
cce855bc | 260 | if (job == NO_JOB || jobs == 0 || job < 0 || job >= job_slots || jobs[job] == 0) |
ccc6cda3 | 261 | { |
7117c2d2 | 262 | sh_badjob (list ? list->word->word : "current"); |
ccc6cda3 JA |
263 | retval = EXECUTION_FAILURE; |
264 | } | |
265 | else if (nohup_only) | |
266 | nohup_job (job); | |
267 | else | |
cce855bc | 268 | delete_job (job, 1); |
ccc6cda3 JA |
269 | UNBLOCK_CHILD (oset); |
270 | ||
271 | if (list) | |
272 | list = list->next; | |
273 | } | |
274 | while (list); | |
d166f048 | 275 | |
ccc6cda3 JA |
276 | return (retval); |
277 | } | |
278 | #endif /* JOB_CONTROL */ |