hush: remove code which errors out on $- and $_, it's useless;
wrap some longish lines function old new delta handle_dollar 667 626 -41
This commit is contained in:
parent
7c9861214b
commit
a24c8caeb2
303
shell/hush.c
303
shell/hush.c
@ -1517,13 +1517,16 @@ static int o_save_ptr_helper(o_string *o, int n)
|
||||
list = (char**)o->data;
|
||||
memmove(list + n + 0x10, list + n, string_len);
|
||||
o->length += 0x10 * sizeof(list[0]);
|
||||
} else
|
||||
debug_printf_list("list[%d]=%d string_start=%d\n", n, string_len, string_start);
|
||||
} else {
|
||||
debug_printf_list("list[%d]=%d string_start=%d\n",
|
||||
n, string_len, string_start);
|
||||
}
|
||||
} else {
|
||||
/* We have empty slot at list[n], reuse without growth */
|
||||
string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */
|
||||
string_len = o->length - string_start;
|
||||
debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n", n, string_len, string_start);
|
||||
debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n",
|
||||
n, string_len, string_start);
|
||||
o->has_empty_slot = 0;
|
||||
}
|
||||
list[n] = (char*)(ptrdiff_t)string_len;
|
||||
@ -1917,7 +1920,6 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
|
||||
}
|
||||
|
||||
arg[0] = first_ch;
|
||||
|
||||
#if ENABLE_HUSH_TICK
|
||||
store_val:
|
||||
#endif
|
||||
@ -2203,8 +2205,12 @@ typedef struct nommu_save_t {
|
||||
* XXX no exit() here. If you don't exec, use _exit instead.
|
||||
* The at_exit handlers apparently confuse the calling process,
|
||||
* in particular stdin handling. Not sure why? -- because of vfork! (vda) */
|
||||
static void pseudo_exec_argv(nommu_save_t *nommu_save, char **argv, int assignment_cnt, char **argv_expanded) NORETURN;
|
||||
static void pseudo_exec_argv(nommu_save_t *nommu_save, char **argv, int assignment_cnt, char **argv_expanded)
|
||||
static void pseudo_exec_argv(nommu_save_t *nommu_save,
|
||||
char **argv, int assignment_cnt,
|
||||
char **argv_expanded) NORETURN;
|
||||
static void pseudo_exec_argv(nommu_save_t *nommu_save,
|
||||
char **argv, int assignment_cnt,
|
||||
char **argv_expanded)
|
||||
{
|
||||
int rcode;
|
||||
char **new_env;
|
||||
@ -2279,8 +2285,12 @@ static int run_list(struct pipe *pi);
|
||||
|
||||
/* Called after [v]fork() in run_pipe()
|
||||
*/
|
||||
static void pseudo_exec(nommu_save_t *nommu_save, struct command *command, char **argv_expanded) NORETURN;
|
||||
static void pseudo_exec(nommu_save_t *nommu_save, struct command *command, char **argv_expanded)
|
||||
static void pseudo_exec(nommu_save_t *nommu_save,
|
||||
struct command *command,
|
||||
char **argv_expanded) NORETURN;
|
||||
static void pseudo_exec(nommu_save_t *nommu_save,
|
||||
struct command *command,
|
||||
char **argv_expanded)
|
||||
{
|
||||
if (command->argv)
|
||||
pseudo_exec_argv(nommu_save, command->argv, command->assignment_cnt, argv_expanded);
|
||||
@ -2655,7 +2665,8 @@ static int run_pipe(struct pipe *pi)
|
||||
setup_redirects(command, squirrel);
|
||||
new_env = expand_assignments(argv, command->assignment_cnt);
|
||||
old_env = putenv_all_and_save_old(new_env);
|
||||
debug_printf_exec(": builtin '%s' '%s'...\n", x->cmd, argv_expanded[1]);
|
||||
debug_printf_exec(": builtin '%s' '%s'...\n",
|
||||
x->cmd, argv_expanded[1]);
|
||||
rcode = x->function(argv_expanded) & 0xff;
|
||||
#if ENABLE_FEATURE_SH_STANDALONE
|
||||
clean_up_and_ret:
|
||||
@ -2677,7 +2688,8 @@ static int run_pipe(struct pipe *pi)
|
||||
save_nofork_data(&G.nofork_save);
|
||||
new_env = expand_assignments(argv, command->assignment_cnt);
|
||||
old_env = putenv_all_and_save_old(new_env);
|
||||
debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]);
|
||||
debug_printf_exec(": run_nofork_applet '%s' '%s'...\n",
|
||||
argv_expanded[0], argv_expanded[1]);
|
||||
rcode = run_nofork_applet_prime(&G.nofork_save, i, argv_expanded);
|
||||
goto clean_up_and_ret;
|
||||
}
|
||||
@ -2701,7 +2713,8 @@ static int run_pipe(struct pipe *pi)
|
||||
#endif
|
||||
command = &(pi->cmds[i]);
|
||||
if (command->argv) {
|
||||
debug_printf_exec(": pipe member '%s' '%s'...\n", command->argv[0], command->argv[1]);
|
||||
debug_printf_exec(": pipe member '%s' '%s'...\n",
|
||||
command->argv[0], command->argv[1]);
|
||||
} else
|
||||
debug_printf_exec(": pipe member with no argv\n");
|
||||
|
||||
@ -2841,7 +2854,9 @@ static void debug_print_tree(struct pipe *pi, int lvl)
|
||||
struct command *command = &pi->cmds[prn];
|
||||
char **argv = command->argv;
|
||||
|
||||
fprintf(stderr, "%*s prog %d assignment_cnt:%d", lvl*2, "", prn, command->assignment_cnt);
|
||||
fprintf(stderr, "%*s prog %d assignment_cnt:%d",
|
||||
lvl*2, "", prn,
|
||||
command->assignment_cnt);
|
||||
if (command->group) {
|
||||
fprintf(stderr, " group %s: (argv=%p)\n",
|
||||
GRPTYPE[command->grp_type],
|
||||
@ -3046,8 +3061,9 @@ static int run_list(struct pipe *pi)
|
||||
pi->cmds[0].argv[0] = xasprintf("%s=%s", for_varname, *for_lcur++);
|
||||
pi->cmds[0].assignment_cnt = 1;
|
||||
}
|
||||
if (rword == RES_IN) /* "for v IN list;..." - "in" has no cmds anyway */
|
||||
continue;
|
||||
if (rword == RES_IN) {
|
||||
continue; /* "for v IN list;..." - "in" has no cmds anyway */
|
||||
}
|
||||
if (rword == RES_DONE) {
|
||||
continue; /* "done" has no cmds too */
|
||||
}
|
||||
@ -3603,7 +3619,8 @@ static int done_word(o_string *word, struct parse_context *ctx)
|
||||
debug_printf_parse(": checking '%s' for reserved-ness\n", word->data);
|
||||
if (reserved_word(word, ctx)) {
|
||||
o_reset(word);
|
||||
debug_printf_parse("done_word return %d\n", (ctx->ctx_res_w == RES_SNTX));
|
||||
debug_printf_parse("done_word return %d\n",
|
||||
(ctx->ctx_res_w == RES_SNTX));
|
||||
return (ctx->ctx_res_w == RES_SNTX);
|
||||
}
|
||||
}
|
||||
@ -3800,7 +3817,8 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
|
||||
|| dest->nonnull /* ""(... */
|
||||
) {
|
||||
syntax(NULL);
|
||||
debug_printf_parse("parse_group return 1: syntax error, groups and arglists don't mix\n");
|
||||
debug_printf_parse("parse_group return 1: "
|
||||
"syntax error, groups and arglists don't mix\n");
|
||||
return 1;
|
||||
}
|
||||
endch = '}';
|
||||
@ -3812,7 +3830,8 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
|
||||
/* empty ()/{} or parse error? */
|
||||
if (!pipe_list || pipe_list == ERR_PTR) {
|
||||
syntax(NULL);
|
||||
debug_printf_parse("parse_group return 1: parse_stream returned %p\n", pipe_list);
|
||||
debug_printf_parse("parse_group return 1: "
|
||||
"parse_stream returned %p\n", pipe_list);
|
||||
return 1;
|
||||
}
|
||||
command->group = pipe_list;
|
||||
@ -3910,7 +3929,7 @@ static void add_till_closing_paren(o_string *dest, struct in_str *input, bool db
|
||||
break;
|
||||
if (ch == '(')
|
||||
count++;
|
||||
if (ch == ')')
|
||||
if (ch == ')') {
|
||||
if (--count < 0) {
|
||||
if (!dbl)
|
||||
break;
|
||||
@ -3919,6 +3938,7 @@ static void add_till_closing_paren(o_string *dest, struct in_str *input, bool db
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
o_addchr(dest, ch);
|
||||
if (ch == '\'') {
|
||||
add_till_single_quote(dest, input);
|
||||
@ -3971,136 +3991,130 @@ static int handle_dollar(o_string *dest, struct in_str *input)
|
||||
o_addchr(dest, ch | quote_mask);
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
} else switch (ch) {
|
||||
case '$': /* pid */
|
||||
case '!': /* last bg pid */
|
||||
case '?': /* last exit code */
|
||||
case '#': /* number of args */
|
||||
case '*': /* args */
|
||||
case '@': /* args */
|
||||
goto make_one_char_var;
|
||||
case '{': {
|
||||
bool first_char, all_digits;
|
||||
case '$': /* pid */
|
||||
case '!': /* last bg pid */
|
||||
case '?': /* last exit code */
|
||||
case '#': /* number of args */
|
||||
case '*': /* args */
|
||||
case '@': /* args */
|
||||
goto make_one_char_var;
|
||||
case '{': {
|
||||
bool first_char, all_digits;
|
||||
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
i_getch(input);
|
||||
/* XXX maybe someone will try to escape the '}' */
|
||||
expansion = 0;
|
||||
first_char = true;
|
||||
all_digits = false;
|
||||
while (1) {
|
||||
ch = i_getch(input);
|
||||
if (ch == '}')
|
||||
break;
|
||||
|
||||
if (first_char) {
|
||||
if (ch == '#')
|
||||
/* ${#var}: length of var contents */
|
||||
goto char_ok;
|
||||
else if (isdigit(ch)) {
|
||||
all_digits = true;
|
||||
goto char_ok;
|
||||
}
|
||||
}
|
||||
|
||||
if (expansion < 2 &&
|
||||
((all_digits && !isdigit(ch)) ||
|
||||
(!all_digits && !isalnum(ch) && ch != '_')))
|
||||
{
|
||||
/* handle parameter expansions
|
||||
* http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
|
||||
*/
|
||||
if (first_char)
|
||||
goto case_default;
|
||||
switch (ch) {
|
||||
case ':': /* null modifier */
|
||||
if (expansion == 0) {
|
||||
debug_printf_parse(": null modifier\n");
|
||||
++expansion;
|
||||
break;
|
||||
}
|
||||
goto case_default;
|
||||
|
||||
#if 0 /* not implemented yet :( */
|
||||
case '#': /* remove prefix */
|
||||
case '%': /* remove suffix */
|
||||
if (expansion == 0) {
|
||||
debug_printf_parse(": remove suffix/prefix\n");
|
||||
expansion = 2;
|
||||
break;
|
||||
}
|
||||
goto case_default;
|
||||
#endif
|
||||
|
||||
case '-': /* default value */
|
||||
case '=': /* assign default */
|
||||
case '+': /* alternative */
|
||||
case '?': /* error indicate */
|
||||
debug_printf_parse(": parameter expansion\n");
|
||||
expansion = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
case_default:
|
||||
syntax("unterminated ${name}");
|
||||
debug_printf_parse("handle_dollar return 1: unterminated ${name}\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
char_ok:
|
||||
debug_printf_parse(": '%c'\n", ch);
|
||||
o_addchr(dest, ch | quote_mask);
|
||||
quote_mask = 0;
|
||||
first_char = false;
|
||||
}
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
break;
|
||||
}
|
||||
case '(': {
|
||||
i_getch(input);
|
||||
|
||||
#if ENABLE_SH_MATH_SUPPORT
|
||||
if (i_peek(input) == '(') {
|
||||
i_getch(input);
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
o_addchr(dest, /*quote_mask |*/ '+');
|
||||
add_till_closing_paren(dest, input, true);
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
i_getch(input);
|
||||
/* XXX maybe someone will try to escape the '}' */
|
||||
expansion = 0;
|
||||
first_char = true;
|
||||
all_digits = false;
|
||||
while (1) {
|
||||
ch = i_getch(input);
|
||||
if (ch == '}')
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_HUSH_TICK
|
||||
//int pos = dest->length;
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
o_addchr(dest, quote_mask | '`');
|
||||
add_till_closing_paren(dest, input, false);
|
||||
//debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
if (first_char) {
|
||||
if (ch == '#')
|
||||
/* ${#var}: length of var contents */
|
||||
goto char_ok;
|
||||
else if (isdigit(ch)) {
|
||||
all_digits = true;
|
||||
goto char_ok;
|
||||
}
|
||||
}
|
||||
|
||||
if (expansion < 2
|
||||
&& ( (all_digits && !isdigit(ch))
|
||||
|| (!all_digits && !isalnum(ch) && ch != '_')
|
||||
)
|
||||
) {
|
||||
/* handle parameter expansions
|
||||
* http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
|
||||
*/
|
||||
if (first_char)
|
||||
goto case_default;
|
||||
switch (ch) {
|
||||
case ':': /* null modifier */
|
||||
if (expansion == 0) {
|
||||
debug_printf_parse(": null modifier\n");
|
||||
++expansion;
|
||||
break;
|
||||
}
|
||||
goto case_default;
|
||||
#if 0 /* not implemented yet :( */
|
||||
case '#': /* remove prefix */
|
||||
case '%': /* remove suffix */
|
||||
if (expansion == 0) {
|
||||
debug_printf_parse(": remove suffix/prefix\n");
|
||||
expansion = 2;
|
||||
break;
|
||||
}
|
||||
goto case_default;
|
||||
#endif
|
||||
case '-': /* default value */
|
||||
case '=': /* assign default */
|
||||
case '+': /* alternative */
|
||||
case '?': /* error indicate */
|
||||
debug_printf_parse(": parameter expansion\n");
|
||||
expansion = 2;
|
||||
break;
|
||||
default:
|
||||
case_default:
|
||||
syntax("unterminated ${name}");
|
||||
debug_printf_parse("handle_dollar return 1: unterminated ${name}\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
char_ok:
|
||||
debug_printf_parse(": '%c'\n", ch);
|
||||
o_addchr(dest, ch | quote_mask);
|
||||
quote_mask = 0;
|
||||
first_char = false;
|
||||
}
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
break;
|
||||
}
|
||||
case '(': {
|
||||
i_getch(input);
|
||||
#if ENABLE_SH_MATH_SUPPORT
|
||||
if (i_peek(input) == '(') {
|
||||
i_getch(input);
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
o_addchr(dest, /*quote_mask |*/ '+');
|
||||
add_till_closing_paren(dest, input, true);
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
break;
|
||||
}
|
||||
case '_':
|
||||
i_getch(input);
|
||||
ch = i_peek(input);
|
||||
if (isalnum(ch)) { /* it's $_name or $_123 */
|
||||
ch = '_';
|
||||
goto make_var;
|
||||
}
|
||||
/* else: it's $_ */
|
||||
case '-':
|
||||
/* still unhandled, but should be eventually */
|
||||
bb_error_msg("unhandled syntax: $%c", ch);
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
o_addQchr(dest, '$');
|
||||
#endif
|
||||
#if ENABLE_HUSH_TICK
|
||||
//int pos = dest->length;
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
o_addchr(dest, quote_mask | '`');
|
||||
add_till_closing_paren(dest, input, false);
|
||||
//debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
|
||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case '_':
|
||||
i_getch(input);
|
||||
ch = i_peek(input);
|
||||
if (isalnum(ch)) { /* it's $_name or $_123 */
|
||||
ch = '_';
|
||||
goto make_var;
|
||||
}
|
||||
/* else: it's $_ */
|
||||
/* TODO: */
|
||||
/* $_ Shell or shell script name; or last cmd name */
|
||||
/* $- Option flags set by set builtin or shell options (-i etc) */
|
||||
default:
|
||||
o_addQchr(dest, '$');
|
||||
}
|
||||
debug_printf_parse("handle_dollar return 0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_stream_dquoted(o_string *dest, struct in_str *input, int dquote_end)
|
||||
static int parse_stream_dquoted(o_string *dest,
|
||||
struct in_str *input, int dquote_end)
|
||||
{
|
||||
int ch;
|
||||
int next;
|
||||
@ -4149,7 +4163,8 @@ static int parse_stream_dquoted(o_string *dest, struct in_str *input, int dquote
|
||||
}
|
||||
if (ch == '$') {
|
||||
if (handle_dollar(dest, input) != 0) {
|
||||
debug_printf_parse("parse_stream_dquoted return 1: handle_dollar returned non-0\n");
|
||||
debug_printf_parse("parse_stream_dquoted return 1: "
|
||||
"handle_dollar returned non-0\n");
|
||||
return 1;
|
||||
}
|
||||
goto again;
|
||||
@ -4196,8 +4211,8 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
|
||||
|
||||
/* Double-quote state is handled in the state variable is_in_dquote.
|
||||
* A single-quote triggers a bypass of the main loop until its mate is
|
||||
* found. When recursing, quote state is passed in via dest->o_escape. */
|
||||
|
||||
* found. When recursing, quote state is passed in via dest->o_escape.
|
||||
*/
|
||||
debug_printf_parse("parse_stream entered, end_trigger='%c'\n",
|
||||
end_trigger ? : 'X');
|
||||
|
||||
@ -4338,7 +4353,8 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
|
||||
break;
|
||||
case '$':
|
||||
if (handle_dollar(&dest, input) != 0) {
|
||||
debug_printf_parse("parse_stream parse error: handle_dollar returned non-0\n");
|
||||
debug_printf_parse("parse_stream parse error: "
|
||||
"handle_dollar returned non-0\n");
|
||||
goto parse_error;
|
||||
}
|
||||
break;
|
||||
@ -4532,8 +4548,9 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
|
||||
|
||||
/* Clean up allocated tree.
|
||||
* Samples for finding leaks on syntax error recovery path.
|
||||
* Execute them from interactive shell and watch pmap `pidof hush`.
|
||||
* while if false; then false; fi do break; done (bash accepts it)
|
||||
* Run them from interactive shell, watch pmap `pidof hush`.
|
||||
* while if false; then false; fi do break; done
|
||||
* (bash accepts it)
|
||||
* while if false; then false; fi; do break; fi
|
||||
*/
|
||||
pctx = &ctx;
|
||||
|
Loading…
Reference in New Issue
Block a user