aboutsummaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-07-16 12:36:14 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-07-16 12:36:14 +0200
commit202a2d121905a6245cdf7441c9f83ff213b5502e (patch)
tree6e7ab10e31a21668a25df918e4f2ddd809d186a0 /shell/hush.c
parent3f5fae07725b0cc24587c7965f17ac57e5610bfb (diff)
downloadbusybox-w32-202a2d121905a6245cdf7441c9f83ff213b5502e.tar.gz
busybox-w32-202a2d121905a6245cdf7441c9f83ff213b5502e.tar.bz2
busybox-w32-202a2d121905a6245cdf7441c9f83ff213b5502e.zip
hush: make set -x support optional
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c155
1 files changed, 147 insertions, 8 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 7640bd6ba..c67aebdd7 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -101,6 +101,136 @@
101# define PIPE_BUF 4096 /* amount of buffering in a pipe */ 101# define PIPE_BUF 4096 /* amount of buffering in a pipe */
102#endif 102#endif
103 103
104//applet:IF_HUSH(APPLET(hush, _BB_DIR_BIN, _BB_SUID_DROP))
105//applet:IF_MSH(APPLET(msh, _BB_DIR_BIN, _BB_SUID_DROP))
106//applet:IF_LASH(APPLET(lash, _BB_DIR_BIN, _BB_SUID_DROP))
107//applet:IF_FEATURE_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, _BB_DIR_BIN, _BB_SUID_DROP, sh))
108//applet:IF_FEATURE_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, _BB_DIR_BIN, _BB_SUID_DROP, bash))
109
110//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
111//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
112
113//config:config HUSH
114//config: bool "hush"
115//config: default y
116//config: help
117//config: hush is a small shell (22k). It handles the normal flow control
118//config: constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
119//config: case/esac. Redirections, here documents, $((arithmetic))
120//config: and functions are supported.
121//config:
122//config: It will compile and work on no-mmu systems.
123//config:
124//config: It does not handle select, aliases, brace expansion,
125//config: tilde expansion, &>file and >&file redirection of stdout+stderr.
126//config:
127//config:config HUSH_BASH_COMPAT
128//config: bool "bash-compatible extensions"
129//config: default y
130//config: depends on HUSH
131//config: help
132//config: Enable bash-compatible extensions.
133//config:
134//config:config HUSH_HELP
135//config: bool "help builtin"
136//config: default y
137//config: depends on HUSH
138//config: help
139//config: Enable help builtin in hush. Code size + ~1 kbyte.
140//config:
141//config:config HUSH_INTERACTIVE
142//config: bool "Interactive mode"
143//config: default y
144//config: depends on HUSH
145//config: help
146//config: Enable interactive mode (prompt and command editing).
147//config: Without this, hush simply reads and executes commands
148//config: from stdin just like a shell script from a file.
149//config: No prompt, no PS1/PS2 magic shell variables.
150//config:
151//config:config HUSH_JOB
152//config: bool "Job control"
153//config: default y
154//config: depends on HUSH_INTERACTIVE
155//config: help
156//config: Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
157//config: command (not entire shell), fg/bg builtins work. Without this option,
158//config: "cmd &" still works by simply spawning a process and immediately
159//config: prompting for next command (or executing next command in a script),
160//config: but no separate process group is formed.
161//config:
162//config:config HUSH_TICK
163//config: bool "Process substitution"
164//config: default y
165//config: depends on HUSH
166//config: help
167//config: Enable process substitution `command` and $(command) in hush.
168//config:
169//config:config HUSH_IF
170//config: bool "Support if/then/elif/else/fi"
171//config: default y
172//config: depends on HUSH
173//config: help
174//config: Enable if/then/elif/else/fi in hush.
175//config:
176//config:config HUSH_LOOPS
177//config: bool "Support for, while and until loops"
178//config: default y
179//config: depends on HUSH
180//config: help
181//config: Enable for, while and until loops in hush.
182//config:
183//config:config HUSH_CASE
184//config: bool "Support case ... esac statement"
185//config: default y
186//config: depends on HUSH
187//config: help
188//config: Enable case ... esac statement in hush. +400 bytes.
189//config:
190//config:config HUSH_FUNCTIONS
191//config: bool "Support funcname() { commands; } syntax"
192//config: default y
193//config: depends on HUSH
194//config: help
195//config: Enable support for shell functions in hush. +800 bytes.
196//config:
197//config:config HUSH_LOCAL
198//config: bool "Support local builtin"
199//config: default y
200//config: depends on HUSH_FUNCTIONS
201//config: help
202//config: Enable support for local variables in functions.
203//config:
204//config:config HUSH_RANDOM_SUPPORT
205//config: bool "Pseudorandom generator and $RANDOM variable"
206//config: default y
207//config: depends on HUSH
208//config: help
209//config: Enable pseudorandom generator and dynamic variable "$RANDOM".
210//config: Each read of "$RANDOM" will generate a new pseudorandom value.
211//config:
212//config:config HUSH_EXPORT_N
213//config: bool "Support 'export -n' option"
214//config: default y
215//config: depends on HUSH
216//config: help
217//config: export -n unexports variables. It is a bash extension.
218//config:
219//config:config HUSH_MODE_X
220//config: bool "Support 'hush -x' option and 'set -x' command"
221//config: default y
222//config: depends on HUSH
223//config: help
224//config: This instructs hush to print commands before execution. Adds ~300 bytes.
225//config:
226
227//usage:#define hush_trivial_usage NOUSAGE_STR
228//usage:#define hush_full_usage ""
229//usage:#define lash_trivial_usage NOUSAGE_STR
230//usage:#define lash_full_usage ""
231//usage:#define msh_trivial_usage NOUSAGE_STR
232//usage:#define msh_full_usage ""
233
104 234
105/* Build knobs */ 235/* Build knobs */
106#define LEAK_HUNTING 0 236#define LEAK_HUNTING 0
@@ -531,8 +661,13 @@ struct globals {
531 */ 661 */
532 smallint flag_return_in_progress; 662 smallint flag_return_in_progress;
533#endif 663#endif
534 smallint fake_mode; 664 smallint n_mode;
665#if ENABLE_HUSH_MODE_X
535 smallint x_mode; 666 smallint x_mode;
667# define G_x_mode G.x_mode
668#else
669# define G_x_mode 0
670#endif
536 smallint exiting; /* used to prevent EXIT trap recursion */ 671 smallint exiting; /* used to prevent EXIT trap recursion */
537 /* These four support $?, $#, and $1 */ 672 /* These four support $?, $#, and $1 */
538 smalluint last_exitcode; 673 smalluint last_exitcode;
@@ -3693,9 +3828,10 @@ static void execvp_or_die(char **argv)
3693 _exit(127); /* bash compat */ 3828 _exit(127); /* bash compat */
3694} 3829}
3695 3830
3831#if ENABLE_HUSH_MODE_X
3696static void dump_cmd_in_x_mode(char **argv) 3832static void dump_cmd_in_x_mode(char **argv)
3697{ 3833{
3698 if (G.x_mode && argv) { 3834 if (G_x_mode && argv) {
3699 /* We want to output the line in one write op */ 3835 /* We want to output the line in one write op */
3700 char *buf, *p; 3836 char *buf, *p;
3701 int len; 3837 int len;
@@ -3717,6 +3853,9 @@ static void dump_cmd_in_x_mode(char **argv)
3717 free(buf); 3853 free(buf);
3718 } 3854 }
3719} 3855}
3856#else
3857# define dump_cmd_in_x_mode(argv) ((void)0)
3858#endif
3720 3859
3721#if BB_MMU 3860#if BB_MMU
3722#define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \ 3861#define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \
@@ -4267,18 +4406,18 @@ static NOINLINE int run_pipe(struct pipe *pi)
4267 rcode = setup_redirects(command, squirrel); 4406 rcode = setup_redirects(command, squirrel);
4268 restore_redirects(squirrel); 4407 restore_redirects(squirrel);
4269 /* Set shell variables */ 4408 /* Set shell variables */
4270 if (G.x_mode) 4409 if (G_x_mode)
4271 bb_putchar_stderr('+'); 4410 bb_putchar_stderr('+');
4272 while (*argv) { 4411 while (*argv) {
4273 p = expand_string_to_string(*argv); 4412 p = expand_string_to_string(*argv);
4274 if (G.x_mode) 4413 if (G_x_mode)
4275 fprintf(stderr, " %s", p); 4414 fprintf(stderr, " %s", p);
4276 debug_printf_exec("set shell var:'%s'->'%s'\n", 4415 debug_printf_exec("set shell var:'%s'->'%s'\n",
4277 *argv, p); 4416 *argv, p);
4278 set_local_var(p, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); 4417 set_local_var(p, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
4279 argv++; 4418 argv++;
4280 } 4419 }
4281 if (G.x_mode) 4420 if (G_x_mode)
4282 bb_putchar_stderr('\n'); 4421 bb_putchar_stderr('\n');
4283 /* Redirect error sets $? to 1. Otherwise, 4422 /* Redirect error sets $? to 1. Otherwise,
4284 * if evaluating assignment value set $?, retain it. 4423 * if evaluating assignment value set $?, retain it.
@@ -4943,7 +5082,7 @@ static int run_and_free_list(struct pipe *pi)
4943{ 5082{
4944 int rcode = 0; 5083 int rcode = 0;
4945 debug_printf_exec("run_and_free_list entered\n"); 5084 debug_printf_exec("run_and_free_list entered\n");
4946 if (!G.fake_mode) { 5085 if (!G.n_mode) {
4947 debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds); 5086 debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds);
4948 rcode = run_list(pi); 5087 rcode = run_list(pi);
4949 } 5088 }
@@ -6969,8 +7108,8 @@ static int set_mode(const char cstate, const char mode)
6969{ 7108{
6970 int state = (cstate == '-' ? 1 : 0); 7109 int state = (cstate == '-' ? 1 : 0);
6971 switch (mode) { 7110 switch (mode) {
6972 case 'n': G.fake_mode = state; break; 7111 case 'n': G.n_mode = state; break;
6973 case 'x': G.x_mode = state; break; 7112 case 'x': IF_HUSH_MODE_X(G_x_mode = state;) break;
6974 default: return EXIT_FAILURE; 7113 default: return EXIT_FAILURE;
6975 } 7114 }
6976 return EXIT_SUCCESS; 7115 return EXIT_SUCCESS;