1/* kill.c, created from kill.def. */ 2#line 23 "kill.def" 3 4#line 35 "kill.def" 5 6#include <config.h> 7 8#include <stdio.h> 9#include <errno.h> 10#if defined (HAVE_UNISTD_H) 11# ifdef _MINIX 12# include <sys/types.h> 13# endif 14# include <unistd.h> 15#endif 16 17#include "../bashansi.h" 18#include "../bashintl.h" 19 20#include "../shell.h" 21#include "../trap.h" 22#include "../jobs.h" 23#include "common.h" 24 25/* Not all systems declare ERRNO in errno.h... and some systems #define it! */ 26#if !defined (errno) 27extern int errno; 28#endif /* !errno */ 29 30extern int posixly_correct; 31 32static void kill_error __P((pid_t, int)); 33 34#if !defined (CONTINUE_AFTER_KILL_ERROR) 35# define CONTINUE_OR_FAIL return (EXECUTION_FAILURE) 36#else 37# define CONTINUE_OR_FAIL goto continue_killing 38#endif /* CONTINUE_AFTER_KILL_ERROR */ 39 40/* Here is the kill builtin. We only have it so that people can type 41 kill -KILL %1? No, if you fill up the process table this way you 42 can still kill some. */ 43int 44kill_builtin (list) 45 WORD_LIST *list; 46{ 47 int sig, any_succeeded, listing, saw_signal, dflags; 48 char *sigspec, *word; 49 pid_t pid; 50 intmax_t pid_value; 51 52 if (list == 0) 53 { 54 builtin_usage (); 55 return (EXECUTION_FAILURE); 56 } 57 58 any_succeeded = listing = saw_signal = 0; 59 sig = SIGTERM; 60 sigspec = "TERM"; 61 62 dflags = DSIG_NOCASE | ((posixly_correct == 0) ? DSIG_SIGPREFIX : 0); 63 /* Process options. */ 64 while (list) 65 { 66 word = list->word->word; 67 68 if (ISOPTION (word, 'l')) 69 { 70 listing++; 71 list = list->next; 72 } 73 else if (ISOPTION (word, 's') || ISOPTION (word, 'n')) 74 { 75 list = list->next; 76 if (list) 77 { 78 sigspec = list->word->word; 79 if (sigspec[0] == '0' && sigspec[1] == '\0') 80 sig = 0; 81 else 82 sig = decode_signal (sigspec, dflags); 83 list = list->next; 84 } 85 else 86 { 87 sh_needarg (word); 88 return (EXECUTION_FAILURE); 89 } 90 } 91 else if (ISOPTION (word, '-')) 92 { 93 list = list->next; 94 break; 95 } 96 else if (ISOPTION (word, '?')) 97 { 98 builtin_usage (); 99 return (EXECUTION_SUCCESS); 100 } 101 /* If this is a signal specification then process it. We only process 102 the first one seen; other arguments may signify process groups (e.g, 103 -num == process group num). */ 104 else if ((*word == '-') && !saw_signal) 105 { 106 sigspec = word + 1; 107 sig = decode_signal (sigspec, dflags); 108 saw_signal++; 109 list = list->next; 110 } 111 else 112 break; 113 } 114 115 if (listing) 116 return (display_signal_list (list, 0)); 117 118 /* OK, we are killing processes. */ 119 if (sig == NO_SIG) 120 { 121 sh_invalidsig (sigspec); 122 return (EXECUTION_FAILURE); 123 } 124 125 if (list == 0) 126 { 127 builtin_usage (); 128 return (EXECUTION_FAILURE); 129 } 130 131 while (list) 132 { 133 word = list->word->word; 134 135 if (*word == '-') 136 word++; 137 138 /* Use the entire argument in case of minus sign presence. */ 139 if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value)) 140 { 141 pid = (pid_t) pid_value; 142 143 if (kill_pid (pid, sig, pid < -1) < 0) 144 { 145 if (errno == EINVAL) 146 sh_invalidsig (sigspec); 147 else 148 kill_error (pid, errno); 149 CONTINUE_OR_FAIL; 150 } 151 else 152 any_succeeded++; 153 } 154#if defined (JOB_CONTROL) 155 else if (*list->word->word && *list->word->word != '%') 156 { 157 builtin_error (_("%s: arguments must be process or job IDs"), list->word->word); 158 CONTINUE_OR_FAIL; 159 } 160 else if (*word) 161 /* Posix.2 says you can kill without job control active (4.32.4) */ 162 { /* Must be a job spec. Check it out. */ 163 int job; 164 sigset_t set, oset; 165 JOB *j; 166 167 BLOCK_CHILD (set, oset); 168 job = get_job_spec (list); 169 170 if (INVALID_JOB (job)) 171 { 172 if (job != DUP_JOB) 173 sh_badjob (list->word->word); 174 UNBLOCK_CHILD (oset); 175 CONTINUE_OR_FAIL; 176 } 177 178 j = get_job_by_jid (job); 179 /* Job spec used. Kill the process group. If the job was started 180 without job control, then its pgrp == shell_pgrp, so we have 181 to be careful. We take the pid of the first job in the pipeline 182 in that case. */ 183 pid = IS_JOBCONTROL (job) ? j->pgrp : j->pipe->pid; 184 185 UNBLOCK_CHILD (oset); 186 187 if (kill_pid (pid, sig, 1) < 0) 188 { 189 if (errno == EINVAL) 190 sh_invalidsig (sigspec); 191 else 192 kill_error (pid, errno); 193 CONTINUE_OR_FAIL; 194 } 195 else 196 any_succeeded++; 197 } 198#endif /* !JOB_CONTROL */ 199 else 200 { 201 sh_badpid (list->word->word); 202 CONTINUE_OR_FAIL; 203 } 204 continue_killing: 205 list = list->next; 206 } 207 208 return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE); 209} 210 211static void 212kill_error (pid, e) 213 pid_t pid; 214 int e; 215{ 216 char *x; 217 218 x = strerror (e); 219 if (x == 0) 220 x = _("Unknown error"); 221 builtin_error ("(%ld) - %s", (long)pid, x); 222} 223