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
54 new->val = pid;
55 new->next = TT.pids;
56 TT.pids = new;
57 }
58 for (;;) {
59 if (TT.names[offset] == name) {
60 TT.err[offset] = errno;
61 break;
62 } else offset++;
63 }
64 if (errno) {
65 if (!FLAG(q)) perror_msg("pid %d", (int)pid);
66 } else if (FLAG(v))
67 printf("Killed %s(%d) with signal %d\n", name, pid, TT.signum);
68
69 return 0;
70 }
71
killall_main(void)72 void killall_main(void)
73 {
74 int i;
75
76 TT.names = toys.optargs;
77 TT.signum = SIGTERM;
78
79 if (FLAG(l)) {
80 list_signals();
81 return;
82 }
83
84 if (TT.s || (*TT.names && **TT.names == '-')) {
85 if (0 > (TT.signum = sig_to_num(TT.s ? TT.s : (*TT.names)+1))) {
86 if (FLAG(q)) exit(1);
87 error_exit("Invalid signal");
88 }
89 if (!TT.s) {
90 TT.names++;
91 toys.optc--;
92 }
93 }
94
95 if (!toys.optc) help_exit("no name");
96
97 TT.cur_pid = getpid();
98
99 TT.err = xmalloc(2*toys.optc);
100 for (i=0; i<toys.optc; i++) TT.err[i] = ESRCH;
101 names_to_pid(TT.names, kill_process, 1);
102 for (i=0; i<toys.optc; i++) {
103 if (TT.err[i]) {
104 toys.exitval = 1;
105 errno = TT.err[i];
106 perror_msg_raw(TT.names[i]);
107 }
108 }
109 if (FLAG(w)) {
110 for (;;) {
111 struct int_list *p = TT.pids;
112 int c = 0;
113
114 for (; p; p=p->next) if (kill(p->val, 0) != -1 || errno != ESRCH) ++c;
115 if (!c) break;
116 sleep(1);
117 }
118 }
119 if (CFG_TOYBOX_FREE) {
120 free(TT.err);
121 llist_traverse(TT.pids, free);
122 }
123 }
124