1This file is kill.def, from which is created kill.c. 2It implements the builtin "kill" in Bash. 3 4Copyright (C) 1987-2020 Free Software Foundation, Inc. 5 6This file is part of GNU Bash, the Bourne Again SHell. 7 8Bash 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. 12 13Bash 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. 17 18You should have received a copy of the GNU General Public License 19along with Bash. If not, see <http://www.gnu.org/licenses/>. 20 21$PRODUCES kill.c 22 23$BUILTIN kill 24$FUNCTION kill_builtin 25$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec] 26Send a signal to a job. 27 28Send the processes identified by PID or JOBSPEC the signal named by 29SIGSPEC or SIGNUM. If neither SIGSPEC nor SIGNUM is present, then 30SIGTERM is assumed. 31 32Options: 33 -s sig SIG is a signal name 34 -n sig SIG is a signal number 35 -l list the signal names; if arguments follow `-l' they are 36 assumed to be signal numbers for which names should be listed 37 -L synonym for -l 38 39Kill is a shell builtin for two reasons: it allows job IDs to be used 40instead of process IDs, and allows processes to be killed if the limit 41on processes that you can create is reached. 42 43Exit Status: 44Returns success unless an invalid option is given or an error occurs. 45$END 46 47#include <config.h> 48 49#include <stdio.h> 50#include <errno.h> 51#if defined (HAVE_UNISTD_H) 52# ifdef _MINIX 53# include <sys/types.h> 54# endif 55# include <unistd.h> 56#endif 57 58#include "../bashansi.h" 59#include "../bashintl.h" 60 61#include <signal.h> 62 63#include "../shell.h" 64#include "../trap.h" 65#include "../jobs.h" 66#include "common.h" 67 68/* Not all systems declare ERRNO in errno.h... and some systems #define it! */ 69#if !defined (errno) 70extern int errno; 71#endif /* !errno */ 72 73static void kill_error PARAMS((pid_t, int)); 74 75#if !defined (CONTINUE_AFTER_KILL_ERROR) 76# define CONTINUE_OR_FAIL return (EXECUTION_FAILURE) 77#else 78# define CONTINUE_OR_FAIL goto continue_killing 79#endif /* CONTINUE_AFTER_KILL_ERROR */ 80 81/* Here is the kill builtin. We only have it so that people can type 82 kill -KILL %1? No, if you fill up the process table this way you 83 can still kill some. */ 84int 85kill_builtin (list) 86 WORD_LIST *list; 87{ 88 int sig, any_succeeded, listing, saw_signal, dflags; 89 char *sigspec, *word; 90 pid_t pid; 91 intmax_t pid_value; 92 93 if (list == 0) 94 { 95 builtin_usage (); 96 return (EX_USAGE); 97 } 98 CHECK_HELPOPT (list); 99 100 any_succeeded = listing = saw_signal = 0; 101 sig = SIGTERM; 102 sigspec = "TERM"; 103 104 dflags = DSIG_NOCASE | ((posixly_correct == 0) ? DSIG_SIGPREFIX : 0); 105 /* Process options. */ 106 while (list) 107 { 108 word = list->word->word; 109 110 if (ISOPTION (word, 'l') || ISOPTION (word, 'L')) 111 { 112 listing++; 113 list = list->next; 114 } 115 else if (ISOPTION (word, 's') || ISOPTION (word, 'n')) 116 { 117 list = list->next; 118 if (list) 119 { 120 sigspec = list->word->word; 121use_sigspec: 122 if (sigspec[0] == '0' && sigspec[1] == '\0') 123 sig = 0; 124 else 125 sig = decode_signal (sigspec, dflags); 126 list = list->next; 127 saw_signal++; 128 } 129 else 130 { 131 sh_needarg (word); 132 return (EXECUTION_FAILURE); 133 } 134 } 135 else if (word[0] == '-' && word[1] == 's' && ISALPHA (word[2])) 136 { 137 sigspec = word + 2; 138 goto use_sigspec; 139 } 140 else if (word[0] == '-' && word[1] == 'n' && ISDIGIT (word[2])) 141 { 142 sigspec = word + 2; 143 goto use_sigspec; 144 } 145 else if (ISOPTION (word, '-')) 146 { 147 list = list->next; 148 break; 149 } 150 else if (ISOPTION (word, '?')) 151 { 152 builtin_usage (); 153 return (EX_USAGE); 154 } 155 /* If this is a signal specification then process it. We only process 156 the first one seen; other arguments may signify process groups (e.g, 157 -num == process group num). */ 158 else if (*word == '-' && saw_signal == 0) 159 { 160 sigspec = word + 1; 161 sig = decode_signal (sigspec, dflags); 162 saw_signal++; 163 list = list->next; 164 } 165 else 166 break; 167 } 168 169 if (listing) 170 return (display_signal_list (list, 0)); 171 172 /* OK, we are killing processes. */ 173 if (sig == NO_SIG) 174 { 175 sh_invalidsig (sigspec); 176 return (EXECUTION_FAILURE); 177 } 178 179 if (list == 0) 180 { 181 builtin_usage (); 182 return (EX_USAGE); 183 } 184 185 while (list) 186 { 187 word = list->word->word; 188 189 if (*word == '-') 190 word++; 191 192 /* Use the entire argument in case of minus sign presence. */ 193 if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value)) 194 { 195 pid = (pid_t) pid_value; 196 197 if (kill_pid (pid, sig, pid < -1) < 0) 198 { 199 if (errno == EINVAL) 200 sh_invalidsig (sigspec); 201 else 202 kill_error (pid, errno); 203 CONTINUE_OR_FAIL; 204 } 205 else 206 any_succeeded++; 207 } 208#if defined (JOB_CONTROL) 209 else if (*list->word->word && *list->word->word != '%') 210 { 211 builtin_error (_("%s: arguments must be process or job IDs"), list->word->word); 212 CONTINUE_OR_FAIL; 213 } 214 else if (*word) 215 /* Posix.2 says you can kill without job control active (4.32.4) */ 216 { /* Must be a job spec. Check it out. */ 217 int job; 218 sigset_t set, oset; 219 JOB *j; 220 221 BLOCK_CHILD (set, oset); 222 job = get_job_spec (list); 223 224 if (INVALID_JOB (job)) 225 { 226 if (job != DUP_JOB) 227 sh_badjob (list->word->word); 228 UNBLOCK_CHILD (oset); 229 CONTINUE_OR_FAIL; 230 } 231 232 j = get_job_by_jid (job); 233 /* Job spec used. Kill the process group. If the job was started 234 without job control, then its pgrp == shell_pgrp, so we have 235 to be careful. We take the pid of the first job in the pipeline 236 in that case. */ 237 pid = IS_JOBCONTROL (job) ? j->pgrp : j->pipe->pid; 238 239 UNBLOCK_CHILD (oset); 240 241 if (kill_pid (pid, sig, 1) < 0) 242 { 243 if (errno == EINVAL) 244 sh_invalidsig (sigspec); 245 else 246 kill_error (pid, errno); 247 CONTINUE_OR_FAIL; 248 } 249 else 250 any_succeeded++; 251 } 252#endif /* !JOB_CONTROL */ 253 else 254 { 255 sh_badpid (list->word->word); 256 CONTINUE_OR_FAIL; 257 } 258 continue_killing: 259 list = list->next; 260 } 261 262 return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE); 263} 264 265static void 266kill_error (pid, e) 267 pid_t pid; 268 int e; 269{ 270 char *x; 271 272 x = strerror (e); 273 if (x == 0) 274 x = _("Unknown error"); 275 builtin_error ("(%ld) - %s", (long)pid, x); 276} 277