1 /* kill.c - a program to send signals to processes 2 * 3 * Copyright 2012 Daniel Walter <d.walter (at) 0x90.at> 4 * 5 * See http://opengroup.org/onlinepubs/9699919799/utilities/kill.html 6 * 7 * killall5.c - Send signal to all processes outside current session. 8 * 9 * Copyright 2014 Ranjan Kumar <ranjankumar.bth (at) gmail.com> 10 * Copyright 2014 Kyungwan Han <asura321 (at) gamil.com> 11 * 12 * No Standard 13 14 USE_KILL(NEWTOY(kill, "?ls: ", TOYFLAG_BIN)) 15 USE_KILLALL5(NEWTOY(killall5, "?o*ls: [!lo][!ls]", TOYFLAG_SBIN)) 16 17 config KILL 18 bool "kill" 19 default y 20 help 21 usage: kill [-l [SIGNAL] | -s SIGNAL | -SIGNAL] pid... 22 23 Send signal to process(es). 24 25 -l List signal name(s) and number(s) 26 -s Send SIGNAL (default SIGTERM) 27 28 config KILLALL5 29 bool "killall5" 30 default y 31 depends on KILL 32 help 33 usage: killall5 [-l [SIGNAL]] [-SIGNAL|-s SIGNAL] [-o PID]... 34 35 Send a signal to all processes outside current session. 36 37 -l List signal name(s) and number(s) 38 -o PID Omit PID 39 -s send SIGNAL (default SIGTERM) 40 */ 41 42 // This has to match the filename: 43 #define FOR_kill 44 #include "toys.h" 45 46 GLOBALS( 47 char *signame; 48 struct arg_list *olist; 49 ) 50 51 // But kill's flags are a subset of killall5's 52 53 #define CLEANUP_kill 54 #define FOR_killall5 55 #include "generated/flags.h" 56 57 void kill_main(void) 58 { 59 int signum; 60 char *tmp, **args = toys.optargs; 61 pid_t pid; 62 63 // list signal(s) 64 if (toys.optflags & FLAG_l) { 65 if (*args) { 66 int signum = sig_to_num(*args); 67 char *s = NULL; 68 69 if (signum>=0) s = num_to_sig(signum&127); 70 puts(s ? s : "UNKNOWN"); 71 } else sig_to_num(NULL); 72 return; 73 } 74 75 // signal must come before pids, so "kill -9 -1" isn't confusing. 76 77 if (!TT.signame && *args && **args=='-') TT.signame=*(args++)+1; 78 if (TT.signame) { 79 char *arg; 80 int i = strtol(TT.signame, &arg, 10); 81 if (!*arg) arg = num_to_sig(i); 82 else arg = TT.signame; 83 84 if (!arg || -1 == (signum = sig_to_num(arg))) 85 error_exit("Unknown signal '%s'", arg); 86 } else signum = SIGTERM; 87 88 // is it killall5? 89 if (CFG_KILLALL5 && toys.which->name[4]=='a') { 90 DIR *dp; 91 struct dirent *entry; 92 int pid, sid; 93 long *olist = 0, ocount = 0; 94 95 // parse omit list 96 if (toys.optflags & FLAG_o) { 97 struct arg_list *ptr; 98 99 for (ptr = TT.olist; ptr; ptr = ptr->next) ocount++; 100 olist = xmalloc(ocount*sizeof(long)); 101 ocount = 0; 102 for (ptr = TT.olist; ptr; ptr=ptr->next) 103 olist[ocount++] = atolx(ptr->arg); 104 } 105 106 sid = getsid(pid = getpid()); 107 108 if (!(dp = opendir("/proc"))) perror_exit("/proc"); 109 while ((entry = readdir(dp))) { 110 int count, procpid, procsid; 111 112 if (!(procpid = atoi(entry->d_name))) continue; 113 114 snprintf(toybuf, sizeof(toybuf), "/proc/%d/stat", procpid); 115 if (!readfile(toybuf, toybuf, sizeof(toybuf))) continue; 116 if (sscanf(toybuf, "%*d %*s %*c %*d %*d %d", &procsid) != 1) continue; 117 if (pid == procpid || sid == procsid || procpid == 1) continue; 118 119 // Check for kernel threads. 120 snprintf(toybuf, sizeof(toybuf), "/proc/%d/cmdline", procpid); 121 if (!readfile(toybuf, toybuf, sizeof(toybuf)) || !*toybuf) continue; 122 123 // Check with omit list. 124 for (count = 0; count < ocount; count++) 125 if (procpid == olist[count]) break; 126 if (count != ocount) continue; 127 128 kill(procpid, signum); 129 } 130 if (CFG_TOYBOX_FREE) { 131 closedir(dp); 132 free(olist); 133 } 134 135 // is it kill? 136 } else { 137 138 // "<1" in optstr wouldn't cover this because "-SIGNAL" 139 if (!*args) help_exit("missing argument"); 140 141 while (*args) { 142 char *arg = *(args++); 143 144 pid = strtol(arg, &tmp, 10); 145 if (*tmp || kill(pid, signum) < 0) error_msg("unknown pid '%s'", arg); 146 } 147 } 148 } 149 150 void killall5_main(void) 151 { 152 kill_main(); 153 } 154