Contents of /trunk/mkinitrd-magellan/busybox/procps/kill.c
Parent Directory | Revision Log
Revision 1123 -
(show annotations)
(download)
Wed Aug 18 21:56:57 2010 UTC (14 years, 1 month ago) by niro
File MIME type: text/plain
File size: 5224 byte(s)
Wed Aug 18 21:56:57 2010 UTC (14 years, 1 month ago) by niro
File MIME type: text/plain
File size: 5224 byte(s)
-updated to busybox-1.17.1
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * Mini kill/killall[5] implementation for busybox |
4 | * |
5 | * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. |
6 | * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> |
7 | * |
8 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. |
9 | */ |
10 | |
11 | #include "libbb.h" |
12 | |
13 | /* Note: kill_main is directly called from shell in order to implement |
14 | * kill built-in. Shell substitutes job ids with process groups first. |
15 | * |
16 | * This brings some complications: |
17 | * |
18 | * + we can't use xfunc here |
19 | * + we can't use applet_name |
20 | * + we can't use bb_show_usage |
21 | * (Above doesn't apply for killall[5] cases) |
22 | * |
23 | * kill %n gets translated into kill ' -<process group>' by shell (note space!) |
24 | * This is needed to avoid collision with kill -9 ... syntax |
25 | */ |
26 | |
27 | int kill_main(int argc, char **argv) |
28 | { |
29 | char *arg; |
30 | pid_t pid; |
31 | int signo = SIGTERM, errors = 0, quiet = 0; |
32 | #if !ENABLE_KILLALL && !ENABLE_KILLALL5 |
33 | #define killall 0 |
34 | #define killall5 0 |
35 | #else |
36 | /* How to determine who we are? find 3rd char from the end: |
37 | * kill, killall, killall5 |
38 | * ^i ^a ^l - it's unique |
39 | * (checking from the start is complicated by /bin/kill... case) */ |
40 | const char char3 = argv[0][strlen(argv[0]) - 3]; |
41 | #define killall (ENABLE_KILLALL && char3 == 'a') |
42 | #define killall5 (ENABLE_KILLALL5 && char3 == 'l') |
43 | #endif |
44 | |
45 | /* Parse any options */ |
46 | argc--; |
47 | arg = *++argv; |
48 | |
49 | if (argc < 1 || arg[0] != '-') { |
50 | goto do_it_now; |
51 | } |
52 | |
53 | /* The -l option, which prints out signal names. |
54 | * Intended usage in shell: |
55 | * echo "Died of SIG`kill -l $?`" |
56 | * We try to mimic what kill from coreutils-6.8 does */ |
57 | if (arg[1] == 'l' && arg[2] == '\0') { |
58 | if (argc == 1) { |
59 | /* Print the whole signal list */ |
60 | print_signames(); |
61 | return 0; |
62 | } |
63 | /* -l <sig list> */ |
64 | while ((arg = *++argv)) { |
65 | if (isdigit(arg[0])) { |
66 | signo = bb_strtou(arg, NULL, 10); |
67 | if (errno) { |
68 | bb_error_msg("unknown signal '%s'", arg); |
69 | return EXIT_FAILURE; |
70 | } |
71 | /* Exitcodes >= 0x80 are to be treated |
72 | * as "killed by signal (exitcode & 0x7f)" */ |
73 | puts(get_signame(signo & 0x7f)); |
74 | /* TODO: 'bad' signal# - coreutils says: |
75 | * kill: 127: invalid signal |
76 | * we just print "127" instead */ |
77 | } else { |
78 | signo = get_signum(arg); |
79 | if (signo < 0) { |
80 | bb_error_msg("unknown signal '%s'", arg); |
81 | return EXIT_FAILURE; |
82 | } |
83 | printf("%d\n", signo); |
84 | } |
85 | } |
86 | /* If they specified -l, we are all done */ |
87 | return EXIT_SUCCESS; |
88 | } |
89 | |
90 | /* The -q quiet option */ |
91 | if (killall && arg[1] == 'q' && arg[2] == '\0') { |
92 | quiet = 1; |
93 | arg = *++argv; |
94 | argc--; |
95 | if (argc < 1) |
96 | bb_show_usage(); |
97 | if (arg[0] != '-') |
98 | goto do_it_now; |
99 | } |
100 | |
101 | arg++; /* skip '-' */ |
102 | |
103 | /* -o PID? (if present, it always is at the end of command line) */ |
104 | if (killall5 && arg[0] == 'o') |
105 | goto do_it_now; |
106 | |
107 | if (argc > 1 && arg[0] == 's' && arg[1] == '\0') { /* -s SIG? */ |
108 | argc--; |
109 | arg = *++argv; |
110 | } /* else it must be -SIG */ |
111 | signo = get_signum(arg); |
112 | if (signo < 0) { /* || signo > MAX_SIGNUM ? */ |
113 | bb_error_msg("bad signal name '%s'", arg); |
114 | return EXIT_FAILURE; |
115 | } |
116 | arg = *++argv; |
117 | argc--; |
118 | |
119 | do_it_now: |
120 | pid = getpid(); |
121 | |
122 | if (killall5) { |
123 | pid_t sid; |
124 | procps_status_t* p = NULL; |
125 | int ret = 0; |
126 | |
127 | /* Find out our session id */ |
128 | sid = getsid(pid); |
129 | /* Stop all processes */ |
130 | kill(-1, SIGSTOP); |
131 | /* Signal all processes except those in our session */ |
132 | while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID))) { |
133 | int i; |
134 | |
135 | if (p->sid == (unsigned)sid |
136 | || p->pid == (unsigned)pid |
137 | || p->pid == 1) |
138 | continue; |
139 | |
140 | /* All remaining args must be -o PID options. |
141 | * Check p->pid against them. */ |
142 | for (i = 0; i < argc; i++) { |
143 | pid_t omit; |
144 | |
145 | arg = argv[i]; |
146 | if (arg[0] != '-' || arg[1] != 'o') { |
147 | bb_error_msg("bad option '%s'", arg); |
148 | ret = 1; |
149 | goto resume; |
150 | } |
151 | arg += 2; |
152 | if (!arg[0] && argv[++i]) |
153 | arg = argv[i]; |
154 | omit = bb_strtoi(arg, NULL, 10); |
155 | if (errno) { |
156 | bb_error_msg("bad pid '%s'", arg); |
157 | ret = 1; |
158 | goto resume; |
159 | } |
160 | if (p->pid == omit) |
161 | goto dont_kill; |
162 | } |
163 | kill(p->pid, signo); |
164 | dont_kill: ; |
165 | } |
166 | resume: |
167 | /* And let them continue */ |
168 | kill(-1, SIGCONT); |
169 | return ret; |
170 | } |
171 | |
172 | /* Pid or name is required for kill/killall */ |
173 | if (argc < 1) { |
174 | bb_error_msg("you need to specify whom to kill"); |
175 | return EXIT_FAILURE; |
176 | } |
177 | |
178 | if (killall) { |
179 | /* Looks like they want to do a killall. Do that */ |
180 | while (arg) { |
181 | pid_t* pidList; |
182 | |
183 | pidList = find_pid_by_name(arg); |
184 | if (*pidList == 0) { |
185 | errors++; |
186 | if (!quiet) |
187 | bb_error_msg("%s: no process killed", arg); |
188 | } else { |
189 | pid_t *pl; |
190 | |
191 | for (pl = pidList; *pl; pl++) { |
192 | if (*pl == pid) |
193 | continue; |
194 | if (kill(*pl, signo) == 0) |
195 | continue; |
196 | errors++; |
197 | if (!quiet) |
198 | bb_perror_msg("can't kill pid %d", (int)*pl); |
199 | } |
200 | } |
201 | free(pidList); |
202 | arg = *++argv; |
203 | } |
204 | return errors; |
205 | } |
206 | |
207 | /* Looks like they want to do a kill. Do that */ |
208 | while (arg) { |
209 | /* Support shell 'space' trick */ |
210 | if (arg[0] == ' ') |
211 | arg++; |
212 | pid = bb_strtoi(arg, NULL, 10); |
213 | if (errno) { |
214 | bb_error_msg("bad pid '%s'", arg); |
215 | errors++; |
216 | } else if (kill(pid, signo) != 0) { |
217 | bb_perror_msg("can't kill pid %d", (int)pid); |
218 | errors++; |
219 | } |
220 | arg = *++argv; |
221 | } |
222 | return errors; |
223 | } |