From fb132e47370378474c68ad22c1c0cb2ccee178de Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 29 Oct 2010 11:46:52 +0200 Subject: whitespace cleanup Signed-off-by: Denys Vlasenko --- shell/ash_test/recho.c | 13 ++++--------- shell/ash_test/zecho.c | 5 +---- 2 files changed, 5 insertions(+), 13 deletions(-) (limited to 'shell') diff --git a/shell/ash_test/recho.c b/shell/ash_test/recho.c index fb48d9c48..42a5feafd 100644 --- a/shell/ash_test/recho.c +++ b/shell/ash_test/recho.c @@ -29,12 +29,9 @@ void strprint(); -int -main(argc, argv) -int argc; -char **argv; +int main(int argc, char **argv) { - register int i; + int i; for (i = 1; i < argc; i++) { printf("argv[%d] = <", i); @@ -44,11 +41,9 @@ char **argv; exit(EXIT_SUCCESS); } -void -strprint(str) -char *str; +void strprint(char *str) { - register unsigned char *s; + unsigned char *s; for (s = (unsigned char *)str; s && *s; s++) { if (*s < ' ') { diff --git a/shell/ash_test/zecho.c b/shell/ash_test/zecho.c index bf876f641..cbaa59b81 100644 --- a/shell/ash_test/zecho.c +++ b/shell/ash_test/zecho.c @@ -21,10 +21,7 @@ #include #include -int -main(argc, argv) -int argc; -char **argv; +int main(int argc, char **argv) { argv++; -- cgit v1.2.3-55-g6feb From c08c3f5d262acab7082cca88d0b2a329184b133b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 14 Nov 2010 01:59:55 +0100 Subject: hush: preparatory patch for set -o pipefail support Signed-off-by: Denys Vlasenko --- shell/hush.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index 9dd30c436..126aaf074 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -6309,7 +6309,8 @@ static int checkjobs(struct pipe *fg_pipe) #endif /* Were we asked to wait for fg pipe? */ if (fg_pipe) { - for (i = 0; i < fg_pipe->num_cmds; i++) { + i = fg_pipe->num_cmds; + while (--i >= 0) { debug_printf_jobs("check pid %d\n", fg_pipe->cmds[i].pid); if (fg_pipe->cmds[i].pid != childpid) continue; @@ -6338,19 +6339,19 @@ static int checkjobs(struct pipe *fg_pipe) } debug_printf_jobs("fg_pipe: alive_cmds %d stopped_cmds %d\n", fg_pipe->alive_cmds, fg_pipe->stopped_cmds); - if (fg_pipe->alive_cmds - fg_pipe->stopped_cmds <= 0) { + if (fg_pipe->alive_cmds == fg_pipe->stopped_cmds) { /* All processes in fg pipe have exited or stopped */ /* Note: *non-interactive* bash does not continue if all processes in fg pipe * are stopped. Testcase: "cat | cat" in a script (not on command line!) * and "killall -STOP cat" */ if (G_interactive_fd) { #if ENABLE_HUSH_JOB - if (fg_pipe->alive_cmds) + if (fg_pipe->alive_cmds != 0) insert_bg_job(fg_pipe); #endif return rcode; } - if (!fg_pipe->alive_cmds) + if (fg_pipe->alive_cmds == 0) return rcode; } /* There are still running processes in the fg pipe */ -- cgit v1.2.3-55-g6feb From 6696eac274b5dcf5932b211fe9ee748d8268a39c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 14 Nov 2010 02:01:50 +0100 Subject: hush: add support for "set -o pipefail" function old new delta checkjobs 467 517 +50 builtin_set 259 286 +27 o_opt_strings - 10 +10 hush_main 1011 1013 +2 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/0 up/down: 89/0) Total: 89 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 124 +++++++++++++++++++++++++------ shell/hush_test/hush-misc/pipefail.right | 40 ++++++++++ shell/hush_test/hush-misc/pipefail.tests | 45 +++++++++++ 3 files changed, 186 insertions(+), 23 deletions(-) create mode 100644 shell/hush_test/hush-misc/pipefail.right create mode 100755 shell/hush_test/hush-misc/pipefail.tests (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index 126aaf074..50e9ce333 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -507,6 +507,7 @@ struct command { # define CMD_FUNCDEF 3 #endif + smalluint cmd_exitcode; /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */ struct pipe *group; #if !BB_MMU @@ -637,6 +638,43 @@ struct function { #endif +/* set -/+o OPT support. (TODO: make it optional) + * bash supports the following opts: + * allexport off + * braceexpand on + * emacs on + * errexit off + * errtrace off + * functrace off + * hashall on + * histexpand off + * history on + * ignoreeof off + * interactive-comments on + * keyword off + * monitor on + * noclobber off + * noexec off + * noglob off + * nolog off + * notify off + * nounset off + * onecmd off + * physical off + * pipefail off + * posix off + * privileged off + * verbose off + * vi off + * xtrace off + */ +static const char o_opt_strings[] ALIGN1 = "pipefail\0"; +enum { + OPT_O_PIPEFAIL, + NUM_OPT_O +}; + + /* "Globals" within this file */ /* Sorted roughly by size (smaller offsets == smaller code) */ struct globals { @@ -675,6 +713,7 @@ struct globals { int last_jobid; pid_t saved_tty_pgrp; struct pipe *job_list; + char o_opt[NUM_OPT_O]; # define G_saved_tty_pgrp (G.saved_tty_pgrp) #else # define G_saved_tty_pgrp 0 @@ -6315,24 +6354,23 @@ static int checkjobs(struct pipe *fg_pipe) if (fg_pipe->cmds[i].pid != childpid) continue; if (dead) { + int ex; fg_pipe->cmds[i].pid = 0; fg_pipe->alive_cmds--; - if (i == fg_pipe->num_cmds - 1) { - /* last process gives overall exitstatus */ - rcode = WEXITSTATUS(status); - /* bash prints killer signal's name for *last* - * process in pipe (prints just newline for SIGINT). - * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT) - */ - if (WIFSIGNALED(status)) { - int sig = WTERMSIG(status); + ex = WEXITSTATUS(status); + /* bash prints killer signal's name for *last* + * process in pipe (prints just newline for SIGINT). + * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT) + */ + if (WIFSIGNALED(status)) { + int sig = WTERMSIG(status); + if (i == fg_pipe->num_cmds-1) printf("%s\n", sig == SIGINT ? "" : get_signame(sig)); - /* TODO: MIPS has 128 sigs (1..128), what if sig==128 here? - * Maybe we need to use sig | 128? */ - rcode = sig + 128; - } - IF_HAS_KEYWORDS(if (fg_pipe->pi_inverted) rcode = !rcode;) + /* TODO: MIPS has 128 sigs (1..128), what if sig==128 here? + * Maybe we need to use sig | 128? */ + ex = sig + 128; } + fg_pipe->cmds[i].cmd_exitcode = ex; } else { fg_pipe->cmds[i].is_stopped = 1; fg_pipe->stopped_cmds++; @@ -6341,6 +6379,15 @@ static int checkjobs(struct pipe *fg_pipe) fg_pipe->alive_cmds, fg_pipe->stopped_cmds); if (fg_pipe->alive_cmds == fg_pipe->stopped_cmds) { /* All processes in fg pipe have exited or stopped */ + i = fg_pipe->num_cmds; + while (--i >= 0) { + rcode = fg_pipe->cmds[i].cmd_exitcode; + /* usually last process gives overall exitstatus, + * but with "set -o pipefail", last *failed* process does */ + if (G.o_opt[OPT_O_PIPEFAIL] == 0 || rcode != 0) + break; + } + IF_HAS_KEYWORDS(if (fg_pipe->pi_inverted) rcode = !rcode;) /* Note: *non-interactive* bash does not continue if all processes in fg pipe * are stopped. Testcase: "cat | cat" in a script (not on command line!) * and "killall -STOP cat" */ @@ -7340,13 +7387,41 @@ static void set_fatal_handlers(void) } #endif -static int set_mode(const char cstate, const char mode) +static int set_mode(int state, char mode, const char *o_opt) { - int state = (cstate == '-' ? 1 : 0); + int idx; switch (mode) { - case 'n': G.n_mode = state; break; - case 'x': IF_HUSH_MODE_X(G_x_mode = state;) break; - default: return EXIT_FAILURE; + case 'n': + G.n_mode = state; + break; + case 'x': + IF_HUSH_MODE_X(G_x_mode = state;) + break; + case 'o': + if (!o_opt) { + /* "set -+o" without parameter. + * in bash, set -o produces this output: + * pipefail off + * and set +o: + * set +o pipefail + * We always use the second form. + */ + const char *p = o_opt_strings; + idx = 0; + while (*p) { + printf("set %co %s\n", (G.o_opt[idx] ? '-' : '+'), p); + idx++; + p += strlen(p) + 1; + } + break; + } + idx = index_in_strings(o_opt_strings, o_opt); + if (idx >= 0) { + G.o_opt[idx] = state; + break; + } + default: + return EXIT_FAILURE; } return EXIT_SUCCESS; } @@ -7586,7 +7661,7 @@ int hush_main(int argc, char **argv) #endif case 'n': case 'x': - if (set_mode('-', opt) == 0) /* no error */ + if (set_mode(1, opt, NULL) == 0) /* no error */ break; default: #ifndef BB_VER @@ -8376,15 +8451,18 @@ static int FAST_FUNC builtin_set(char **argv) } do { - if (!strcmp(arg, "--")) { + if (strcmp(arg, "--") == 0) { ++argv; goto set_argv; } if (arg[0] != '+' && arg[0] != '-') break; - for (n = 1; arg[n]; ++n) - if (set_mode(arg[0], arg[n])) + for (n = 1; arg[n]; ++n) { + if (set_mode((arg[0] == '-'), arg[n], argv[1])) goto error; + if (arg[n] == 'o' && argv[1]) + argv++; + } } while ((arg = *++argv) != NULL); /* Now argv[0] is 1st argument */ diff --git a/shell/hush_test/hush-misc/pipefail.right b/shell/hush_test/hush-misc/pipefail.right new file mode 100644 index 000000000..5845d8939 --- /dev/null +++ b/shell/hush_test/hush-misc/pipefail.right @@ -0,0 +1,40 @@ +Default: +true | true: +0 +1 +true | false: +1 +0 +false | true: +0 +1 +exit 2 | exit 3 | exit 4: +4 +0 +Pipefail on: +true | true: +0 +1 +true | false: +1 +0 +false | true: +1 +0 +exit 2 | exit 3 | exit 4: +4 +0 +Pipefail off: +true | true: +0 +1 +true | false: +1 +0 +false | true: +0 +1 +exit 2 | exit 3 | exit 4: +4 +0 +Done diff --git a/shell/hush_test/hush-misc/pipefail.tests b/shell/hush_test/hush-misc/pipefail.tests new file mode 100755 index 000000000..9df841861 --- /dev/null +++ b/shell/hush_test/hush-misc/pipefail.tests @@ -0,0 +1,45 @@ +echo Default: +echo "true | true:" + true | true; echo $? +! true | true; echo $? +echo "true | false:" + true | false; echo $? +! true | false; echo $? +echo "false | true:" + false | true; echo $? +! false | true; echo $? +echo "exit 2 | exit 3 | exit 4:" + exit 2 | exit 3 | exit 4; echo $? +! exit 2 | exit 3 | exit 4; echo $? + +echo Pipefail on: +set -o pipefail +echo "true | true:" + true | true; echo $? +! true | true; echo $? +echo "true | false:" + true | false; echo $? +! true | false; echo $? +echo "false | true:" + false | true; echo $? +! false | true; echo $? +echo "exit 2 | exit 3 | exit 4:" + exit 2 | exit 3 | exit 4; echo $? +! exit 2 | exit 3 | exit 4; echo $? + +echo Pipefail off: +set +o pipefail +echo "true | true:" + true | true; echo $? +! true | true; echo $? +echo "true | false:" + true | false; echo $? +! true | false; echo $? +echo "false | true:" + false | true; echo $? +! false | true; echo $? +echo "exit 2 | exit 3 | exit 4:" + exit 2 | exit 3 | exit 4; echo $? +! exit 2 | exit 3 | exit 4; echo $? + +echo Done -- cgit v1.2.3-55-g6feb From 7b4c0fd5f4df4541a1659de04823326cd22c254e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 22 Nov 2010 17:58:14 +0100 Subject: hush: fix improper handling of newline and hash chars in few corner cases Signed-off-by: Denys Vlasenko --- shell/hush.c | 253 ++++++++++++++-------------- shell/hush_test/hush-misc/assignment3.right | 2 + shell/hush_test/hush-misc/assignment3.tests | 5 + shell/hush_test/hush-parsing/comment1.right | 2 + shell/hush_test/hush-parsing/comment1.tests | 2 + shell/hush_test/hush-parsing/eol1.right | 1 + shell/hush_test/hush-parsing/eol1.tests | 18 ++ 7 files changed, 160 insertions(+), 123 deletions(-) create mode 100644 shell/hush_test/hush-misc/assignment3.right create mode 100755 shell/hush_test/hush-misc/assignment3.tests create mode 100644 shell/hush_test/hush-parsing/comment1.right create mode 100755 shell/hush_test/hush-parsing/comment1.tests create mode 100644 shell/hush_test/hush-parsing/eol1.right create mode 100755 shell/hush_test/hush-parsing/eol1.tests (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index 50e9ce333..da32c2435 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -543,7 +543,6 @@ struct command { #define IS_NULL_CMD(cmd) \ (!(cmd)->group && !(cmd)->argv && !(cmd)->redirects) - struct pipe { struct pipe *next; int num_cmds; /* total number of commands in pipe */ @@ -2622,6 +2621,94 @@ static void free_pipe_list(struct pipe *pi) /*** Parsing routines ***/ +#ifndef debug_print_tree +static void debug_print_tree(struct pipe *pi, int lvl) +{ + static const char *const PIPE[] = { + [PIPE_SEQ] = "SEQ", + [PIPE_AND] = "AND", + [PIPE_OR ] = "OR" , + [PIPE_BG ] = "BG" , + }; + static const char *RES[] = { + [RES_NONE ] = "NONE" , +# if ENABLE_HUSH_IF + [RES_IF ] = "IF" , + [RES_THEN ] = "THEN" , + [RES_ELIF ] = "ELIF" , + [RES_ELSE ] = "ELSE" , + [RES_FI ] = "FI" , +# endif +# if ENABLE_HUSH_LOOPS + [RES_FOR ] = "FOR" , + [RES_WHILE] = "WHILE", + [RES_UNTIL] = "UNTIL", + [RES_DO ] = "DO" , + [RES_DONE ] = "DONE" , +# endif +# if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE + [RES_IN ] = "IN" , +# endif +# if ENABLE_HUSH_CASE + [RES_CASE ] = "CASE" , + [RES_CASE_IN ] = "CASE_IN" , + [RES_MATCH] = "MATCH", + [RES_CASE_BODY] = "CASE_BODY", + [RES_ESAC ] = "ESAC" , +# endif + [RES_XXXX ] = "XXXX" , + [RES_SNTX ] = "SNTX" , + }; + static const char *const CMDTYPE[] = { + "{}", + "()", + "[noglob]", +# if ENABLE_HUSH_FUNCTIONS + "func()", +# endif + }; + + int pin, prn; + + pin = 0; + while (pi) { + fprintf(stderr, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "", + pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]); + prn = 0; + while (prn < pi->num_cmds) { + struct command *command = &pi->cmds[prn]; + char **argv = command->argv; + + fprintf(stderr, "%*s cmd %d assignment_cnt:%d", + lvl*2, "", prn, + command->assignment_cnt); + if (command->group) { + fprintf(stderr, " group %s: (argv=%p)%s%s\n", + CMDTYPE[command->cmd_type], + argv +# if !BB_MMU + , " group_as_string:", command->group_as_string +# else + , "", "" +# endif + ); + debug_print_tree(command->group, lvl+1); + prn++; + continue; + } + if (argv) while (*argv) { + fprintf(stderr, " '%s'", *argv); + argv++; + } + fprintf(stderr, "\n"); + prn++; + } + pi = pi->next; + pin++; + } +} +#endif /* debug_print_tree */ + static struct pipe *new_pipe(void) { struct pipe *pi; @@ -4011,15 +4098,16 @@ static struct pipe *parse_stream(char **pstring, goto parse_error; } if (ch == '\n') { -#if ENABLE_HUSH_CASE - /* "case ... in word) ..." - - * newlines are ignored (but ';' wouldn't be) */ - if (ctx.command->argv == NULL - && ctx.ctx_res_w == RES_MATCH + /* Is this a case when newline is simply ignored? + * Some examples: + * "cmd | cmd ..." + * "case ... in word) ..." + */ + if (IS_NULL_CMD(ctx.command) + && dest.length == 0 && !dest.has_quoted_part ) { continue; } -#endif /* Treat newline as a command separator. */ done_pipe(&ctx, PIPE_SEQ); debug_printf_parse("heredoc_cnt:%d\n", heredoc_cnt); @@ -4151,6 +4239,31 @@ static struct pipe *parse_stream(char **pstring, if (parse_redirect(&ctx, redir_fd, redir_style, input)) goto parse_error; continue; /* back to top of while (1) */ + case '#': + if (dest.length == 0 && !dest.has_quoted_part) { + /* skip "#comment" */ + while (1) { + ch = i_peek(input); + if (ch == EOF || ch == '\n') + break; + i_getch(input); + /* note: we do not add it to &ctx.as_string */ + } + nommu_addchr(&ctx.as_string, '\n'); + continue; /* back to top of while (1) */ + } + break; + case '\\': + if (next == '\n') { + /* It's "\" */ +#if !BB_MMU + /* Remove trailing '\' from ctx.as_string */ + ctx.as_string.data[--ctx.as_string.length] = '\0'; +#endif + ch = i_getch(input); /* eat it */ + continue; /* back to top of while (1) */ + } + break; } if (dest.o_assignment == MAYBE_ASSIGNMENT @@ -4165,19 +4278,8 @@ static struct pipe *parse_stream(char **pstring, /* Note: nommu_addchr(&ctx.as_string, ch) is already done */ switch (ch) { - case '#': - if (dest.length == 0) { - while (1) { - ch = i_peek(input); - if (ch == EOF || ch == '\n') - break; - i_getch(input); - /* note: we do not add it to &ctx.as_string */ - } - nommu_addchr(&ctx.as_string, '\n'); - } else { - o_addQchr(&dest, ch); - } + case '#': /* non-comment #: "echo a#b" etc */ + o_addQchr(&dest, ch); break; case '\\': if (next == EOF) { @@ -4185,21 +4287,14 @@ static struct pipe *parse_stream(char **pstring, xfunc_die(); } ch = i_getch(input); - if (ch != '\n') { - o_addchr(&dest, '\\'); - /*nommu_addchr(&ctx.as_string, '\\'); - already done */ - o_addchr(&dest, ch); - nommu_addchr(&ctx.as_string, ch); - /* Example: echo Hello \2>file - * we need to know that word 2 is quoted */ - dest.has_quoted_part = 1; - } -#if !BB_MMU - else { - /* It's "\". Remove trailing '\' from ctx.as_string */ - ctx.as_string.data[--ctx.as_string.length] = '\0'; - } -#endif + /* note: ch != '\n' (that case does not reach this place) */ + o_addchr(&dest, '\\'); + /*nommu_addchr(&ctx.as_string, '\\'); - already done */ + o_addchr(&dest, ch); + nommu_addchr(&ctx.as_string, ch); + /* Example: echo Hello \2>file + * we need to know that word 2 is quoted */ + dest.has_quoted_part = 1; break; case '$': if (parse_dollar(&ctx.as_string, &dest, input, /*quote_mask:*/ 0) != 0) { @@ -6869,94 +6964,6 @@ static NOINLINE int run_pipe(struct pipe *pi) return -1; } -#ifndef debug_print_tree -static void debug_print_tree(struct pipe *pi, int lvl) -{ - static const char *const PIPE[] = { - [PIPE_SEQ] = "SEQ", - [PIPE_AND] = "AND", - [PIPE_OR ] = "OR" , - [PIPE_BG ] = "BG" , - }; - static const char *RES[] = { - [RES_NONE ] = "NONE" , -# if ENABLE_HUSH_IF - [RES_IF ] = "IF" , - [RES_THEN ] = "THEN" , - [RES_ELIF ] = "ELIF" , - [RES_ELSE ] = "ELSE" , - [RES_FI ] = "FI" , -# endif -# if ENABLE_HUSH_LOOPS - [RES_FOR ] = "FOR" , - [RES_WHILE] = "WHILE", - [RES_UNTIL] = "UNTIL", - [RES_DO ] = "DO" , - [RES_DONE ] = "DONE" , -# endif -# if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE - [RES_IN ] = "IN" , -# endif -# if ENABLE_HUSH_CASE - [RES_CASE ] = "CASE" , - [RES_CASE_IN ] = "CASE_IN" , - [RES_MATCH] = "MATCH", - [RES_CASE_BODY] = "CASE_BODY", - [RES_ESAC ] = "ESAC" , -# endif - [RES_XXXX ] = "XXXX" , - [RES_SNTX ] = "SNTX" , - }; - static const char *const CMDTYPE[] = { - "{}", - "()", - "[noglob]", -# if ENABLE_HUSH_FUNCTIONS - "func()", -# endif - }; - - int pin, prn; - - pin = 0; - while (pi) { - fprintf(stderr, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "", - pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]); - prn = 0; - while (prn < pi->num_cmds) { - struct command *command = &pi->cmds[prn]; - char **argv = command->argv; - - fprintf(stderr, "%*s cmd %d assignment_cnt:%d", - lvl*2, "", prn, - command->assignment_cnt); - if (command->group) { - fprintf(stderr, " group %s: (argv=%p)%s%s\n", - CMDTYPE[command->cmd_type], - argv -# if !BB_MMU - , " group_as_string:", command->group_as_string -# else - , "", "" -# endif - ); - debug_print_tree(command->group, lvl+1); - prn++; - continue; - } - if (argv) while (*argv) { - fprintf(stderr, " '%s'", *argv); - argv++; - } - fprintf(stderr, "\n"); - prn++; - } - pi = pi->next; - pin++; - } -} -#endif /* debug_print_tree */ - /* NB: called by pseudo_exec, and therefore must not modify any * global data until exec/_exit (we can be a child after vfork!) */ static int run_list(struct pipe *pi) diff --git a/shell/hush_test/hush-misc/assignment3.right b/shell/hush_test/hush-misc/assignment3.right new file mode 100644 index 000000000..0f02d7cbc --- /dev/null +++ b/shell/hush_test/hush-misc/assignment3.right @@ -0,0 +1,2 @@ +Done:0 +abc=123 diff --git a/shell/hush_test/hush-misc/assignment3.tests b/shell/hush_test/hush-misc/assignment3.tests new file mode 100755 index 000000000..790129be1 --- /dev/null +++ b/shell/hush_test/hush-misc/assignment3.tests @@ -0,0 +1,5 @@ +# This must be interpreted as assignments +a=1 b\ +=2 c=3 +echo Done:$? +echo abc=$a$b$c diff --git a/shell/hush_test/hush-parsing/comment1.right b/shell/hush_test/hush-parsing/comment1.right new file mode 100644 index 000000000..a102b1d4e --- /dev/null +++ b/shell/hush_test/hush-parsing/comment1.right @@ -0,0 +1,2 @@ +Nothing: +String: #should-be-echoed diff --git a/shell/hush_test/hush-parsing/comment1.tests b/shell/hush_test/hush-parsing/comment1.tests new file mode 100755 index 000000000..d268860ff --- /dev/null +++ b/shell/hush_test/hush-parsing/comment1.tests @@ -0,0 +1,2 @@ +echo Nothing: #should-not-be-echoed +echo String: ""#should-be-echoed diff --git a/shell/hush_test/hush-parsing/eol1.right b/shell/hush_test/hush-parsing/eol1.right new file mode 100644 index 000000000..31c896f62 --- /dev/null +++ b/shell/hush_test/hush-parsing/eol1.right @@ -0,0 +1 @@ +Done:0 diff --git a/shell/hush_test/hush-parsing/eol1.tests b/shell/hush_test/hush-parsing/eol1.tests new file mode 100755 index 000000000..f1b55e8b8 --- /dev/null +++ b/shell/hush_test/hush-parsing/eol1.tests @@ -0,0 +1,18 @@ +# bug was that we treated as ';' in this line: +true || echo foo | +echo BAD1 | cat + +# variation on the same theme +true || echo foo | +# comment +echo BAD2 | cat + +# variation on the same theme +true || echo foo | + +echo BAD3 | cat + +# this should error out, but currently works in hush: +#true || echo foo |; + +echo Done:$? -- cgit v1.2.3-55-g6feb From 26777aa1c659b229f07205291241e45e64712a72 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 22 Nov 2010 23:49:10 +0100 Subject: fixes for bugs discovered by randomconfig builds and tests Signed-off-by: Denys Vlasenko --- libbb/Kbuild.src | 1 + scripts/randomtest.loop | 2 +- shell/ash.c | 9 ++++++++- shell/hush.c | 6 ++++-- testsuite/du/du-h-works | 2 +- testsuite/md5sum.tests | 5 +++++ util-linux/acpid.c | 11 ++++++----- 7 files changed, 26 insertions(+), 10 deletions(-) (limited to 'shell') diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 806cace28..0fa145159 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src @@ -158,6 +158,7 @@ lib-$(CONFIG_RTCWAKE) += rtc.o lib-$(CONFIG_IOSTAT) += get_cpu_count.o lib-$(CONFIG_MPSTAT) += get_cpu_count.o +lib-$(CONFIG_POWERTOP) += get_cpu_count.o # We shouldn't build xregcomp.c if we don't need it - this ensures we don't # require regex.h to be in the include dir even if we don't need it thereby diff --git a/scripts/randomtest.loop b/scripts/randomtest.loop index 311536df8..2c8a9bd35 100755 --- a/scripts/randomtest.loop +++ b/scripts/randomtest.loop @@ -4,7 +4,7 @@ test -d "$1" || { echo "'$1' is not a directory"; exit 1; } test -x "$1/scripts/randomtest" || { echo "No scripts/randomtest in '$1'"; exit 1; } export LIBC="uclibc" -export CROSS_COMPILER_PREFIX="i486-linux-uclibc-" +export CROSS_COMPILER_PREFIX="i686-" export MAKEOPTS="-j9" cnt=0 diff --git a/shell/ash.c b/shell/ash.c index 5ef7efbdb..5671a524b 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -43,7 +43,9 @@ #include #include "shell_common.h" -#include "math.h" +#if ENABLE_SH_MATH_SUPPORT +# include "math.h" +#endif #if ENABLE_ASH_RANDOM_SUPPORT # include "random.h" #else @@ -5510,6 +5512,11 @@ static struct arglist exparg; /* * Our own itoa(). */ +#if !ENABLE_SH_MATH_SUPPORT +/* cvtnum() is used even if math support is off (to prepare $? values and such) */ +typedef long arith_t; +# define ARITH_FMT "%ld" +#endif static int cvtnum(arith_t num) { diff --git a/shell/hush.c b/shell/hush.c index da32c2435..26a50744e 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -712,11 +712,11 @@ struct globals { int last_jobid; pid_t saved_tty_pgrp; struct pipe *job_list; - char o_opt[NUM_OPT_O]; # define G_saved_tty_pgrp (G.saved_tty_pgrp) #else # define G_saved_tty_pgrp 0 #endif + char o_opt[NUM_OPT_O]; smallint flag_SIGINT; #if ENABLE_HUSH_LOOPS smallint flag_break_continue; @@ -4500,7 +4500,9 @@ static struct pipe *parse_stream(char **pstring, expand_string_to_string(str) #endif static char *expand_string_to_string(const char *str, int do_unbackslash); +#if ENABLE_HUSH_TICK static int process_command_subs(o_string *dest, const char *s); +#endif /* expand_strvec_to_strvec() takes a list of strings, expands * all variable references within and returns a pointer to @@ -6579,7 +6581,7 @@ static int checkjobs_and_fg_shell(struct pipe *fg_pipe) * subshell: ( list ) [&] */ #if !ENABLE_HUSH_MODE_X -#define redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel, char argv_expanded) \ +#define redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel, argv_expanded) \ redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel) #endif static int redirect_and_varexp_helper(char ***new_env_p, diff --git a/testsuite/du/du-h-works b/testsuite/du/du-h-works index c18433c29..1c77b6552 100644 --- a/testsuite/du/du-h-works +++ b/testsuite/du/du-h-works @@ -1,4 +1,4 @@ # FEATURE: CONFIG_FEATURE_HUMAN_READABLE dd if=/dev/zero of=file bs=1M count=1 2>/dev/null -test x"`busybox du -h .`" = x"1.0M ." +test x"`busybox du -h file`" = x"1.0M file" diff --git a/testsuite/md5sum.tests b/testsuite/md5sum.tests index 35ec67cb4..1068b083f 100755 --- a/testsuite/md5sum.tests +++ b/testsuite/md5sum.tests @@ -18,6 +18,11 @@ fi sum="$1" expected="$2" +test -f "$bindir/.config" && . "$bindir/.config" + +test x"$CONFIG_FEATURE_FANCY_HEAD" != x"y" \ +&& { echo "SKIPPED: $sum"; exit 0; } + text="The quick brown fox jumps over the lazy dog" text=`yes "$text" | head -c 9999` diff --git a/util-linux/acpid.c b/util-linux/acpid.c index 0b227a8ae..ce4c98ebe 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c @@ -16,9 +16,9 @@ enum { OPT_e = (1 << 2), OPT_f = (1 << 3), OPT_l = (1 << 4), - OPT_p = (1 << 5) * ENABLE_FEATURE_PIDFILE, - OPT_a = (1 << 6), - OPT_M = (1 << 7), + OPT_a = (1 << 5), + OPT_M = (1 << 6), + OPT_p = (1 << 7) * ENABLE_FEATURE_PIDFILE, }; struct acpi_event { @@ -199,8 +199,9 @@ int acpid_main(int argc UNUSED_PARAM, char **argv) INIT_G(); opt_complementary = "df:e--e"; - opts = getopt32(argv, "c:de:fl:p:a:M:" IF_FEATURE_ACPID_COMPAT("g:m:s:S:v"), - &opt_dir, &opt_input, &opt_logfile, &opt_pidfile, &opt_action, &opt_map + opts = getopt32(argv, "c:de:fl:a:M:" IF_FEATURE_PIDFILE("p:") IF_FEATURE_ACPID_COMPAT("g:m:s:S:v"), + &opt_dir, &opt_input, &opt_logfile, &opt_action, &opt_map + IF_FEATURE_PIDFILE(, &opt_pidfile) IF_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL) ); -- cgit v1.2.3-55-g6feb From 89ca2f99a20e78f392fb95d52d62cb32925bc9b2 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Sun, 28 Nov 2010 01:54:39 +0100 Subject: hush: display useful help text Signed-off-by: Dan Fandrich Signed-off-by: Denys Vlasenko --- shell/hush.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index 26a50744e..a710f7cd9 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -245,9 +245,15 @@ //config: msh is deprecated and will be removed, please migrate to hush. //config: -//usage:#define hush_trivial_usage NOUSAGE_STR +/* -i (interactive) and -s (read stdin) are also accepted, + * but currently do nothing, therefore aren't shown in help. + * NOMMU-specific options are not meant to be used by users, + * therefore we don't show them either. + */ +//usage:#define hush_trivial_usage +//usage: "[-nx] [-c SCRIPT]" //usage:#define hush_full_usage "" -//usage:#define msh_trivial_usage NOUSAGE_STR +//usage:#define msh_trivial_usage hush_trivial_usage //usage:#define msh_full_usage "" //usage:#define sh_trivial_usage NOUSAGE_STR //usage:#define sh_full_usage "" -- cgit v1.2.3-55-g6feb From 85c62470b75b9256e36d8f488a0701aff94ca512 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Sat, 20 Nov 2010 13:05:17 -0800 Subject: Support set -o xtrace/noexec alternates for set -x/-n Signed-off-by: Dan Fandrich Signed-off-by: Denys Vlasenko --- shell/hush.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index a710f7cd9..0cc587e19 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -673,9 +673,19 @@ struct function { * vi off * xtrace off */ -static const char o_opt_strings[] ALIGN1 = "pipefail\0"; +static const char o_opt_strings[] ALIGN1 = + "pipefail\0" + "noexec\0" +#if ENABLE_HUSH_MODE_X + "xtrace\0" +#endif + ; enum { OPT_O_PIPEFAIL, + OPT_O_NOEXEC, +#if ENABLE_HUSH_MODE_X + OPT_O_XTRACE, +#endif NUM_OPT_O }; @@ -734,10 +744,8 @@ struct globals { */ smallint flag_return_in_progress; #endif - smallint n_mode; #if ENABLE_HUSH_MODE_X - smallint x_mode; -# define G_x_mode (G.x_mode) +# define G_x_mode (G.o_opt[OPT_O_XTRACE]) #else # define G_x_mode 0 #endif @@ -7304,7 +7312,7 @@ static int run_and_free_list(struct pipe *pi) { int rcode = 0; debug_printf_exec("run_and_free_list entered\n"); - if (!G.n_mode) { + if (!G.o_opt[OPT_O_NOEXEC]) { debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds); rcode = run_list(pi); } @@ -7407,7 +7415,7 @@ static int set_mode(int state, char mode, const char *o_opt) int idx; switch (mode) { case 'n': - G.n_mode = state; + G.o_opt[OPT_O_NOEXEC] = state; break; case 'x': IF_HUSH_MODE_X(G_x_mode = state;) -- cgit v1.2.3-55-g6feb From 57542ebe4fee39b6d3091b964c42ce07ecfec7ef Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 28 Nov 2010 03:59:30 +0100 Subject: hush: move G_x_mode define to the more appropriate place Signed-off-by: Denys Vlasenko --- shell/hush.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index 0cc587e19..584af9e06 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -733,6 +733,11 @@ struct globals { # define G_saved_tty_pgrp 0 #endif char o_opt[NUM_OPT_O]; +#if ENABLE_HUSH_MODE_X +# define G_x_mode (G.o_opt[OPT_O_XTRACE]) +#else +# define G_x_mode 0 +#endif smallint flag_SIGINT; #if ENABLE_HUSH_LOOPS smallint flag_break_continue; @@ -743,11 +748,6 @@ struct globals { * 1: return is invoked, skip all till end of func */ smallint flag_return_in_progress; -#endif -#if ENABLE_HUSH_MODE_X -# define G_x_mode (G.o_opt[OPT_O_XTRACE]) -#else -# define G_x_mode 0 #endif smallint exiting; /* used to prevent EXIT trap recursion */ /* These four support $?, $#, and $1 */ -- cgit v1.2.3-55-g6feb From 8da415ef2503936bc9730f78a25b00177ff2db1d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 5 Dec 2010 01:30:14 +0100 Subject: add if guards around include Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 6 +++++- shell/hush.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'shell') diff --git a/libbb/appletlib.c b/libbb/appletlib.c index efd7a5a81..3e32fa1ef 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -28,7 +28,11 @@ */ #include "busybox.h" #include -#include +#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ + || defined(__APPLE__) \ + ) +# include /* for mallopt */ +#endif /* Try to pull in PAGE_SIZE */ #ifdef __linux__ # include diff --git a/shell/hush.c b/shell/hush.c index 584af9e06..087636b6d 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -82,7 +82,11 @@ * aaa */ #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ -#include /* for malloc_trim */ +#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ + || defined(__APPLE__) \ + ) +# include /* for malloc_trim */ +#endif #include /* #include */ #if ENABLE_HUSH_CASE -- cgit v1.2.3-55-g6feb From 0d6a4ecb30f596570585bbde29f7c9b42a60b623 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 18 Dec 2010 01:34:49 +0100 Subject: hush: fix build breakage (variable declared in for()) Signed-off-by: Denys Vlasenko --- shell/hush.c | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index 087636b6d..2bca9aa87 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7013,27 +7013,30 @@ static int run_list(struct pipe *pi) #if ENABLE_HUSH_LOOPS /* Check syntax for "for" */ - for (struct pipe *cpipe = pi; cpipe; cpipe = cpipe->next) { - if (cpipe->res_word != RES_FOR && cpipe->res_word != RES_IN) - continue; - /* current word is FOR or IN (BOLD in comments below) */ - if (cpipe->next == NULL) { - syntax_error("malformed for"); - debug_leave(); - debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level); - return 1; - } - /* "FOR v; do ..." and "for v IN a b; do..." are ok */ - if (cpipe->next->res_word == RES_DO) - continue; - /* next word is not "do". It must be "in" then ("FOR v in ...") */ - if (cpipe->res_word == RES_IN /* "for v IN a b; not_do..."? */ - || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */ - ) { - syntax_error("malformed for"); - debug_leave(); - debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level); - return 1; + { + struct pipe *cpipe; + for (cpipe = pi; cpipe; cpipe = cpipe->next) { + if (cpipe->res_word != RES_FOR && cpipe->res_word != RES_IN) + continue; + /* current word is FOR or IN (BOLD in comments below) */ + if (cpipe->next == NULL) { + syntax_error("malformed for"); + debug_leave(); + debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level); + return 1; + } + /* "FOR v; do ..." and "for v IN a b; do..." are ok */ + if (cpipe->next->res_word == RES_DO) + continue; + /* next word is not "do". It must be "in" then ("FOR v in ...") */ + if (cpipe->res_word == RES_IN /* "for v IN a b; not_do..."? */ + || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */ + ) { + syntax_error("malformed for"); + debug_leave(); + debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level); + return 1; + } } } #endif -- cgit v1.2.3-55-g6feb From 75eb9d20e9e672c33e377221d1f7d4546f919f9e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 21 Dec 2010 21:18:12 +0100 Subject: hush: fix FEATURE_CLEAN_UP code (was freeing unallocated memory) Signed-off-by: Denys Vlasenko --- shell/hush.c | 94 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 49 insertions(+), 45 deletions(-) (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index 2bca9aa87..a771e9cd9 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -931,7 +931,7 @@ static const struct built_in_command bltins2[] = { */ #if HUSH_DEBUG /* prevent disasters with G.debug_indent < 0 */ -# define indent() fprintf(stderr, "%*s", (G.debug_indent * 2) & 0xff, "") +# define indent() fdprintf(2, "%*s", (G.debug_indent * 2) & 0xff, "") # define debug_enter() (G.debug_indent++) # define debug_leave() (G.debug_indent--) #else @@ -941,56 +941,56 @@ static const struct built_in_command bltins2[] = { #endif #ifndef debug_printf -# define debug_printf(...) (indent(), fprintf(stderr, __VA_ARGS__)) +# define debug_printf(...) (indent(), fdprintf(2, __VA_ARGS__)) #endif #ifndef debug_printf_parse -# define debug_printf_parse(...) (indent(), fprintf(stderr, __VA_ARGS__)) +# define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__)) #endif #ifndef debug_printf_exec -#define debug_printf_exec(...) (indent(), fprintf(stderr, __VA_ARGS__)) +#define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__)) #endif #ifndef debug_printf_env -# define debug_printf_env(...) (indent(), fprintf(stderr, __VA_ARGS__)) +# define debug_printf_env(...) (indent(), fdprintf(2, __VA_ARGS__)) #endif #ifndef debug_printf_jobs -# define debug_printf_jobs(...) (indent(), fprintf(stderr, __VA_ARGS__)) +# define debug_printf_jobs(...) (indent(), fdprintf(2, __VA_ARGS__)) # define DEBUG_JOBS 1 #else # define DEBUG_JOBS 0 #endif #ifndef debug_printf_expand -# define debug_printf_expand(...) (indent(), fprintf(stderr, __VA_ARGS__)) +# define debug_printf_expand(...) (indent(), fdprintf(2, __VA_ARGS__)) # define DEBUG_EXPAND 1 #else # define DEBUG_EXPAND 0 #endif #ifndef debug_printf_varexp -# define debug_printf_varexp(...) (indent(), fprintf(stderr, __VA_ARGS__)) +# define debug_printf_varexp(...) (indent(), fdprintf(2, __VA_ARGS__)) #endif #ifndef debug_printf_glob -# define debug_printf_glob(...) (indent(), fprintf(stderr, __VA_ARGS__)) +# define debug_printf_glob(...) (indent(), fdprintf(2, __VA_ARGS__)) # define DEBUG_GLOB 1 #else # define DEBUG_GLOB 0 #endif #ifndef debug_printf_list -# define debug_printf_list(...) (indent(), fprintf(stderr, __VA_ARGS__)) +# define debug_printf_list(...) (indent(), fdprintf(2, __VA_ARGS__)) #endif #ifndef debug_printf_subst -# define debug_printf_subst(...) (indent(), fprintf(stderr, __VA_ARGS__)) +# define debug_printf_subst(...) (indent(), fdprintf(2, __VA_ARGS__)) #endif #ifndef debug_printf_clean -# define debug_printf_clean(...) (indent(), fprintf(stderr, __VA_ARGS__)) +# define debug_printf_clean(...) (indent(), fdprintf(2, __VA_ARGS__)) # define DEBUG_CLEAN 1 #else # define DEBUG_CLEAN 0 @@ -1000,9 +1000,9 @@ static const struct built_in_command bltins2[] = { static void debug_print_strings(const char *prefix, char **vv) { indent(); - fprintf(stderr, "%s:\n", prefix); + fdprintf(2, "%s:\n", prefix); while (*vv) - fprintf(stderr, " '%s'\n", *vv++); + fdprintf(2, " '%s'\n", *vv++); } #else # define debug_print_strings(prefix, vv) ((void)0) @@ -1434,6 +1434,22 @@ static void hush_exit(int exitcode) builtin_eval(argv); } +#if ENABLE_FEATURE_CLEAN_UP + { + struct variable *cur_var; + if (G.cwd != bb_msg_unknown) + free((char*)G.cwd); + cur_var = G.top_var; + while (cur_var) { + struct variable *tmp = cur_var; + if (!cur_var->max_len) + free(cur_var->varstr); + cur_var = cur_var->next; + free(tmp); + } + } +#endif + #if ENABLE_HUSH_JOB fflush_all(); sigexit(- (exitcode & 0xff)); @@ -2176,22 +2192,22 @@ static void debug_print_list(const char *prefix, o_string *o, int n) int i = 0; indent(); - fprintf(stderr, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n", + fdprintf(2, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n", prefix, list, n, string_start, o->length, o->maxlen, !!(o->o_expflags & EXP_FLAG_GLOB), o->has_quoted_part, !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); while (i < n) { indent(); - fprintf(stderr, " list[%d]=%d '%s' %p\n", i, (int)list[i], - o->data + (int)list[i] + string_start, - o->data + (int)list[i] + string_start); + fdprintf(2, " list[%d]=%d '%s' %p\n", i, (int)(uintptr_t)list[i], + o->data + (int)(uintptr_t)list[i] + string_start, + o->data + (int)(uintptr_t)list[i] + string_start); i++; } if (n) { - const char *p = o->data + (int)list[n - 1] + string_start; + const char *p = o->data + (int)(uintptr_t)list[n - 1] + string_start; indent(); - fprintf(stderr, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data)); + fdprintf(2, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data)); } } #else @@ -2690,18 +2706,18 @@ static void debug_print_tree(struct pipe *pi, int lvl) pin = 0; while (pi) { - fprintf(stderr, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "", + fdprintf(2, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "", pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]); prn = 0; while (prn < pi->num_cmds) { struct command *command = &pi->cmds[prn]; char **argv = command->argv; - fprintf(stderr, "%*s cmd %d assignment_cnt:%d", + fdprintf(2, "%*s cmd %d assignment_cnt:%d", lvl*2, "", prn, command->assignment_cnt); if (command->group) { - fprintf(stderr, " group %s: (argv=%p)%s%s\n", + fdprintf(2, " group %s: (argv=%p)%s%s\n", CMDTYPE[command->cmd_type], argv # if !BB_MMU @@ -2715,10 +2731,10 @@ static void debug_print_tree(struct pipe *pi, int lvl) continue; } if (argv) while (*argv) { - fprintf(stderr, " '%s'", *argv); + fdprintf(2, " '%s'", *argv); argv++; } - fprintf(stderr, "\n"); + fdprintf(2, "\n"); prn++; } pi = pi->next; @@ -7463,7 +7479,7 @@ int hush_main(int argc, char **argv) unsigned builtin_argc; char **e; struct variable *cur_var; - struct variable shell_ver; + struct variable *shell_ver; INIT_G(); if (EXIT_SUCCESS) /* if EXIT_SUCCESS == 0, it is already done */ @@ -7472,17 +7488,17 @@ int hush_main(int argc, char **argv) G.argv0_for_re_execing = argv[0]; #endif /* Deal with HUSH_VERSION */ - memset(&shell_ver, 0, sizeof(shell_ver)); - shell_ver.flg_export = 1; - shell_ver.flg_read_only = 1; + shell_ver = xzalloc(sizeof(*shell_ver)); + shell_ver->flg_export = 1; + shell_ver->flg_read_only = 1; /* Code which handles ${var...} needs writable values for all variables, * therefore we xstrdup: */ - shell_ver.varstr = xstrdup(hush_version_str), - G.top_var = &shell_ver; + shell_ver->varstr = xstrdup(hush_version_str); /* Create shell local variables from the values * currently living in the environment */ debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); unsetenv("HUSH_VERSION"); /* in case it exists in initial env */ + G.top_var = shell_ver; cur_var = G.top_var; e = environ; if (e) while (*e) { @@ -7497,8 +7513,8 @@ int hush_main(int argc, char **argv) e++; } /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */ - debug_printf_env("putenv '%s'\n", shell_ver.varstr); - putenv(shell_ver.varstr); + debug_printf_env("putenv '%s'\n", shell_ver->varstr); + putenv(shell_ver->varstr); /* Export PWD */ set_pwd_var(/*exp:*/ 1); @@ -7858,18 +7874,6 @@ int hush_main(int argc, char **argv) parse_and_run_file(stdin); final_return: -#if ENABLE_FEATURE_CLEAN_UP - if (G.cwd != bb_msg_unknown) - free((char*)G.cwd); - cur_var = G.top_var->next; - while (cur_var) { - struct variable *tmp = cur_var; - if (!cur_var->max_len) - free(cur_var->varstr); - cur_var = cur_var->next; - free(tmp); - } -#endif hush_exit(G.last_exitcode); } -- cgit v1.2.3-55-g6feb From 6088e138e1c6d0b73f8004fc4b4e9ec40430e18e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 25 Dec 2010 23:58:42 +0100 Subject: init: simpler handling of leading dash in commands function old new delta init_exec 233 219 -14 Signed-off-by: Denys Vlasenko --- init/init.c | 20 +++++++++++--------- shell/ash.c | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'shell') diff --git a/init/init.c b/init/init.c index 0a0d503b5..a2cc3b5f5 100644 --- a/init/init.c +++ b/init/init.c @@ -401,20 +401,22 @@ static void init_exec(const char *command) char buf[COMMAND_SIZE + 6]; /* COMMAND_SIZE+strlen("exec ")+1 */ int dash = (command[0] == '-' /* maybe? && command[1] == '/' */); + command += dash; + /* See if any special /bin/sh requiring characters are present */ if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) { - strcpy(buf, "exec "); - strcpy(buf + 5, command + dash); /* excluding "-" */ + sprintf(buf, "exec %s", command); /* excluding "-" */ /* NB: LIBBB_DEFAULT_LOGIN_SHELL define has leading dash */ cmd[0] = (char*)(LIBBB_DEFAULT_LOGIN_SHELL + !dash); cmd[1] = (char*)"-c"; cmd[2] = buf; cmd[3] = NULL; + command = LIBBB_DEFAULT_LOGIN_SHELL + 1; } else { /* Convert command (char*) into cmd (char**, one word per string) */ char *word, *next; int i = 0; - next = strcpy(buf, command); /* including "-" */ + next = strcpy(buf, command - dash); /* command including "-" */ while ((word = strsep(&next, " \t")) != NULL) { if (*word != '\0') { /* not two spaces/tabs together? */ cmd[i] = word; @@ -425,14 +427,14 @@ static void init_exec(const char *command) } /* If we saw leading "-", it is interactive shell. * Try harder to give it a controlling tty. - * And skip "-" in actual exec call. */ - if (dash) { + */ + if (ENABLE_FEATURE_INIT_SCTTY && dash) { /* _Attempt_ to make stdin a controlling tty. */ - if (ENABLE_FEATURE_INIT_SCTTY) - ioctl(STDIN_FILENO, TIOCSCTTY, 0 /*only try, don't steal*/); + ioctl(STDIN_FILENO, TIOCSCTTY, 0 /*only try, don't steal*/); } - BB_EXECVP(cmd[0] + dash, cmd); - message(L_LOG | L_CONSOLE, "can't run '%s': %s", cmd[0], strerror(errno)); + /* Here command never contains the dash, cmd[0] might */ + BB_EXECVP(command, cmd); + message(L_LOG | L_CONSOLE, "can't run '%s': %s", command, strerror(errno)); /* returns if execvp fails */ } diff --git a/shell/ash.c b/shell/ash.c index 5671a524b..6f03ac1c6 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13063,7 +13063,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) } } #endif - if (/* argv[0] && */ argv[0][0] == '-') + if (argv[0] && argv[0][0] == '-') isloginsh = 1; if (isloginsh) { state = 1; -- cgit v1.2.3-55-g6feb