• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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))
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 = NULL;
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     return;
75   }
76 
77   // signal must come before pids, so "kill -9 -1" isn't confusing.
78 
79   if (!TT.s && *args && **args=='-') TT.s = *(args++)+1;
80   if (TT.s) {
81     char *arg;
82     int i = strtol(TT.s, &arg, 10);
83     if (!*arg) arg = num_to_sig(i);
84     else arg = TT.s;
85 
86     if (!arg || -1 == (signum = sig_to_num(arg)))
87       error_exit("Unknown signal '%s'", arg);
88   } else signum = SIGTERM;
89 
90   // is it killall5?
91   if (CFG_KILLALL5 && toys.which->name[4]=='a') {
92     DIR *dp;
93     struct dirent *entry;
94     int pid, sid;
95     long *olist = 0, ocount = 0;
96 
97     // parse omit list
98     if (FLAG(o)) {
99       struct arg_list *ptr;
100 
101       for (ptr = TT.o; ptr; ptr = ptr->next) ocount++;
102       olist = xmalloc(ocount*sizeof(long));
103       ocount = 0;
104       for (ptr = TT.o; ptr; ptr=ptr->next) olist[ocount++] = atolx(ptr->arg);
105     }
106 
107     sid = getsid(pid = getpid());
108 
109     if (!(dp = opendir("/proc"))) perror_exit("/proc");
110     while ((entry = readdir(dp))) {
111       int count, procpid, procsid;
112 
113       if (!(procpid = atoi(entry->d_name))) continue;
114 
115       snprintf(toybuf, sizeof(toybuf), "/proc/%d/stat", procpid);
116       if (!readfile(toybuf, toybuf, sizeof(toybuf))) continue;
117       if (sscanf(toybuf, "%*d %*s %*c %*d %*d %d", &procsid) != 1) continue;
118       if (pid == procpid || sid == procsid || procpid == 1) continue;
119 
120       // Check for kernel threads.
121       snprintf(toybuf, sizeof(toybuf), "/proc/%d/cmdline", procpid);
122       if (!readfile(toybuf, toybuf, sizeof(toybuf)) || !*toybuf) continue;
123 
124       // Check with omit list.
125       for (count = 0; count < ocount; count++)
126         if (procpid == olist[count]) break;
127       if (count != ocount) continue;
128 
129       kill(procpid, signum);
130     }
131     if (CFG_TOYBOX_FREE) {
132       closedir(dp);
133       free(olist);
134     }
135 
136   // is it kill?
137   } else {
138 
139     // "<1" in optstr wouldn't cover this because "-SIGNAL"
140     if (!*args) help_exit("missing argument");
141 
142     while (*args) {
143       char *arg = *(args++);
144 
145       pid = strtol(arg, &tmp, 10);
146       if (*tmp || kill(pid, signum) < 0) error_msg("unknown pid '%s'", arg);
147     }
148   }
149 }
150 
killall5_main(void)151 void killall5_main(void)
152 {
153   kill_main();
154 }
155