diff options
author | Ron Yorston <rmy@pobox.com> | 2020-02-18 09:11:07 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2020-02-18 10:16:24 +0000 |
commit | d7a88599bd88035b1eeae276140f0ce9e405c271 (patch) | |
tree | 88ce3b05250cdb046130d5c443db3f03adff95c5 | |
parent | 56d1d4639c705537a8661ff0005392b82b0ee039 (diff) | |
parent | 22c75924daa41b7ea097796afd4baafa2fc99d05 (diff) | |
download | busybox-w32-d7a88599bd88035b1eeae276140f0ce9e405c271.tar.gz busybox-w32-d7a88599bd88035b1eeae276140f0ce9e405c271.tar.bz2 busybox-w32-d7a88599bd88035b1eeae276140f0ce9e405c271.zip |
Merge branch 'busybox' into merge
-rw-r--r-- | include/libbb.h | 2 | ||||
-rw-r--r-- | shell/ash.c | 330 | ||||
-rw-r--r-- | shell/ash_test/ash-psubst/tick_in_heredoc.right | 5 | ||||
-rwxr-xr-x | shell/ash_test/ash-psubst/tick_in_heredoc.tests | 7 | ||||
-rw-r--r-- | shell/ash_test/ash-vars/var_10.right | 3 | ||||
-rwxr-xr-x | shell/ash_test/ash-vars/var_10.tests | 4 | ||||
-rw-r--r-- | shell/hush_test/hush-psubst/tick_in_heredoc.right | 5 | ||||
-rwxr-xr-x | shell/hush_test/hush-psubst/tick_in_heredoc.tests | 7 | ||||
-rw-r--r-- | shell/hush_test/hush-vars/var_10.right | 3 | ||||
-rwxr-xr-x | shell/hush_test/hush-vars/var_10.tests | 4 |
10 files changed, 236 insertions, 134 deletions
diff --git a/include/libbb.h b/include/libbb.h index cbb178c0b..8979665b2 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -2210,9 +2210,11 @@ extern const char bb_busybox_exec_path[] ALIGN1; | |||
2210 | #if !ENABLE_PLATFORM_MINGW32 | 2210 | #if !ENABLE_PLATFORM_MINGW32 |
2211 | #define BB_PATH_ROOT_PATH "PATH=/sbin:/usr/sbin:/bin:/usr/bin" BB_ADDITIONAL_PATH | 2211 | #define BB_PATH_ROOT_PATH "PATH=/sbin:/usr/sbin:/bin:/usr/bin" BB_ADDITIONAL_PATH |
2212 | #define PATH_SEP ':' | 2212 | #define PATH_SEP ':' |
2213 | #define PATH_SEP_STR ":" | ||
2213 | #else | 2214 | #else |
2214 | #define BB_PATH_ROOT_PATH "PATH=/sbin;/usr/sbin;/bin;/usr/bin" BB_ADDITIONAL_PATH | 2215 | #define BB_PATH_ROOT_PATH "PATH=/sbin;/usr/sbin;/bin;/usr/bin" BB_ADDITIONAL_PATH |
2215 | #define PATH_SEP ';' | 2216 | #define PATH_SEP ';' |
2217 | #define PATH_SEP_STR ";" | ||
2216 | #endif | 2218 | #endif |
2217 | extern const char bb_PATH_root_path[] ALIGN1; /* BB_PATH_ROOT_PATH */ | 2219 | extern const char bb_PATH_root_path[] ALIGN1; /* BB_PATH_ROOT_PATH */ |
2218 | #define bb_default_root_path (bb_PATH_root_path + sizeof("PATH")) | 2220 | #define bb_default_root_path (bb_PATH_root_path + sizeof("PATH")) |
diff --git a/shell/ash.c b/shell/ash.c index c6eb930e4..4c143b8e9 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -1900,6 +1900,15 @@ growstackstr(void) | |||
1900 | return (char *)stackblock() + len; | 1900 | return (char *)stackblock() + len; |
1901 | } | 1901 | } |
1902 | 1902 | ||
1903 | static char * | ||
1904 | growstackto(size_t len) | ||
1905 | { | ||
1906 | while (stackblocksize() < len) | ||
1907 | growstackblock(); | ||
1908 | |||
1909 | return stackblock(); | ||
1910 | } | ||
1911 | |||
1903 | /* | 1912 | /* |
1904 | * Called from CHECKSTRSPACE. | 1913 | * Called from CHECKSTRSPACE. |
1905 | */ | 1914 | */ |
@@ -1907,18 +1916,8 @@ static char * | |||
1907 | makestrspace(size_t newlen, char *p) | 1916 | makestrspace(size_t newlen, char *p) |
1908 | { | 1917 | { |
1909 | size_t len = p - g_stacknxt; | 1918 | size_t len = p - g_stacknxt; |
1910 | size_t size; | ||
1911 | 1919 | ||
1912 | for (;;) { | 1920 | return growstackto(len + newlen) + len; |
1913 | size_t nleft; | ||
1914 | |||
1915 | size = stackblocksize(); | ||
1916 | nleft = size - len; | ||
1917 | if (nleft >= newlen) | ||
1918 | break; | ||
1919 | growstackblock(); | ||
1920 | } | ||
1921 | return (char *)stackblock() + len; | ||
1922 | } | 1921 | } |
1923 | 1922 | ||
1924 | static char * | 1923 | static char * |
@@ -2775,53 +2774,103 @@ listvars(int on, int off, struct strlist *lp, char ***end) | |||
2775 | } | 2774 | } |
2776 | 2775 | ||
2777 | 2776 | ||
2778 | /* ============ Path search helper | 2777 | /* ============ Path search helper */ |
2779 | * | 2778 | static const char * |
2779 | legal_pathopt(const char *opt, const char *term, int magic) | ||
2780 | { | ||
2781 | switch (magic) { | ||
2782 | case 0: | ||
2783 | opt = NULL; | ||
2784 | break; | ||
2785 | |||
2786 | case 1: | ||
2787 | opt = prefix(opt, "builtin") ?: prefix(opt, "func"); | ||
2788 | break; | ||
2789 | |||
2790 | default: | ||
2791 | opt += strcspn(opt, term); | ||
2792 | break; | ||
2793 | } | ||
2794 | |||
2795 | if (opt && *opt == '%') | ||
2796 | opt++; | ||
2797 | |||
2798 | return opt; | ||
2799 | } | ||
2800 | |||
2801 | /* | ||
2780 | * The variable path (passed by reference) should be set to the start | 2802 | * The variable path (passed by reference) should be set to the start |
2781 | * of the path before the first call; path_advance will update | 2803 | * of the path before the first call; padvance will update |
2782 | * this value as it proceeds. Successive calls to path_advance will return | 2804 | * this value as it proceeds. Successive calls to padvance will return |
2783 | * the possible path expansions in sequence. If an option (indicated by | 2805 | * the possible path expansions in sequence. If an option (indicated by |
2784 | * a percent sign) appears in the path entry then the global variable | 2806 | * a percent sign) appears in the path entry then the global variable |
2785 | * pathopt will be set to point to it; otherwise pathopt will be set to | 2807 | * pathopt will be set to point to it; otherwise pathopt will be set to |
2786 | * NULL. | 2808 | * NULL. |
2809 | * | ||
2810 | * If magic is 0 then pathopt recognition will be disabled. If magic is | ||
2811 | * 1 we shall recognise %builtin/%func. Otherwise we shall accept any | ||
2812 | * pathopt. | ||
2787 | */ | 2813 | */ |
2788 | static const char *pathopt; /* set by path_advance */ | 2814 | static const char *pathopt; /* set by padvance */ |
2789 | 2815 | ||
2790 | static char * | 2816 | static int |
2791 | path_advance(const char **path, const char *name) | 2817 | padvance_magic(const char **path, const char *name, int magic) |
2792 | { | 2818 | { |
2819 | const char *term = "%"PATH_SEP_STR; | ||
2820 | const char *lpathopt; | ||
2793 | const char *p; | 2821 | const char *p; |
2794 | char *q; | 2822 | char *q; |
2795 | const char *start; | 2823 | const char *start; |
2824 | size_t qlen; | ||
2796 | size_t len; | 2825 | size_t len; |
2797 | 2826 | ||
2798 | if (*path == NULL) | 2827 | if (*path == NULL) |
2799 | return NULL; | 2828 | return -1; |
2829 | |||
2830 | lpathopt = NULL; | ||
2800 | start = *path; | 2831 | start = *path; |
2801 | for (p = start; *p && *p != PATH_SEP && *p != '%'; p++) | ||
2802 | continue; | ||
2803 | len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ | ||
2804 | 2832 | ||
2833 | if (*start == '%' && (p = legal_pathopt(start + 1, term, magic))) { | ||
2834 | lpathopt = start + 1; | ||
2835 | start = p; | ||
2836 | term = PATH_SEP_STR; | ||
2837 | } | ||
2838 | |||
2839 | len = strcspn(start, term); | ||
2840 | p = start + len; | ||
2841 | |||
2842 | if (*p == '%') { | ||
2843 | size_t extra = strchrnul(p, PATH_SEP) - p; | ||
2844 | |||
2845 | if (legal_pathopt(p + 1, term, magic)) | ||
2846 | lpathopt = p + 1; | ||
2847 | else | ||
2848 | len += extra; | ||
2849 | |||
2850 | p += extra; | ||
2851 | } | ||
2852 | |||
2853 | pathopt = lpathopt; | ||
2854 | *path = *p == PATH_SEP ? p + 1 : NULL; | ||
2855 | |||
2856 | /* "2" is for '/' and '\0' */ | ||
2805 | /* reserve space for suffix on WIN32 */ | 2857 | /* reserve space for suffix on WIN32 */ |
2806 | while (stackblocksize() < (ENABLE_PLATFORM_MINGW32 ? len+4 : len)) | 2858 | qlen = len + strlen(name) + 2 IF_PLATFORM_MINGW32(+ 4); |
2807 | growstackblock(); | 2859 | q = growstackto(qlen); |
2808 | q = stackblock(); | 2860 | |
2809 | if (p != start) { | 2861 | if (len) { |
2810 | q = mempcpy(q, start, p - start); | 2862 | q = mempcpy(q, start, len); |
2811 | *q++ = '/'; | 2863 | *q++ = '/'; |
2812 | } | 2864 | } |
2813 | strcpy(q, name); | 2865 | strcpy(q, name); |
2814 | pathopt = NULL; | 2866 | |
2815 | if (*p == '%') { | 2867 | return qlen; |
2816 | pathopt = ++p; | 2868 | } |
2817 | while (*p && *p != PATH_SEP) | 2869 | |
2818 | p++; | 2870 | static int |
2819 | } | 2871 | padvance(const char **path, const char *name) |
2820 | if (*p == PATH_SEP) | 2872 | { |
2821 | *path = p + 1; | 2873 | return padvance_magic(path, name, 1); |
2822 | else | ||
2823 | *path = NULL; | ||
2824 | return stalloc(len); | ||
2825 | } | 2874 | } |
2826 | 2875 | ||
2827 | 2876 | ||
@@ -3179,6 +3228,7 @@ cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
3179 | char c; | 3228 | char c; |
3180 | struct stat statb; | 3229 | struct stat statb; |
3181 | int flags; | 3230 | int flags; |
3231 | int len; | ||
3182 | 3232 | ||
3183 | flags = cdopt(); | 3233 | flags = cdopt(); |
3184 | dest = *argptr; | 3234 | dest = *argptr; |
@@ -3208,9 +3258,10 @@ cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
3208 | if (!*dest) | 3258 | if (!*dest) |
3209 | dest = "."; | 3259 | dest = "."; |
3210 | path = bltinlookup("CDPATH"); | 3260 | path = bltinlookup("CDPATH"); |
3211 | while (path) { | 3261 | while (p = path, (len = padvance(&path, dest)) >= 0) { |
3212 | c = *path; | 3262 | c = *p; |
3213 | p = path_advance(&path, dest); | 3263 | p = stalloc(len); |
3264 | |||
3214 | if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) { | 3265 | if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) { |
3215 | if (c && c != PATH_SEP) | 3266 | if (c && c != PATH_SEP) |
3216 | flags |= CD_PRINT; | 3267 | flags |= CD_PRINT; |
@@ -7109,8 +7160,8 @@ expbackq(union node *cmd, int flag) | |||
7109 | 7160 | ||
7110 | /* Eat all trailing newlines */ | 7161 | /* Eat all trailing newlines */ |
7111 | dest = expdest; | 7162 | dest = expdest; |
7112 | for (; dest > (char *)stackblock() && (dest[-1] == '\n' || | 7163 | for (; dest > ((char *)stackblock() + startloc) && (dest[-1] == '\n' |
7113 | (ENABLE_PLATFORM_MINGW32 && dest[-1] == '\r'));) | 7164 | IF_PLATFORM_MINGW32(|| dest[-1] == '\r'));) |
7114 | STUNPUTC(dest); | 7165 | STUNPUTC(dest); |
7115 | expdest = dest; | 7166 | expdest = dest; |
7116 | 7167 | ||
@@ -8718,13 +8769,13 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) | |||
8718 | } else { | 8769 | } else { |
8719 | try_PATH: | 8770 | try_PATH: |
8720 | e = ENOENT; | 8771 | e = ENOENT; |
8721 | while ((cmdname = path_advance(&path, prog)) != NULL) { | 8772 | while (padvance(&path, argv[0]) >= 0) { |
8773 | cmdname = stackblock(); | ||
8722 | if (--idx < 0 && pathopt == NULL) { | 8774 | if (--idx < 0 && pathopt == NULL) { |
8723 | tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); | 8775 | tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); |
8724 | if (errno != ENOENT && errno != ENOTDIR) | 8776 | if (errno != ENOENT && errno != ENOTDIR) |
8725 | e = errno; | 8777 | e = errno; |
8726 | } | 8778 | } |
8727 | stunalloc(cmdname); | ||
8728 | } | 8779 | } |
8729 | } | 8780 | } |
8730 | 8781 | ||
@@ -8757,9 +8808,9 @@ printentry(struct tblentry *cmdp) | |||
8757 | idx = cmdp->param.index; | 8808 | idx = cmdp->param.index; |
8758 | path = pathval(); | 8809 | path = pathval(); |
8759 | do { | 8810 | do { |
8760 | name = path_advance(&path, cmdp->cmdname); | 8811 | padvance(&path, cmdp->cmdname); |
8761 | stunalloc(name); | ||
8762 | } while (--idx >= 0); | 8812 | } while (--idx >= 0); |
8813 | name = stackblock(); | ||
8763 | #if ENABLE_PLATFORM_MINGW32 | 8814 | #if ENABLE_PLATFORM_MINGW32 |
8764 | add_win32_extension(name); | 8815 | add_win32_extension(name); |
8765 | #endif | 8816 | #endif |
@@ -8767,11 +8818,10 @@ printentry(struct tblentry *cmdp) | |||
8767 | } | 8818 | } |
8768 | 8819 | ||
8769 | /* | 8820 | /* |
8770 | * Clear out command entries. The argument specifies the first entry in | 8821 | * Clear out command entries. |
8771 | * PATH which has changed. | ||
8772 | */ | 8822 | */ |
8773 | static void | 8823 | static void |
8774 | clearcmdentry(int firstchange) | 8824 | clearcmdentry(void) |
8775 | { | 8825 | { |
8776 | struct tblentry **tblp; | 8826 | struct tblentry **tblp; |
8777 | struct tblentry **pp; | 8827 | struct tblentry **pp; |
@@ -8781,10 +8831,11 @@ clearcmdentry(int firstchange) | |||
8781 | for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) { | 8831 | for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) { |
8782 | pp = tblp; | 8832 | pp = tblp; |
8783 | while ((cmdp = *pp) != NULL) { | 8833 | while ((cmdp = *pp) != NULL) { |
8784 | if ((cmdp->cmdtype == CMDNORMAL && | 8834 | if (cmdp->cmdtype == CMDNORMAL |
8785 | cmdp->param.index >= firstchange) | 8835 | || (cmdp->cmdtype == CMDBUILTIN |
8786 | || (cmdp->cmdtype == CMDBUILTIN && | 8836 | && !IS_BUILTIN_REGULAR(cmdp->param.cmd) |
8787 | builtinloc >= firstchange) | 8837 | && builtinloc > 0 |
8838 | ) | ||
8788 | ) { | 8839 | ) { |
8789 | *pp = cmdp->next; | 8840 | *pp = cmdp->next; |
8790 | free(cmdp); | 8841 | free(cmdp); |
@@ -8884,7 +8935,7 @@ hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
8884 | char *name; | 8935 | char *name; |
8885 | 8936 | ||
8886 | if (nextopt("r") != '\0') { | 8937 | if (nextopt("r") != '\0') { |
8887 | clearcmdentry(0); | 8938 | clearcmdentry(); |
8888 | return 0; | 8939 | return 0; |
8889 | } | 8940 | } |
8890 | 8941 | ||
@@ -8903,7 +8954,11 @@ hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
8903 | cmdp = cmdlookup(name, 0); | 8954 | cmdp = cmdlookup(name, 0); |
8904 | if (cmdp != NULL | 8955 | if (cmdp != NULL |
8905 | && (cmdp->cmdtype == CMDNORMAL | 8956 | && (cmdp->cmdtype == CMDNORMAL |
8906 | || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)) | 8957 | || (cmdp->cmdtype == CMDBUILTIN |
8958 | && !IS_BUILTIN_REGULAR(cmdp->param.cmd) | ||
8959 | && builtinloc > 0 | ||
8960 | ) | ||
8961 | ) | ||
8907 | ) { | 8962 | ) { |
8908 | delete_cmd_entry(); | 8963 | delete_cmd_entry(); |
8909 | } | 8964 | } |
@@ -8945,42 +9000,28 @@ hashcd(void) | |||
8945 | * Called with interrupts off. | 9000 | * Called with interrupts off. |
8946 | */ | 9001 | */ |
8947 | static void FAST_FUNC | 9002 | static void FAST_FUNC |
8948 | changepath(const char *new) | 9003 | changepath(const char *newval) |
8949 | { | 9004 | { |
8950 | const char *old; | 9005 | const char *new; |
8951 | int firstchange; | ||
8952 | int idx; | 9006 | int idx; |
8953 | int idx_bltin; | 9007 | int bltin; |
8954 | 9008 | ||
8955 | old = pathval(); | 9009 | new = newval; |
8956 | firstchange = 9999; /* assume no change */ | ||
8957 | idx = 0; | 9010 | idx = 0; |
8958 | idx_bltin = -1; | 9011 | bltin = -1; |
8959 | for (;;) { | 9012 | for (;;) { |
8960 | if (*old != *new) { | 9013 | if (*new == '%' && prefix(new + 1, "builtin")) { |
8961 | firstchange = idx; | 9014 | bltin = idx; |
8962 | if ((*old == '\0' && *new == PATH_SEP) | 9015 | break; |
8963 | || (*old == PATH_SEP && *new == '\0') | ||
8964 | ) { | ||
8965 | firstchange++; | ||
8966 | } | ||
8967 | old = new; /* ignore subsequent differences */ | ||
8968 | } | 9016 | } |
8969 | if (*new == '\0') | 9017 | new = strchr(new, PATH_SEP); |
9018 | if (!new) | ||
8970 | break; | 9019 | break; |
8971 | if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin")) | 9020 | idx++; |
8972 | idx_bltin = idx; | ||
8973 | if (*new == PATH_SEP) | ||
8974 | idx++; | ||
8975 | new++; | 9021 | new++; |
8976 | old++; | ||
8977 | } | 9022 | } |
8978 | if (builtinloc < 0 && idx_bltin >= 0) | 9023 | builtinloc = bltin; |
8979 | builtinloc = idx_bltin; /* zap builtins */ | 9024 | clearcmdentry(); |
8980 | if (builtinloc >= 0 && idx_bltin < 0) | ||
8981 | firstchange = 0; | ||
8982 | clearcmdentry(firstchange); | ||
8983 | builtinloc = idx_bltin; | ||
8984 | } | 9025 | } |
8985 | enum { | 9026 | enum { |
8986 | TEOF, | 9027 | TEOF, |
@@ -9155,9 +9196,9 @@ describe_command(char *command, const char *path, int describe_command_verbose) | |||
9155 | p = command; | 9196 | p = command; |
9156 | } else { | 9197 | } else { |
9157 | do { | 9198 | do { |
9158 | p = path_advance(&path, command); | 9199 | padvance(&path, command); |
9159 | stunalloc(p); | ||
9160 | } while (--j >= 0); | 9200 | } while (--j >= 0); |
9201 | p = stackblock(); | ||
9161 | } | 9202 | } |
9162 | #if ENABLE_PLATFORM_MINGW32 | 9203 | #if ENABLE_PLATFORM_MINGW32 |
9163 | add_win32_extension(p); | 9204 | add_win32_extension(p); |
@@ -11736,8 +11777,12 @@ chkmail(void) | |||
11736 | mpath = mpathset() ? mpathval() : mailval(); | 11777 | mpath = mpathset() ? mpathval() : mailval(); |
11737 | new_hash = 0; | 11778 | new_hash = 0; |
11738 | for (;;) { | 11779 | for (;;) { |
11739 | p = path_advance(&mpath, nullstr); | 11780 | int len; |
11740 | if (p == NULL) | 11781 | |
11782 | len = padvance_magic(&mpath, nullstr, 2); | ||
11783 | if (!len) | ||
11784 | break; | ||
11785 | p = stackblock(); | ||
11741 | break; | 11786 | break; |
11742 | if (*p == '\0') | 11787 | if (*p == '\0') |
11743 | continue; | 11788 | continue; |
@@ -13338,7 +13383,7 @@ parsesub: { | |||
13338 | do { | 13383 | do { |
13339 | STPUTC(c, out); | 13384 | STPUTC(c, out); |
13340 | c = pgetc_eatbnl(); | 13385 | c = pgetc_eatbnl(); |
13341 | } while (isdigit(c)); | 13386 | } while (!subtype && isdigit(c)); |
13342 | } else if (c != '}') { | 13387 | } else if (c != '}') { |
13343 | /* $[{[#]]<specialchar>[}] */ | 13388 | /* $[{[#]]<specialchar>[}] */ |
13344 | int cc = c; | 13389 | int cc = c; |
@@ -13469,6 +13514,7 @@ parsebackq: { | |||
13469 | union node *n; | 13514 | union node *n; |
13470 | char *str; | 13515 | char *str; |
13471 | size_t savelen; | 13516 | size_t savelen; |
13517 | struct heredoc *saveheredoclist; | ||
13472 | smallint saveprompt = 0; | 13518 | smallint saveprompt = 0; |
13473 | 13519 | ||
13474 | str = NULL; | 13520 | str = NULL; |
@@ -13544,6 +13590,9 @@ parsebackq: { | |||
13544 | *nlpp = stzalloc(sizeof(**nlpp)); | 13590 | *nlpp = stzalloc(sizeof(**nlpp)); |
13545 | /* (*nlpp)->next = NULL; - stzalloc did it */ | 13591 | /* (*nlpp)->next = NULL; - stzalloc did it */ |
13546 | 13592 | ||
13593 | saveheredoclist = heredoclist; | ||
13594 | heredoclist = NULL; | ||
13595 | |||
13547 | if (oldstyle) { | 13596 | if (oldstyle) { |
13548 | saveprompt = doprompt; | 13597 | saveprompt = doprompt; |
13549 | doprompt = 0; | 13598 | doprompt = 0; |
@@ -13553,21 +13602,22 @@ parsebackq: { | |||
13553 | 13602 | ||
13554 | if (oldstyle) | 13603 | if (oldstyle) |
13555 | doprompt = saveprompt; | 13604 | doprompt = saveprompt; |
13556 | else if (readtoken() != TRP) | 13605 | else { |
13557 | raise_error_unexpected_syntax(TRP); | 13606 | if (readtoken() != TRP) |
13607 | raise_error_unexpected_syntax(TRP); | ||
13608 | setinputstring(nullstr); | ||
13609 | parseheredoc(); | ||
13610 | } | ||
13611 | |||
13612 | heredoclist = saveheredoclist; | ||
13558 | 13613 | ||
13559 | (*nlpp)->n = n; | 13614 | (*nlpp)->n = n; |
13560 | if (oldstyle) { | 13615 | /* Start reading from old file again. */ |
13561 | /* | 13616 | popfile(); |
13562 | * Start reading from old file again, ignoring any pushed back | 13617 | /* Ignore any pushed back tokens left from the backquote parsing. */ |
13563 | * tokens left from the backquote parsing | 13618 | if (oldstyle) |
13564 | */ | ||
13565 | popfile(); | ||
13566 | tokpushback = 0; | 13619 | tokpushback = 0; |
13567 | } | 13620 | out = growstackto(savelen + 1); |
13568 | while (stackblocksize() <= savelen) | ||
13569 | growstackblock(); | ||
13570 | STARTSTACKSTR(out); | ||
13571 | if (str) { | 13621 | if (str) { |
13572 | memcpy(out, str, savelen); | 13622 | memcpy(out, str, savelen); |
13573 | STADJUST(savelen, out); | 13623 | STADJUST(savelen, out); |
@@ -14078,33 +14128,32 @@ cmdloop(int top) | |||
14078 | * search for the file, which is necessary to find sub-commands. | 14128 | * search for the file, which is necessary to find sub-commands. |
14079 | */ | 14129 | */ |
14080 | static char * | 14130 | static char * |
14081 | find_dot_file(char *name) | 14131 | find_dot_file(char *basename) |
14082 | { | 14132 | { |
14083 | char *fullname; | 14133 | char *fullname; |
14084 | const char *path = pathval(); | 14134 | const char *path = pathval(); |
14085 | struct stat statb; | 14135 | struct stat statb; |
14136 | int len; | ||
14086 | 14137 | ||
14087 | /* don't try this for absolute or relative paths */ | 14138 | /* don't try this for absolute or relative paths */ |
14088 | if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) | 14139 | if (strchr(basename, '/') IF_PLATFORM_MINGW32(|| strchr(basename, '\\'))) |
14089 | return name; | 14140 | return basename; |
14090 | 14141 | ||
14091 | while ((fullname = path_advance(&path, name)) != NULL) { | 14142 | while ((len = padvance(&path, basename)) >= 0) { |
14092 | if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) { | 14143 | fullname = stackblock(); |
14093 | /* | 14144 | if ((!pathopt || *pathopt == 'f') |
14094 | * Don't bother freeing here, since it will | 14145 | && !stat(fullname, &statb) && S_ISREG(statb.st_mode) |
14095 | * be freed by the caller. | 14146 | ) { |
14096 | */ | 14147 | /* This will be freed by the caller. */ |
14097 | return fullname; | 14148 | return stalloc(len); |
14098 | } | 14149 | } |
14099 | if (fullname != name) | ||
14100 | stunalloc(fullname); | ||
14101 | } | 14150 | } |
14102 | /* not found in PATH */ | 14151 | /* not found in PATH */ |
14103 | 14152 | ||
14104 | #if ENABLE_ASH_BASH_SOURCE_CURDIR | 14153 | #if ENABLE_ASH_BASH_SOURCE_CURDIR |
14105 | return name; | 14154 | return basename; |
14106 | #else | 14155 | #else |
14107 | ash_msg_and_raise_error("%s: not found", name); | 14156 | ash_msg_and_raise_error("%s: not found", basename); |
14108 | /* NOTREACHED */ | 14157 | /* NOTREACHED */ |
14109 | #endif | 14158 | #endif |
14110 | } | 14159 | } |
@@ -14207,6 +14256,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
14207 | int e; | 14256 | int e; |
14208 | int updatetbl; | 14257 | int updatetbl; |
14209 | struct builtincmd *bcmd; | 14258 | struct builtincmd *bcmd; |
14259 | int len; | ||
14210 | 14260 | ||
14211 | /* If name contains a slash, don't use PATH or hash table */ | 14261 | /* If name contains a slash, don't use PATH or hash table */ |
14212 | if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) { | 14262 | if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) { |
@@ -14255,7 +14305,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
14255 | bit = DO_NOFUNC; | 14305 | bit = DO_NOFUNC; |
14256 | break; | 14306 | break; |
14257 | case CMDBUILTIN: | 14307 | case CMDBUILTIN: |
14258 | bit = DO_ALTBLTIN; | 14308 | bit = IS_BUILTIN_REGULAR(cmdp->param.cmd) ? 0 : DO_ALTBLTIN; |
14259 | break; | 14309 | break; |
14260 | } | 14310 | } |
14261 | if (act & bit) { | 14311 | if (act & bit) { |
@@ -14302,20 +14352,20 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
14302 | e = ENOENT; | 14352 | e = ENOENT; |
14303 | idx = -1; | 14353 | idx = -1; |
14304 | loop: | 14354 | loop: |
14305 | while ((fullname = path_advance(&path, name)) != NULL) { | 14355 | while ((len = padvance(&path, name)) >= 0) { |
14306 | stunalloc(fullname); | 14356 | const char *lpathopt = pathopt; |
14307 | /* NB: code below will still use fullname | 14357 | |
14308 | * despite it being "unallocated" */ | 14358 | fullname = stackblock(); |
14309 | idx++; | 14359 | idx++; |
14310 | if (pathopt) { | 14360 | if (lpathopt) { |
14311 | if (prefix(pathopt, "builtin")) { | 14361 | if (*lpathopt == 'b') { |
14312 | if (bcmd) | 14362 | if (bcmd) |
14313 | goto builtin_success; | 14363 | goto builtin_success; |
14314 | continue; | 14364 | continue; |
14315 | } | 14365 | } else if (!(act & DO_NOFUNC)) { |
14316 | if ((act & DO_NOFUNC) | 14366 | /* handled below */ |
14317 | || !prefix(pathopt, "func") | 14367 | } else { |
14318 | ) { /* ignore unimplemented options */ | 14368 | /* ignore unimplemented options */ |
14319 | continue; | 14369 | continue; |
14320 | } | 14370 | } |
14321 | } | 14371 | } |
@@ -14341,8 +14391,8 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
14341 | e = EACCES; /* if we fail, this will be the error */ | 14391 | e = EACCES; /* if we fail, this will be the error */ |
14342 | if (!S_ISREG(statb.st_mode)) | 14392 | if (!S_ISREG(statb.st_mode)) |
14343 | continue; | 14393 | continue; |
14344 | if (pathopt) { /* this is a %func directory */ | 14394 | if (lpathopt) { /* this is a %func directory */ |
14345 | stalloc(strlen(fullname) + 1); | 14395 | stalloc(len); |
14346 | /* NB: stalloc will return space pointed by fullname | 14396 | /* NB: stalloc will return space pointed by fullname |
14347 | * (because we don't have any intervening allocations | 14397 | * (because we don't have any intervening allocations |
14348 | * between stunalloc above and this stalloc) */ | 14398 | * between stunalloc above and this stalloc) */ |
@@ -15145,11 +15195,11 @@ read_profile(const char *name) | |||
15145 | 15195 | ||
15146 | /* | 15196 | /* |
15147 | * This routine is called when an error or an interrupt occurs in an | 15197 | * This routine is called when an error or an interrupt occurs in an |
15148 | * interactive shell and control is returned to the main command loop. | 15198 | * interactive shell and control is returned to the main command loop |
15149 | * (In dash, this function is auto-generated by build machinery). | 15199 | * but prior to exitshell. |
15150 | */ | 15200 | */ |
15151 | static void | 15201 | static void |
15152 | reset(void) | 15202 | exitreset(void) |
15153 | { | 15203 | { |
15154 | /* from eval.c: */ | 15204 | /* from eval.c: */ |
15155 | evalskip = 0; | 15205 | evalskip = 0; |
@@ -15162,14 +15212,23 @@ reset(void) | |||
15162 | /* from expand.c: */ | 15212 | /* from expand.c: */ |
15163 | ifsfree(); | 15213 | ifsfree(); |
15164 | 15214 | ||
15215 | /* from redir.c: */ | ||
15216 | unwindredir(NULL); | ||
15217 | } | ||
15218 | |||
15219 | /* | ||
15220 | * This routine is called when an error or an interrupt occurs in an | ||
15221 | * interactive shell and control is returned to the main command loop. | ||
15222 | * (In dash, this function is auto-generated by build machinery). | ||
15223 | */ | ||
15224 | static void | ||
15225 | reset(void) | ||
15226 | { | ||
15165 | /* from input.c: */ | 15227 | /* from input.c: */ |
15166 | g_parsefile->left_in_buffer = 0; | 15228 | g_parsefile->left_in_buffer = 0; |
15167 | g_parsefile->left_in_line = 0; /* clear input buffer */ | 15229 | g_parsefile->left_in_line = 0; /* clear input buffer */ |
15168 | popallfiles(); | 15230 | popallfiles(); |
15169 | 15231 | ||
15170 | /* from redir.c: */ | ||
15171 | unwindredir(NULL); | ||
15172 | |||
15173 | /* from var.c: */ | 15232 | /* from var.c: */ |
15174 | unwindlocalvars(NULL); | 15233 | unwindlocalvars(NULL); |
15175 | } | 15234 | } |
@@ -15220,13 +15279,16 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
15220 | smallint e; | 15279 | smallint e; |
15221 | smallint s; | 15280 | smallint s; |
15222 | 15281 | ||
15223 | reset(); | 15282 | exitreset(); |
15224 | 15283 | ||
15225 | e = exception_type; | 15284 | e = exception_type; |
15226 | s = state; | 15285 | s = state; |
15227 | if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) { | 15286 | if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) { |
15228 | exitshell(); | 15287 | exitshell(); |
15229 | } | 15288 | } |
15289 | |||
15290 | reset(); | ||
15291 | |||
15230 | if (e == EXINT) { | 15292 | if (e == EXINT) { |
15231 | newline_and_flush(stderr); | 15293 | newline_and_flush(stderr); |
15232 | } | 15294 | } |
diff --git a/shell/ash_test/ash-psubst/tick_in_heredoc.right b/shell/ash_test/ash-psubst/tick_in_heredoc.right new file mode 100644 index 000000000..7e7bac6d3 --- /dev/null +++ b/shell/ash_test/ash-psubst/tick_in_heredoc.right | |||
@@ -0,0 +1,5 @@ | |||
1 | 1 | ||
2 | |||
3 | 2 | ||
4 | |||
5 | 3 | ||
diff --git a/shell/ash_test/ash-psubst/tick_in_heredoc.tests b/shell/ash_test/ash-psubst/tick_in_heredoc.tests new file mode 100755 index 000000000..c8eb8f4f4 --- /dev/null +++ b/shell/ash_test/ash-psubst/tick_in_heredoc.tests | |||
@@ -0,0 +1,7 @@ | |||
1 | cat <<END | ||
2 | 1 | ||
3 | $(echo "") | ||
4 | 2 | ||
5 | `echo ""` | ||
6 | 3 | ||
7 | END | ||
diff --git a/shell/ash_test/ash-vars/var_10.right b/shell/ash_test/ash-vars/var_10.right new file mode 100644 index 000000000..675ab45f6 --- /dev/null +++ b/shell/ash_test/ash-vars/var_10.right | |||
@@ -0,0 +1,3 @@ | |||
1 | Zero:0 | ||
2 | One:1 | ||
3 | Done:0 | ||
diff --git a/shell/ash_test/ash-vars/var_10.tests b/shell/ash_test/ash-vars/var_10.tests new file mode 100755 index 000000000..7364efb55 --- /dev/null +++ b/shell/ash_test/ash-vars/var_10.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | set -- : 2 3 4 5 6 7 8 9 ten eleven | ||
2 | echo Zero$10 | ||
3 | echo One$11 | ||
4 | echo Done:$? | ||
diff --git a/shell/hush_test/hush-psubst/tick_in_heredoc.right b/shell/hush_test/hush-psubst/tick_in_heredoc.right new file mode 100644 index 000000000..7e7bac6d3 --- /dev/null +++ b/shell/hush_test/hush-psubst/tick_in_heredoc.right | |||
@@ -0,0 +1,5 @@ | |||
1 | 1 | ||
2 | |||
3 | 2 | ||
4 | |||
5 | 3 | ||
diff --git a/shell/hush_test/hush-psubst/tick_in_heredoc.tests b/shell/hush_test/hush-psubst/tick_in_heredoc.tests new file mode 100755 index 000000000..c8eb8f4f4 --- /dev/null +++ b/shell/hush_test/hush-psubst/tick_in_heredoc.tests | |||
@@ -0,0 +1,7 @@ | |||
1 | cat <<END | ||
2 | 1 | ||
3 | $(echo "") | ||
4 | 2 | ||
5 | `echo ""` | ||
6 | 3 | ||
7 | END | ||
diff --git a/shell/hush_test/hush-vars/var_10.right b/shell/hush_test/hush-vars/var_10.right new file mode 100644 index 000000000..675ab45f6 --- /dev/null +++ b/shell/hush_test/hush-vars/var_10.right | |||
@@ -0,0 +1,3 @@ | |||
1 | Zero:0 | ||
2 | One:1 | ||
3 | Done:0 | ||
diff --git a/shell/hush_test/hush-vars/var_10.tests b/shell/hush_test/hush-vars/var_10.tests new file mode 100755 index 000000000..7364efb55 --- /dev/null +++ b/shell/hush_test/hush-vars/var_10.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | set -- : 2 3 4 5 6 7 8 9 ten eleven | ||
2 | echo Zero$10 | ||
3 | echo One$11 | ||
4 | echo Done:$? | ||