diff options
| -rw-r--r-- | shell/ash.c | 90 | ||||
| -rw-r--r-- | shell/ash_test/ash-heredoc/herestring1.right | 33 | ||||
| -rwxr-xr-x | shell/ash_test/ash-heredoc/herestring1.tests | 35 | ||||
| -rw-r--r-- | shell/hush.c | 16 |
4 files changed, 139 insertions, 35 deletions
diff --git a/shell/ash.c b/shell/ash.c index 773de79f5..61f10d74e 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -431,7 +431,7 @@ struct forkshell { | |||
| 431 | int fd[3]; | 431 | int fd[3]; |
| 432 | union node *n; | 432 | union node *n; |
| 433 | char **argv; | 433 | char **argv; |
| 434 | char *path; | 434 | const char *path; |
| 435 | } ALIGN64; | 435 | } ALIGN64; |
| 436 | 436 | ||
| 437 | enum { | 437 | enum { |
| @@ -1181,14 +1181,15 @@ static const char dolatstr[] ALIGN1 = { | |||
| 1181 | #endif | 1181 | #endif |
| 1182 | #define NCLOBBER 18 | 1182 | #define NCLOBBER 18 |
| 1183 | #define NFROM 19 | 1183 | #define NFROM 19 |
| 1184 | #define NFROMTO 20 | 1184 | #define NFROMSTR 20 |
| 1185 | #define NAPPEND 21 | 1185 | #define NFROMTO 21 |
| 1186 | #define NTOFD 22 | 1186 | #define NAPPEND 22 |
| 1187 | #define NFROMFD 23 | 1187 | #define NTOFD 23 |
| 1188 | #define NHERE 24 | 1188 | #define NFROMFD 24 |
| 1189 | #define NXHERE 25 | 1189 | #define NHERE 25 |
| 1190 | #define NNOT 26 | 1190 | #define NXHERE 26 |
| 1191 | #define N_NUMBER 27 | 1191 | #define NNOT 27 |
| 1192 | #define N_NUMBER 28 | ||
| 1192 | 1193 | ||
| 1193 | union node; | 1194 | union node; |
| 1194 | 1195 | ||
| @@ -1619,6 +1620,7 @@ shcmd(union node *cmd, FILE *fp) | |||
| 1619 | #endif | 1620 | #endif |
| 1620 | case NTOFD: s = ">&"; dftfd = 1; break; | 1621 | case NTOFD: s = ">&"; dftfd = 1; break; |
| 1621 | case NFROM: s = "<"; break; | 1622 | case NFROM: s = "<"; break; |
| 1623 | case NFROMSTR: s = "<<<"; break; | ||
| 1622 | case NFROMFD: s = "<&"; break; | 1624 | case NFROMFD: s = "<&"; break; |
| 1623 | case NFROMTO: s = "<>"; break; | 1625 | case NFROMTO: s = "<>"; break; |
| 1624 | default: s = "*error*"; break; | 1626 | default: s = "*error*"; break; |
| @@ -5881,6 +5883,9 @@ cmdtxt(union node *n) | |||
| 5881 | case NXHERE: | 5883 | case NXHERE: |
| 5882 | p = "<<..."; | 5884 | p = "<<..."; |
| 5883 | goto dotail2; | 5885 | goto dotail2; |
| 5886 | case NFROMSTR: | ||
| 5887 | p = "<<<"; | ||
| 5888 | goto dotail2; | ||
| 5884 | case NCASE: | 5889 | case NCASE: |
| 5885 | cmdputs("case "); | 5890 | cmdputs("case "); |
| 5886 | cmdputs(n->ncase.expr->narg.text); | 5891 | cmdputs(n->ncase.expr->narg.text); |
| @@ -6371,26 +6376,11 @@ stoppedjobs(void) | |||
| 6371 | * data to a pipe. If the document is short, we can stuff the data in | 6376 | * data to a pipe. If the document is short, we can stuff the data in |
| 6372 | * the pipe without forking. | 6377 | * the pipe without forking. |
| 6373 | */ | 6378 | */ |
| 6374 | /* openhere needs this forward reference */ | ||
| 6375 | static void expandhere(union node *arg); | ||
| 6376 | static int | 6379 | static int |
| 6377 | openhere(union node *redir) | 6380 | write2pipe(int pip[2], const char *p, size_t len) |
| 6378 | { | 6381 | { |
| 6379 | char *p; | ||
| 6380 | int pip[2]; | ||
| 6381 | size_t len = 0; | ||
| 6382 | IF_PLATFORM_MINGW32(struct forkshell fs); | 6382 | IF_PLATFORM_MINGW32(struct forkshell fs); |
| 6383 | 6383 | ||
| 6384 | if (pipe(pip) < 0) | ||
| 6385 | ash_msg_and_raise_perror("can't create pipe"); | ||
| 6386 | |||
| 6387 | p = redir->nhere.doc->narg.text; | ||
| 6388 | if (redir->type == NXHERE) { | ||
| 6389 | expandhere(redir->nhere.doc); | ||
| 6390 | p = stackblock(); | ||
| 6391 | } | ||
| 6392 | |||
| 6393 | len = strlen(p); | ||
| 6394 | if (len <= PIPE_BUF) { | 6384 | if (len <= PIPE_BUF) { |
| 6395 | xwrite(pip[1], p, len); | 6385 | xwrite(pip[1], p, len); |
| 6396 | goto out; | 6386 | goto out; |
| @@ -6421,6 +6411,42 @@ openhere(union node *redir) | |||
| 6421 | return pip[0]; | 6411 | return pip[0]; |
| 6422 | } | 6412 | } |
| 6423 | 6413 | ||
| 6414 | /* openhere needs this forward reference */ | ||
| 6415 | static void expandhere(union node *arg); | ||
| 6416 | static int | ||
| 6417 | openhere(union node *redir) | ||
| 6418 | { | ||
| 6419 | char *p; | ||
| 6420 | int pip[2]; | ||
| 6421 | |||
| 6422 | if (pipe(pip) < 0) | ||
| 6423 | ash_msg_and_raise_perror("can't create pipe"); | ||
| 6424 | |||
| 6425 | p = redir->nhere.doc->narg.text; | ||
| 6426 | if (redir->type == NXHERE) { | ||
| 6427 | expandhere(redir->nhere.doc); | ||
| 6428 | p = stackblock(); | ||
| 6429 | } | ||
| 6430 | |||
| 6431 | return write2pipe(pip, p, strlen(p)); | ||
| 6432 | } | ||
| 6433 | |||
| 6434 | static int | ||
| 6435 | openherestr(char *str) | ||
| 6436 | { | ||
| 6437 | int pip[2]; | ||
| 6438 | size_t len; | ||
| 6439 | |||
| 6440 | if (pipe(pip) < 0) | ||
| 6441 | ash_msg_and_raise_perror("can't create pipe"); | ||
| 6442 | |||
| 6443 | len = strlen(str); | ||
| 6444 | str[len] = '\n'; | ||
| 6445 | write2pipe(pip, str, len + 1); | ||
| 6446 | str[len] = '\0'; | ||
| 6447 | return pip[0]; | ||
| 6448 | } | ||
| 6449 | |||
| 6424 | static int | 6450 | static int |
| 6425 | openredirect(union node *redir) | 6451 | openredirect(union node *redir) |
| 6426 | { | 6452 | { |
| @@ -6439,6 +6465,9 @@ openredirect(union node *redir) | |||
| 6439 | lseek(f, 0, SEEK_END); | 6465 | lseek(f, 0, SEEK_END); |
| 6440 | #endif | 6466 | #endif |
| 6441 | break; | 6467 | break; |
| 6468 | case NFROMSTR: | ||
| 6469 | f = openherestr(redir->nfile.expfname); | ||
| 6470 | break; | ||
| 6442 | case NFROMTO: | 6471 | case NFROMTO: |
| 6443 | flags = O_RDWR|O_CREAT; | 6472 | flags = O_RDWR|O_CREAT; |
| 6444 | goto do_open; | 6473 | goto do_open; |
| @@ -10176,6 +10205,7 @@ calcsize(int funcblocksize, union node *n) | |||
| 10176 | #endif | 10205 | #endif |
| 10177 | case NCLOBBER: | 10206 | case NCLOBBER: |
| 10178 | case NFROM: | 10207 | case NFROM: |
| 10208 | case NFROMSTR: | ||
| 10179 | case NFROMTO: | 10209 | case NFROMTO: |
| 10180 | case NAPPEND: | 10210 | case NAPPEND: |
| 10181 | funcblocksize = calcsize(funcblocksize, n->nfile.fname); | 10211 | funcblocksize = calcsize(funcblocksize, n->nfile.fname); |
| @@ -10392,6 +10422,7 @@ copynode(union node *n) | |||
| 10392 | #endif | 10422 | #endif |
| 10393 | case NCLOBBER: | 10423 | case NCLOBBER: |
| 10394 | case NFROM: | 10424 | case NFROM: |
| 10425 | case NFROMSTR: | ||
| 10395 | case NFROMTO: | 10426 | case NFROMTO: |
| 10396 | case NAPPEND: | 10427 | case NAPPEND: |
| 10397 | new->nfile.fname = copynode(n->nfile.fname); | 10428 | new->nfile.fname = copynode(n->nfile.fname); |
| @@ -10929,6 +10960,7 @@ expredir(union node *n) | |||
| 10929 | switch (redir->type) { | 10960 | switch (redir->type) { |
| 10930 | case NFROMTO: | 10961 | case NFROMTO: |
| 10931 | case NFROM: | 10962 | case NFROM: |
| 10963 | case NFROMSTR: | ||
| 10932 | case NTO: | 10964 | case NTO: |
| 10933 | #if BASH_REDIR_OUTPUT | 10965 | #if BASH_REDIR_OUTPUT |
| 10934 | case NTO2: | 10966 | case NTO2: |
| @@ -14306,6 +14338,11 @@ parseredir: { | |||
| 14306 | c = pgetc_eatbnl(); | 14338 | c = pgetc_eatbnl(); |
| 14307 | switch (c) { | 14339 | switch (c) { |
| 14308 | case '<': | 14340 | case '<': |
| 14341 | c = pgetc_eatbnl(); | ||
| 14342 | if (c == '<') { | ||
| 14343 | np->type = NFROMSTR; | ||
| 14344 | break; | ||
| 14345 | } | ||
| 14309 | if (sizeof(struct nfile) != sizeof(struct nhere)) { | 14346 | if (sizeof(struct nfile) != sizeof(struct nhere)) { |
| 14310 | np = stzalloc(sizeof(struct nhere)); | 14347 | np = stzalloc(sizeof(struct nhere)); |
| 14311 | /*np->nfile.fd = 0; - stzalloc did it */ | 14348 | /*np->nfile.fd = 0; - stzalloc did it */ |
| @@ -14313,7 +14350,6 @@ parseredir: { | |||
| 14313 | np->type = NHERE; | 14350 | np->type = NHERE; |
| 14314 | heredoc = stzalloc(sizeof(struct heredoc)); | 14351 | heredoc = stzalloc(sizeof(struct heredoc)); |
| 14315 | heredoc->here = np; | 14352 | heredoc->here = np; |
| 14316 | c = pgetc_eatbnl(); | ||
| 14317 | if (c == '-') { | 14353 | if (c == '-') { |
| 14318 | heredoc->striptabs = 1; | 14354 | heredoc->striptabs = 1; |
| 14319 | } else { | 14355 | } else { |
| @@ -16768,7 +16804,7 @@ forkshell_shellexec(struct forkshell *fs) | |||
| 16768 | { | 16804 | { |
| 16769 | int idx = fs->fd[0]; | 16805 | int idx = fs->fd[0]; |
| 16770 | char **argv = fs->argv; | 16806 | char **argv = fs->argv; |
| 16771 | char *path = fs->path; | 16807 | const char *path = fs->path; |
| 16772 | 16808 | ||
| 16773 | FORCEINTON; | 16809 | FORCEINTON; |
| 16774 | shellexec(argv[0], argv, path, idx, TRUE); | 16810 | shellexec(argv[0], argv, path, idx, TRUE); |
diff --git a/shell/ash_test/ash-heredoc/herestring1.right b/shell/ash_test/ash-heredoc/herestring1.right new file mode 100644 index 000000000..555937daa --- /dev/null +++ b/shell/ash_test/ash-heredoc/herestring1.right | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | one | ||
| 2 | _two | ||
| 3 | \_three | ||
| 4 | \_four | ||
| 5 | \_two | ||
| 6 | \_three | ||
| 7 | \\_four | ||
| 8 | two_newlines | ||
| 9 | |||
| 10 | /bin/c* | ||
| 11 | star_* | ||
| 12 | star_* | ||
| 13 | star_* | ||
| 14 | star_\* | ||
| 15 | star_* | ||
| 16 | star_\* | ||
| 17 | line1 | ||
| 18 | line2 | ||
| 19 | line3 | ||
| 20 | line1 | ||
| 21 | line2 | ||
| 22 | line3 | ||
| 23 | 512 | ||
| 24 | 256 | ||
| 25 | 128 | ||
| 26 | 64 | ||
| 27 | 32 | ||
| 28 | 16 | ||
| 29 | 8 | ||
| 30 | 4 | ||
| 31 | 2 | ||
| 32 | v-$a-\t-\-\"-\x-`-\--\z-\*-\?- | ||
| 33 | v-$a-\t-\-"-\x-`-\--\z-\*-\?- | ||
diff --git a/shell/ash_test/ash-heredoc/herestring1.tests b/shell/ash_test/ash-heredoc/herestring1.tests new file mode 100755 index 000000000..fb7bd0dda --- /dev/null +++ b/shell/ash_test/ash-heredoc/herestring1.tests | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | cat <<<one | ||
| 2 | cat <<<\_two | ||
| 3 | cat <<<"\_three" | ||
| 4 | cat <<<'\_four' | ||
| 5 | cat <<<\\_two | ||
| 6 | cat <<<"\\_three" | ||
| 7 | cat <<<'\\_four' | ||
| 8 | |||
| 9 | cat <<<$'two_newlines\n' | ||
| 10 | |||
| 11 | cat <<</bin/c* | ||
| 12 | |||
| 13 | cat <<<star_* | ||
| 14 | cat <<<star_\* | ||
| 15 | cat <<<"star_*" | ||
| 16 | cat <<<"star_\*" | ||
| 17 | cat <<<'star_*' | ||
| 18 | cat <<<'star_\*' | ||
| 19 | |||
| 20 | var=$'line1 | ||
| 21 | line2 | ||
| 22 | line3' | ||
| 23 | |||
| 24 | cat <<<$var | ||
| 25 | |||
| 26 | cat <<<"$var" | ||
| 27 | |||
| 28 | i=10 | ||
| 29 | until test $((--i)) = 0; do | ||
| 30 | cat <<<$((2**i)) | ||
| 31 | done | ||
| 32 | |||
| 33 | a=qwerty | ||
| 34 | cat <<<`echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'` | ||
| 35 | cat <<<"`echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'`" | ||
diff --git a/shell/hush.c b/shell/hush.c index 226a6d68f..da0db7948 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -683,6 +683,7 @@ struct command { | |||
| 683 | # endif | 683 | # endif |
| 684 | # define CMD_FUNCDEF 5 | 684 | # define CMD_FUNCDEF 5 |
| 685 | #endif | 685 | #endif |
| 686 | /* ^^^ if you change this, update CMDTYPE[] array too */ | ||
| 686 | 687 | ||
| 687 | smalluint cmd_exitcode; | 688 | smalluint cmd_exitcode; |
| 688 | /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */ | 689 | /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */ |
| @@ -3947,7 +3948,7 @@ static void debug_print_tree(struct pipe *pi, int lvl) | |||
| 3947 | # endif | 3948 | # endif |
| 3948 | # if ENABLE_HUSH_CASE | 3949 | # if ENABLE_HUSH_CASE |
| 3949 | [RES_CASE ] = "CASE" , | 3950 | [RES_CASE ] = "CASE" , |
| 3950 | [RES_CASE_IN] = "CASE_IN" , | 3951 | [RES_CASE_IN] = "CASE_IN", |
| 3951 | [RES_MATCH] = "MATCH", | 3952 | [RES_MATCH] = "MATCH", |
| 3952 | [RES_CASE_BODY] = "CASE_BODY", | 3953 | [RES_CASE_BODY] = "CASE_BODY", |
| 3953 | [RES_ESAC ] = "ESAC" , | 3954 | [RES_ESAC ] = "ESAC" , |
| @@ -3956,11 +3957,13 @@ static void debug_print_tree(struct pipe *pi, int lvl) | |||
| 3956 | [RES_SNTX ] = "SNTX" , | 3957 | [RES_SNTX ] = "SNTX" , |
| 3957 | }; | 3958 | }; |
| 3958 | static const char *const CMDTYPE[] ALIGN_PTR = { | 3959 | static const char *const CMDTYPE[] ALIGN_PTR = { |
| 3959 | "{}", | 3960 | "{}", //CMD_NORMAL |
| 3960 | "()", | 3961 | "()", //CMD_SUBSHELL |
| 3961 | "[noglob]", | 3962 | "[test2]", //CMD_TEST2_SINGLEWORD_NOGLOB |
| 3963 | "[noglob]", //CMD_SINGLEWORD_NOGLOB | ||
| 3962 | # if ENABLE_HUSH_FUNCTIONS | 3964 | # if ENABLE_HUSH_FUNCTIONS |
| 3963 | "func()", | 3965 | "func()", //CMD_FUNCTION_KWORD |
| 3966 | "funcdef", //CMD_FUNCDEF | ||
| 3964 | # endif | 3967 | # endif |
| 3965 | }; | 3968 | }; |
| 3966 | 3969 | ||
| @@ -12988,9 +12991,6 @@ static int FAST_FUNC builtin_alias(char **argv) | |||
| 12988 | } | 12991 | } |
| 12989 | 12992 | ||
| 12990 | while (*++argv) { | 12993 | while (*++argv) { |
| 12991 | /* The characters /, $, `, = and any of the shell | ||
| 12992 | * metacharacters or quoting characters | ||
| 12993 | * may not appear in an alias name */ | ||
| 12994 | char *eq = end_of_alias_name(*argv); | 12994 | char *eq = end_of_alias_name(*argv); |
| 12995 | if (*eq == '=' && eq != *argv) { | 12995 | if (*eq == '=' && eq != *argv) { |
| 12996 | /* alias NAME=VALUE */ | 12996 | /* alias NAME=VALUE */ |
