1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
/* killall5.c - Send signal (default: TERM) to all processes outside current session.
*
* Copyright 2014 Ranjan Kumar <ranjankumar.bth@gmail.com>
* Copyright 2014 Kyungwan Han <asura321@gamil.com>
*
* No Standard
USE_KILLALL5(NEWTOY(killall5, "?o*ls:[!lo]", TOYFLAG_SBIN))
config KILLALL5
bool "killall5"
default n
help
usage: killall5 [-l] [-SIGNAL|-s SIGNAL] [-o PID]...
Send a signal (default: TERM) to all processes outside current session.
-l List all signal names and numbers
-o PID Don't signal this PID
-s send SIGNAL instead of SIGTERM
*/
#define FOR_killall5
#include "toys.h"
GLOBALS(
char *signame;
struct arg_list *olist;
)
void killall5_main(void)
{
DIR *dp;
struct dirent *entry;
int signo, pid, sid, signum = SIGTERM;
long *olist = NULL, ocount = 0;
char *s, **args = toys.optargs;
// list all signal names and numbers
if (toys.optflags & FLAG_l) {
if (*args) {
for (; *args; args++) {
signo = sig_to_num(*args);
if (isdigit(**args) && (s = num_to_sig(signo&127))) xputs(s);
else if (signo > 0) xprintf("%d\n", signo);
else error_exit("UNKNOWN signal '%s'", *args);
}
} else sig_to_num(NULL);
return;
}
// when SIGNUM will be in the form of -SIGNUM
if (TT.signame || (*args && **args == '-')) {
if (0 > (signum = sig_to_num(TT.signame ? TT.signame : (*args)+1)))
error_exit("Unknown signal '%s'", *args);
if (!TT.signame) args++;
}
pid = getpid();
sid = getsid(pid);
// prepare omit list
if (toys.optflags & FLAG_o) {
struct arg_list *ptr = TT.olist;
if (*args) error_exit("invalid omit list");
for (; ptr; ptr=ptr->next) {
long val = atolx(ptr->arg);
olist = xrealloc(olist, (ocount+1)*sizeof(long));
olist[ocount++] = val;
}
}
if (!(dp = opendir("/proc"))) perror_exit("opendir");
while ((entry = readdir(dp))) {
int count, procpid, procsid;
if (!(procpid = atoi(entry->d_name))) continue;
snprintf(toybuf, sizeof(toybuf), "/proc/%d/stat", procpid);
if (!readfile(toybuf, toybuf, sizeof(toybuf))) continue;
if (sscanf(toybuf, "%*d %*s %*c %*d %*d %d", &procsid) != 1) continue;
if (pid == procpid || sid == procsid || procpid == 1) continue;
// Check for kernel threads.
snprintf(toybuf, sizeof(toybuf), "/proc/%d/cmdline", procpid);
if (readfile(toybuf, toybuf, sizeof(toybuf)) && !*toybuf) continue;
// Check with omit list.
if (toys.optflags & FLAG_o) {
for (count = 0; count < ocount; count++) {
if (procpid == olist[count]) goto OMIT;
}
}
kill(procpid, signum);
OMIT: ;
}
closedir(dp);
if (CFG_TOYBOX_FREE && olist) free(olist);
}
|