blob: 176e12ac769623b94de08957137738a4686e9172 [file] [log] [blame]
Dan Pasanenc6e37862014-10-02 14:08:59 -05001/* jobs.c, created from jobs.def. */
2#line 22 "./jobs.def"
3
4#line 48 "./jobs.def"
5
6#include <config.h>
7
8#if defined (JOB_CONTROL)
9#include "../bashtypes.h"
10#include <signal.h>
11#if defined (HAVE_UNISTD_H)
12# include <unistd.h>
13#endif
14
15#include "../bashansi.h"
16#include "../bashintl.h"
17
18#include "../shell.h"
19#include "../jobs.h"
20#include "../execute_cmd.h"
21#include "bashgetopt.h"
22#include "common.h"
23
24#define JSTATE_ANY 0x0
25#define JSTATE_RUNNING 0x1
26#define JSTATE_STOPPED 0x2
27
28static int execute_list_with_replacements __P((WORD_LIST *));
29
30/* The `jobs' command. Prints outs a list of active jobs. If the
31 argument `-l' is given, then the process id's are printed also.
32 If the argument `-p' is given, print the process group leader's
33 pid only. If `-n' is given, only processes that have changed
34 status since the last notification are printed. If -x is given,
35 replace all job specs with the pid of the appropriate process
36 group leader and execute the command. The -r and -s options mean
37 to print info about running and stopped jobs only, respectively. */
38int
39jobs_builtin (list)
40 WORD_LIST *list;
41{
42 int form, execute, state, opt, any_failed, job;
43 sigset_t set, oset;
44
45 execute = any_failed = 0;
46 form = JLIST_STANDARD;
47 state = JSTATE_ANY;
48
49 reset_internal_getopt ();
50 while ((opt = internal_getopt (list, "lpnxrs")) != -1)
51 {
52 switch (opt)
53 {
54 case 'l':
55 form = JLIST_LONG;
56 break;
57 case 'p':
58 form = JLIST_PID_ONLY;
59 break;
60 case 'n':
61 form = JLIST_CHANGED_ONLY;
62 break;
63 case 'x':
64 if (form != JLIST_STANDARD)
65 {
66 builtin_error (_("no other options allowed with `-x'"));
67 return (EXECUTION_FAILURE);
68 }
69 execute++;
70 break;
71 case 'r':
72 state = JSTATE_RUNNING;
73 break;
74 case 's':
75 state = JSTATE_STOPPED;
76 break;
77
78 default:
79 builtin_usage ();
80 return (EX_USAGE);
81 }
82 }
83
84 list = loptend;
85
86 if (execute)
87 return (execute_list_with_replacements (list));
88
89 if (!list)
90 {
91 switch (state)
92 {
93 case JSTATE_ANY:
94 list_all_jobs (form);
95 break;
96 case JSTATE_RUNNING:
97 list_running_jobs (form);
98 break;
99 case JSTATE_STOPPED:
100 list_stopped_jobs (form);
101 break;
102 }
103 return (EXECUTION_SUCCESS);
104 }
105
106 while (list)
107 {
108 BLOCK_CHILD (set, oset);
109 job = get_job_spec (list);
110
111 if ((job == NO_JOB) || jobs == 0 || get_job_by_jid (job) == 0)
112 {
113 sh_badjob (list->word->word);
114 any_failed++;
115 }
116 else if (job != DUP_JOB)
117 list_one_job ((JOB *)NULL, form, 0, job);
118
119 UNBLOCK_CHILD (oset);
120 list = list->next;
121 }
122 return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
123}
124
125static int
126execute_list_with_replacements (list)
127 WORD_LIST *list;
128{
129 register WORD_LIST *l;
130 int job, result;
131 COMMAND *command;
132 JOB *j;
133
134 /* First do the replacement of job specifications with pids. */
135 for (l = list; l; l = l->next)
136 {
137 if (l->word->word[0] == '%') /* we have a winner */
138 {
139 job = get_job_spec (l);
140
141 /* A bad job spec is not really a job spec! Pass it through. */
142 if (INVALID_JOB (job))
143 continue;
144
145 j = get_job_by_jid (job);
146 free (l->word->word);
147 l->word->word = itos (j->pgrp);
148 }
149 }
150
151 /* Next make a new simple command and execute it. */
152 begin_unwind_frame ("jobs_builtin");
153
154 command = make_bare_simple_command ();
155 command->value.Simple->words = copy_word_list (list);
156 command->value.Simple->redirects = (REDIRECT *)NULL;
157 command->flags |= CMD_INHIBIT_EXPANSION;
158 command->value.Simple->flags |= CMD_INHIBIT_EXPANSION;
159
160 add_unwind_protect (dispose_command, command);
161 result = execute_command (command);
162 dispose_command (command);
163
164 discard_unwind_frame ("jobs_builtin");
165 return (result);
166}
167#endif /* JOB_CONTROL */
168
169#line 230 "./jobs.def"
170
171#if defined (JOB_CONTROL)
172int
173disown_builtin (list)
174 WORD_LIST *list;
175{
176 int opt, job, retval, nohup_only, running_jobs, all_jobs;
177 sigset_t set, oset;
178 intmax_t pid_value;
179
180 nohup_only = running_jobs = all_jobs = 0;
181 reset_internal_getopt ();
182 while ((opt = internal_getopt (list, "ahr")) != -1)
183 {
184 switch (opt)
185 {
186 case 'a':
187 all_jobs = 1;
188 break;
189 case 'h':
190 nohup_only = 1;
191 break;
192 case 'r':
193 running_jobs = 1;
194 break;
195 default:
196 builtin_usage ();
197 return (EX_USAGE);
198 }
199 }
200 list = loptend;
201 retval = EXECUTION_SUCCESS;
202
203 /* `disown -a' or `disown -r' */
204 if (list == 0 && (all_jobs || running_jobs))
205 {
206 if (nohup_only)
207 nohup_all_jobs (running_jobs);
208 else
209 delete_all_jobs (running_jobs);
210 return (EXECUTION_SUCCESS);
211 }
212
213 do
214 {
215 BLOCK_CHILD (set, oset);
216 job = (list && legal_number (list->word->word, &pid_value) && pid_value == (pid_t) pid_value)
217 ? get_job_by_pid ((pid_t) pid_value, 0)
218 : get_job_spec (list);
219
220 if (job == NO_JOB || jobs == 0 || INVALID_JOB (job))
221 {
222 sh_badjob (list ? list->word->word : _("current"));
223 retval = EXECUTION_FAILURE;
224 }
225 else if (nohup_only)
226 nohup_job (job);
227 else
228 delete_job (job, 1);
229 UNBLOCK_CHILD (oset);
230
231 if (list)
232 list = list->next;
233 }
234 while (list);
235
236 return (retval);
237}
238#endif /* JOB_CONTROL */