OSDN Git Service

"printf %x 64" wasn't working right on 32 bit because a variable type was wrong.
[android-x86/external-toybox.git] / toys / posix / kill.c
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 #include "toys.h"
45
46 GLOBALS(
47   char *signame;
48   struct arg_list *olist;
49 )
50
51 // But kill's flags are a subset of killall5's
52
53 #define CLEANUP_kill
54 #define FOR_killall5
55 #include "generated/flags.h"
56
57 void kill_main(void)
58 {
59   int signum;
60   char *tmp, **args = toys.optargs;
61   pid_t pid;
62
63   // list signal(s)
64   if (toys.optflags & FLAG_l) {
65     if (*args) {
66       int signum = sig_to_num(*args);
67       char *s = NULL;
68
69       if (signum>=0) s = num_to_sig(signum&127);
70       puts(s ? s : "UNKNOWN");
71     } else sig_to_num(NULL);
72     return;
73   }
74
75   // signal must come before pids, so "kill -9 -1" isn't confusing.
76
77   if (!TT.signame && *args && **args=='-') TT.signame=*(args++)+1;
78   if (TT.signame) {
79     char *arg;
80     int i = strtol(TT.signame, &arg, 10);
81     if (!*arg) arg = num_to_sig(i);
82     else arg = TT.signame;
83
84     if (!arg || -1 == (signum = sig_to_num(arg)))
85       error_exit("Unknown signal '%s'", arg);
86   } else signum = SIGTERM;
87
88   // is it killall5?
89   if (CFG_KILLALL5 && toys.which->name[4]=='a') {
90     DIR *dp;
91     struct dirent *entry;
92     int pid, sid;
93     long *olist = 0, ocount = 0;
94
95     // parse omit list
96     if (toys.optflags & FLAG_o) {
97       struct arg_list *ptr;
98
99       for (ptr = TT.olist; ptr; ptr = ptr->next) ocount++;
100       olist = xmalloc(ocount*sizeof(long));
101       ocount = 0;
102       for (ptr = TT.olist; ptr; ptr=ptr->next)
103         olist[ocount++] = atolx(ptr->arg);
104     }
105
106     sid = getsid(pid = getpid());
107
108     if (!(dp = opendir("/proc"))) perror_exit("/proc");
109     while ((entry = readdir(dp))) {
110       int count, procpid, procsid;
111
112       if (!(procpid = atoi(entry->d_name))) continue;
113
114       snprintf(toybuf, sizeof(toybuf), "/proc/%d/stat", procpid);
115       if (!readfile(toybuf, toybuf, sizeof(toybuf))) continue;
116       if (sscanf(toybuf, "%*d %*s %*c %*d %*d %d", &procsid) != 1) continue;
117       if (pid == procpid || sid == procsid || procpid == 1) continue;
118
119       // Check for kernel threads.
120       snprintf(toybuf, sizeof(toybuf), "/proc/%d/cmdline", procpid);
121       if (!readfile(toybuf, toybuf, sizeof(toybuf)) || !*toybuf) continue;
122
123       // Check with omit list.
124       for (count = 0; count < ocount; count++) 
125         if (procpid == olist[count]) break;
126       if (count != ocount) continue;
127
128       kill(procpid, signum);
129     }
130     if (CFG_TOYBOX_FREE) {
131       closedir(dp);
132       free(olist);
133     }
134
135   // is it kill?
136   } else {
137
138     // "<1" in optstr wouldn't cover this because "-SIGNAL"
139     if (!*args) help_exit("missing argument");
140
141     while (*args) {
142       char *arg = *(args++);
143
144       pid = strtol(arg, &tmp, 10);
145       if (*tmp || kill(pid, signum) < 0) error_msg("unknown pid '%s'", arg);
146     }
147   }
148 }
149
150 void killall5_main(void)
151 {
152   kill_main();
153 }