xref: /aosp_15_r20/external/toybox/toys/posix/kill.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /* kill.c - a program to send signals to processes
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2012 Daniel Walter <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker  *
5*cf5a6c84SAndroid Build Coastguard Worker  * See http://opengroup.org/onlinepubs/9699919799/utilities/kill.html
6*cf5a6c84SAndroid Build Coastguard Worker  *
7*cf5a6c84SAndroid Build Coastguard Worker  * killall5.c - Send signal to all processes outside current session.
8*cf5a6c84SAndroid Build Coastguard Worker  *
9*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2014 Ranjan Kumar <[email protected]>
10*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2014 Kyungwan Han <[email protected]>
11*cf5a6c84SAndroid Build Coastguard Worker  *
12*cf5a6c84SAndroid Build Coastguard Worker  * No Standard
13*cf5a6c84SAndroid Build Coastguard Worker  *
14*cf5a6c84SAndroid Build Coastguard Worker  * TODO: toysh jobspec support, -n -L
15*cf5a6c84SAndroid Build Coastguard Worker 
16*cf5a6c84SAndroid Build Coastguard Worker USE_KILL(NEWTOY(kill, "?ls: ", TOYFLAG_BIN|TOYFLAG_MAYFORK))
17*cf5a6c84SAndroid Build Coastguard Worker USE_KILLALL5(NEWTOY(killall5, "?o*ls: [!lo][!ls]", TOYFLAG_SBIN))
18*cf5a6c84SAndroid Build Coastguard Worker 
19*cf5a6c84SAndroid Build Coastguard Worker config KILL
20*cf5a6c84SAndroid Build Coastguard Worker   bool "kill"
21*cf5a6c84SAndroid Build Coastguard Worker   default y
22*cf5a6c84SAndroid Build Coastguard Worker   help
23*cf5a6c84SAndroid Build Coastguard Worker     usage: kill [-l [SIGNAL] | -s SIGNAL | -SIGNAL] PID...
24*cf5a6c84SAndroid Build Coastguard Worker 
25*cf5a6c84SAndroid Build Coastguard Worker     Send signal to process(es).
26*cf5a6c84SAndroid Build Coastguard Worker 
27*cf5a6c84SAndroid Build Coastguard Worker     -l	List signal name(s) and number(s)
28*cf5a6c84SAndroid Build Coastguard Worker     -s	Send SIGNAL (default SIGTERM)
29*cf5a6c84SAndroid Build Coastguard Worker 
30*cf5a6c84SAndroid Build Coastguard Worker config KILLALL5
31*cf5a6c84SAndroid Build Coastguard Worker   bool "killall5"
32*cf5a6c84SAndroid Build Coastguard Worker   default y
33*cf5a6c84SAndroid Build Coastguard Worker   depends on KILL
34*cf5a6c84SAndroid Build Coastguard Worker   help
35*cf5a6c84SAndroid Build Coastguard Worker     usage: killall5 [-l [SIGNAL]] [-SIGNAL|-s SIGNAL] [-o PID]...
36*cf5a6c84SAndroid Build Coastguard Worker 
37*cf5a6c84SAndroid Build Coastguard Worker     Send a signal to all processes outside current session.
38*cf5a6c84SAndroid Build Coastguard Worker 
39*cf5a6c84SAndroid Build Coastguard Worker     -l	List signal name(s) and number(s)
40*cf5a6c84SAndroid Build Coastguard Worker     -o PID	Omit PID
41*cf5a6c84SAndroid Build Coastguard Worker     -s	Send SIGNAL (default SIGTERM)
42*cf5a6c84SAndroid Build Coastguard Worker */
43*cf5a6c84SAndroid Build Coastguard Worker 
44*cf5a6c84SAndroid Build Coastguard Worker // This has to match the filename:
45*cf5a6c84SAndroid Build Coastguard Worker #define FOR_kill
46*cf5a6c84SAndroid Build Coastguard Worker #define FORCE_FLAGS
47*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
48*cf5a6c84SAndroid Build Coastguard Worker 
GLOBALS(char * s;struct arg_list * o;)49*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
50*cf5a6c84SAndroid Build Coastguard Worker   char *s;
51*cf5a6c84SAndroid Build Coastguard Worker   struct arg_list *o;
52*cf5a6c84SAndroid Build Coastguard Worker )
53*cf5a6c84SAndroid Build Coastguard Worker 
54*cf5a6c84SAndroid Build Coastguard Worker // But kill's flags are a subset of killall5's
55*cf5a6c84SAndroid Build Coastguard Worker 
56*cf5a6c84SAndroid Build Coastguard Worker #define FOR_killall5
57*cf5a6c84SAndroid Build Coastguard Worker #include "generated/flags.h"
58*cf5a6c84SAndroid Build Coastguard Worker 
59*cf5a6c84SAndroid Build Coastguard Worker void kill_main(void)
60*cf5a6c84SAndroid Build Coastguard Worker {
61*cf5a6c84SAndroid Build Coastguard Worker   int signum;
62*cf5a6c84SAndroid Build Coastguard Worker   char *tmp, **args = toys.optargs;
63*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
64*cf5a6c84SAndroid Build Coastguard Worker 
65*cf5a6c84SAndroid Build Coastguard Worker   // list signal(s)
66*cf5a6c84SAndroid Build Coastguard Worker   if (FLAG(l)) {
67*cf5a6c84SAndroid Build Coastguard Worker     if (*args) {
68*cf5a6c84SAndroid Build Coastguard Worker       int signum = sig_to_num(*args);
69*cf5a6c84SAndroid Build Coastguard Worker       char *s = 0;
70*cf5a6c84SAndroid Build Coastguard Worker 
71*cf5a6c84SAndroid Build Coastguard Worker       if (signum>=0) s = num_to_sig(signum&127);
72*cf5a6c84SAndroid Build Coastguard Worker       if (isdigit(**args)) puts(s ? s : "UNKNOWN");
73*cf5a6c84SAndroid Build Coastguard Worker       else printf("%d\n", signum);
74*cf5a6c84SAndroid Build Coastguard Worker     } else list_signals();
75*cf5a6c84SAndroid Build Coastguard Worker 
76*cf5a6c84SAndroid Build Coastguard Worker     return;
77*cf5a6c84SAndroid Build Coastguard Worker   }
78*cf5a6c84SAndroid Build Coastguard Worker 
79*cf5a6c84SAndroid Build Coastguard Worker   // signal must come before pids, so "kill -9 -1" isn't confusing.
80*cf5a6c84SAndroid Build Coastguard Worker 
81*cf5a6c84SAndroid Build Coastguard Worker   if (!TT.s && *args && **args=='-') TT.s = *(args++)+1;
82*cf5a6c84SAndroid Build Coastguard Worker   if (TT.s) {
83*cf5a6c84SAndroid Build Coastguard Worker     char *arg;
84*cf5a6c84SAndroid Build Coastguard Worker     int i = strtol(TT.s, &arg, 10);
85*cf5a6c84SAndroid Build Coastguard Worker 
86*cf5a6c84SAndroid Build Coastguard Worker     if (!*arg) arg = num_to_sig(i);
87*cf5a6c84SAndroid Build Coastguard Worker     else arg = TT.s;
88*cf5a6c84SAndroid Build Coastguard Worker 
89*cf5a6c84SAndroid Build Coastguard Worker     if (!arg || -1 == (signum = sig_to_num(arg)))
90*cf5a6c84SAndroid Build Coastguard Worker       error_exit("Unknown signal '%s'", arg);
91*cf5a6c84SAndroid Build Coastguard Worker   } else signum = SIGTERM;
92*cf5a6c84SAndroid Build Coastguard Worker 
93*cf5a6c84SAndroid Build Coastguard Worker   // is it killall5?
94*cf5a6c84SAndroid Build Coastguard Worker   if (CFG_KILLALL5 && toys.which->name[4]=='a') {
95*cf5a6c84SAndroid Build Coastguard Worker     DIR *dp;
96*cf5a6c84SAndroid Build Coastguard Worker     struct dirent *entry;
97*cf5a6c84SAndroid Build Coastguard Worker     int pid, sid;
98*cf5a6c84SAndroid Build Coastguard Worker     long *olist = 0, ocount = 0;
99*cf5a6c84SAndroid Build Coastguard Worker 
100*cf5a6c84SAndroid Build Coastguard Worker     // parse omit list
101*cf5a6c84SAndroid Build Coastguard Worker     if (FLAG(o)) {
102*cf5a6c84SAndroid Build Coastguard Worker       struct arg_list *ptr;
103*cf5a6c84SAndroid Build Coastguard Worker 
104*cf5a6c84SAndroid Build Coastguard Worker       for (ptr = TT.o; ptr; ptr = ptr->next) ocount++;
105*cf5a6c84SAndroid Build Coastguard Worker       olist = xmalloc(ocount*sizeof(long));
106*cf5a6c84SAndroid Build Coastguard Worker       ocount = 0;
107*cf5a6c84SAndroid Build Coastguard Worker       for (ptr = TT.o; ptr; ptr=ptr->next) olist[ocount++] = atolx(ptr->arg);
108*cf5a6c84SAndroid Build Coastguard Worker     }
109*cf5a6c84SAndroid Build Coastguard Worker 
110*cf5a6c84SAndroid Build Coastguard Worker     sid = getsid(pid = getpid());
111*cf5a6c84SAndroid Build Coastguard Worker 
112*cf5a6c84SAndroid Build Coastguard Worker     if (!(dp = opendir("/proc"))) {
113*cf5a6c84SAndroid Build Coastguard Worker       free(olist);
114*cf5a6c84SAndroid Build Coastguard Worker       perror_exit("/proc");
115*cf5a6c84SAndroid Build Coastguard Worker     }
116*cf5a6c84SAndroid Build Coastguard Worker     while ((entry = readdir(dp))) {
117*cf5a6c84SAndroid Build Coastguard Worker       int count, procpid, procsid;
118*cf5a6c84SAndroid Build Coastguard Worker 
119*cf5a6c84SAndroid Build Coastguard Worker       if (!(procpid = atoi(entry->d_name))) continue;
120*cf5a6c84SAndroid Build Coastguard Worker 
121*cf5a6c84SAndroid Build Coastguard Worker       snprintf(toybuf, sizeof(toybuf), "/proc/%d/stat", procpid);
122*cf5a6c84SAndroid Build Coastguard Worker       if (!readfile(toybuf, toybuf, sizeof(toybuf))) continue;
123*cf5a6c84SAndroid Build Coastguard Worker       // command name can have embedded space and/or )
124*cf5a6c84SAndroid Build Coastguard Worker       if (!(tmp = strrchr(toybuf, ')'))
125*cf5a6c84SAndroid Build Coastguard Worker           || sscanf(tmp, " %*c %*d %*d %d", &procsid) != 1) continue;
126*cf5a6c84SAndroid Build Coastguard Worker       if (pid == procpid || sid == procsid || procpid == 1) continue;
127*cf5a6c84SAndroid Build Coastguard Worker 
128*cf5a6c84SAndroid Build Coastguard Worker       // Check for kernel threads.
129*cf5a6c84SAndroid Build Coastguard Worker       snprintf(toybuf, sizeof(toybuf), "/proc/%d/cmdline", procpid);
130*cf5a6c84SAndroid Build Coastguard Worker       if (!readfile(toybuf, toybuf, sizeof(toybuf)) || !*toybuf) continue;
131*cf5a6c84SAndroid Build Coastguard Worker 
132*cf5a6c84SAndroid Build Coastguard Worker       // Check with omit list.
133*cf5a6c84SAndroid Build Coastguard Worker       for (count = 0; count < ocount; count++)
134*cf5a6c84SAndroid Build Coastguard Worker         if (procpid == olist[count]) break;
135*cf5a6c84SAndroid Build Coastguard Worker       if (count != ocount) continue;
136*cf5a6c84SAndroid Build Coastguard Worker 
137*cf5a6c84SAndroid Build Coastguard Worker       kill(procpid, signum);
138*cf5a6c84SAndroid Build Coastguard Worker     }
139*cf5a6c84SAndroid Build Coastguard Worker     closedir(dp);
140*cf5a6c84SAndroid Build Coastguard Worker     free(olist);
141*cf5a6c84SAndroid Build Coastguard Worker 
142*cf5a6c84SAndroid Build Coastguard Worker   // is it kill?
143*cf5a6c84SAndroid Build Coastguard Worker   } else {
144*cf5a6c84SAndroid Build Coastguard Worker 
145*cf5a6c84SAndroid Build Coastguard Worker     // "<1" in optstr wouldn't cover this because "-SIGNAL"
146*cf5a6c84SAndroid Build Coastguard Worker     if (!*args) help_exit("missing argument");
147*cf5a6c84SAndroid Build Coastguard Worker 
148*cf5a6c84SAndroid Build Coastguard Worker     while (*args) {
149*cf5a6c84SAndroid Build Coastguard Worker       char *arg = *(args++);
150*cf5a6c84SAndroid Build Coastguard Worker 
151*cf5a6c84SAndroid Build Coastguard Worker       pid = estrtol(arg, &tmp, 10);
152*cf5a6c84SAndroid Build Coastguard Worker       if (!errno && *tmp) errno = ESRCH;
153*cf5a6c84SAndroid Build Coastguard Worker       if (errno || kill(pid, signum)<0) perror_msg("bad pid '%s'", arg);
154*cf5a6c84SAndroid Build Coastguard Worker     }
155*cf5a6c84SAndroid Build Coastguard Worker   }
156*cf5a6c84SAndroid Build Coastguard Worker }
157*cf5a6c84SAndroid Build Coastguard Worker 
killall5_main(void)158*cf5a6c84SAndroid Build Coastguard Worker void killall5_main(void)
159*cf5a6c84SAndroid Build Coastguard Worker {
160*cf5a6c84SAndroid Build Coastguard Worker   kill_main();
161*cf5a6c84SAndroid Build Coastguard Worker }
162