1 /* kill.c - a program to send signals to processes
2 *
3 * Copyright 2012 Daniel Walter <d.walter@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@gmail.com>
10 * Copyright 2014 Kyungwan Han <asura321@gamil.com>
11 *
12 * No Standard
13
14 USE_KILL(NEWTOY(kill, "?ls: ", TOYFLAG_BIN|TOYFLAG_MAYFORK))
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 #define FORCE_FLAGS
45 #include "toys.h"
46
GLOBALS(char * s;struct arg_list * o;)47 GLOBALS(
48 char *s;
49 struct arg_list *o;
50 )
51
52 // But kill's flags are a subset of killall5's
53
54 #define CLEANUP_kill
55 #define FOR_killall5
56 #include "generated/flags.h"
57
58 void kill_main(void)
59 {
60 int signum;
61 char *tmp, **args = toys.optargs;
62 pid_t pid;
63
64 // list signal(s)
65 if (FLAG(l)) {
66 if (*args) {
67 int signum = sig_to_num(*args);
68 char *s = 0;
69
70 if (signum>=0) s = num_to_sig(signum&127);
71 if (isdigit(**args)) puts(s ? s : "UNKNOWN");
72 else printf("%d\n", signum);
73 } else list_signals();
74
75 return;
76 }
77
78 // signal must come before pids, so "kill -9 -1" isn't confusing.
79
80 if (!TT.s && *args && **args=='-') TT.s = *(args++)+1;
81 if (TT.s) {
82 char *arg;
83 int i = strtol(TT.s, &arg, 10);
84
85 if (!*arg) arg = num_to_sig(i);
86 else arg = TT.s;
87
88 if (!arg || -1 == (signum = sig_to_num(arg)))
89 error_exit("Unknown signal '%s'", arg);
90 } else signum = SIGTERM;
91
92 // is it killall5?
93 if (CFG_KILLALL5 && toys.which->name[4]=='a') {
94 DIR *dp;
95 struct dirent *entry;
96 int pid, sid;
97 long *olist = 0, ocount = 0;
98
99 // parse omit list
100 if (FLAG(o)) {
101 struct arg_list *ptr;
102
103 for (ptr = TT.o; ptr; ptr = ptr->next) ocount++;
104 olist = xmalloc(ocount*sizeof(long));
105 ocount = 0;
106 for (ptr = TT.o; ptr; ptr=ptr->next) olist[ocount++] = atolx(ptr->arg);
107 }
108
109 sid = getsid(pid = getpid());
110
111 if (!(dp = opendir("/proc"))) {
112 free(olist);
113 perror_exit("/proc");
114 }
115 while ((entry = readdir(dp))) {
116 int count, procpid, procsid;
117
118 if (!(procpid = atoi(entry->d_name))) continue;
119
120 snprintf(toybuf, sizeof(toybuf), "/proc/%d/stat", procpid);
121 if (!readfile(toybuf, toybuf, sizeof(toybuf))) continue;
122 if (sscanf(toybuf, "%*d %*s %*c %*d %*d %d", &procsid) != 1) continue;
123 if (pid == procpid || sid == procsid || procpid == 1) continue;
124
125 // Check for kernel threads.
126 snprintf(toybuf, sizeof(toybuf), "/proc/%d/cmdline", procpid);
127 if (!readfile(toybuf, toybuf, sizeof(toybuf)) || !*toybuf) continue;
128
129 // Check with omit list.
130 for (count = 0; count < ocount; count++)
131 if (procpid == olist[count]) break;
132 if (count != ocount) continue;
133
134 kill(procpid, signum);
135 }
136 closedir(dp);
137 free(olist);
138
139 // is it kill?
140 } else {
141
142 // "<1" in optstr wouldn't cover this because "-SIGNAL"
143 if (!*args) help_exit("missing argument");
144
145 while (*args) {
146 char *arg = *(args++);
147
148 pid = strtol(arg, &tmp, 10);
149 if (*tmp || kill(pid, signum) < 0) error_msg("unknown pid '%s'", arg);
150 }
151 }
152 }
153
killall5_main(void)154 void killall5_main(void)
155 {
156 kill_main();
157 }
158