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