1/* jobs.c, created from jobs.def. */ 2#line 23 "jobs.def" 3 4#line 38 "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 212 "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 */ 239