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
7 USE_KILLALL(NEWTOY(killall, "?s:ilqvw", TOYFLAG_USR|TOYFLAG_BIN))
8
9 config 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
GLOBALS(char * s;int signum;pid_t cur_pid;char ** names;short * err;struct int_list{ struct int_list *next; int val; } * pids;)28 GLOBALS(
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
38 static 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
killall_main(void)71 void 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