top: improve CPU% calculation
[oweals/busybox.git] / procps / kill.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini kill/killall 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 "busybox.h"
12
13 int kill_main(int argc, char **argv)
14 {
15         char *arg;
16         pid_t pid;
17         int signo = SIGTERM, errors = 0, quiet = 0;
18         const int killall = (ENABLE_KILLALL && applet_name[4] == 'a'
19                        && (!ENABLE_KILLALL5 || applet_name[7] != '5'));
20         const int killall5 = (ENABLE_KILLALL5 && applet_name[4] == 'a'
21                           && (!ENABLE_KILLALL || applet_name[7] == '5'));
22
23         /* Parse any options */
24         argc--;
25         arg = *++argv;
26
27         if (argc < 1 || arg[0] != '-') {
28                 goto do_it_now;
29         }
30
31         /* The -l option, which prints out signal names. */
32         if (arg[1] == 'l' && arg[2] == '\0') {
33                 const char *name;
34                 if (argc == 1) {
35                         /* Print the whole signal list */
36                         int col = 0;
37                         for (signo = 1; signo < 32; signo++) {
38                                 name = get_signame(signo);
39                                 if (isdigit(name[0])) continue;
40                                 if (col > 66) {
41                                         puts("");
42                                         col = 0;
43                                 }
44                                 col += printf("%2d) %-6s", signo, name);
45                         }
46                         puts("");
47                 } else { /* -l <sig list> */
48                         while ((arg = *++argv)) {
49                                 if (isdigit(arg[0])) {
50                                         signo = xatoi_u(arg);
51                                         name = get_signame(signo);
52                                 } else {
53                                         signo = get_signum(arg);
54                                         if (signo < 0)
55                                                 bb_error_msg_and_die("unknown signal '%s'", arg);
56                                         name = get_signame(signo);
57                                 }
58                                 printf("%2d) %s\n", signo, name);
59                         }
60                 }
61                 /* If they specified -l, we are all done */
62                 return EXIT_SUCCESS;
63         }
64
65         /* The -q quiet option */
66         if (killall && arg[1] == 'q' && arg[2] == '\0') {
67                 quiet = 1;
68                 arg = *++argv;
69                 argc--;
70                 if (argc < 1) bb_show_usage();
71                 if (arg[0] != '-') goto do_it_now;
72         }
73
74         /* -SIG */
75         signo = get_signum(&arg[1]);
76         if (signo < 0)
77                 bb_error_msg_and_die("bad signal name '%s'", &arg[1]);
78         arg = *++argv;
79         argc--;
80
81 do_it_now:
82
83         if (killall5) {
84                 pid_t sid;
85                 procps_status_t* p;
86
87 // Cannot happen anyway? We don't TERM ourself, we STOP
88 //              /* kill(-1, sig) on Linux (at least 2.1.x)
89 //               * might send signal to the calling process too */
90 //              signal(SIGTERM, SIG_IGN);
91                 /* Now stop all processes */
92                 kill(-1, SIGSTOP);
93                 /* Find out our own session id */
94                 pid = getpid();
95                 sid = getsid(pid);
96                 /* Now kill all processes except our session */
97                 while ((p = procps_scan(0))!=0) {
98                         if (getsid(p->pid)!=sid && p->pid!=pid && p->pid!=1)
99                                 kill(p->pid, signo);
100                 }
101                 /* And let them continue */
102                 kill(-1, SIGCONT);
103                 return 0;
104         }
105
106         /* Pid or name required for kill/killall */
107         if (argc < 1)
108                 bb_show_usage();
109
110         if (killall) {
111                 /* Looks like they want to do a killall.  Do that */
112                 pid = getpid();
113                 while (arg) {
114                         pid_t* pidList;
115
116                         pidList = find_pid_by_name(arg);
117                         if (*pidList == 0) {
118                                 errors++;
119                                 if (!quiet)
120                                         bb_error_msg("%s: no process killed", arg);
121                         } else {
122                                 pid_t *pl;
123
124                                 for (pl = pidList; *pl; pl++) {
125                                         if (*pl == pid)
126                                                 continue;
127                                         if (kill(*pl, signo) == 0)
128                                                 continue;
129                                         errors++;
130                                         if (!quiet)
131                                                 bb_perror_msg("cannot kill pid %u", (unsigned)*pl);
132                                 }
133                         }
134                         free(pidList);
135                         arg = *++argv;
136                 }
137                 return errors;
138         }
139
140         /* Looks like they want to do a kill. Do that */
141         while (arg) {
142                 /* Huh?
143                 if (!isdigit(arg[0]) && arg[0] != '-')
144                         bb_error_msg_and_die("bad pid '%s'", arg);
145                 */
146                 pid = xatou(arg);
147                 /* FIXME: better overflow check? */
148                 if (kill(pid, signo) != 0) {
149                         bb_perror_msg("cannot kill pid %u", (unsigned)pid);
150                         errors++;
151                 }
152                 arg = *++argv;
153         }
154         return errors;
155 }