to accommodate symbolic key sequences; should be a no-op for `raw'
key sequences such as the arrow key seqeunces from terminfo. Change
from Koichi Murase <myoga.murase@gmail.com>
+
+ 4/2
+ ---
+jobs.c
+ - wait_for: when setting the SIGINT signal handler to wait_sigint_handler
+ make sure we're not setting old_sigint_handler recursively, as we
+ can when running an external command in a trap we took after a
+ command exited due to SIGINT. We don't want to overwrite
+ old_sigint_handler here. Fixes bug reported by Dr. Werner Fink
+ <werner@suse.de>
+
+execute_cmd.c
+ - execute_disk_command: when there is a command_not_found_hook, make
+ sure the subshell turns off job control before running it, in case
+ it runs processes. We don't want it to manipulate process groups.
+ Fixes bug reported by ÐиÑиллов Ðима <dk.1997-fast@yandex.ru>
+ - execute_command_internal: make sure the command run by the `command'
+ builtin doesn't cause the ERR trap to be executed; wait for the
+ status to be returned by the command builtin. Fixes bug reported by
+ Martijn Dekker <martijn@inlv.org>
+
+ 4/4
+ ---
+subst.c
+ - process_substitute: handle longjmp back to top_level and function
+ returns (return_catch) in the child process, like command
+ substitution, so we don't longjmp back to some arbitrary spot from
+ the `exit' or `return' builtins, or on an expansion error, like
+ the command timing code. Fixes bug reported by Basin Ilya
+ <basinilya@gmail.com>
+
+ 4/6
+ ---
+parse.y
+ - read_token_word: when reading a matched pair of backquotes as part
+ of a word, treat it as quoted so the characters are read as a single
+ word, but do not let the presence of the backquote mark the word as
+ quoted. Fixes here-document delimiter bug reported by Denys Vlasenko
+ <dvlasenk@redhat.com>
+
+ 4/7
+ ---
+execute_cmd.c
+ - execute_case_command: call quote_string_for_globbing with the
+ QGLOB_CTLESC flag for both quoted and unquoted words, so it will
+ remove CTLESC/CTLESC in all cases while converting other quoted
+ characters to use a preceding backslash. Bug reported by
+ Martijn Dekker <martijn@inlv.org>
+
+ 4/9
+ ---
+smatch.c
+ - posix_cclass_only: helper function that checks whether a pattern has
+ only posix single-byte character classes ([:alpha:], etc.) or has
+ none at all
+ - xstrmatch: if running in a multibyte locale, make sure to short-
+ circuit to the single-byte matching code only if there are no
+ unrecognized character class names, since the wide character ctype
+ functions allow locales to define their own character class names
+ (e.g., "hyphen"). Fixes issue reported by yangyajing <yyj_cqu@163.com>
tests/case.right f
tests/case1.sub f
tests/case2.sub f
+tests/case3.sub f
tests/casemod.tests f
tests/casemod.right f
tests/comsub.tests f
tests/heredoc1.sub f
tests/heredoc2.sub f
tests/heredoc3.sub f
+tests/heredoc4.sub f
tests/herestr.tests f
tests/herestr.right f
tests/herestr1.sub f
}
/* 2009/02/13 -- pipeline failure is processed elsewhere. This handles
- only the failure of a simple command. */
- if (was_error_trap && ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)
+ only the failure of a simple command. We don't want to run the error
+ trap if the command run by the `command' builtin fails; we want to
+ defer that until the command builtin itself returns failure. */
+ if (was_error_trap && ignore_return == 0 && invert == 0 &&
+ pipe_in == NO_PIPE && pipe_out == NO_PIPE &&
+ (command->value.Simple->flags & CMD_COMMAND_BUILTIN) == 0 &&
+ exec_result != EXECUTION_SUCCESS)
{
last_command_exit_value = exec_result;
line_number = line_number_for_err_trap;
else
time_format = BASH_TIMEFORMAT;
}
+
if (time_format && *time_format)
print_formatted_time (stderr, time_format, rs, rsf, us, usf, ss, ssf, cpu);
if (es && es->word && es->word->word && *(es->word->word))
{
+ /* Convert quoted null strings into empty strings. */
qflags = QGLOB_CVTNULL;
+
/* We left CTLESC in place quoting CTLESC after the call to
expand_word_leave_quoted; tell quote_string_for_globbing to
- remove those here */
- if ((list->word->flags & W_QUOTED) == 0)
- qflags |= QGLOB_CTLESC;
+ remove those here. This works for both unquoted portions of
+ the word (which call quote_escapes) and quoted portions
+ (which call quote_string). */
+ qflags |= QGLOB_CTLESC;
pattern = quote_string_for_globbing (es->word->word, qflags);
}
else
exit (EX_NOTFOUND); /* Posix.2 says the exit status is 127 */
}
+ /* We don't want to manage process groups for processes we start
+ from here, so we turn off job control and don't attempt to
+ manipulate the terminal's process group. */
+ without_job_control ();
+
#if defined (JOB_CONTROL)
- /* May need to reinitialize more of the job control state here. */
- kill_current_pipeline ();
+ set_sigchld_handler ();
#endif
wl = make_word_list (make_word (NOTFOUND_HOOK), words);
};
#endif
+/* Placeholder for later expansion to include more execution state */
+/* XXX - watch out for pid_t */
+struct execstate
+ {
+ pid_t pid;
+ int subshell_env;
+ };
+
+
/* Variables delared in execute_cmd.c, used by many other files */
extern int return_catch_flag;
extern int return_catch_value;
wait_sigint_received = child_caught_sigint = 0;
if (job_control == 0 || (subshell_environment&SUBSHELL_COMSUB))
{
- old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
+ SigHandler *temp_sigint_handler;
+
+ temp_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
+ if (temp_sigint_handler == wait_sigint_handler)
+ {
+#if defined (DEBUG)
+ internal_warning ("wait_for: recursively setting old_sigint_handler to wait_sigint_handler: running_trap = %d", running_trap);
+#endif
+ }
+ else
+ old_sigint_handler = temp_sigint_handler;
waiting_for_child = 0;
if (old_sigint_handler == SIG_IGN)
set_signal_handler (SIGINT, old_sigint_handler);
return (iswctype (wc, desc));
}
+/* Return 1 if there are no char class [:class:] expressions (degenerate case)
+ or only posix-specified (C locale supported) char class expressions in
+ PATTERN. These are the ones where it's safe to punt to the single-byte
+ code, since wide character support allows locale-defined char classes.
+ This only uses single-byte code, but is only needed to support multibyte
+ locales. */
+static int
+posix_cclass_only (pattern)
+ char *pattern;
+{
+ char *p, *p1;
+ char cc[16]; /* sufficient for all valid posix char class names */
+ enum char_class valid;
+
+ p = pattern;
+ while (p = strchr (p, '['))
+ {
+ if (p[1] != ':')
+ {
+ p++;
+ continue;
+ }
+ p += 2; /* skip past "[:" */
+ /* Find end of char class expression */
+ for (p1 = p; *p1; p1++)
+ if (*p1 == ':' && p1[1] == ']')
+ break;
+ if (*p1 == 0) /* no char class expression found */
+ break;
+ /* Find char class name and validate it against posix char classes */
+ if ((p1 - p) >= sizeof (cc))
+ return 0;
+ bcopy (p, cc, p1 - p);
+ cc[p1 - p] = '\0';
+ valid = is_valid_cclass (cc);
+ if (valid == CC_NO_CLASS)
+ return 0; /* found unrecognized char class name */
+
+ p = p1 + 2; /* found posix char class name */
+ }
+
+ return 1; /* no char class names or only posix */
+}
+
/* Now include `sm_loop.c' for multibyte characters. */
#define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c))
#define FCT internal_wstrmatch
if (MB_CUR_MAX == 1)
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
- if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0)
+ if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0 && posix_cclass_only (pattern) )
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
n = xdupmbstowcs (&wpattern, NULL, pattern);
.B call\-last\-kbd\-macro (C\-x e)
Re-execute the last keyboard macro defined, by making the characters
in the macro appear as if typed at the keyboard.
+.TP
.B print\-last\-kbd\-macro ()
Print the last keyboard macro defined in a format suitable for the
\fIinputrc\fP file.
strcpy (token + token_index, ttok);
token_index += ttoklen;
all_digit_token = 0;
- quoted = 1;
+ if (character != '`')
+ quoted = 1;
dollar_present |= (character == '"' && strchr (ttok, '$') != 0);
FREE (ttok);
goto next_character;
#define QGLOB_FILENAME 0x02 /* do correct quoting for matching filenames */
#define QGLOB_REGEXP 0x04 /* quote an ERE for regcomp/regexec */
#define QGLOB_CTLESC 0x08 /* turn CTLESC CTLESC into CTLESC for BREs */
+#define QGLOB_DEQUOTE 0x10 /* like dequote_string but quote glob chars */
#if defined (EXTENDED_GLOB)
/* Flags to OR with other flag args to strmatch() to enabled the extended
int open_for_read_in_child;
{
char *pathname;
- int fd, result;
+ int fd, result, rc, function_value;
pid_t old_pid, pid;
#if defined (HAVE_DEV_FD)
int parent_pipe_fd, child_pipe_fd;
remove_quoted_escapes (string);
- subshell_level++;
- result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
- /* leave subshell level intact for any exit trap */
+ /* Give process substitution a place to jump back to on failure,
+ so we don't go back up to main (). */
+ result = setjmp_nosigs (top_level);
+
+ /* If we're running a process substitution inside a shell function,
+ trap `return' so we don't return from the function in the subshell
+ and go off to never-never land. */
+ if (result == 0 && return_catch_flag)
+ function_value = setjmp_nosigs (return_catch);
+ else
+ function_value = 0;
+
+ if (result == ERREXIT)
+ rc = last_command_exit_value;
+ else if (result == EXITPROG)
+ rc = last_command_exit_value;
+ else if (result)
+ rc = EXECUTION_FAILURE;
+ else if (function_value)
+ rc = return_catch_value;
+ else
+ {
+ subshell_level++;
+ rc = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
+ /* leave subshell level intact for any exit trap */
+ }
#if !defined (HAVE_DEV_FD)
/* Make sure we close the named pipe in the child before we exit. */
close (open_for_read_in_child ? 0 : 1);
#endif /* !HAVE_DEV_FD */
- last_command_exit_value = result;
- result = run_exit_trap ();
- exit (result);
+ last_command_exit_value = rc;
+ rc = run_exit_trap ();
+ exit (rc);
/*NOTREACHED*/
}
#endif /* PROCESS_SUBSTITUTION */
-BUILD_DIR=/usr/local/build/chet/bash/bash-current
+BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
ok 6
ok 7
ok 8
+--- testing: soh
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+--- testing: stx
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
# tests of quote removal and pattern matching
${THIS_SH} ./case1.sub
${THIS_SH} ./case2.sub
+${THIS_SH} ./case3.sub
--- /dev/null
+#!/bin/sh
+
+testmatch() {
+ case $1 in
+ ( $2 ) printf ok1 ;;
+ ( * ) printf fail1 ;;
+ esac
+ case $1,$2 in
+ ( $2,"$2" ) printf ok2 ;;
+ ( * ) printf fail2 ;;
+ esac
+ case $1, in
+ ( $2, ) printf ok3 ;;
+ ( * ) printf fail3 ;;
+ esac
+ case ,$2 in
+ ( ,"$2" ) printf ok4 ;;
+ ( * ) printf fail4 ;;
+ esac
+ case "$1,$2" in
+ ( $2,"$2" ) printf ok5 ;;
+ ( * ) printf fail5 ;;
+ esac
+ echo
+}
+
+for c in $'\1' $'\2'; do
+ echo -n "--- testing: "
+ echo "$c" | od -t a | awk 'NR==1 { print $2 } '
+ testmatch "${c}" "\\${c}"
+ testmatch "${c}x" "\\${c}\\x" # bash-git fails case 2 and 5 for $'\1'
+ testmatch "${c}x" "${c}\\x"
+ testmatch "${c}x" "${c}x"
+ testmatch "${c}x" "\\${c}x"
+ testmatch "x${c}" "\\x\\${c}"
+ testmatch "x${c}" "x\\${c}"
+done
end hello<NL>\END
./heredoc3.sub: line 85: warning: here-document at line 83 delimited by end-of-file (wanted `EOF')
./heredoc3.sub: line 86: syntax error: unexpected end of file
+heredoc1
+EOF
+Ok:0
+argv[1] = <onetwo>
+argv[2] = <threefour>
+argv[1] = <two>
+argv[2] = <threefi>
+argv[3] = <ve>
comsub here-string
./heredoc.tests: line 105: warning: here-document at line 103 delimited by end-of-file (wanted `EOF')
hi
# test heredocs in command substitutions
${THIS_SH} ./heredoc2.sub
-
${THIS_SH} ./heredoc3.sub
+${THIS_SH} ./heredoc4.sub
echo $(
cat <<< "comsub here-string"
--- /dev/null
+cat <<EO`true`F
+heredoc1
+EO`false`F
+EO`true`F
+echo Ok:$?
+
+one=one
+four=four
+five='fi ve'
+
+recho $one`echo two three`$four
+recho `echo two three`$five
job 6 returns 0
Waiting for job 7
job 7 returns 0
-[1] Running sleep 5 &
-[2] Running sleep 5 &
-[3] Running sleep 5 &
-[4]- Running sleep 5 &
-[5]+ Running ( sleep 5; exit 4 ) &
+[1] Running sleep 2 &
+[2] Running sleep 2 &
+[3] Running sleep 2 &
+[4]- Running sleep 2 &
+[5]+ Running ( sleep 2; exit 4 ) &
4
0
i killed it
before false in trap2a.sub
after false in trap2a.sub
command substitution
+ERRTRAP
+ERRTRAP
+bar
+ERRTRAP
+ERRTRAP
+ERRTRAP
+ERRTRAP
+ERRTRAP
+[6] echo 1
1
+[7] echo 2
./trap2a.sub
echo $(false ; echo command substitution)
+
+# test behavior of failed commands following `command' builtin
+command false
+
+(command false)
+command false | echo bar
+
+(false)
+
+exit 42 | command false
+
+command command command false
+
+unset FALSE
+if [ -x /bin/false ]; then
+ FALSE=/bin/false
+elif [ -x /usr/bin/false ]; then
+ FALSE=/usr/bin/false
+else
+ FALSE='command false'
+fi
+
+command $FALSE
+command command command $FALSE