hush: make set -x support optional

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko
2010-07-16 12:36:14 +02:00
parent 3f5fae0772
commit 202a2d1219
5 changed files with 147 additions and 127 deletions

View File

@ -76,7 +76,6 @@ IF_ASH(APPLET(ash, _BB_DIR_BIN, _BB_SUID_DROP))
IF_AWK(APPLET_NOEXEC(awk, awk, _BB_DIR_USR_BIN, _BB_SUID_DROP, awk)) IF_AWK(APPLET_NOEXEC(awk, awk, _BB_DIR_USR_BIN, _BB_SUID_DROP, awk))
IF_BASENAME(APPLET_NOFORK(basename, basename, _BB_DIR_USR_BIN, _BB_SUID_DROP, basename)) IF_BASENAME(APPLET_NOFORK(basename, basename, _BB_DIR_USR_BIN, _BB_SUID_DROP, basename))
IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, _BB_DIR_BIN, _BB_SUID_DROP, bash)) IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, _BB_DIR_BIN, _BB_SUID_DROP, bash))
IF_FEATURE_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, _BB_DIR_BIN, _BB_SUID_DROP, bash))
IF_BBCONFIG(APPLET(bbconfig, _BB_DIR_BIN, _BB_SUID_DROP)) IF_BBCONFIG(APPLET(bbconfig, _BB_DIR_BIN, _BB_SUID_DROP))
//IF_BBSH(APPLET(bbsh, _BB_DIR_BIN, _BB_SUID_DROP)) //IF_BBSH(APPLET(bbsh, _BB_DIR_BIN, _BB_SUID_DROP))
IF_BEEP(APPLET(beep, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_BEEP(APPLET(beep, _BB_DIR_USR_BIN, _BB_SUID_DROP))
@ -183,7 +182,6 @@ IF_HEXDUMP(APPLET_NOEXEC(hexdump, hexdump, _BB_DIR_USR_BIN, _BB_SUID_DROP, hexdu
IF_HOSTID(APPLET_NOFORK(hostid, hostid, _BB_DIR_USR_BIN, _BB_SUID_DROP, hostid)) IF_HOSTID(APPLET_NOFORK(hostid, hostid, _BB_DIR_USR_BIN, _BB_SUID_DROP, hostid))
IF_HOSTNAME(APPLET(hostname, _BB_DIR_BIN, _BB_SUID_DROP)) IF_HOSTNAME(APPLET(hostname, _BB_DIR_BIN, _BB_SUID_DROP))
IF_HTTPD(APPLET(httpd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) IF_HTTPD(APPLET(httpd, _BB_DIR_USR_SBIN, _BB_SUID_DROP))
IF_HUSH(APPLET(hush, _BB_DIR_BIN, _BB_SUID_DROP))
IF_HWCLOCK(APPLET(hwclock, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_HWCLOCK(APPLET(hwclock, _BB_DIR_SBIN, _BB_SUID_DROP))
IF_ID(APPLET(id, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_ID(APPLET(id, _BB_DIR_USR_BIN, _BB_SUID_DROP))
IF_IFCONFIG(APPLET(ifconfig, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_IFCONFIG(APPLET(ifconfig, _BB_DIR_SBIN, _BB_SUID_DROP))
@ -218,7 +216,6 @@ IF_KILL(APPLET(kill, _BB_DIR_BIN, _BB_SUID_DROP))
IF_KILLALL(APPLET_ODDNAME(killall, kill, _BB_DIR_USR_BIN, _BB_SUID_DROP, killall)) IF_KILLALL(APPLET_ODDNAME(killall, kill, _BB_DIR_USR_BIN, _BB_SUID_DROP, killall))
IF_KILLALL5(APPLET_ODDNAME(killall5, kill, _BB_DIR_USR_BIN, _BB_SUID_DROP, killall5)) IF_KILLALL5(APPLET_ODDNAME(killall5, kill, _BB_DIR_USR_BIN, _BB_SUID_DROP, killall5))
IF_KLOGD(APPLET(klogd, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_KLOGD(APPLET(klogd, _BB_DIR_SBIN, _BB_SUID_DROP))
IF_LASH(APPLET(lash, _BB_DIR_BIN, _BB_SUID_DROP))
IF_LAST(APPLET(last, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_LAST(APPLET(last, _BB_DIR_USR_BIN, _BB_SUID_DROP))
IF_LENGTH(APPLET_NOFORK(length, length, _BB_DIR_USR_BIN, _BB_SUID_DROP, length)) IF_LENGTH(APPLET_NOFORK(length, length, _BB_DIR_USR_BIN, _BB_SUID_DROP, length))
IF_LESS(APPLET(less, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_LESS(APPLET(less, _BB_DIR_USR_BIN, _BB_SUID_DROP))
@ -273,7 +270,6 @@ IF_MODPROBE_SMALL(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP))
IF_MORE(APPLET(more, _BB_DIR_BIN, _BB_SUID_DROP)) IF_MORE(APPLET(more, _BB_DIR_BIN, _BB_SUID_DROP))
IF_MOUNT(APPLET(mount, _BB_DIR_BIN, IF_DESKTOP(_BB_SUID_MAYBE) IF_NOT_DESKTOP(_BB_SUID_DROP))) IF_MOUNT(APPLET(mount, _BB_DIR_BIN, IF_DESKTOP(_BB_SUID_MAYBE) IF_NOT_DESKTOP(_BB_SUID_DROP)))
IF_MOUNTPOINT(APPLET(mountpoint, _BB_DIR_BIN, _BB_SUID_DROP)) IF_MOUNTPOINT(APPLET(mountpoint, _BB_DIR_BIN, _BB_SUID_DROP))
IF_MSH(APPLET(msh, _BB_DIR_BIN, _BB_SUID_DROP))
IF_MT(APPLET(mt, _BB_DIR_BIN, _BB_SUID_DROP)) IF_MT(APPLET(mt, _BB_DIR_BIN, _BB_SUID_DROP))
IF_MV(APPLET(mv, _BB_DIR_BIN, _BB_SUID_DROP)) IF_MV(APPLET(mv, _BB_DIR_BIN, _BB_SUID_DROP))
IF_NAMEIF(APPLET(nameif, _BB_DIR_SBIN, _BB_SUID_DROP)) IF_NAMEIF(APPLET(nameif, _BB_DIR_SBIN, _BB_SUID_DROP))
@ -349,7 +345,6 @@ IF_SETSEBOOL(APPLET(setsebool, _BB_DIR_USR_SBIN, _BB_SUID_DROP))
IF_SETSID(APPLET(setsid, _BB_DIR_USR_BIN, _BB_SUID_DROP)) IF_SETSID(APPLET(setsid, _BB_DIR_USR_BIN, _BB_SUID_DROP))
IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, _BB_DIR_USR_BIN, _BB_SUID_DROP, setuidgid)) IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, _BB_DIR_USR_BIN, _BB_SUID_DROP, setuidgid))
IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, _BB_DIR_BIN, _BB_SUID_DROP, sh)) IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, _BB_DIR_BIN, _BB_SUID_DROP, sh))
IF_FEATURE_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, _BB_DIR_BIN, _BB_SUID_DROP, sh))
IF_SHA1SUM(APPLET_ODDNAME(sha1sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha1sum)) IF_SHA1SUM(APPLET_ODDNAME(sha1sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha1sum))
IF_SHA256SUM(APPLET_ODDNAME(sha256sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha256sum)) IF_SHA256SUM(APPLET_ODDNAME(sha256sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha256sum))
IF_SHA512SUM(APPLET_ODDNAME(sha512sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha512sum)) IF_SHA512SUM(APPLET_ODDNAME(sha512sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha512sum))

View File

@ -119,12 +119,6 @@ INSERT
#define sh_full_usage "" #define sh_full_usage ""
#define ash_trivial_usage NOUSAGE_STR #define ash_trivial_usage NOUSAGE_STR
#define ash_full_usage "" #define ash_full_usage ""
#define hush_trivial_usage NOUSAGE_STR
#define hush_full_usage ""
#define lash_trivial_usage NOUSAGE_STR
#define lash_full_usage ""
#define msh_trivial_usage NOUSAGE_STR
#define msh_full_usage ""
#define bash_trivial_usage NOUSAGE_STR #define bash_trivial_usage NOUSAGE_STR
#define bash_full_usage "" #define bash_full_usage ""

View File

@ -110,112 +110,6 @@ config ASH_EXPAND_PRMT
This option recreates the prompt string from the environment This option recreates the prompt string from the environment
variable each time it is displayed. variable each time it is displayed.
config HUSH
bool "hush"
default y
help
hush is a small shell (22k). It handles the normal flow control
constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
case/esac. Redirections, here documents, $((arithmetic))
and functions are supported.
It will compile and work on no-mmu systems.
It does not handle select, aliases, brace expansion,
tilde expansion, &>file and >&file redirection of stdout+stderr.
config HUSH_BASH_COMPAT
bool "bash-compatible extensions"
default y
depends on HUSH
help
Enable bash-compatible extensions.
config HUSH_HELP
bool "help builtin"
default y
depends on HUSH
help
Enable help builtin in hush. Code size + ~1 kbyte.
config HUSH_INTERACTIVE
bool "Interactive mode"
default y
depends on HUSH
help
Enable interactive mode (prompt and command editing).
Without this, hush simply reads and executes commands
from stdin just like a shell script from a file.
No prompt, no PS1/PS2 magic shell variables.
config HUSH_JOB
bool "Job control"
default y
depends on HUSH_INTERACTIVE
help
Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
command (not entire shell), fg/bg builtins work. Without this option,
"cmd &" still works by simply spawning a process and immediately
prompting for next command (or executing next command in a script),
but no separate process group is formed.
config HUSH_TICK
bool "Process substitution"
default y
depends on HUSH
help
Enable process substitution `command` and $(command) in hush.
config HUSH_IF
bool "Support if/then/elif/else/fi"
default y
depends on HUSH
help
Enable if/then/elif/else/fi in hush.
config HUSH_LOOPS
bool "Support for, while and until loops"
default y
depends on HUSH
help
Enable for, while and until loops in hush.
config HUSH_CASE
bool "Support case ... esac statement"
default y
depends on HUSH
help
Enable case ... esac statement in hush. +400 bytes.
config HUSH_FUNCTIONS
bool "Support funcname() { commands; } syntax"
default y
depends on HUSH
help
Enable support for shell functions in hush. +800 bytes.
config HUSH_LOCAL
bool "Support local builtin"
default y
depends on HUSH_FUNCTIONS
help
Enable support for local variables in functions.
config HUSH_EXPORT_N
bool "Support export '-n' option"
default y
depends on HUSH
help
Enable support for export '-n' option in hush. It is a bash extension.
config HUSH_RANDOM_SUPPORT
bool "Pseudorandom generator and $RANDOM variable"
default y
depends on HUSH
help
Enable pseudorandom generator and dynamic variable "$RANDOM".
Each read of "$RANDOM" will generate a new pseudorandom value.
choice choice
prompt "Choose which shell is aliased to 'sh' name" prompt "Choose which shell is aliased to 'sh' name"

View File

@ -9,9 +9,7 @@ lib-y:=
INSERT INSERT
lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
lib-$(CONFIG_CTTYHACK) += cttyhack.o lib-$(CONFIG_CTTYHACK) += cttyhack.o
lib-$(CONFIG_SH_MATH_SUPPORT) += math.o lib-$(CONFIG_SH_MATH_SUPPORT) += math.o
lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o

View File

@ -101,6 +101,136 @@
# define PIPE_BUF 4096 /* amount of buffering in a pipe */ # define PIPE_BUF 4096 /* amount of buffering in a pipe */
#endif #endif
//applet:IF_HUSH(APPLET(hush, _BB_DIR_BIN, _BB_SUID_DROP))
//applet:IF_MSH(APPLET(msh, _BB_DIR_BIN, _BB_SUID_DROP))
//applet:IF_LASH(APPLET(lash, _BB_DIR_BIN, _BB_SUID_DROP))
//applet:IF_FEATURE_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, _BB_DIR_BIN, _BB_SUID_DROP, sh))
//applet:IF_FEATURE_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, _BB_DIR_BIN, _BB_SUID_DROP, bash))
//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
//config:config HUSH
//config: bool "hush"
//config: default y
//config: help
//config: hush is a small shell (22k). It handles the normal flow control
//config: constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
//config: case/esac. Redirections, here documents, $((arithmetic))
//config: and functions are supported.
//config:
//config: It will compile and work on no-mmu systems.
//config:
//config: It does not handle select, aliases, brace expansion,
//config: tilde expansion, &>file and >&file redirection of stdout+stderr.
//config:
//config:config HUSH_BASH_COMPAT
//config: bool "bash-compatible extensions"
//config: default y
//config: depends on HUSH
//config: help
//config: Enable bash-compatible extensions.
//config:
//config:config HUSH_HELP
//config: bool "help builtin"
//config: default y
//config: depends on HUSH
//config: help
//config: Enable help builtin in hush. Code size + ~1 kbyte.
//config:
//config:config HUSH_INTERACTIVE
//config: bool "Interactive mode"
//config: default y
//config: depends on HUSH
//config: help
//config: Enable interactive mode (prompt and command editing).
//config: Without this, hush simply reads and executes commands
//config: from stdin just like a shell script from a file.
//config: No prompt, no PS1/PS2 magic shell variables.
//config:
//config:config HUSH_JOB
//config: bool "Job control"
//config: default y
//config: depends on HUSH_INTERACTIVE
//config: help
//config: Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
//config: command (not entire shell), fg/bg builtins work. Without this option,
//config: "cmd &" still works by simply spawning a process and immediately
//config: prompting for next command (or executing next command in a script),
//config: but no separate process group is formed.
//config:
//config:config HUSH_TICK
//config: bool "Process substitution"
//config: default y
//config: depends on HUSH
//config: help
//config: Enable process substitution `command` and $(command) in hush.
//config:
//config:config HUSH_IF
//config: bool "Support if/then/elif/else/fi"
//config: default y
//config: depends on HUSH
//config: help
//config: Enable if/then/elif/else/fi in hush.
//config:
//config:config HUSH_LOOPS
//config: bool "Support for, while and until loops"
//config: default y
//config: depends on HUSH
//config: help
//config: Enable for, while and until loops in hush.
//config:
//config:config HUSH_CASE
//config: bool "Support case ... esac statement"
//config: default y
//config: depends on HUSH
//config: help
//config: Enable case ... esac statement in hush. +400 bytes.
//config:
//config:config HUSH_FUNCTIONS
//config: bool "Support funcname() { commands; } syntax"
//config: default y
//config: depends on HUSH
//config: help
//config: Enable support for shell functions in hush. +800 bytes.
//config:
//config:config HUSH_LOCAL
//config: bool "Support local builtin"
//config: default y
//config: depends on HUSH_FUNCTIONS
//config: help
//config: Enable support for local variables in functions.
//config:
//config:config HUSH_RANDOM_SUPPORT
//config: bool "Pseudorandom generator and $RANDOM variable"
//config: default y
//config: depends on HUSH
//config: help
//config: Enable pseudorandom generator and dynamic variable "$RANDOM".
//config: Each read of "$RANDOM" will generate a new pseudorandom value.
//config:
//config:config HUSH_EXPORT_N
//config: bool "Support 'export -n' option"
//config: default y
//config: depends on HUSH
//config: help
//config: export -n unexports variables. It is a bash extension.
//config:
//config:config HUSH_MODE_X
//config: bool "Support 'hush -x' option and 'set -x' command"
//config: default y
//config: depends on HUSH
//config: help
//config: This instructs hush to print commands before execution. Adds ~300 bytes.
//config:
//usage:#define hush_trivial_usage NOUSAGE_STR
//usage:#define hush_full_usage ""
//usage:#define lash_trivial_usage NOUSAGE_STR
//usage:#define lash_full_usage ""
//usage:#define msh_trivial_usage NOUSAGE_STR
//usage:#define msh_full_usage ""
/* Build knobs */ /* Build knobs */
#define LEAK_HUNTING 0 #define LEAK_HUNTING 0
@ -531,8 +661,13 @@ struct globals {
*/ */
smallint flag_return_in_progress; smallint flag_return_in_progress;
#endif #endif
smallint fake_mode; smallint n_mode;
#if ENABLE_HUSH_MODE_X
smallint x_mode; smallint x_mode;
# define G_x_mode G.x_mode
#else
# define G_x_mode 0
#endif
smallint exiting; /* used to prevent EXIT trap recursion */ smallint exiting; /* used to prevent EXIT trap recursion */
/* These four support $?, $#, and $1 */ /* These four support $?, $#, and $1 */
smalluint last_exitcode; smalluint last_exitcode;
@ -3693,9 +3828,10 @@ static void execvp_or_die(char **argv)
_exit(127); /* bash compat */ _exit(127); /* bash compat */
} }
#if ENABLE_HUSH_MODE_X
static void dump_cmd_in_x_mode(char **argv) static void dump_cmd_in_x_mode(char **argv)
{ {
if (G.x_mode && argv) { if (G_x_mode && argv) {
/* We want to output the line in one write op */ /* We want to output the line in one write op */
char *buf, *p; char *buf, *p;
int len; int len;
@ -3717,6 +3853,9 @@ static void dump_cmd_in_x_mode(char **argv)
free(buf); free(buf);
} }
} }
#else
# define dump_cmd_in_x_mode(argv) ((void)0)
#endif
#if BB_MMU #if BB_MMU
#define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \ #define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \
@ -4267,18 +4406,18 @@ static NOINLINE int run_pipe(struct pipe *pi)
rcode = setup_redirects(command, squirrel); rcode = setup_redirects(command, squirrel);
restore_redirects(squirrel); restore_redirects(squirrel);
/* Set shell variables */ /* Set shell variables */
if (G.x_mode) if (G_x_mode)
bb_putchar_stderr('+'); bb_putchar_stderr('+');
while (*argv) { while (*argv) {
p = expand_string_to_string(*argv); p = expand_string_to_string(*argv);
if (G.x_mode) if (G_x_mode)
fprintf(stderr, " %s", p); fprintf(stderr, " %s", p);
debug_printf_exec("set shell var:'%s'->'%s'\n", debug_printf_exec("set shell var:'%s'->'%s'\n",
*argv, p); *argv, p);
set_local_var(p, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); set_local_var(p, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
argv++; argv++;
} }
if (G.x_mode) if (G_x_mode)
bb_putchar_stderr('\n'); bb_putchar_stderr('\n');
/* Redirect error sets $? to 1. Otherwise, /* Redirect error sets $? to 1. Otherwise,
* if evaluating assignment value set $?, retain it. * if evaluating assignment value set $?, retain it.
@ -4943,7 +5082,7 @@ static int run_and_free_list(struct pipe *pi)
{ {
int rcode = 0; int rcode = 0;
debug_printf_exec("run_and_free_list entered\n"); debug_printf_exec("run_and_free_list entered\n");
if (!G.fake_mode) { if (!G.n_mode) {
debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds); debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds);
rcode = run_list(pi); rcode = run_list(pi);
} }
@ -6969,8 +7108,8 @@ static int set_mode(const char cstate, const char mode)
{ {
int state = (cstate == '-' ? 1 : 0); int state = (cstate == '-' ? 1 : 0);
switch (mode) { switch (mode) {
case 'n': G.fake_mode = state; break; case 'n': G.n_mode = state; break;
case 'x': G.x_mode = state; break; case 'x': IF_HUSH_MODE_X(G_x_mode = state;) break;
default: return EXIT_FAILURE; default: return EXIT_FAILURE;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;