hush: fix heredoc <<- handling.
hush-misc/heredoc2.tests testcase needs only one fix now - $var and `cmd` expancsion in heredocs function old new delta parse_redirect 265 306 +41 parse_stream 1866 1899 +33
This commit is contained in:
parent
50f3aa4547
commit
af07b7c5b6
272
shell/hush.c
272
shell/hush.c
@ -250,16 +250,6 @@ static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER;
|
|||||||
|
|
||||||
#define SPECIAL_VAR_SYMBOL 3
|
#define SPECIAL_VAR_SYMBOL 3
|
||||||
|
|
||||||
typedef enum redir_type {
|
|
||||||
REDIRECT_INVALID = 0,
|
|
||||||
REDIRECT_INPUT = 1,
|
|
||||||
REDIRECT_OVERWRITE = 2,
|
|
||||||
REDIRECT_APPEND = 3,
|
|
||||||
REDIRECT_HEREDOC = 4,
|
|
||||||
REDIRECT_IO = 5,
|
|
||||||
REDIRECT_HEREDOC2 = 6, /* REDIRECT_HEREDOC after heredoc load */
|
|
||||||
} redir_type;
|
|
||||||
|
|
||||||
/* The descrip member of this structure is only used to make
|
/* The descrip member of this structure is only used to make
|
||||||
* debugging output pretty */
|
* debugging output pretty */
|
||||||
static const struct {
|
static const struct {
|
||||||
@ -349,10 +339,24 @@ typedef struct in_str {
|
|||||||
struct redir_struct {
|
struct redir_struct {
|
||||||
struct redir_struct *next;
|
struct redir_struct *next;
|
||||||
char *rd_filename; /* filename */
|
char *rd_filename; /* filename */
|
||||||
int fd; /* file descriptor being redirected */
|
int rd_fd; /* file descriptor being redirected */
|
||||||
int dup; /* -1, or file descriptor being duplicated */
|
int rd_dup; /* -1, or file descriptor being duplicated */
|
||||||
smallint /*enum redir_type*/ rd_type;
|
smallint rd_type; /* (enum redir_type) */
|
||||||
|
/* note: for heredocs, rd_filename contains heredoc delimiter,
|
||||||
|
* and subsequently heredoc itself; and rd_dup is
|
||||||
|
* "do we need to trim leading tabs?" bool flag
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
typedef enum redir_type {
|
||||||
|
REDIRECT_INVALID = 0,
|
||||||
|
REDIRECT_INPUT = 1,
|
||||||
|
REDIRECT_OVERWRITE = 2,
|
||||||
|
REDIRECT_APPEND = 3,
|
||||||
|
REDIRECT_HEREDOC = 4,
|
||||||
|
REDIRECT_IO = 5,
|
||||||
|
REDIRECT_HEREDOC2 = 6, /* REDIRECT_HEREDOC after heredoc is loaded */
|
||||||
|
} redir_type;
|
||||||
|
|
||||||
|
|
||||||
struct command {
|
struct command {
|
||||||
pid_t pid; /* 0 if exited */
|
pid_t pid; /* 0 if exited */
|
||||||
@ -910,6 +914,11 @@ static int check_and_run_traps(int sig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_HUSH_JOB
|
#if ENABLE_HUSH_JOB
|
||||||
|
/* After [v]fork, in child: do not restore tty pgrp on xfunc death */
|
||||||
|
#define disable_restore_tty_pgrp_on_exit() (die_sleep = 0)
|
||||||
|
/* After [v]fork, in parent: do not restore tty pgrp on xfunc death */
|
||||||
|
#define enable_restore_tty_pgrp_on_exit() (die_sleep = -1)
|
||||||
|
|
||||||
/* Restores tty foreground process group, and exits.
|
/* Restores tty foreground process group, and exits.
|
||||||
* May be called as signal handler for fatal signal
|
* May be called as signal handler for fatal signal
|
||||||
* (will faithfully resend signal to itself, producing correct exit state)
|
* (will faithfully resend signal to itself, producing correct exit state)
|
||||||
@ -932,6 +941,11 @@ static void sigexit(int sig)
|
|||||||
|
|
||||||
kill_myself_with_sig(sig); /* does not return */
|
kill_myself_with_sig(sig); /* does not return */
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define disable_restore_tty_pgrp_on_exit() ((void)0)
|
||||||
|
#define enable_restore_tty_pgrp_on_exit() ((void)0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Restores tty foreground process group, and exits. */
|
/* Restores tty foreground process group, and exits. */
|
||||||
@ -1359,6 +1373,13 @@ static void o_addstr(o_string *o, const char *str)
|
|||||||
{
|
{
|
||||||
o_addblock(o, str, strlen(str));
|
o_addblock(o, str, strlen(str));
|
||||||
}
|
}
|
||||||
|
static void nommu_addchr(o_string *o, int ch)
|
||||||
|
{
|
||||||
|
if (o)
|
||||||
|
o_addchr(o, ch);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define nommu_addchr(o, str) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void o_addstr_with_NUL(o_string *o, const char *str)
|
static void o_addstr_with_NUL(o_string *o, const char *str)
|
||||||
@ -2201,8 +2222,8 @@ static void setup_heredoc(int fd, const char *heredoc)
|
|||||||
|
|
||||||
/* Okay, pipe buffer was not big enough */
|
/* Okay, pipe buffer was not big enough */
|
||||||
/* Note: we must not create a stray child (bastard? :)
|
/* Note: we must not create a stray child (bastard? :)
|
||||||
* for the unsuspecting parent process. We create a grandchild
|
* for the unsuspecting parent process. Child creates a grandchild
|
||||||
* and exit before we exec the process which consumes heredoc
|
* and exits before parent execs the process which consumes heredoc
|
||||||
* (that exec happens after we return from this function) */
|
* (that exec happens after we return from this function) */
|
||||||
pid = vfork();
|
pid = vfork();
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
@ -2217,24 +2238,20 @@ static void setup_heredoc(int fd, const char *heredoc)
|
|||||||
/* grandchild */
|
/* grandchild */
|
||||||
close(fd); /* read side of the pipe */
|
close(fd); /* read side of the pipe */
|
||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
full_write(pair.wr, heredoc, len);
|
full_write(pair.wr, heredoc, len); /* may loop or block */
|
||||||
_exit(0);
|
_exit(0);
|
||||||
#else
|
#else
|
||||||
/* Delegate blocking writes to another process */
|
/* Delegate blocking writes to another process */
|
||||||
# if ENABLE_HUSH_JOB
|
disable_restore_tty_pgrp_on_exit();
|
||||||
die_sleep = 0; /* do not restore tty pgrp on xfunc death */
|
|
||||||
# endif
|
|
||||||
xmove_fd(pair.wr, STDOUT_FILENO);
|
xmove_fd(pair.wr, STDOUT_FILENO);
|
||||||
re_execute_shell(heredoc, 1);
|
re_execute_shell(heredoc, 1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
/* parent */
|
/* parent */
|
||||||
#if ENABLE_HUSH_JOB
|
enable_restore_tty_pgrp_on_exit();
|
||||||
die_sleep = -1; /* restore tty pgrp on xfunc death */
|
|
||||||
#endif
|
|
||||||
clean_up_after_re_execute();
|
clean_up_after_re_execute();
|
||||||
close(pair.wr);
|
close(pair.wr);
|
||||||
wait(NULL); /* wiat till child has died */
|
wait(NULL); /* wait till child has died */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* squirrel != NULL means we squirrel away copies of stdin, stdout,
|
/* squirrel != NULL means we squirrel away copies of stdin, stdout,
|
||||||
@ -2247,18 +2264,18 @@ static int setup_redirects(struct command *prog, int squirrel[])
|
|||||||
|
|
||||||
for (redir = prog->redirects; redir; redir = redir->next) {
|
for (redir = prog->redirects; redir; redir = redir->next) {
|
||||||
if (redir->rd_type == REDIRECT_HEREDOC2) {
|
if (redir->rd_type == REDIRECT_HEREDOC2) {
|
||||||
if (squirrel && redir->fd < 3) {
|
if (squirrel && redir->rd_fd < 3) {
|
||||||
squirrel[redir->fd] = dup(redir->fd);
|
squirrel[redir->rd_fd] = dup(redir->rd_fd);
|
||||||
}
|
}
|
||||||
/* for REDIRECT_HEREDOC2, rd_filename holds _contents_
|
/* for REDIRECT_HEREDOC2, rd_filename holds _contents_
|
||||||
* of the heredoc */
|
* of the heredoc */
|
||||||
debug_printf_parse("set heredoc '%s'\n",
|
debug_printf_parse("set heredoc '%s'\n",
|
||||||
redir->rd_filename);
|
redir->rd_filename);
|
||||||
setup_heredoc(redir->fd, redir->rd_filename);
|
setup_heredoc(redir->rd_fd, redir->rd_filename);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (redir->dup == -1) {
|
if (redir->rd_dup == -1) {
|
||||||
char *p;
|
char *p;
|
||||||
if (redir->rd_filename == NULL) {
|
if (redir->rd_filename == NULL) {
|
||||||
/* Something went wrong in the parse.
|
/* Something went wrong in the parse.
|
||||||
@ -2277,19 +2294,19 @@ static int setup_redirects(struct command *prog, int squirrel[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
openfd = redir->dup;
|
openfd = redir->rd_dup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openfd != redir->fd) {
|
if (openfd != redir->rd_fd) {
|
||||||
if (squirrel && redir->fd < 3) {
|
if (squirrel && redir->rd_fd < 3) {
|
||||||
squirrel[redir->fd] = dup(redir->fd);
|
squirrel[redir->rd_fd] = dup(redir->rd_fd);
|
||||||
}
|
}
|
||||||
if (openfd == -3) {
|
if (openfd == -3) {
|
||||||
/* "-" means "close me" and we use -3 for that */
|
/* "-" means "close me" and we use -3 for that */
|
||||||
close(redir->fd);
|
close(redir->rd_fd);
|
||||||
} else {
|
} else {
|
||||||
dup2(openfd, redir->fd);
|
dup2(openfd, redir->rd_fd);
|
||||||
if (redir->dup == -1)
|
if (redir->rd_dup == -1)
|
||||||
close(openfd);
|
close(openfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2350,7 +2367,7 @@ static void free_pipe(struct pipe *pi, int indent)
|
|||||||
#endif
|
#endif
|
||||||
for (r = command->redirects; r; r = rnext) {
|
for (r = command->redirects; r; r = rnext) {
|
||||||
debug_printf_clean("%s redirect %d%s", indenter(indent), r->fd, redir_table[r->rd_type].descrip);
|
debug_printf_clean("%s redirect %d%s", indenter(indent), r->fd, redir_table[r->rd_type].descrip);
|
||||||
if (r->dup == -1) {
|
if (r->rd_dup == -1) {
|
||||||
/* guard against the case >$FOO, where foo is unset or blank */
|
/* guard against the case >$FOO, where foo is unset or blank */
|
||||||
if (r->rd_filename) {
|
if (r->rd_filename) {
|
||||||
debug_printf_clean(" %s\n", r->rd_filename);
|
debug_printf_clean(" %s\n", r->rd_filename);
|
||||||
@ -2358,7 +2375,7 @@ static void free_pipe(struct pipe *pi, int indent)
|
|||||||
r->rd_filename = NULL;
|
r->rd_filename = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug_printf_clean("&%d\n", r->dup);
|
debug_printf_clean("&%d\n", r->rd_dup);
|
||||||
}
|
}
|
||||||
rnext = r->next;
|
rnext = r->next;
|
||||||
free(r);
|
free(r);
|
||||||
@ -2968,7 +2985,7 @@ static int run_pipe(struct pipe *pi)
|
|||||||
command->pid = BB_MMU ? fork() : vfork();
|
command->pid = BB_MMU ? fork() : vfork();
|
||||||
if (!command->pid) { /* child */
|
if (!command->pid) { /* child */
|
||||||
#if ENABLE_HUSH_JOB
|
#if ENABLE_HUSH_JOB
|
||||||
die_sleep = 0; /* do not restore tty pgrp on xfunc death */
|
disable_restore_tty_pgrp_on_exit();
|
||||||
|
|
||||||
/* Every child adds itself to new process group
|
/* Every child adds itself to new process group
|
||||||
* with pgid == pid_of_first_child_in_pipe */
|
* with pgid == pid_of_first_child_in_pipe */
|
||||||
@ -3003,9 +3020,7 @@ static int run_pipe(struct pipe *pi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* parent or error */
|
/* parent or error */
|
||||||
#if ENABLE_HUSH_JOB
|
enable_restore_tty_pgrp_on_exit();
|
||||||
die_sleep = -1; /* restore tty pgrp on xfunc death */
|
|
||||||
#endif
|
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
/* Clean up after vforked child */
|
/* Clean up after vforked child */
|
||||||
clean_up_after_re_execute();
|
clean_up_after_re_execute();
|
||||||
@ -3914,15 +3929,11 @@ static int redirect_dup_num(o_string *as_string, struct in_str *input)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ch = i_getch(input); /* get the & */
|
ch = i_getch(input); /* get the & */
|
||||||
#if !BB_MMU
|
nommu_addchr(as_string, ch);
|
||||||
o_addchr(as_string, ch);
|
|
||||||
#endif
|
|
||||||
ch = i_peek(input);
|
ch = i_peek(input);
|
||||||
if (ch == '-') {
|
if (ch == '-') {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(as_string, ch);
|
||||||
o_addchr(as_string, ch);
|
|
||||||
#endif
|
|
||||||
return -3; /* "-" represents "close me" */
|
return -3; /* "-" represents "close me" */
|
||||||
}
|
}
|
||||||
d = 0;
|
d = 0;
|
||||||
@ -3931,9 +3942,7 @@ static int redirect_dup_num(o_string *as_string, struct in_str *input)
|
|||||||
d = d*10 + (ch-'0');
|
d = d*10 + (ch-'0');
|
||||||
ok = 1;
|
ok = 1;
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(as_string, ch);
|
||||||
o_addchr(as_string, ch);
|
|
||||||
#endif
|
|
||||||
ch = i_peek(input);
|
ch = i_peek(input);
|
||||||
}
|
}
|
||||||
if (ok) return d;
|
if (ok) return d;
|
||||||
@ -3962,8 +3971,21 @@ static int parse_redirect(struct parse_context *ctx,
|
|||||||
dup_num = redirect_dup_num(&ctx->as_string, input);
|
dup_num = redirect_dup_num(&ctx->as_string, input);
|
||||||
if (dup_num == -2)
|
if (dup_num == -2)
|
||||||
return 1; /* syntax error */
|
return 1; /* syntax error */
|
||||||
|
} else {
|
||||||
|
int ch = i_peek(input);
|
||||||
|
dup_num = (ch == '-');
|
||||||
|
if (dup_num) { /* <<-... */
|
||||||
|
ch = i_getch(input);
|
||||||
|
nommu_addchr(&ctx->as_string, ch);
|
||||||
|
ch = i_peek(input);
|
||||||
|
}
|
||||||
|
/* <<[-] word is the same as <<[-]word */
|
||||||
|
while (ch == ' ' || ch == '\t') {
|
||||||
|
ch = i_getch(input);
|
||||||
|
nommu_addchr(&ctx->as_string, ch);
|
||||||
|
ch = i_peek(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//TODO: else { check for <<-word }
|
|
||||||
|
|
||||||
if (style == REDIRECT_OVERWRITE && dup_num == -1) {
|
if (style == REDIRECT_OVERWRITE && dup_num == -1) {
|
||||||
int ch = i_peek(input);
|
int ch = i_peek(input);
|
||||||
@ -3973,9 +3995,7 @@ static int parse_redirect(struct parse_context *ctx,
|
|||||||
* >| and > are the same for now. Just eat |.
|
* >| and > are the same for now. Just eat |.
|
||||||
*/
|
*/
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(&ctx->as_string, ch);
|
||||||
o_addchr(&ctx->as_string, ch);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3988,16 +4008,16 @@ static int parse_redirect(struct parse_context *ctx,
|
|||||||
/* redir->next = NULL; */
|
/* redir->next = NULL; */
|
||||||
/* redir->rd_filename = NULL; */
|
/* redir->rd_filename = NULL; */
|
||||||
redir->rd_type = style;
|
redir->rd_type = style;
|
||||||
redir->fd = (fd == -1) ? redir_table[style].default_fd : fd;
|
redir->rd_fd = (fd == -1) ? redir_table[style].default_fd : fd;
|
||||||
|
|
||||||
debug_printf_parse("redirect type %d %s\n", redir->fd, redir_table[style].descrip);
|
debug_printf_parse("redirect type %d %s\n", redir->rd_fd, redir_table[style].descrip);
|
||||||
|
|
||||||
redir->dup = dup_num;
|
redir->rd_dup = dup_num;
|
||||||
if (dup_num != -1) {
|
if (style != REDIRECT_HEREDOC && dup_num != -1) {
|
||||||
/* Erik had a check here that the file descriptor in question
|
/* Erik had a check here that the file descriptor in question
|
||||||
* is legit; I postpone that to "run time"
|
* is legit; I postpone that to "run time"
|
||||||
* A "-" representation of "close me" shows up as a -3 here */
|
* A "-" representation of "close me" shows up as a -3 here */
|
||||||
debug_printf_parse("duplicating redirect '%d>&%d'\n", redir->fd, redir->dup);
|
debug_printf_parse("duplicating redirect '%d>&%d'\n", redir->rd_fd, redir->rd_dup);
|
||||||
} else {
|
} else {
|
||||||
/* Set ctx->pending_redirect, so we know what to do at the
|
/* Set ctx->pending_redirect, so we know what to do at the
|
||||||
* end of the next parsed word. */
|
* end of the next parsed word. */
|
||||||
@ -4039,28 +4059,45 @@ static int redirect_opt_num(o_string *o)
|
|||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: add NOMMU as_string fill
|
#if BB_MMU
|
||||||
static char *fetch_till_str(struct in_str *input, const char *word)
|
#define fetch_till_str(as_string, input, word, skip_tabs) \
|
||||||
|
fetch_till_str(input, word, skip_tabs)
|
||||||
|
#endif
|
||||||
|
static char *fetch_till_str(o_string *as_string,
|
||||||
|
struct in_str *input,
|
||||||
|
const char *word,
|
||||||
|
int skip_tabs)
|
||||||
{
|
{
|
||||||
o_string heredoc = NULL_O_STRING;
|
o_string heredoc = NULL_O_STRING;
|
||||||
int past_EOL = 0;
|
int past_EOL = 0;
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
|
goto jump_in;
|
||||||
while (1) {
|
while (1) {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
if (ch == EOF) {
|
nommu_addchr(as_string, ch);
|
||||||
o_free_unsafe(&heredoc);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (ch == '\n') {
|
if (ch == '\n') {
|
||||||
if (strcmp(heredoc.data + past_EOL, word) == 0) {
|
if (strcmp(heredoc.data + past_EOL, word) == 0) {
|
||||||
heredoc.data[past_EOL] = '\0';
|
heredoc.data[past_EOL] = '\0';
|
||||||
debug_printf_parse("parsed heredoc '%s'\n", heredoc.data);
|
debug_printf_parse("parsed heredoc '%s'\n", heredoc.data);
|
||||||
return heredoc.data;
|
return heredoc.data;
|
||||||
}
|
}
|
||||||
past_EOL = heredoc.length + 1;
|
do {
|
||||||
|
o_addchr(&heredoc, ch);
|
||||||
|
past_EOL = heredoc.length;
|
||||||
|
jump_in:
|
||||||
|
do {
|
||||||
|
ch = i_getch(input);
|
||||||
|
nommu_addchr(as_string, ch);
|
||||||
|
} while (skip_tabs && ch == '\t');
|
||||||
|
} while (ch == '\n');
|
||||||
|
}
|
||||||
|
if (ch == EOF) {
|
||||||
|
o_free_unsafe(&heredoc);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
o_addchr(&heredoc, ch);
|
o_addchr(&heredoc, ch);
|
||||||
|
nommu_addchr(as_string, ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4076,25 +4113,27 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_
|
|||||||
pi->num_cmds,
|
pi->num_cmds,
|
||||||
cmd->argv ? cmd->argv[0] : "NONE");
|
cmd->argv ? cmd->argv[0] : "NONE");
|
||||||
for (i = 0; i < pi->num_cmds; i++) {
|
for (i = 0; i < pi->num_cmds; i++) {
|
||||||
struct redir_struct *redirect = cmd->redirects;
|
struct redir_struct *redir = cmd->redirects;
|
||||||
|
|
||||||
debug_printf_parse("fetch_heredocs: %d cmd argv0:'%s'\n",
|
debug_printf_parse("fetch_heredocs: %d cmd argv0:'%s'\n",
|
||||||
i, cmd->argv ? cmd->argv[0] : "NONE");
|
i, cmd->argv ? cmd->argv[0] : "NONE");
|
||||||
while (redirect) {
|
while (redir) {
|
||||||
if (redirect->rd_type == REDIRECT_HEREDOC) {
|
if (redir->rd_type == REDIRECT_HEREDOC) {
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if (heredoc_cnt <= 0)
|
if (heredoc_cnt <= 0)
|
||||||
return 1; /* error */
|
return 1; /* error */
|
||||||
redirect->rd_type = REDIRECT_HEREDOC2;
|
redir->rd_type = REDIRECT_HEREDOC2;
|
||||||
p = fetch_till_str(input, redirect->rd_filename);
|
/* redir->dup is (ab)used to indicate <<- */
|
||||||
|
p = fetch_till_str(&ctx->as_string, input,
|
||||||
|
redir->rd_filename, redir->rd_dup);
|
||||||
if (!p)
|
if (!p)
|
||||||
return 1; /* unexpected EOF */
|
return 1; /* unexpected EOF */
|
||||||
free(redirect->rd_filename);
|
free(redir->rd_filename);
|
||||||
redirect->rd_filename = p;
|
redir->rd_filename = p;
|
||||||
heredoc_cnt--;
|
heredoc_cnt--;
|
||||||
}
|
}
|
||||||
redirect = redirect->next;
|
redir = redir->next;
|
||||||
}
|
}
|
||||||
cmd++;
|
cmd++;
|
||||||
}
|
}
|
||||||
@ -4126,9 +4165,7 @@ static FILE *generate_stream_from_string(const char *s)
|
|||||||
bb_perror_msg_and_die(BB_MMU ? "fork" : "vfork");
|
bb_perror_msg_and_die(BB_MMU ? "fork" : "vfork");
|
||||||
|
|
||||||
if (pid == 0) { /* child */
|
if (pid == 0) { /* child */
|
||||||
#if ENABLE_HUSH_JOB
|
disable_restore_tty_pgrp_on_exit();
|
||||||
die_sleep = 0; /* do not restore tty pgrp on xfunc death */
|
|
||||||
#endif
|
|
||||||
/* Process substitution is not considered to be usual
|
/* Process substitution is not considered to be usual
|
||||||
* 'command execution'.
|
* 'command execution'.
|
||||||
* SUSv3 says ctrl-Z should be ignored, ctrl-C should not.
|
* SUSv3 says ctrl-Z should be ignored, ctrl-C should not.
|
||||||
@ -4157,9 +4194,7 @@ static FILE *generate_stream_from_string(const char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* parent */
|
/* parent */
|
||||||
#if ENABLE_HUSH_JOB
|
enable_restore_tty_pgrp_on_exit();
|
||||||
die_sleep = -1; /* restore tty pgrp on xfunc death */
|
|
||||||
#endif
|
|
||||||
clean_up_after_re_execute();
|
clean_up_after_re_execute();
|
||||||
close(channel[1]);
|
close(channel[1]);
|
||||||
pf = fdopen(channel[0], "r");
|
pf = fdopen(channel[0], "r");
|
||||||
@ -4409,9 +4444,7 @@ static int handle_dollar(o_string *as_string,
|
|||||||
debug_printf_parse("handle_dollar entered: ch='%c'\n", ch);
|
debug_printf_parse("handle_dollar entered: ch='%c'\n", ch);
|
||||||
if (isalpha(ch)) {
|
if (isalpha(ch)) {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(as_string, ch);
|
||||||
if (as_string) o_addchr(as_string, ch);
|
|
||||||
#endif
|
|
||||||
make_var:
|
make_var:
|
||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -4422,17 +4455,13 @@ static int handle_dollar(o_string *as_string,
|
|||||||
if (!isalnum(ch) && ch != '_')
|
if (!isalnum(ch) && ch != '_')
|
||||||
break;
|
break;
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(as_string, ch);
|
||||||
if (as_string) o_addchr(as_string, ch);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
} else if (isdigit(ch)) {
|
} else if (isdigit(ch)) {
|
||||||
make_one_char_var:
|
make_one_char_var:
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(as_string, ch);
|
||||||
if (as_string) o_addchr(as_string, ch);
|
|
||||||
#endif
|
|
||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
debug_printf_parse(": '%c'\n", ch);
|
debug_printf_parse(": '%c'\n", ch);
|
||||||
o_addchr(dest, ch | quote_mask);
|
o_addchr(dest, ch | quote_mask);
|
||||||
@ -4450,18 +4479,14 @@ static int handle_dollar(o_string *as_string,
|
|||||||
|
|
||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(as_string, ch);
|
||||||
if (as_string) o_addchr(as_string, ch);
|
|
||||||
#endif
|
|
||||||
/* XXX maybe someone will try to escape the '}' */
|
/* XXX maybe someone will try to escape the '}' */
|
||||||
expansion = 0;
|
expansion = 0;
|
||||||
first_char = true;
|
first_char = true;
|
||||||
all_digits = false;
|
all_digits = false;
|
||||||
while (1) {
|
while (1) {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(as_string, ch);
|
||||||
if (as_string) o_addchr(as_string, ch);
|
|
||||||
#endif
|
|
||||||
if (ch == '}')
|
if (ch == '}')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -4530,15 +4555,11 @@ static int handle_dollar(o_string *as_string,
|
|||||||
int pos;
|
int pos;
|
||||||
# endif
|
# endif
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
# if !BB_MMU
|
nommu_addchr(as_string, ch);
|
||||||
if (as_string) o_addchr(as_string, ch);
|
|
||||||
# endif
|
|
||||||
# if ENABLE_SH_MATH_SUPPORT
|
# if ENABLE_SH_MATH_SUPPORT
|
||||||
if (i_peek(input) == '(') {
|
if (i_peek(input) == '(') {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
# if !BB_MMU
|
nommu_addchr(as_string, ch);
|
||||||
if (as_string) o_addchr(as_string, ch);
|
|
||||||
# endif
|
|
||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
o_addchr(dest, /*quote_mask |*/ '+');
|
o_addchr(dest, /*quote_mask |*/ '+');
|
||||||
# if !BB_MMU
|
# if !BB_MMU
|
||||||
@ -4578,9 +4599,7 @@ static int handle_dollar(o_string *as_string,
|
|||||||
#endif
|
#endif
|
||||||
case '_':
|
case '_':
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(as_string, ch);
|
||||||
if (as_string) o_addchr(as_string, ch);
|
|
||||||
#endif
|
|
||||||
ch = i_peek(input);
|
ch = i_peek(input);
|
||||||
if (isalnum(ch)) { /* it's $_name or $_123 */
|
if (isalnum(ch)) { /* it's $_name or $_123 */
|
||||||
ch = '_';
|
ch = '_';
|
||||||
@ -4611,9 +4630,8 @@ static int parse_stream_dquoted(o_string *as_string,
|
|||||||
|
|
||||||
again:
|
again:
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
if (ch != EOF)
|
||||||
if (as_string && ch != EOF) o_addchr(as_string, ch);
|
nommu_addchr(as_string, ch);
|
||||||
#endif
|
|
||||||
if (ch == dquote_end) { /* may be only '"' or EOF */
|
if (ch == dquote_end) { /* may be only '"' or EOF */
|
||||||
dest->nonnull = 1;
|
dest->nonnull = 1;
|
||||||
if (dest->o_assignment == NOT_ASSIGNMENT)
|
if (dest->o_assignment == NOT_ASSIGNMENT)
|
||||||
@ -4769,9 +4787,7 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
#endif
|
#endif
|
||||||
return pi;
|
return pi;
|
||||||
}
|
}
|
||||||
#if !BB_MMU
|
nommu_addchr(&ctx.as_string, ch);
|
||||||
o_addchr(&ctx.as_string, ch);
|
|
||||||
#endif
|
|
||||||
is_ifs = strchr(G.ifs, ch);
|
is_ifs = strchr(G.ifs, ch);
|
||||||
is_special = strchr("<>;&|(){}#'" /* special outside of "str" */
|
is_special = strchr("<>;&|(){}#'" /* special outside of "str" */
|
||||||
"\\$\"" USE_HUSH_TICK("`") /* always special */
|
"\\$\"" USE_HUSH_TICK("`") /* always special */
|
||||||
@ -4882,10 +4898,8 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
i_getch(input);
|
i_getch(input);
|
||||||
/* note: we do not add it to &ctx.as_string */
|
/* note: we do not add it to &ctx.as_string */
|
||||||
}
|
}
|
||||||
#if !BB_MMU
|
|
||||||
//TODO: go back one char?
|
//TODO: go back one char?
|
||||||
o_addchr(&ctx.as_string, '\n');
|
nommu_addchr(&ctx.as_string, '\n');
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
o_addQchr(&dest, ch);
|
o_addQchr(&dest, ch);
|
||||||
}
|
}
|
||||||
@ -4898,9 +4912,7 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
o_addchr(&dest, '\\');
|
o_addchr(&dest, '\\');
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
o_addchr(&dest, ch);
|
o_addchr(&dest, ch);
|
||||||
#if !BB_MMU
|
nommu_addchr(&ctx.as_string, ch);
|
||||||
o_addchr(&ctx.as_string, ch);
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case '$':
|
case '$':
|
||||||
if (handle_dollar(&ctx.as_string, &dest, input) != 0) {
|
if (handle_dollar(&ctx.as_string, &dest, input) != 0) {
|
||||||
@ -4917,9 +4929,7 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
syntax("unterminated '");
|
syntax("unterminated '");
|
||||||
goto parse_error;
|
goto parse_error;
|
||||||
}
|
}
|
||||||
#if !BB_MMU
|
nommu_addchr(&ctx.as_string, ch);
|
||||||
o_addchr(&ctx.as_string, ch);
|
|
||||||
#endif
|
|
||||||
if (ch == '\'')
|
if (ch == '\'')
|
||||||
break;
|
break;
|
||||||
if (dest.o_assignment == NOT_ASSIGNMENT)
|
if (dest.o_assignment == NOT_ASSIGNMENT)
|
||||||
@ -4954,9 +4964,7 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
if (next == '>') {
|
if (next == '>') {
|
||||||
redir_style = REDIRECT_APPEND;
|
redir_style = REDIRECT_APPEND;
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(&ctx.as_string, ch);
|
||||||
o_addchr(&ctx.as_string, ch);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
else if (next == '(') {
|
else if (next == '(') {
|
||||||
@ -4978,15 +4986,11 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
heredoc_cnt++;
|
heredoc_cnt++;
|
||||||
debug_printf_parse("++heredoc_cnt=%d\n", heredoc_cnt);
|
debug_printf_parse("++heredoc_cnt=%d\n", heredoc_cnt);
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(&ctx.as_string, ch);
|
||||||
o_addchr(&ctx.as_string, ch);
|
|
||||||
#endif
|
|
||||||
} else if (next == '>') {
|
} else if (next == '>') {
|
||||||
redir_style = REDIRECT_IO;
|
redir_style = REDIRECT_IO;
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(&ctx.as_string, ch);
|
||||||
o_addchr(&ctx.as_string, ch);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
else if (next == '(') {
|
else if (next == '(') {
|
||||||
@ -5013,9 +5017,7 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
if (ch != ';')
|
if (ch != ';')
|
||||||
break;
|
break;
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(&ctx.as_string, ch);
|
||||||
o_addchr(&ctx.as_string, ch);
|
|
||||||
#endif
|
|
||||||
if (ctx.ctx_res_w == RES_CASEI) {
|
if (ctx.ctx_res_w == RES_CASEI) {
|
||||||
ctx.ctx_dsemicolon = 1;
|
ctx.ctx_dsemicolon = 1;
|
||||||
ctx.ctx_res_w = RES_MATCH;
|
ctx.ctx_res_w = RES_MATCH;
|
||||||
@ -5034,9 +5036,7 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
}
|
}
|
||||||
if (next == '&') {
|
if (next == '&') {
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(&ctx.as_string, ch);
|
||||||
o_addchr(&ctx.as_string, ch);
|
|
||||||
#endif
|
|
||||||
done_pipe(&ctx, PIPE_AND);
|
done_pipe(&ctx, PIPE_AND);
|
||||||
} else {
|
} else {
|
||||||
done_pipe(&ctx, PIPE_BG);
|
done_pipe(&ctx, PIPE_BG);
|
||||||
@ -5052,9 +5052,7 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
#endif
|
#endif
|
||||||
if (next == '|') { /* || */
|
if (next == '|') { /* || */
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
#if !BB_MMU
|
nommu_addchr(&ctx.as_string, ch);
|
||||||
o_addchr(&ctx.as_string, ch);
|
|
||||||
#endif
|
|
||||||
done_pipe(&ctx, PIPE_OR);
|
done_pipe(&ctx, PIPE_OR);
|
||||||
} else {
|
} else {
|
||||||
/* we could pick up a file descriptor choice here
|
/* we could pick up a file descriptor choice here
|
||||||
@ -5537,7 +5535,7 @@ int hush_main(int argc, char **argv)
|
|||||||
tcsetpgrp(G_interactive_fd, getpid());
|
tcsetpgrp(G_interactive_fd, getpid());
|
||||||
/* -1 is special - makes xfuncs longjmp, not exit
|
/* -1 is special - makes xfuncs longjmp, not exit
|
||||||
* (we reset die_sleep = 0 whereever we [v]fork) */
|
* (we reset die_sleep = 0 whereever we [v]fork) */
|
||||||
die_sleep = -1;
|
enable_restore_tty_pgrp_on_exit(); /* sets die_sleep = -1 */
|
||||||
if (setjmp(die_jmp)) {
|
if (setjmp(die_jmp)) {
|
||||||
/* xfunc has failed! die die die */
|
/* xfunc has failed! die die die */
|
||||||
hush_exit(xfunc_error_retval);
|
hush_exit(xfunc_error_retval);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user