diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-04-29 23:42:54 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-04-29 23:42:54 +0000 |
commit | 6f9a6375e52b169fc0a0ce7e4ac71fd10af3041d (patch) | |
tree | 4fc060596d599d6ac86bc964970c466496f67954 | |
parent | e844cd1c557e78d2d1b67d63a8f21e8c5406c335 (diff) | |
download | busybox-w32-6f9a6375e52b169fc0a0ce7e4ac71fd10af3041d.tar.gz busybox-w32-6f9a6375e52b169fc0a0ce7e4ac71fd10af3041d.tar.bz2 busybox-w32-6f9a6375e52b169fc0a0ce7e4ac71fd10af3041d.zip |
ash,kill: use common code for kill applet/builtin
# make bloatcheck
function old new delta
evaltreenr 644 654 +10
evaltree 644 654 +10
parse_conf 1440 1444 +4
dpkg_deb_main 426 429 +3
ed_main 3319 3321 +2
passwd_main 2093 2091 -2
kill_main 830 826 -4
singlemount 4609 4601 -8
find_command 962 954 -8
get_lcm 123 105 -18
.rodata 132243 132147 -96
killcmd 449 120 -329
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 5/7 up/down: 29/-465) Total: -436 bytes
# size busybox_old busybox_unstripped
text data bss dec hex filename
723901 2940 27504 754345 b82a9 busybox_old
723457 2940 27504 753901 b80ed busybox_unstripped
git-svn-id: svn://busybox.net/trunk/busybox@18532 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r-- | include/libbb.h | 1 | ||||
-rw-r--r-- | procps/Kbuild | 1 | ||||
-rw-r--r-- | procps/kill.c | 95 | ||||
-rw-r--r-- | shell/ash.c | 119 |
4 files changed, 86 insertions, 130 deletions
diff --git a/include/libbb.h b/include/libbb.h index 9950c61f2..be51f2520 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -636,6 +636,7 @@ extern void bb_vinfo_msg(const char *s, va_list p); | |||
636 | int bb_cat(char** argv); | 636 | int bb_cat(char** argv); |
637 | int bb_echo(char** argv); | 637 | int bb_echo(char** argv); |
638 | int bb_test(int argc, char** argv); | 638 | int bb_test(int argc, char** argv); |
639 | int kill_main(int argc, char **argv); | ||
639 | #if ENABLE_ROUTE | 640 | #if ENABLE_ROUTE |
640 | void bb_displayroutes(int noresolve, int netstatfmt); | 641 | void bb_displayroutes(int noresolve, int netstatfmt); |
641 | #endif | 642 | #endif |
diff --git a/procps/Kbuild b/procps/Kbuild index 6a9a86637..33f616fc2 100644 --- a/procps/Kbuild +++ b/procps/Kbuild | |||
@@ -7,6 +7,7 @@ | |||
7 | lib-y:= | 7 | lib-y:= |
8 | lib-$(CONFIG_FREE) += free.o | 8 | lib-$(CONFIG_FREE) += free.o |
9 | lib-$(CONFIG_KILL) += kill.o | 9 | lib-$(CONFIG_KILL) += kill.o |
10 | lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash | ||
10 | lib-$(CONFIG_PIDOF) += pidof.o | 11 | lib-$(CONFIG_PIDOF) += pidof.o |
11 | lib-$(CONFIG_PS) += ps.o | 12 | lib-$(CONFIG_PS) += ps.o |
12 | lib-$(CONFIG_RENICE) += renice.o | 13 | lib-$(CONFIG_RENICE) += renice.o |
diff --git a/procps/kill.c b/procps/kill.c index 9a6e93665..e2b029d20 100644 --- a/procps/kill.c +++ b/procps/kill.c | |||
@@ -10,16 +10,30 @@ | |||
10 | 10 | ||
11 | #include "busybox.h" | 11 | #include "busybox.h" |
12 | 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 | |||
13 | int kill_main(int argc, char **argv); | 27 | int kill_main(int argc, char **argv); |
14 | int kill_main(int argc, char **argv) | 28 | int kill_main(int argc, char **argv) |
15 | { | 29 | { |
16 | char *arg; | 30 | char *arg; |
17 | pid_t pid; | 31 | pid_t pid; |
18 | int signo = SIGTERM, errors = 0, quiet = 0; | 32 | int signo = SIGTERM, errors = 0, quiet = 0; |
19 | const int killall = (ENABLE_KILLALL && applet_name[4] == 'a' | 33 | const int killall = (ENABLE_KILLALL && argv[0][4] == 'a' |
20 | && (!ENABLE_KILLALL5 || applet_name[7] != '5')); | 34 | && (!ENABLE_KILLALL5 || argv[0][7] != '5')); |
21 | const int killall5 = (ENABLE_KILLALL5 && applet_name[4] == 'a' | 35 | const int killall5 = (ENABLE_KILLALL5 && argv[0][4] == 'a' |
22 | && (!ENABLE_KILLALL || applet_name[7] == '5')); | 36 | && (!ENABLE_KILLALL || argv[0][7] == '5')); |
23 | 37 | ||
24 | /* Parse any options */ | 38 | /* Parse any options */ |
25 | argc--; | 39 | argc--; |
@@ -29,34 +43,38 @@ int kill_main(int argc, char **argv) | |||
29 | goto do_it_now; | 43 | goto do_it_now; |
30 | } | 44 | } |
31 | 45 | ||
32 | /* The -l option, which prints out signal names. */ | 46 | /* The -l option, which prints out signal names. |
47 | * Intended usage in shell: | ||
48 | * echo "Died of SIG`kill -l $?`" | ||
49 | * We try to mimic what kill from coreutils-6.8 does */ | ||
33 | if (arg[1] == 'l' && arg[2] == '\0') { | 50 | if (arg[1] == 'l' && arg[2] == '\0') { |
34 | const char *name; | ||
35 | if (argc == 1) { | 51 | if (argc == 1) { |
36 | /* Print the whole signal list */ | 52 | /* Print the whole signal list */ |
37 | int col = 0; | ||
38 | for (signo = 1; signo < 32; signo++) { | 53 | for (signo = 1; signo < 32; signo++) { |
39 | name = get_signame(signo); | 54 | puts(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 | } | 55 | } |
47 | puts(""); | ||
48 | } else { /* -l <sig list> */ | 56 | } else { /* -l <sig list> */ |
49 | while ((arg = *++argv)) { | 57 | while ((arg = *++argv)) { |
50 | if (isdigit(arg[0])) { | 58 | if (isdigit(arg[0])) { |
51 | signo = xatoi_u(arg); | 59 | signo = bb_strtou(arg, NULL, 10); |
52 | name = get_signame(signo); | 60 | if (errno) { |
61 | bb_error_msg("unknown signal '%s'", arg); | ||
62 | return EXIT_FAILURE; | ||
63 | } | ||
64 | /* Exitcodes >= 0x80 are to be treated | ||
65 | * as "killed by signal (exitcode & 0x7f)" */ | ||
66 | puts(get_signame(signo & 0x7f)); | ||
67 | /* TODO: 'bad' signal# - coreutils says: | ||
68 | * kill: 127: invalid signal | ||
69 | * we just print "127" instead */ | ||
53 | } else { | 70 | } else { |
54 | signo = get_signum(arg); | 71 | signo = get_signum(arg); |
55 | if (signo < 0) | 72 | if (signo < 0) { |
56 | bb_error_msg_and_die("unknown signal '%s'", arg); | 73 | bb_error_msg("unknown signal '%s'", arg); |
57 | name = get_signame(signo); | 74 | return EXIT_FAILURE; |
75 | } | ||
76 | printf("%d\n", signo); | ||
58 | } | 77 | } |
59 | printf("%2d) %s\n", signo, name); | ||
60 | } | 78 | } |
61 | } | 79 | } |
62 | /* If they specified -l, we are all done */ | 80 | /* If they specified -l, we are all done */ |
@@ -74,8 +92,10 @@ int kill_main(int argc, char **argv) | |||
74 | 92 | ||
75 | /* -SIG */ | 93 | /* -SIG */ |
76 | signo = get_signum(&arg[1]); | 94 | signo = get_signum(&arg[1]); |
77 | if (signo < 0) | 95 | if (signo < 0) { /* || signo > MAX_SIGNUM ? */ |
78 | bb_error_msg_and_die("bad signal name '%s'", &arg[1]); | 96 | bb_error_msg("bad signal name '%s'", &arg[1]); |
97 | return EXIT_FAILURE; | ||
98 | } | ||
79 | arg = *++argv; | 99 | arg = *++argv; |
80 | argc--; | 100 | argc--; |
81 | 101 | ||
@@ -85,10 +105,6 @@ do_it_now: | |||
85 | pid_t sid; | 105 | pid_t sid; |
86 | procps_status_t* p = NULL; | 106 | procps_status_t* p = NULL; |
87 | 107 | ||
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 */ | 108 | /* Now stop all processes */ |
93 | kill(-1, SIGSTOP); | 109 | kill(-1, SIGSTOP); |
94 | /* Find out our own session id */ | 110 | /* Find out our own session id */ |
@@ -104,9 +120,11 @@ do_it_now: | |||
104 | return 0; | 120 | return 0; |
105 | } | 121 | } |
106 | 122 | ||
107 | /* Pid or name required for kill/killall */ | 123 | /* Pid or name is required for kill/killall */ |
108 | if (argc < 1) | 124 | if (argc < 1) { |
109 | bb_show_usage(); | 125 | puts("You need to specify whom to kill"); |
126 | return EXIT_FAILURE; | ||
127 | } | ||
110 | 128 | ||
111 | if (killall) { | 129 | if (killall) { |
112 | /* Looks like they want to do a killall. Do that */ | 130 | /* Looks like they want to do a killall. Do that */ |
@@ -140,14 +158,15 @@ do_it_now: | |||
140 | 158 | ||
141 | /* Looks like they want to do a kill. Do that */ | 159 | /* Looks like they want to do a kill. Do that */ |
142 | while (arg) { | 160 | while (arg) { |
143 | /* Huh? | 161 | /* Support shell 'space' trick */ |
144 | if (!isdigit(arg[0]) && arg[0] != '-') | 162 | if (arg[0] == ' ') |
145 | bb_error_msg_and_die("bad pid '%s'", arg); | 163 | arg++; |
146 | */ | 164 | pid = bb_strtoi(arg, NULL, 10); |
147 | pid = xatou(arg); | 165 | if (errno) { |
148 | /* FIXME: better overflow check? */ | 166 | bb_error_msg("bad pid '%s'", arg); |
149 | if (kill(pid, signo) != 0) { | 167 | errors++; |
150 | bb_perror_msg("cannot kill pid %u", (unsigned)pid); | 168 | } else if (kill(pid, signo) != 0) { |
169 | bb_perror_msg("cannot kill pid %d", (int)pid); | ||
151 | errors++; | 170 | errors++; |
152 | } | 171 | } |
153 | arg = *++argv; | 172 | arg = *++argv; |
diff --git a/shell/ash.c b/shell/ash.c index 16818cfc9..4b37f403c 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -3519,91 +3519,22 @@ setjobctl(int on) | |||
3519 | static int | 3519 | static int |
3520 | killcmd(int argc, char **argv) | 3520 | killcmd(int argc, char **argv) |
3521 | { | 3521 | { |
3522 | int signo = -1; | 3522 | if (argv[1] && strcmp(argv[1], "-l") != 0) { |
3523 | int list = 0; | 3523 | int i = 1; |
3524 | int i; | 3524 | do { |
3525 | pid_t pid; | 3525 | if (argv[i][0] == '%') { |
3526 | struct job *jp; | 3526 | struct job *jp = getjob(argv[i], 0); |
3527 | 3527 | unsigned pid = jp->ps[0].pid; | |
3528 | if (argc <= 1) { | 3528 | /* Enough space for ' -NNN<nul>' */ |
3529 | usage: | 3529 | argv[i] = alloca(sizeof(int)*3 + 3); |
3530 | ash_msg_and_raise_error( | 3530 | /* kill_main has matching code to expect |
3531 | "usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n" | 3531 | * leading space. Needed to not confuse |
3532 | "kill -l [exitstatus]" | 3532 | * negative pids with "kill -SIGNAL_NO" syntax */ |
3533 | ); | 3533 | sprintf(argv[i], " -%u", pid); |
3534 | } | ||
3535 | |||
3536 | if (**++argv == '-') { | ||
3537 | signo = get_signum(*argv + 1); | ||
3538 | if (signo < 0) { | ||
3539 | int c; | ||
3540 | |||
3541 | while ((c = nextopt("ls:")) != '\0') { | ||
3542 | switch (c) { | ||
3543 | default: | ||
3544 | #if DEBUG | ||
3545 | abort(); | ||
3546 | #endif | ||
3547 | case 'l': | ||
3548 | list = 1; | ||
3549 | break; | ||
3550 | case 's': | ||
3551 | signo = get_signum(optionarg); | ||
3552 | if (signo < 0) { | ||
3553 | ash_msg_and_raise_error( | ||
3554 | "invalid signal number or name: %s", | ||
3555 | optionarg | ||
3556 | ); | ||
3557 | } | ||
3558 | break; | ||
3559 | } | ||
3560 | } | ||
3561 | argv = argptr; | ||
3562 | } else | ||
3563 | argv++; | ||
3564 | } | ||
3565 | |||
3566 | if (!list && signo < 0) | ||
3567 | signo = SIGTERM; | ||
3568 | |||
3569 | if ((signo < 0 || !*argv) ^ list) { | ||
3570 | goto usage; | ||
3571 | } | ||
3572 | |||
3573 | if (list) { | ||
3574 | const char *name; | ||
3575 | |||
3576 | if (!*argv) { | ||
3577 | for (i = 1; i < NSIG; i++) { | ||
3578 | name = get_signame(i); | ||
3579 | if (!isdigit(*name)) | ||
3580 | out1fmt(snlfmt, name); | ||
3581 | } | 3534 | } |
3582 | return 0; | 3535 | } while (argv[++i]); |
3583 | } | ||
3584 | name = get_signame(signo); | ||
3585 | if (!isdigit(*name)) | ||
3586 | ash_msg_and_raise_error("invalid signal number or exit status: %s", *argptr); | ||
3587 | out1fmt(snlfmt, name); | ||
3588 | return 0; | ||
3589 | } | 3536 | } |
3590 | 3537 | return kill_main(argc, argv); | |
3591 | i = 0; | ||
3592 | do { | ||
3593 | if (**argv == '%') { | ||
3594 | jp = getjob(*argv, 0); | ||
3595 | pid = -jp->ps[0].pid; | ||
3596 | } else { | ||
3597 | pid = **argv == '-' ? | ||
3598 | -number(*argv + 1) : number(*argv); | ||
3599 | } | ||
3600 | if (kill(pid, signo) != 0) { | ||
3601 | ash_msg("(%d) - %m", pid); | ||
3602 | i = 1; | ||
3603 | } | ||
3604 | } while (*++argv); | ||
3605 | |||
3606 | return i; | ||
3607 | } | 3538 | } |
3608 | 3539 | ||
3609 | static void | 3540 | static void |
@@ -3642,7 +3573,8 @@ restartjob(struct job *jp, int mode) | |||
3642 | if (WIFSTOPPED(ps->status)) { | 3573 | if (WIFSTOPPED(ps->status)) { |
3643 | ps->status = -1; | 3574 | ps->status = -1; |
3644 | } | 3575 | } |
3645 | } while (ps++, --i); | 3576 | ps++; |
3577 | } while (--i); | ||
3646 | out: | 3578 | out: |
3647 | status = (mode == FORK_FG) ? waitforjob(jp) : 0; | 3579 | status = (mode == FORK_FG) ? waitforjob(jp) : 0; |
3648 | INT_ON; | 3580 | INT_ON; |
@@ -5070,8 +5002,9 @@ esclen(const char *start, const char *p) | |||
5070 | static char * | 5002 | static char * |
5071 | _rmescapes(char *str, int flag) | 5003 | _rmescapes(char *str, int flag) |
5072 | { | 5004 | { |
5005 | static const char qchars[] = { CTLESC, CTLQUOTEMARK, '\0' }; | ||
5006 | |||
5073 | char *p, *q, *r; | 5007 | char *p, *q, *r; |
5074 | static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 }; | ||
5075 | unsigned inquotes; | 5008 | unsigned inquotes; |
5076 | int notescaped; | 5009 | int notescaped; |
5077 | int globbing; | 5010 | int globbing; |
@@ -11117,13 +11050,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
11117 | return; | 11050 | return; |
11118 | } | 11051 | } |
11119 | 11052 | ||
11120 | #if ENABLE_FEATURE_SH_STANDALONE | 11053 | /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */ |
11121 | if (find_applet_by_name(name)) { | ||
11122 | entry->cmdtype = CMDNORMAL; | ||
11123 | entry->u.index = -1; | ||
11124 | return; | ||
11125 | } | ||
11126 | #endif | ||
11127 | 11054 | ||
11128 | updatetbl = (path == pathval()); | 11055 | updatetbl = (path == pathval()); |
11129 | if (!updatetbl) { | 11056 | if (!updatetbl) { |
@@ -11173,6 +11100,14 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
11173 | } | 11100 | } |
11174 | } | 11101 | } |
11175 | 11102 | ||
11103 | #if ENABLE_FEATURE_SH_STANDALONE | ||
11104 | if (find_applet_by_name(name)) { | ||
11105 | entry->cmdtype = CMDNORMAL; | ||
11106 | entry->u.index = -1; | ||
11107 | return; | ||
11108 | } | ||
11109 | #endif | ||
11110 | |||
11176 | /* We have to search path. */ | 11111 | /* We have to search path. */ |
11177 | prev = -1; /* where to start */ | 11112 | prev = -1; /* where to start */ |
11178 | if (cmdp && cmdp->rehash) { /* doing a rehash */ | 11113 | if (cmdp && cmdp->rehash) { /* doing a rehash */ |