kill: optimizations for single-applet build

* Fix a bug with a configuration in which the shell's kill builtin
  would be mistreated as a killall command (i.e. '-q' works, and
  'kill process_name' succeeds when it shouldn't):

    CONFIG_ASH_JOB_CONTROL=y
    CONFIG_HUSH_KILL=y
    # CONFIG_KILL is not set
    CONFIG_KILLALL=y
    # CONFIG_KILLALL5 is not set

* Optimize out unneeded code when the relevant applets are not
  selected.

* Move kbuild lines about shells' kill builtins from Kbuild.src to
  kill.c, to accompany the new HAVE_SH_KILL macro. I hope this would
  make maintanence a little bit easier.

Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Kang-Che Sung 2017-01-09 18:46:58 +01:00 committed by Denys Vlasenko
parent 1cc6804f69
commit 61a91af63d
2 changed files with 28 additions and 21 deletions

View File

@ -7,6 +7,3 @@
lib-y:=
INSERT
lib-$(CONFIG_ASH_JOB_CONTROL) += kill.o # used for built-in kill by ash
lib-$(CONFIG_HUSH_KILL) += kill.o # used for built-in kill by hush

View File

@ -92,28 +92,34 @@
* This is needed to avoid collision with kill -9 ... syntax
*/
//kbuild:lib-$(CONFIG_ASH_JOB_CONTROL) += kill.o
//kbuild:lib-$(CONFIG_HUSH_KILL) += kill.o
#define SH_KILL (ENABLE_ASH_JOB_CONTROL || ENABLE_HUSH_KILL)
/* If shells want to have "kill", for ifdefs it's like ENABLE_KILL=1 */
#if SH_KILL
# undef ENABLE_KILL
# define ENABLE_KILL 1
#endif
#define KILL_APPLET_CNT (ENABLE_KILL + ENABLE_KILLALL + ENABLE_KILLALL5)
int kill_main(int argc UNUSED_PARAM, char **argv)
{
char *arg;
pid_t pid;
int signo = SIGTERM, errors = 0, quiet = 0;
#if ENABLE_KILL && !ENABLE_KILLALL && !ENABLE_KILLALL5
# define killall 0
# define killall5 0
#elif !ENABLE_KILL && ENABLE_KILLALL && !ENABLE_KILLALL5
# define killall 1
# define killall5 0
#elif !ENABLE_KILL && !ENABLE_KILLALL && ENABLE_KILLALL5
# define killall 0
# define killall5 1
#if KILL_APPLET_CNT == 1
# define is_killall ENABLE_KILLALL
# define is_killall5 ENABLE_KILLALL5
#else
/* How to determine who we are? find 3rd char from the end:
* kill, killall, killall5
* ^i ^a ^l - it's unique
* (checking from the start is complicated by /bin/kill... case) */
const char char3 = argv[0][strlen(argv[0]) - 3];
# define killall (ENABLE_KILLALL && char3 == 'a')
# define killall5 (ENABLE_KILLALL5 && char3 == 'l')
# define is_killall (ENABLE_KILLALL && char3 == 'a')
# define is_killall5 (ENABLE_KILLALL5 && char3 == 'l')
#endif
/* Parse any options */
@ -162,7 +168,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
}
/* The -q quiet option */
if (killall && arg[1] == 'q' && arg[2] == '\0') {
if (is_killall && arg[1] == 'q' && arg[2] == '\0') {
quiet = 1;
arg = *++argv;
if (!arg)
@ -174,7 +180,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
arg++; /* skip '-' */
/* -o PID? (if present, it always is at the end of command line) */
if (killall5 && arg[0] == 'o')
if (is_killall5 && arg[0] == 'o')
goto do_it_now;
if (argv[1] && arg[0] == 's' && arg[1] == '\0') { /* -s SIG? */
@ -190,7 +196,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
do_it_now:
pid = getpid();
if (killall5) {
if (is_killall5) {
pid_t sid;
procps_status_t* p = NULL;
/* compat: exitcode 2 is "no one was signaled" */
@ -248,13 +254,14 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
return ret;
}
#if ENABLE_KILL || ENABLE_KILLALL
/* Pid or name is required for kill/killall */
if (!arg) {
bb_error_msg("you need to specify whom to kill");
return EXIT_FAILURE;
}
if (killall) {
if (!ENABLE_KILL || is_killall) {
/* Looks like they want to do a killall. Do that */
do {
pid_t* pidList;
@ -282,10 +289,12 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
} while (arg);
return errors;
}
#endif
#if ENABLE_KILL
/* Looks like they want to do a kill. Do that */
while (arg) {
#if ENABLE_ASH_JOB_CONTROL || ENABLE_HUSH_KILL
# if SH_KILL
/*
* We need to support shell's "hack formats" of
* " -PRGP_ID" (yes, with a leading space)
@ -307,7 +316,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
}
arg = end; /* can only point to ' ' or '\0' now */
}
#else
# else /* ENABLE_KILL but !SH_KILL */
pid = bb_strtoi(arg, NULL, 10);
if (errno) {
bb_error_msg("invalid number '%s'", arg);
@ -316,8 +325,9 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
bb_perror_msg("can't kill pid %d", (int)pid);
errors++;
}
#endif
# endif
arg = *++argv;
}
return errors;
#endif
}