1/* killall.c - Send signal (default: TERM) to all processes with given names. 2 * 3 * Copyright 2012 Andreas Heck <aheck@gmx.de> 4 * 5 * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/killall.html 6 7USE_KILLALL(NEWTOY(killall, "?s:ilqvw", TOYFLAG_USR|TOYFLAG_BIN)) 8 9config KILLALL 10 bool "killall" 11 default y 12 help 13 usage: killall [-l] [-iqv] [-SIGNAL|-s SIGNAL] PROCESS_NAME... 14 15 Send a signal (default: TERM) to all processes with the given names. 16 17 -i Ask for confirmation before killing 18 -l Print list of all available signals 19 -q Don't print any warnings or error messages 20 -s Send SIGNAL instead of SIGTERM 21 -v Report if the signal was successfully sent 22 -w Wait until all signaled processes are dead 23*/ 24 25#define FOR_killall 26#include "toys.h" 27 28GLOBALS( 29 char *s; 30 31 int signum; 32 pid_t cur_pid; 33 char **names; 34 short *err; 35 struct int_list { struct int_list *next; int val; } *pids; 36) 37 38static int kill_process(pid_t pid, char *name) 39{ 40 int offset = 0; 41 42 if (pid == TT.cur_pid) return 0; 43 44 if (FLAG(i)) { 45 fprintf(stderr, "Signal %s(%d)", name, (int)pid); 46 if (!yesno(0)) return 0; 47 } 48 49 errno = 0; 50 kill(pid, TT.signum); 51 if (FLAG(w)) { 52 struct int_list *new = xmalloc(sizeof(*TT.pids)); 53 new->val = pid; 54 new->next = TT.pids; 55 TT.pids = new; 56 } 57 for (;;) { 58 if (TT.names[offset] == name) { 59 TT.err[offset] = errno; 60 break; 61 } else offset++; 62 } 63 if (errno) { 64 if (!FLAG(q)) perror_msg("pid %d", (int)pid); 65 } else if (FLAG(v)) 66 printf("Killed %s(%d) with signal %d\n", name, pid, TT.signum); 67 68 return 0; 69} 70 71void killall_main(void) 72{ 73 int i; 74 75 TT.names = toys.optargs; 76 TT.signum = SIGTERM; 77 78 if (FLAG(l)) { 79 list_signals(); 80 return; 81 } 82 83 if (TT.s || (*TT.names && **TT.names == '-')) { 84 if (0 > (TT.signum = sig_to_num(TT.s ? TT.s : (*TT.names)+1))) { 85 if (FLAG(q)) exit(1); 86 error_exit("Invalid signal"); 87 } 88 if (!TT.s) { 89 TT.names++; 90 toys.optc--; 91 } 92 } 93 94 if (!toys.optc) help_exit("no name"); 95 96 TT.cur_pid = getpid(); 97 98 TT.err = xmalloc(2*toys.optc); 99 for (i=0; i<toys.optc; i++) TT.err[i] = ESRCH; 100 names_to_pid(TT.names, kill_process, 1); 101 for (i=0; i<toys.optc; i++) { 102 if (TT.err[i]) { 103 toys.exitval = 1; 104 errno = TT.err[i]; 105 perror_msg_raw(TT.names[i]); 106 } 107 } 108 if (FLAG(w)) { 109 for (;;) { 110 struct int_list *p = TT.pids; 111 int c = 0; 112 113 for (; p; p=p->next) if (kill(p->val, 0) != -1 || errno != ESRCH) ++c; 114 if (!c) break; 115 sleep(1); 116 } 117 } 118 if (CFG_TOYBOX_FREE) { 119 free(TT.err); 120 llist_traverse(TT.pids, free); 121 } 122} 123