diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 68633188..f6f45358 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -9006,3 +9006,77 @@ subst.c introducing a `@' operator, but instead retains its meaning as all variables whose name begins with vvv. Fixes bug reported by konsolebox + + 7/14 + ---- +execute_cmd.c + - execute_connection: remove the fork optimization from and AND_AND + and OR_OR cases; it has trouble with `a && b && c', since the `&&' + is left-associative. Putting that code here can result in unwanted + fork optimizations since the `b' will end up as `second' on a + recursive call to execute_command. Bug reported by Mike Frysinger + + +builtins/evalstring.c + - optimize_fork: moved code from execute_connection to here; checks + whether the RHS of a && or || passes the suppress_fork() tests and + turns on the NO_FORK bit if so + - parse_and_execute: if suppress_fork() tests fail, check whether the + command to be executed is a connection and attempt to optimize the + fork for the right side using optimize_fork(). The key is dealing + with the entire command passed to `bash -c' or `eval' + +builtins/common.h + - optimize_fork: new extern declaration + +execute_cmd.c + - execute_command_internal: enable code put in to undo redirections + before exiting the shell due to `set -e' in the case of a shell + function that gets command-not-found or a syntax error. Reported + back in May, 2014 by Mark Ferrell + +bashhist.c + - bash_history_inhibit_expansion: enable change from 1/10 that skips + over history expansion character in command and process + substitution + + 7/15 + ---- +lib/readline/{history,undo}.c + - replace_history_data now _hs_replace_history_data + + 7/16 + ---- +lib/readline/readline.c + - make sure _rl_to_lower doesn't ever get characters that are outside + of its valid range by casting arg to unsigned char + +lib/readline/colors.h + - change completion prefix color (C_PREFIX) to be the same as C_SOCK, + which is less likely to collide with file type colorings (magenta) + +lib/readline/complete.c + - fnprint: now takes an additional argument: the full, expanded pathname + corresponding to the `toprint' argument + - fnprint: don't zero out prefix_bytes if we're not printing the + ellipisis but we still want to use prefix_bytes for displaying + the common prefix in a color + - print_filename: move colored-stats display responsibility into fnprint + - fnprint: change so colored-prefix and colored-stats can cooperate + and display filenames with multiple colors: one for the prefix and + one for the file type. The prefix is displayed in the prefix color + and the remainder of the pathname, if any, is displayed in the color + corresponding to the file type. Report and suggestion from Mike + Frysinger + + 7/17 + ---- +lib/readline/readline.[ch] + - rl_readline_state: now unsigned long + + 7/18 + ---- +lib/readline/history.h + - history_offset: now declared here, was always a global variable + - copy_history_entry: now declared here, part of the public interface + - alloc_history_entry: now declared here, part of the public interface diff --git a/MANIFEST b/MANIFEST index 7982cb41..dc28e04e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -529,6 +529,8 @@ po/ja.po f po/lt.gmo f po/lt.po f po/nl.gmo f +po/nb.po f +po/nb.gmo f po/nl.po f po/pl.gmo f po/pl.po f @@ -947,6 +949,7 @@ tests/exec8.sub f tests/exec9.sub f tests/exec10.sub f tests/exec11.sub f +tests/exec12.sub f tests/exp.tests f tests/exp.right f tests/exp1.sub f @@ -1002,6 +1005,7 @@ tests/heredoc3.sub f tests/herestr.tests f tests/herestr.right f tests/histexp.tests f +tests/histexp1.sub f tests/histexp.right f tests/history.tests f tests/history.right f diff --git a/bashhist.c b/bashhist.c index 6d076288..9c0df004 100644 --- a/bashhist.c +++ b/bashhist.c @@ -226,12 +226,11 @@ bash_history_inhibit_expansion (string, i) else if (extended_glob && i > 1 && string[i+1] == '(' && member (')', string + i + 2)) return (1); #endif -#if 0 /* bash-4.4 */ + /* Make sure the history expansion should not be skipped by quoting or command/process substitution. */ - else if (t = skip_to_delim (string, 0, hx, SD_NOJMP) > 0 && t > i) + else if ((t = skip_to_delim (string, 0, hx, SD_NOJMP)) > 0 && t > i) return (1); -#endif else return (0); } diff --git a/builtins/common.h b/builtins/common.h index d682a0a3..83607455 100644 --- a/builtins/common.h +++ b/builtins/common.h @@ -202,6 +202,7 @@ extern int evalstring __P((char *, const char *, int)); extern void parse_and_execute_cleanup __P((void)); extern int parse_string __P((char *, const char *, int, char **)); extern int should_suppress_fork __P((COMMAND *)); +extern int optimize_fork __P((COMMAND *)); /* Functions from evalfile.c */ extern int maybe_execute_file __P((const char *, int)); diff --git a/builtins/evalstring.c b/builtins/evalstring.c index a9734759..d367e103 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -109,6 +109,20 @@ should_suppress_fork (command) ((command->flags & CMD_TIME_PIPELINE) == 0) && ((command->flags & CMD_INVERT_RETURN) == 0)); } + +int +optimize_fork (command) + COMMAND *command; +{ + if (command->type == cm_connection && + (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR) && + should_suppress_fork (command->value.Connection->second)) + { + command->value.Connection->second->flags |= CMD_NO_FORK; + command->value.Connection->second->value.Simple->flags |= CMD_NO_FORK; + } +} + /* How to force parse_and_execute () to clean up after itself. */ void parse_and_execute_cleanup () @@ -375,6 +389,8 @@ parse_and_execute (string, from_file, flags) command->flags |= CMD_NO_FORK; command->value.Simple->flags |= CMD_NO_FORK; } + else if (command->type == cm_connection) + optimize_fork (command); #endif /* ONESHOT */ /* See if this is a candidate for $( value.Connection->second; if (ignore_return && second) second->flags |= CMD_IGNORE_RETURN; - if (should_suppress_fork (second)) - { - second->flags |= CMD_NO_FORK; - second->value.Simple->flags |= CMD_NO_FORK; - } exec_result = execute_command (second); } diff --git a/lib/readline/colors.h b/lib/readline/colors.h index 8627bd48..5c77af9d 100644 --- a/lib/readline/colors.h +++ b/lib/readline/colors.h @@ -114,8 +114,8 @@ enum filetype arg_directory }; -/* Prefix color, currently same as directory */ -#define C_PREFIX C_DIR +/* Prefix color, currently same as socket */ +#define C_PREFIX C_SOCK extern void _rl_put_indicator (const struct bin_str *ind); extern void _rl_set_normal_color (void); diff --git a/lib/readline/complete.c b/lib/readline/complete.c index 8617491d..f905c09f 100644 --- a/lib/readline/complete.c +++ b/lib/readline/complete.c @@ -128,7 +128,7 @@ static int get_y_or_n PARAMS((int)); static int _rl_internal_pager PARAMS((int)); static char *printable_part PARAMS((char *)); static int fnwidth PARAMS((const char *)); -static int fnprint PARAMS((const char *, int)); +static int fnprint PARAMS((const char *, int, const char *)); static int print_filename PARAMS((char *, char *, int)); static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int)); @@ -212,6 +212,8 @@ int rl_visible_stats = 0; completions. The colors used are taken from $LS_COLORS, if set. */ int _rl_colored_stats = 0; +/* Non-zero means to use a color (currently magenta) to indicate the common + prefix of a set of possible word completions. */ int _rl_colored_completion_prefix = 1; #endif @@ -798,9 +800,10 @@ fnwidth (string) #define ELLIPSIS_LEN 3 static int -fnprint (to_print, prefix_bytes) +fnprint (to_print, prefix_bytes, real_pathname) const char *to_print; int prefix_bytes; + const char *real_pathname; { int printed_len, w; const char *s; @@ -819,10 +822,17 @@ fnprint (to_print, prefix_bytes) printed_len = common_prefix_len = 0; /* Don't print only the ellipsis if the common prefix is one of the - possible completions */ - if (to_print[prefix_bytes] == '\0') + possible completions. Only cut off prefix_bytes if we're going to be + printing the ellipsis, which takes precedence over coloring the + completion prefix (see print_filename() below). */ + if (_rl_completion_prefix_display_length > 0 && to_print[prefix_bytes] == '\0') prefix_bytes = 0; +#if defined (COLOR_SUPPORT) + if (_rl_colored_stats && (prefix_bytes == 0 || _rl_colored_completion_prefix <= 0)) + colored_stat_start (real_pathname); +#endif + if (prefix_bytes && _rl_completion_prefix_display_length > 0) { char ellipsis; @@ -893,13 +903,23 @@ fnprint (to_print, prefix_bytes) } if (common_prefix_len > 0 && (s - to_print) >= common_prefix_len) { +#if defined (COLOR_SUPPORT) /* printed bytes = s - to_print */ /* printed bytes should never be > but check for paranoia's sake */ colored_prefix_end (); + if (_rl_colored_stats) + colored_stat_start (real_pathname); /* XXX - experiment */ +#endif common_prefix_len = 0; } } +#if defined (COLOR_SUPPORT) + /* XXX - unconditional for now */ + if (_rl_colored_stats) + colored_stat_end (); +#endif + return printed_len; } @@ -920,7 +940,7 @@ print_filename (to_print, full_pathname, prefix_bytes) /* Defer printing if we want to prefix with a color indicator */ if (_rl_colored_stats == 0 || rl_filename_completion_desired == 0) #endif - printed_len = fnprint (to_print, prefix_bytes); + printed_len = fnprint (to_print, prefix_bytes, to_print); if (rl_filename_completion_desired && ( #if defined (VISIBLE_STATS) @@ -989,13 +1009,10 @@ print_filename (to_print, full_pathname, prefix_bytes) extension_char = '/'; } + /* Move colored-stats code inside fnprint() */ #if defined (COLOR_SUPPORT) if (_rl_colored_stats) - { - colored_stat_start (new_full_pathname); - printed_len = fnprint (to_print, prefix_bytes); - colored_stat_end (); - } + printed_len = fnprint (to_print, prefix_bytes, new_full_pathname); #endif xfree (new_full_pathname); @@ -1012,15 +1029,11 @@ print_filename (to_print, full_pathname, prefix_bytes) if (_rl_complete_mark_directories && path_isdir (s)) extension_char = '/'; + /* Move colored-stats code inside fnprint() */ #if defined (COLOR_SUPPORT) if (_rl_colored_stats) - { - colored_stat_start (s); - printed_len = fnprint (to_print, prefix_bytes); - colored_stat_end (); - } + printed_len = fnprint (to_print, prefix_bytes, s); #endif - } xfree (s); diff --git a/lib/readline/history.c b/lib/readline/history.c index 14696934..92398db7 100644 --- a/lib/readline/history.c +++ b/lib/readline/history.c @@ -405,7 +405,7 @@ replace_history_entry (which, line, data) WHICH >= 0 means to replace that particular history entry's data, as long as it matches OLD. */ void -replace_history_data (which, old, new) +_hs_replace_history_data (which, old, new) int which; histdata_t *old, *new; { diff --git a/lib/readline/history.h b/lib/readline/history.h index 779a573c..b79e51f4 100644 --- a/lib/readline/history.h +++ b/lib/readline/history.h @@ -91,6 +91,13 @@ extern void add_history_time PARAMS((const char *)); elements are numbered from 0. */ extern HIST_ENTRY *remove_history PARAMS((int)); +/* Allocate a history entry consisting of STRING and TIMESTAMP and return + a pointer to it. */ +extern HIST_ENTRY *alloc_history_entry PARAMS((char *, char *)); + +/* Copy the history entry H, but not the (opaque) data pointer */ +extern HIST_ENTRY *copy_history_entry PARAMS((HIST_ENTRY *)); + /* Free the history entry H and return any application-specific data associated with it. */ extern histdata_t free_history_entry PARAMS((HIST_ENTRY *)); @@ -241,6 +248,7 @@ extern char **history_tokenize PARAMS((const char *)); extern int history_base; extern int history_length; extern int history_max_entries; +extern int history_offset; extern int history_lines_read_from_file; extern int history_lines_written_to_file; diff --git a/lib/readline/readline.c b/lib/readline/readline.c index 14633081..0a54dc3c 100644 --- a/lib/readline/readline.c +++ b/lib/readline/readline.c @@ -151,7 +151,7 @@ static int running_in_emacs; #endif /* Flags word encapsulating the current readline state. */ -int rl_readline_state = RL_STATE_NONE; +unsigned long rl_readline_state = RL_STATE_NONE; /* The current offset in the current input line. */ int rl_point; @@ -846,7 +846,7 @@ _rl_dispatch_subseq (key, map, got_subseq) /* Special case rl_do_lowercase_version (). */ if (func == rl_do_lowercase_version) /* Should we do anything special if key == ANYOTHERKEY? */ - return (_rl_dispatch (_rl_to_lower (key), map)); + return (_rl_dispatch (_rl_to_lower ((unsigned char)key), map)); rl_executing_keymap = map; rl_executing_key = key; @@ -1022,7 +1022,7 @@ _rl_subseq_result (r, map, key, got_subseq) type = m[ANYOTHERKEY].type; func = m[ANYOTHERKEY].function; if (type == ISFUNC && func == rl_do_lowercase_version) - r = _rl_dispatch (_rl_to_lower (key), map); + r = _rl_dispatch (_rl_to_lower ((unsigned char)key), map); else if (type == ISFUNC) { /* If we shadowed a function, whatever it is, we somehow need a diff --git a/lib/readline/readline.h b/lib/readline/readline.h index cac13d7b..e1773fa7 100644 --- a/lib/readline/readline.h +++ b/lib/readline/readline.h @@ -493,7 +493,7 @@ extern int rl_readline_version; /* e.g., 0x0402 */ extern int rl_gnu_readline_p; /* Flags word encapsulating the current readline state. */ -extern int rl_readline_state; +extern unsigned long rl_readline_state; /* Says which editing mode readline is currently using. 1 means emacs mode; 0 means vi mode. */ diff --git a/lib/readline/undo.c b/lib/readline/undo.c index e9369b1a..ec0578c4 100644 --- a/lib/readline/undo.c +++ b/lib/readline/undo.c @@ -50,7 +50,7 @@ #include "rlprivate.h" #include "xmalloc.h" -extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *)); +extern void _hs_replace_history_data PARAMS((int, histdata_t *, histdata_t *)); /* Non-zero tells rl_delete_text and rl_insert_text to not add to the undo list. */ @@ -129,7 +129,7 @@ rl_free_undo_list () orig_list = rl_undo_list; _rl_free_undo_list (rl_undo_list); rl_undo_list = (UNDO_LIST *)NULL; - replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL); + _hs_replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL); } UNDO_LIST * @@ -245,7 +245,7 @@ rl_do_undo () xfree (temp); } - replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list); + _hs_replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list); xfree (release); } diff --git a/redir.c b/redir.c index 539af00d..63801548 100644 --- a/redir.c +++ b/redir.c @@ -121,10 +121,7 @@ redirection_error (temp, error) else if ((temp->rflags & REDIR_VARASSIGN) == 0 && temp->redirector.dest < 0) /* This can happen when read_token_word encounters overflow, like in exec 4294967297>x */ -{ -itrace("redirection_error: temp->redirector.dest = %d", temp->redirector.dest); filename = _("file descriptor out of range"); -} #ifdef EBADF /* This error can never involve NOCLOBBER */ else if (error != NOCLOBBER_REDIRECT && temp->redirector.dest >= 0 && error == EBADF) diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 72ec06a2..3efcf32d 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/bash/bash-current +BUILD_DIR=/usr/local/build/chet/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/tests/exec.right b/tests/exec.right index 3c2a7fcd..66b1581e 100644 --- a/tests/exec.right +++ b/tests/exec.right @@ -81,3 +81,19 @@ group pipeline: 1 EXIT-group.1 foo 0 after +exit code: 1 +exit code: 1 +exit code: 1 +exit code: 127 +exit code: 127 +exit code: 127 +a +b +c +A +B +c +d +c +d +e diff --git a/tests/exec12.sub b/tests/exec12.sub new file mode 100644 index 00000000..4bd6121b --- /dev/null +++ b/tests/exec12.sub @@ -0,0 +1,17 @@ +: ${TMPDIR:=/var/tmp} +TMPFILE=$TMPDIR/exitcode + +rm -f $TMPFILE +set -e +exit_handler() { echo "exit code: $?" ; touch $TMPFILE; } +false() { ! :; } +notfound() { nosuchcommand ; } +syntaxerror() { !:; } + +main() +{( + trap exit_handler 0 + "$@" >> /dev/null 2>&1 +)} +main "$@" +echo "after main: should not get here" diff --git a/tests/execscript b/tests/execscript index f9c7aca5..218ccb9d 100644 --- a/tests/execscript +++ b/tests/execscript @@ -128,3 +128,30 @@ ${THIS_SH} -c 'VAR=0; VAR=1 command exec; exit ${VAR}' echo bad ) 2>/dev/null [ $? = 127 ] || echo FAIL: bad exit status $? at $LINENO + +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 + +# problem with undoing redirections before running exit trap through bash-4.3 + +${THIS_SH} ./exec12.sub false # function +${THIS_SH} ./exec12.sub command false +${THIS_SH} ./exec12.sub $FALSE + +${THIS_SH} ./exec12.sub notfound +${THIS_SH} ./exec12.sub syntaxerror +${THIS_SH} ./exec12.sub nosuchcommand + +# problem with fork optimization in bash-4.4-alpha + +$THIS_SH -c 'echo a && /bin/echo b && echo c' +$THIS_SH -c 'echo A && /bin/echo B' + +$THIS_SH -c '/bin/echo c && echo d' +$THIS_SH -c '/bin/echo c && /bin/echo d && echo e' diff --git a/tests/histexp.right b/tests/histexp.right index 2b848bbe..425a8eae 100644 --- a/tests/histexp.right +++ b/tests/histexp.right @@ -130,3 +130,16 @@ ok 3 echo shopt a shopt a echo a b c d 2 > /dev/null +! +! +! +! +! +! +! +! +! +\! +\! +\! +\! diff --git a/tests/histexp.tests b/tests/histexp.tests index d9be836d..f166967c 100644 --- a/tests/histexp.tests +++ b/tests/histexp.tests @@ -127,3 +127,5 @@ shopt a b c d 2>/dev/null echo !shopt-1 echo !shopt* + +${THIS_SH} ./histexp1.sub diff --git a/tests/histexp1.sub b/tests/histexp1.sub new file mode 100644 index 00000000..a5948f1e --- /dev/null +++ b/tests/histexp1.sub @@ -0,0 +1,23 @@ +LC_ALL=C +LANG=C + +set -o history +set -H + +echo '!' +echo "!" +echo ! + +echo "$( echo '!' )" +echo "$( echo "!" )" +echo "$( echo ! )" + +echo $( echo '!' ) +echo $( echo "!" ) +echo $( echo ! ) + +echo "$( echo "\!" )" +echo "\!" + +echo "$( echo '\!' )" +echo '\!'