diff options
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 78 | ||||
-rwxr-xr-x | shell/ash_test/ash-misc/unicode1.tests | 2 | ||||
-rw-r--r-- | shell/ash_test/ash-read/read_SIGCHLD.right | 2 | ||||
-rwxr-xr-x | shell/ash_test/ash-read/read_SIGCHLD.tests | 4 | ||||
-rw-r--r-- | shell/hush.c | 17 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/unicode1.tests | 2 | ||||
-rw-r--r-- | shell/hush_test/hush-read/read_SIGCHLD.right | 2 | ||||
-rwxr-xr-x | shell/hush_test/hush-read/read_SIGCHLD.tests | 4 | ||||
-rw-r--r-- | shell/shell_common.c | 28 |
9 files changed, 77 insertions, 62 deletions
diff --git a/shell/ash.c b/shell/ash.c index 0325a325c..bdbcd6987 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -3554,11 +3554,9 @@ unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
3554 | { | 3554 | { |
3555 | int i; | 3555 | int i; |
3556 | 3556 | ||
3557 | while ((i = nextopt("a")) != '\0') { | 3557 | while (nextopt("a") != '\0') { |
3558 | if (i == 'a') { | 3558 | rmaliases(); |
3559 | rmaliases(); | 3559 | return 0; |
3560 | return 0; | ||
3561 | } | ||
3562 | } | 3560 | } |
3563 | for (i = 0; *argptr; argptr++) { | 3561 | for (i = 0; *argptr; argptr++) { |
3564 | if (unalias(*argptr)) { | 3562 | if (unalias(*argptr)) { |
@@ -4069,7 +4067,7 @@ setjobctl(int on) | |||
4069 | } | 4067 | } |
4070 | /* fd is a tty at this point */ | 4068 | /* fd is a tty at this point */ |
4071 | fd = fcntl(fd, F_DUPFD, 10); | 4069 | fd = fcntl(fd, F_DUPFD, 10); |
4072 | if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, dont */ | 4070 | if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */ |
4073 | close(ofd); | 4071 | close(ofd); |
4074 | if (fd < 0) | 4072 | if (fd < 0) |
4075 | goto out; /* F_DUPFD failed */ | 4073 | goto out; /* F_DUPFD failed */ |
@@ -6692,7 +6690,7 @@ static char *evalvar(char *p, int flags, struct strlist *var_str_list); | |||
6692 | * $@ like $* since no splitting will be performed. | 6690 | * $@ like $* since no splitting will be performed. |
6693 | * | 6691 | * |
6694 | * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence | 6692 | * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence |
6695 | * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it | 6693 | * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it |
6696 | * for correct expansion of "B=$A" word. | 6694 | * for correct expansion of "B=$A" word. |
6697 | */ | 6695 | */ |
6698 | static void | 6696 | static void |
@@ -6902,8 +6900,8 @@ scanright(char *startp, char *rmesc, char *rmescend, | |||
6902 | if (try2optimize) { | 6900 | if (try2optimize) { |
6903 | /* Maybe we can optimize this: | 6901 | /* Maybe we can optimize this: |
6904 | * if pattern ends with unescaped *, we can avoid checking | 6902 | * if pattern ends with unescaped *, we can avoid checking |
6905 | * shorter strings: if "foo*" doesnt match "raw_value_of_v", | 6903 | * shorter strings: if "foo*" doesn't match "raw_value_of_v", |
6906 | * it wont match truncated "raw_value_of_" strings too. | 6904 | * it won't match truncated "raw_value_of_" strings too. |
6907 | */ | 6905 | */ |
6908 | unsigned plen = strlen(pattern); | 6906 | unsigned plen = strlen(pattern); |
6909 | /* Does it end with "*"? */ | 6907 | /* Does it end with "*"? */ |
@@ -7630,7 +7628,7 @@ expandmeta(struct strlist *str /*, int flag*/) | |||
7630 | // Which means you need to unescape the string, right? Not so fast: | 7628 | // Which means you need to unescape the string, right? Not so fast: |
7631 | // if there _is_ a file named "file\?" (with backslash), it is returned | 7629 | // if there _is_ a file named "file\?" (with backslash), it is returned |
7632 | // as "file\?" too (whichever pattern you used to find it, say, "file*"). | 7630 | // as "file\?" too (whichever pattern you used to find it, say, "file*"). |
7633 | // You DONT KNOW by looking at the result whether you need to unescape it. | 7631 | // You DON'T KNOW by looking at the result whether you need to unescape it. |
7634 | // | 7632 | // |
7635 | // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?", | 7633 | // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?", |
7636 | // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file. | 7634 | // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file. |
@@ -8124,9 +8122,8 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** | |||
8124 | * have to change the find_command routine as well. | 8122 | * have to change the find_command routine as well. |
8125 | * argv[-1] must exist and be writable! See tryexec() for why. | 8123 | * argv[-1] must exist and be writable! See tryexec() for why. |
8126 | */ | 8124 | */ |
8127 | static void shellexec(char **, const char *, int) NORETURN; | 8125 | static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN; |
8128 | static void | 8126 | static void shellexec(char *prog, char **argv, const char *path, int idx) |
8129 | shellexec(char **argv, const char *path, int idx) | ||
8130 | { | 8127 | { |
8131 | char *cmdname; | 8128 | char *cmdname; |
8132 | int e; | 8129 | int e; |
@@ -8135,12 +8132,12 @@ shellexec(char **argv, const char *path, int idx) | |||
8135 | int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */ | 8132 | int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */ |
8136 | 8133 | ||
8137 | envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL); | 8134 | envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL); |
8138 | if ((strchr(argv[0], '/') || (ENABLE_PLATFORM_MINGW32 && strchr(argv[0], '\\'))) | 8135 | if ((strchr(prog, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(prog, '\\'))) |
8139 | #if ENABLE_FEATURE_SH_STANDALONE | 8136 | #if ENABLE_FEATURE_SH_STANDALONE |
8140 | || (applet_no = find_applet_by_name(argv[0])) >= 0 | 8137 | || (applet_no = find_applet_by_name(prog)) >= 0 |
8141 | #endif | 8138 | #endif |
8142 | ) { | 8139 | ) { |
8143 | tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp); | 8140 | tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); |
8144 | if (applet_no >= 0) { | 8141 | if (applet_no >= 0) { |
8145 | /* We tried execing ourself, but it didn't work. | 8142 | /* We tried execing ourself, but it didn't work. |
8146 | * Maybe /proc/self/exe doesn't exist? | 8143 | * Maybe /proc/self/exe doesn't exist? |
@@ -8157,7 +8154,7 @@ shellexec(char **argv, const char *path, int idx) | |||
8157 | } else { | 8154 | } else { |
8158 | try_PATH: | 8155 | try_PATH: |
8159 | e = ENOENT; | 8156 | e = ENOENT; |
8160 | while ((cmdname = path_advance(&path, argv[0])) != NULL) { | 8157 | while ((cmdname = path_advance(&path, prog)) != NULL) { |
8161 | if (--idx < 0 && pathopt == NULL) { | 8158 | if (--idx < 0 && pathopt == NULL) { |
8162 | tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); | 8159 | tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); |
8163 | if (errno != ENOENT && errno != ENOTDIR) | 8160 | if (errno != ENOENT && errno != ENOTDIR) |
@@ -8181,8 +8178,8 @@ shellexec(char **argv, const char *path, int idx) | |||
8181 | } | 8178 | } |
8182 | exitstatus = exerrno; | 8179 | exitstatus = exerrno; |
8183 | TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n", | 8180 | TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n", |
8184 | argv[0], e, suppress_int)); | 8181 | prog, e, suppress_int)); |
8185 | ash_msg_and_raise(EXEXIT, "%s: %s", argv[0], errmsg(e, "not found")); | 8182 | ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found")); |
8186 | /* NOTREACHED */ | 8183 | /* NOTREACHED */ |
8187 | } | 8184 | } |
8188 | 8185 | ||
@@ -8551,7 +8548,6 @@ static int | |||
8551 | describe_command(char *command, const char *path, int describe_command_verbose) | 8548 | describe_command(char *command, const char *path, int describe_command_verbose) |
8552 | { | 8549 | { |
8553 | struct cmdentry entry; | 8550 | struct cmdentry entry; |
8554 | struct tblentry *cmdp; | ||
8555 | #if ENABLE_ASH_ALIAS | 8551 | #if ENABLE_ASH_ALIAS |
8556 | const struct alias *ap; | 8552 | const struct alias *ap; |
8557 | #endif | 8553 | #endif |
@@ -8581,15 +8577,8 @@ describe_command(char *command, const char *path, int describe_command_verbose) | |||
8581 | goto out; | 8577 | goto out; |
8582 | } | 8578 | } |
8583 | #endif | 8579 | #endif |
8584 | /* Then check if it is a tracked alias */ | 8580 | /* Brute force */ |
8585 | cmdp = cmdlookup(command, 0); | 8581 | find_command(command, &entry, DO_ABS, path); |
8586 | if (cmdp != NULL) { | ||
8587 | entry.cmdtype = cmdp->cmdtype; | ||
8588 | entry.u = cmdp->param; | ||
8589 | } else { | ||
8590 | /* Finally use brute force */ | ||
8591 | find_command(command, &entry, DO_ABS, path); | ||
8592 | } | ||
8593 | 8582 | ||
8594 | switch (entry.cmdtype) { | 8583 | switch (entry.cmdtype) { |
8595 | case CMDNORMAL: { | 8584 | case CMDNORMAL: { |
@@ -8604,9 +8593,7 @@ describe_command(char *command, const char *path, int describe_command_verbose) | |||
8604 | } while (--j >= 0); | 8593 | } while (--j >= 0); |
8605 | } | 8594 | } |
8606 | if (describe_command_verbose) { | 8595 | if (describe_command_verbose) { |
8607 | out1fmt(" is%s %s", | 8596 | out1fmt(" is %s", p); |
8608 | (cmdp ? " a tracked alias for" : nullstr), p | ||
8609 | ); | ||
8610 | } else { | 8597 | } else { |
8611 | out1str(p); | 8598 | out1str(p); |
8612 | } | 8599 | } |
@@ -9814,7 +9801,14 @@ truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
9814 | static int FAST_FUNC | 9801 | static int FAST_FUNC |
9815 | execcmd(int argc UNUSED_PARAM, char **argv) | 9802 | execcmd(int argc UNUSED_PARAM, char **argv) |
9816 | { | 9803 | { |
9817 | if (argv[1]) { | 9804 | optionarg = NULL; |
9805 | while (nextopt("a:") != '\0') | ||
9806 | /* nextopt() sets optionarg to "-a ARGV0" */; | ||
9807 | |||
9808 | argv = argptr; | ||
9809 | if (argv[0]) { | ||
9810 | char *prog; | ||
9811 | |||
9818 | iflag = 0; /* exit on error */ | 9812 | iflag = 0; /* exit on error */ |
9819 | mflag = 0; | 9813 | mflag = 0; |
9820 | optschanged(); | 9814 | optschanged(); |
@@ -9830,7 +9824,10 @@ execcmd(int argc UNUSED_PARAM, char **argv) | |||
9830 | /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */ | 9824 | /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */ |
9831 | /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */ | 9825 | /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */ |
9832 | 9826 | ||
9833 | shellexec(argv + 1, pathval(), 0); | 9827 | prog = argv[0]; |
9828 | if (optionarg) | ||
9829 | argv[0] = optionarg; | ||
9830 | shellexec(prog, argv, pathval(), 0); | ||
9834 | /* NOTREACHED */ | 9831 | /* NOTREACHED */ |
9835 | } | 9832 | } |
9836 | return 0; | 9833 | return 0; |
@@ -10255,7 +10252,7 @@ evalcommand(union node *cmd, int flags) | |||
10255 | } | 10252 | } |
10256 | #endif | 10253 | #endif |
10257 | listsetvar(varlist.list, VEXPORT|VSTACK); | 10254 | listsetvar(varlist.list, VEXPORT|VSTACK); |
10258 | shellexec(argv, path, cmdentry.u.index); | 10255 | shellexec(argv[0], argv, path, cmdentry.u.index); |
10259 | /* NOTREACHED */ | 10256 | /* NOTREACHED */ |
10260 | } /* default */ | 10257 | } /* default */ |
10261 | case CMDBUILTIN: | 10258 | case CMDBUILTIN: |
@@ -13605,7 +13602,7 @@ exportcmd(int argc UNUSED_PARAM, char **argv) | |||
13605 | } | 13602 | } |
13606 | flag_off = ~flag_off; | 13603 | flag_off = ~flag_off; |
13607 | 13604 | ||
13608 | /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */ | 13605 | /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */ |
13609 | { | 13606 | { |
13610 | aptr = argptr; | 13607 | aptr = argptr; |
13611 | name = *aptr; | 13608 | name = *aptr; |
@@ -13785,6 +13782,7 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
13785 | /* "read -s" needs to save/restore termios, can't allow ^C | 13782 | /* "read -s" needs to save/restore termios, can't allow ^C |
13786 | * to jump out of it. | 13783 | * to jump out of it. |
13787 | */ | 13784 | */ |
13785 | again: | ||
13788 | INT_OFF; | 13786 | INT_OFF; |
13789 | r = shell_builtin_read(setvar0, | 13787 | r = shell_builtin_read(setvar0, |
13790 | argptr, | 13788 | argptr, |
@@ -13797,6 +13795,12 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
13797 | ); | 13795 | ); |
13798 | INT_ON; | 13796 | INT_ON; |
13799 | 13797 | ||
13798 | if ((uintptr_t)r == 1 && errno == EINTR) { | ||
13799 | /* to get SIGCHLD: sleep 1 & read x; echo $x */ | ||
13800 | if (pending_sig == 0) | ||
13801 | goto again; | ||
13802 | } | ||
13803 | |||
13800 | if ((uintptr_t)r > 1) | 13804 | if ((uintptr_t)r > 1) |
13801 | ash_msg_and_raise_error(r); | 13805 | ash_msg_and_raise_error(r); |
13802 | 13806 | ||
@@ -14420,7 +14424,7 @@ forkshell_shellexec(struct forkshell *fs) | |||
14420 | char *path = fs->string; | 14424 | char *path = fs->string; |
14421 | 14425 | ||
14422 | listsetvar(varlist, VEXPORT|VSTACK); | 14426 | listsetvar(varlist, VEXPORT|VSTACK); |
14423 | shellexec(argv, path, idx); | 14427 | shellexec(argv[0], argv, path, idx); |
14424 | } | 14428 | } |
14425 | 14429 | ||
14426 | static void | 14430 | static void |
diff --git a/shell/ash_test/ash-misc/unicode1.tests b/shell/ash_test/ash-misc/unicode1.tests index 8788ba910..b8479cb41 100755 --- a/shell/ash_test/ash-misc/unicode1.tests +++ b/shell/ash_test/ash-misc/unicode1.tests | |||
@@ -5,7 +5,7 @@ a=`printf "\xcc\x80"` | |||
5 | # Should print 1 | 5 | # Should print 1 |
6 | echo ${#a} | 6 | echo ${#a} |
7 | 7 | ||
8 | # A Japanese katakana charachter U+30a3 | 8 | # A Japanese katakana character U+30a3 |
9 | a=`printf "\xe3\x82\xa3"` | 9 | a=`printf "\xe3\x82\xa3"` |
10 | # Should print 1 | 10 | # Should print 1 |
11 | echo ${#a} | 11 | echo ${#a} |
diff --git a/shell/ash_test/ash-read/read_SIGCHLD.right b/shell/ash_test/ash-read/read_SIGCHLD.right new file mode 100644 index 000000000..b3dc7ab0c --- /dev/null +++ b/shell/ash_test/ash-read/read_SIGCHLD.right | |||
@@ -0,0 +1,2 @@ | |||
1 | x='Ok' | ||
2 | exitcode:0 | ||
diff --git a/shell/ash_test/ash-read/read_SIGCHLD.tests b/shell/ash_test/ash-read/read_SIGCHLD.tests new file mode 100755 index 000000000..c5f673aff --- /dev/null +++ b/shell/ash_test/ash-read/read_SIGCHLD.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | x=BAD | ||
2 | { sleep 0.4; echo Ok; } | { sleep 0.2 & read x; echo "x='$x'"; } | ||
3 | echo "exitcode:$?" | ||
4 | |||
diff --git a/shell/hush.c b/shell/hush.c index 4123cc19e..125463a56 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -1908,7 +1908,7 @@ static int check_and_run_traps(void) | |||
1908 | G.count_SIGCHLD++; | 1908 | G.count_SIGCHLD++; |
1909 | //bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); | 1909 | //bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); |
1910 | /* Note: | 1910 | /* Note: |
1911 | * We dont do 'last_sig = sig' here -> NOT returning this sig. | 1911 | * We don't do 'last_sig = sig' here -> NOT returning this sig. |
1912 | * This simplifies wait builtin a bit. | 1912 | * This simplifies wait builtin a bit. |
1913 | */ | 1913 | */ |
1914 | break; | 1914 | break; |
@@ -1917,7 +1917,7 @@ static int check_and_run_traps(void) | |||
1917 | debug_printf_exec("%s: sig:%d default handling is to ignore\n", __func__, sig); | 1917 | debug_printf_exec("%s: sig:%d default handling is to ignore\n", __func__, sig); |
1918 | /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */ | 1918 | /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */ |
1919 | /* Note: | 1919 | /* Note: |
1920 | * We dont do 'last_sig = sig' here -> NOT returning this sig. | 1920 | * We don't do 'last_sig = sig' here -> NOT returning this sig. |
1921 | * Example: wait is not interrupted by TERM | 1921 | * Example: wait is not interrupted by TERM |
1922 | * in interactive shell, because TERM is ignored. | 1922 | * in interactive shell, because TERM is ignored. |
1923 | */ | 1923 | */ |
@@ -2280,7 +2280,7 @@ static void reinit_unicode_for_hush(void) | |||
2280 | * AT\ | 2280 | * AT\ |
2281 | * H\ | 2281 | * H\ |
2282 | * \ | 2282 | * \ |
2283 | * It excercises a lot of corner cases. | 2283 | * It exercises a lot of corner cases. |
2284 | */ | 2284 | */ |
2285 | static void cmdedit_update_prompt(void) | 2285 | static void cmdedit_update_prompt(void) |
2286 | { | 2286 | { |
@@ -5235,7 +5235,7 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len | |||
5235 | /* And now we want to add { or } and continue: | 5235 | /* And now we want to add { or } and continue: |
5236 | * o_addchr(o, c); | 5236 | * o_addchr(o, c); |
5237 | * continue; | 5237 | * continue; |
5238 | * luckily, just falling throught achieves this. | 5238 | * luckily, just falling through achieves this. |
5239 | */ | 5239 | */ |
5240 | } | 5240 | } |
5241 | #endif | 5241 | #endif |
@@ -5830,7 +5830,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
5830 | arg++; | 5830 | arg++; |
5831 | /* Can't just stuff it into output o_string, | 5831 | /* Can't just stuff it into output o_string, |
5832 | * expanded result may need to be globbed | 5832 | * expanded result may need to be globbed |
5833 | * and $IFS-splitted */ | 5833 | * and $IFS-split */ |
5834 | debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch); | 5834 | debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch); |
5835 | G.last_exitcode = process_command_subs(&subst_result, arg); | 5835 | G.last_exitcode = process_command_subs(&subst_result, arg); |
5836 | debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); | 5836 | debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); |
@@ -7320,7 +7320,7 @@ static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status) | |||
7320 | /* There are still running processes in the fg_pipe */ | 7320 | /* There are still running processes in the fg_pipe */ |
7321 | return -1; | 7321 | return -1; |
7322 | } | 7322 | } |
7323 | /* It wasnt in fg_pipe, look for process in bg pipes */ | 7323 | /* It wasn't in fg_pipe, look for process in bg pipes */ |
7324 | } | 7324 | } |
7325 | 7325 | ||
7326 | #if ENABLE_HUSH_JOB | 7326 | #if ENABLE_HUSH_JOB |
@@ -9038,6 +9038,9 @@ static int FAST_FUNC builtin_type(char **argv) | |||
9038 | * - terminates shell (regardless of interactivity); | 9038 | * - terminates shell (regardless of interactivity); |
9039 | * if it has non-empty trap: | 9039 | * if it has non-empty trap: |
9040 | * - executes trap and returns to read; | 9040 | * - executes trap and returns to read; |
9041 | * SIGCHLD from children: | ||
9042 | * - does not interrupt read regardless of interactivity: | ||
9043 | * try: sleep 1 & read x; echo $x | ||
9041 | */ | 9044 | */ |
9042 | static int FAST_FUNC builtin_read(char **argv) | 9045 | static int FAST_FUNC builtin_read(char **argv) |
9043 | { | 9046 | { |
@@ -9071,7 +9074,7 @@ static int FAST_FUNC builtin_read(char **argv) | |||
9071 | 9074 | ||
9072 | if ((uintptr_t)r == 1 && errno == EINTR) { | 9075 | if ((uintptr_t)r == 1 && errno == EINTR) { |
9073 | unsigned sig = check_and_run_traps(); | 9076 | unsigned sig = check_and_run_traps(); |
9074 | if (sig && sig != SIGINT) | 9077 | if (sig != SIGINT) |
9075 | goto again; | 9078 | goto again; |
9076 | } | 9079 | } |
9077 | 9080 | ||
diff --git a/shell/hush_test/hush-misc/unicode1.tests b/shell/hush_test/hush-misc/unicode1.tests index 8788ba910..b8479cb41 100755 --- a/shell/hush_test/hush-misc/unicode1.tests +++ b/shell/hush_test/hush-misc/unicode1.tests | |||
@@ -5,7 +5,7 @@ a=`printf "\xcc\x80"` | |||
5 | # Should print 1 | 5 | # Should print 1 |
6 | echo ${#a} | 6 | echo ${#a} |
7 | 7 | ||
8 | # A Japanese katakana charachter U+30a3 | 8 | # A Japanese katakana character U+30a3 |
9 | a=`printf "\xe3\x82\xa3"` | 9 | a=`printf "\xe3\x82\xa3"` |
10 | # Should print 1 | 10 | # Should print 1 |
11 | echo ${#a} | 11 | echo ${#a} |
diff --git a/shell/hush_test/hush-read/read_SIGCHLD.right b/shell/hush_test/hush-read/read_SIGCHLD.right new file mode 100644 index 000000000..b3dc7ab0c --- /dev/null +++ b/shell/hush_test/hush-read/read_SIGCHLD.right | |||
@@ -0,0 +1,2 @@ | |||
1 | x='Ok' | ||
2 | exitcode:0 | ||
diff --git a/shell/hush_test/hush-read/read_SIGCHLD.tests b/shell/hush_test/hush-read/read_SIGCHLD.tests new file mode 100755 index 000000000..c5f673aff --- /dev/null +++ b/shell/hush_test/hush-read/read_SIGCHLD.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | x=BAD | ||
2 | { sleep 0.4; echo Ok; } | { sleep 0.2 & read x; echo "x='$x'"; } | ||
3 | echo "exitcode:$?" | ||
4 | |||
diff --git a/shell/shell_common.c b/shell/shell_common.c index 653154e34..55617b167 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c | |||
@@ -210,15 +210,17 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
210 | c = buffer[bufpos]; | 210 | c = buffer[bufpos]; |
211 | if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r')) | 211 | if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r')) |
212 | continue; | 212 | continue; |
213 | if (backslash) { | 213 | if (!(read_flags & BUILTIN_READ_RAW)) { |
214 | backslash = 0; | 214 | if (backslash) { |
215 | if (c != '\n') | 215 | backslash = 0; |
216 | goto put; | 216 | if (c != '\n') |
217 | continue; | 217 | goto put; |
218 | } | 218 | continue; |
219 | if (!(read_flags & BUILTIN_READ_RAW) && c == '\\') { | 219 | } |
220 | backslash = 1; | 220 | if (c == '\\') { |
221 | continue; | 221 | backslash = 1; |
222 | continue; | ||
223 | } | ||
222 | } | 224 | } |
223 | if (c == '\n') | 225 | if (c == '\n') |
224 | break; | 226 | break; |
@@ -408,13 +410,7 @@ shell_builtin_ulimit(char **argv) | |||
408 | /* In case getopt was already called: | 410 | /* In case getopt was already called: |
409 | * reset the libc getopt() function, which keeps internal state. | 411 | * reset the libc getopt() function, which keeps internal state. |
410 | */ | 412 | */ |
411 | #ifdef __GLIBC__ | 413 | GETOPT_RESET(); |
412 | optind = 0; | ||
413 | #else /* BSD style */ | ||
414 | optind = 1; | ||
415 | /* optreset = 1; */ | ||
416 | #endif | ||
417 | /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */ | ||
418 | 414 | ||
419 | argc = 1; | 415 | argc = 1; |
420 | while (argv[argc]) | 416 | while (argv[argc]) |