From: Chet Ramey Date: Tue, 5 Jun 2012 14:16:06 +0000 (-0400) Subject: commit bash-20120504 snapshot X-Git-Tag: bash-4.3-alpha~67 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=efc2f955a04ec1e151058babac1269cf5abd3182;p=thirdparty%2Fbash.git commit bash-20120504 snapshot --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index e34c019c5..6168935f3 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -13789,3 +13789,17 @@ execute_cmd.c getdtablesize() and to not stomp on existing open file descriptors, like the fd the shell is using to read a script. Bug report from Greg Wooledge + + 5/6 + --- +subst.c + - expand_word_internal: case '$': after calling param_expand and + setting had_quoted_null, set TEMP to null. The code that builds the + returned string at the end of the function will take care of making + and returning a quoted null string if there's nothing else in + ISTRING. If there is, the quoted null should just go away. Part of + fix for bug reported by Ruediger Kuhlmann + - expand_word_internal: when processing ISTRING to build return value, + only set W_HASQUOTEDNULL in the returned word flags if the word is + a quoted null string AND had_quoted_null is set. Rest of fix + diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ new file mode 100644 index 000000000..e9d535ce0 --- /dev/null +++ b/CWRU/CWRU.chlog~ @@ -0,0 +1,13801 @@ + 7/27/2004 + --------- + +[bash-3.0 released] + + 7/28 + ---- +array.c + - in array_insert(), make sure the value to be added is non-NULL before + calling savestring() on it + +builtins/reserved.def + - fix description of `CDPATH' + +lib/readline/display.c + - when expanding a prompt that spans multiple lines with embedded + newlines, set prompt_physical_chars from the portion after the + final newline, not the preceding portion. Bug reported by + "Ralf S. Engelschall" + +make_cmd.c + - explicitly declare `lineno' in function prologue for make_case_command + +builtins/evalfile.c + - include `trap.h' for declaration for run_return_trap + +bashline.c + - fix a `return' without a value in enable_hostname_completion + +general.c + - include test.h for extern declaration for test_eaccess + +externs.h + - add declaration for zcatfd + +tests/{history,histexp}.tests + - unset HISTFILESIZE to avoid problems if a value of 0 is inherited + from the environment + + 7/30 + ---- +bashline.c + - small changes to glob_expand_word to perform tilde expansion before + attempting globbing + +builtins/Makefile.in + - fix the install-help target to not cd into the `helpfiles' + subdirectory, so a value of $INSTALL_DATA containing a relative + pathname (e.g., .././support/install.sh) remains valid + + 7/31 + ---- +subst.c + - new function, mbstrlen(s), returns length of a multibyte character + string + +include/shmbutil.h + - new macro, MB_STRLEN(s), calls mbstrlen or STRLEN as appropriate + +builtins/trap.def + - small change so that a first argument that's a valid signal number + (digits only -- no symbolic names) will be treated as a signal and + reverted back to the original handling disposition. Fixes debian + complaints + +subst.c + - call MB_STRLEN instead of STRLEN where appropriate in + parameter_brace_expand_length to handle multibyte characters properly + - call MB_STRLEN instead of strlen in verify_substring_values so that + negative substrings of strings with multibyte chars work properly + + 8/1 + --- +jobs.c + - describe_pid needs to write to stderr, not stdout (POSIX) + - start_job, since it's only used by builtins (fg/bg), needs to write + its output to stdout, not stderr (POSIX) + +sig.c + - add an `orig_flags' member to struct terminating_signal so the + original signal handling flags (SA_RESTART, etc.) can be preserved + on POSIX systems + - make sure to preserve the signal flags state in + initialize_terminating_signals and reset them for child processes + in reset_terminating_signals + +builtins/fc.def + - fixed an off-by-one error that caused `fc -l' to list one too many + history entries + - in posix mode, `fc' should not list any indication as to whether or + not history lines have been modified (POSIX) + - when in posix mode, the default editor for `fc' should be `ed' (POSIX) + +doc/bashref.texi + - updated the description of `trap' behavior when given a first + argument that is a valid signal number + - noted that `fc -l' won't indicate whether a history entry has been + modified if the shell is in posix mode + +builtins/command.def + - fixed bug: `command -v' is supposed to be silent if a command is not + found + +builtins/hash.def + - `hash' should print its `hash table empty' message to stderr + +lib/readline/misc.c + - back out 7/7 change to _rl_maybe_save_line; it breaks emacs-mode ^P + +general.c + - changed base_pathname so that it will return reasonable results for + non-absolute pathnames -- this is what is intended by all of its + callers + +arrayfunc.c + - fix array_variable_part to return NULL if it finds an invisible + variable in the hash table. Fixes seg fault caused by referring to + unset local variable using array notation + +{locale,variables}.c + - support LC_TIME as a special locale variable so HISTTIMEFORMAT tracks + the current locale + + 8/2 + --- +variables.c + - fixed small memory leak in makunbound() when a local array variable + is unset. Fix from William Park + +lib/readline/display.c + - fixed a problem when computing the number of invisible characters on + the first line of a prompt whose length exceeds the screen width + (should only happen when invisible characters occur after the + line wrap). Bug reported by agriffis@gentoo.org + +builtins/command.def + - `command -V' passes a new flag, CDESC_ABSPATH, which means to convert + to an absolute path + +builtins/type.def + - in posix mode, `type' and `command -v/-V' should not report + non-executable files, even if the execution code will attempt to + run them. Other posix shells do this + +doc/bashref.texi + - add note to POSIX Mode section describing behavior of type and command + when finding a non-executable file + +execute_cmd.c + - force extended_glob to 1 before calling binary_test in + execute_cond_node so that the right extended pattern matching gets + performed + + 8/3 + --- +braces.c + - make sure lhs[0] and rhs[0] are cast to `unsigned char' so chars + with values > 128 are handled correctly + +builtins/printf.def + - change bexpand() and printstr() to handle strings with a leading + '\0' whose length is non-zero, since that's valid input for the + `%b' format specifier + +subst.c + - fix a couple of instances of find_variable that didn't check the + result for an invisible variable + +variables.c + - BASH_ARGC, BASH_ARGV, BASH_SOURCE, BASH_LINENO no longer created as + invisible vars + +pcomplete.c + - make sure COMP_WORDS is not invisible when bind_comp_words returns + - ditto for COMPREPLY in gen_shell_function_matches + + 8/4 + --- +braces.c + - fix problem where ${ was ignored but did not increment the open + brace count. Bug reported by Tim Waugh + +variables.c + - if make_local_variable finds a variable in the correct context in + the right variable scope, make sure it's not invisible before + returning it + + 8/5 + --- +builtins/trap.def + - fixed usage message to show `action' as not optional, though it + actually is when not in posix mode (for a single argument) + + 8/7 + --- +configure.in + - kfreebsd-gnu has had its sbrk() problems fixed, and no longer needs + to be configured --without-gnu-malloc + +lib/readline/vi_mode.c + - in rl_vi_search, free any saved history line before starting the + search, so failure leaves you at that line, not the last line in + the history (assuming the current line is not the last history line). + Fix from llattanzi@apple.com to replace fix of 7/7 + + 8/9 + --- +support/Makefile.in + - renamed `mostly-clean' target to `mostlyclean' + + 8/11 + ---- +lib/readline/vi_mode.c + - make same change for EOL in multibyte character case of + rl_vi_change_char + + 8/12 + ---- +subst.c + - in verify_substring_values, fix off-by-one error checking bounds of + `offset', esp. in array values (e.g., getting the highest element + of an array) + + 8/16 + ---- +aclocal.m4 + - change BASH_CHECK_DEV_FD to make sure that file descriptors > 2 are + accessible via /dev/fd, unlike FreeBSD 5.x + +lib/sh/strftime.c + - make sure `zone' is initialized with gettimeofday before it is used + - work around HPUX lack of `altzone' and differing definitions of + `timezone' + +lib/malloc/malloc.c + - internal_memalign and memalign now take a `size_t' as their first + argument, which seems to be the prevailing standard + +lib/malloc/{malloc.c,shmalloc.h} + - change sh_memalign to take a `size_t' as its first argument + +builtins/echo.def + - if posixly_correct and xpg_echo are both set, don't try to interpret + any arguments at all, as POSIX/XOPEN requires (fix inspired by Paul + Eggert) + +doc/bashref.texi + - amend description of bash posix mode to include new echo behavior + +builtins/fg_bg.def + - allow bg to take multiple job arguments, as posix seems to specify, + placing them all in the background, returning the status of the last + one as the status of `bg' + +lib/readline/vi_mode + - fix _rl_vi_change_mbchar_case (multibyte-char version of `~' + command) to have the right behavior at EOL -- handle case where vi + mode backs up at the end of the line + + 8/18 + ---- +array.c + - check for an empty array in array_rshift before shifting elements + and adjusting max_index + - check for null array in array_subrange + +jobs.c + - fix raw_job_exit_status to not ignore exit status of the last + process in the pipeline when `set -o pipefail' is enabled + + 8/19 + ---- +lib/readline/mbutil.c + - make sure _rl_find_next_mbchar_internal has a valid multibyte + character before it checks whether or not it's a zero-width + wide character and adjusts point accordingly + + 8/24 + ---- +bashline.c + - new function, bash_directory_expansion, duplicates the expansions + performed on the directory name by rl_filename_completion_function + - call bash_directory_expansion in command_word_completion_function + if we decide we're doing tilde expansion (and any other + canonicalization) on the directory name being completed + + 8/25 + ---- +configure.in + - use new-style AC_CHECK_HEADER to check for sys/ptem.h (which requires + sys/stream.h). The correct checks are in the code, but autoconf + complains if sys/stream.h is not included, rather than simply + checking for the header's presence + + 8/26 + ---- +builtins/hash.def + - fix a bug that prevented `hash -d' from working right (as soon as + hash removed a command from the table, the bug caused it to be added + right back) + + 8/27 + ---- +doc/{bash.1,bashref.texi} + - explicitly note that conditional primaries that operate on files + operate on the targets of symbolic links rather than the links + themselves + + 8/30 + ---- +lib/readline/display.c + - fix multibyte calculation of `physchars' in prompt expansion, to + handle double-width multibyte characters correctly + - changes to rl_redisplay to handle prompts longer than the screenwidth + that might contain double-width multibyte characters. Fixes from + Tomohiro Kubota + + 9/6 + --- +subst.c + - change word_list_split to avoid really bad behavior caused by calling + list_append for each split word -- as the list gets long, you have + to traverse it every time. Keep a pointer to the end of the list and + and just tack onto it + + 9/8 + --- +lib/readline/complete.c + - change fnprint to calculate the displayed width of a filename in + the same way as fnwidth + +subst.c + - in verify_substring_values, when expanding ${array[@]:offset}, make + sure negative offsets count from one greater than the array's + maximum index so things like ${x[@}: -1} work to give the last element + (requires fixing array tests) + +builtins/common.c + - new error function, sh_wrerror(), for builtins to call when a write + error occurs + +builtins/common.h + - extern declaration for sh_wrerror() + +builtins/cd.def + - change builtin_error call to use sh_wrerror() + +builtins/echo.def + - report write errors with sh_wrerror() instead of just returning + failure + +builtins/printf.def + - change printstr to return failure (-1) or success (0) indication + rather than void + - report write errors when printstr() fails, return failure + - if any of the PF/printf calls fail, report write error and return + failure + +execute_cmd.c + - change execute_in_subshell so the subshell command inherits the + command timing flags from the enclosing COMMAND * + + 9/11 + ---- +[prayers for the victims of 9/11/2001] + +lib/sh/strnlen.c + - new file, implementation of GNU libc extension function strnlen + +lib/sh/Makefile.in, {config.h,configure,Makefile}.in, MANIFEST + - changes for strnlen + +configure.in + - version changed to 3.1-devel + +doc/bash.1, lib/readline/doc/rluser.texi + - added description of `-o plusdirs' to complete/compgen (thanks, + Arnold) + +parse.y + - new parser_state flag, PST_ASSIGNOK, if set indicates we're parsing + arguments to a builtin that accepts assignment statement arguments + - turn on PST_ASSIGNOK in read_token_word when appropriate + - turn off PST_ASSIGNOK in read_token when appropriate + - don't attempt to parse a compound assignment specially unless we're + in a position where an assignment statement is acceptable, or + PST_ASSIGNOK is set + + 9/13 + ---- +variables.c + - make BASH_ARGC, BASH_ARGV, BASH_LINENO, and BASH_SOURCE + non-unsettable, since the shell uses those values internally + +expr.c + - make exponentiation right-associative, as is apparently correct + + 9/16 + ---- +arrayfunc.c + - make sure convert_var_to_array marks the environment as needing + recreation if the converted variable was exported + + 9/17 + ---- +braces.c + - mark ${ as introducing an additional level of braces only if it's + not in a quoted string -- quoted strings are handled before brace + matching is done + +parse.y + - fixed an obscure problem in history_delimiting_chars where the `in' + in a case statement could have a semicolon added after it, if the + `case word' was on a previous line + +support/config.guess + - support for newest versions of tandem non-stop kernel + +lib/readline/display.c + - in compute_lcd_of_matches, explicitly cast `text' to `char *' before + passing it to rl_filename_dequoting_function + +lib/readline/terminal.c + - bind the key sequence sent by the keypad `delete' key to delete-char + (same as ^D in emacs mode) + +builtins/ulimit.def + - in print_all_limits, don't print anything if get_limit returns + -1/EINVAL, indicating that the kernel doesn't support that particular + limit + - add -i (max number of pending signals), -q (max size of posix msg + queues), -x (max number of file locks) for systems (Linux) that + support them + +doc/{bash.1,bashref.texi} + - fix description of correspondence between FUNCNAME, BASH_LINENO, + and BASH_SOURCE indices in description of BASH_LINENO + + 9/18 + ---- +lib/sh/shquote.c + - don't quote CTLESC and CTLNUL with CTLESC in sh_backslash_quote, as + long as the resultant string never gets sent to the word expansion + functions without going through the shell parser + +externs.h + - add extern declarations for strnlen and strpbkrk from lib/sh + +subst.[ch] + - changes to handle case where IFS consists of multibyte characters. + Changed: string_extract_verbatim, split_at_delims, + string_list_dollar_star, string_list_dollar_at, list_string, + get_word_from_string, setifs + + 9/19 + ---- +mailcheck.c + - change file_mod_date_changed to reset the cached mail file data if + the file size drops to zero + +lib/readline/complete.c + - change append_to_match so that a non-zero value for + rl_completion_suppress_append will cause no `/' to be appended to a + directory name + +bashline.c + - experimental change to suppress appending a slash for a completed + filename that is found in PATH as well as a directory in the current + directory under certain circumstances: a single instance found in + $PATH when `.' is not in $PATH, and multiple instances found in the + $PATH, even when `.' is in the $PATH + + 9/24 + ---- +command.h + - new word flag: W_ASSIGNRHS, means word is rhs of assignment statement + - new word flag: W_NOTILDE, means word is not to be tilde expanded + - new word flag (internal): W_ITILDE, means the next character is a + tilde that should be expanded + +general.c + - new set of tilde suffixes for use when parsing the RHS of an + assignment statement and =~ should not be subject to tilde expansion + - if ASSIGN_P argument to bash_tilde_expand is 2, use tilde prefixes + for parsing RHS of assignment statement + +general.[ch] + - new function bash_tilde_find_word, drop-in replacement for + tilde_find_word + +subst.c + - call bash_tilde_expand with secord argument of 2 when expanding rhs + of an assignment statement, so tildes after second and subsequent + `=' in an assignment are not expanded + - new function, expand_string_assignment, to expand the rhs of an + assignment statement + - add `~' to EXP_CHAR, the characters that will cause the word + expansion functions to be called + - move tilde expansion into expand_word_internal instead of many + different calls to bash_tilde_expand scattered across different + functions. NOTE: This means that double quotes surrounding a + {paramOPword} expansion will cause tilde expansion to NOT be + performed on `word'. I think this is right, what POSIX specifies, + and consistent with the behavior of other characters in the rhs + +execute_cmd.c + - take out calls to bash_tilde_expand before calling word expansion + functions + + 9/26 + ---- +execute_cmd.c + - make sure to call UNBLOCK_CHILD before returning on a pipe creation + failure in execute_pipeline + + 9/27 + ---- +variables.c + - change get_bash_command to deal with the_printed_command_except_trap + being NULL + +execute_cmd.c + - fix execute_simple_command to deal with the_printed_command being + NULL when assigning to the_printed_command_except_trap -- fixes + seg fault in savestring() + +parse.y + - change the parser so that the closing `)' in a compound variable + assignment delimits a token -- ksh93 does it this way + +doc/{bash.1,bashref.texi} + - change description of tilde expansion to note that expansion is + attempted only after the first =~ in an assignment statement + +builtins/declare.def + - when assigning to an array variable with declare -a x=(...), make + sure the last character in the rhs of the variable assignment is + `)', not just that it appears somewhere + + 9/28 + ---- +command.h + - add a `W_NOEXPAND' flag to inhibit all expansion except quote removal + - add a `W_COMPASSIGN' flag to denote a word is a compound assignment + statement + +parse.y + - set W_COMPASSIGN on words that appear to be compound assignments + +subst.c + - pass W_NOXPAND and W_COMPASSIGN through end of expand_word_internal + +subst.[ch] + - new function, expand_assignment_string_to_string, calls + expand_string_assignment and then string_list on the result + +variables.c + - assign_in_env now calls expand_assignment_string_to_string + + 9/30 + ---- +builtins/common.c + - change get_job_spec so the null job `%' once again means the current + job + + 10/1 + ---- +subst.c + - do_assignment_internal now takes a WORD_DESC * as its first + argument, and uses its `word' member as the assignment string + - change expand_word_list_internal to call do_word_assignment instead + of do_assignment, passing it `word' instead of, e.g., `word->word' + - change extract_array_assignment_list to just return the passed + string minus a trailing `)' if the last character is a right + paren + - change do_assignment_internal to call extract_array_assignment_list + +subst.[ch] + - change do_assignment and do_assignment_no_expand to take a `char *' + instead of `const char *' first argument; change extern prototypes + - new function, do_word_assignment, takes a WORD_DESC * and calls + do_assignment_internal on it; add extern declaration with prototype + +general.h + - new typedef, sh_wassign_func_t, like sh_assign_func_t but takes a + WORD_DESC * as its first argument + +variables.[ch] + - assign_in_env now takes a WORD_DESC * as its first argument + + 10/2 + ---- +command.h + - new word flag, W_ASSNBLTIN, denotes that the word is a builtin + command (in a command position) that takes assignment statements + as arguments, like `declare' + - new word flags, W_ASSIGNARG, denotes that word is an assignment + statement given as argument to assignment builtin + +execute_cmd.c + - set W_ASSNBLTIN flag in fix_assignment_words if necessary (if there + are any arguments that are assignment statements) + - set W_ASSIGNARG flag in fix_assignment_words if necessary + +subst.c + - new function, do_compound_assignment, encapsulates the necessary + code to perform a compound array assignment (including creation of + local variables); called from do_assignment_internal + - to fix the double-expansion problem with compound array assignments + that are arguments to builtins like `declare', changed + shell_expand_word_list to treat those arguments like assignment + statements (with proper creation of local variables inside shell + functions) and pass the attribute-setting portion of the statement + onto the builtin. This is what ksh93 appears to do, from inspection + of the `ksh93 -x' output + +execute_cmd.c + - fix execute_simple_command: in case of pipeline or async command, + when forking early, set `subshell_environment' so that it can contain + both SUBSHELL_PIPE and SUBSHELL_ASYNC -- the two should not be + mutually exclusive. Fixes bug reported by pierre.humblet@ieee.org + - remove references to last_pid, old_command_subst_pid; use NO_PID as + a sentinel value to decide whether or not a child process has been + created and needs to be waited for. Submitted by + pierre.humblet@ieee.org to fix recycling-pid problem on cygwin + +doc/{bash.1,bashref.texi} + - fixed documentation of `@(pattern)' extended globbing operator -- + it succeeds if the string matches one of the patterns, not exactly + one. This is what ksh93 does, too + +lib/readline/complete.c + - fixed rl_menu_complete so that a negative argument cycles backwards + through the list + + 10/3 + ---- +subst.c + - use W_COMPASSIGN flag in do_assignment_internal instead of deciding + lexically which assignments are compound array assignments + + 10/6 + ---- +support/shobj-conf + - additions for System V.5 from Boyd Gerber + +subst.c + - in command_substitute, if subshell_environment includes + SUBSHELL_ASYNC, call make_child with the `async_p' argument set to + non-zero. This keeps command substitutions for async commands or + pipelines from trying to give the terminal back to the shell's + pgrp. make sure to save and restore last_asynchronous_pid. Fix + suggested by + + 10/7 + ---- +config.h.in + - add a placeholder definition for WCONTINUED_BROKEN + + 10/9 + ---- +aclocal.m4 + - add BASH_CHECK_WCONTINUED, checks for glibc bug where WCONTINUED is + defined but rejected as invalid by waitpid(2) + +configure.in + - add call to BASH_CHECK_WCONTINUED, defines WCONTINUED_BROKEN + +redir.c + - experimental change to add_undo_redirect to save manipulations to + file descriptors >= SHELL_FD_BASE (10) on the list of redirections + to be undone even if `exec' causes the list to be discarded + +doc/{bash.1,bashref.texi} + - note that redirections using file descriptors > 9 should be used + carefully, because they might conflict with file descriptors the + shell uses internally + + 10/11 + ----- +parse.y + - fix pipeline_command production to handle case where `pipeline' + as `argument' of `!' or `time' is null (e.g., a syntax error not + handled by the grammar) + + 10/13 + ----- +lib/readline/readline.c + - new internal variable, _rl_bind_stty_chars; if non-zero, bind the + terminal special characters to readline equivalents at startup + - change readline_default_bindings() and reset_default_bindings() to + understand _rl_bind_stty_chars + +lib/readline/rlprivate.h + - new extern declaration for _rl_bind_stty_chars + +lib/readline/rltty.c + - change rl_prep_terminal to add support for _rl_bind_stty_chars + + 10/15 + ----- +lib/readline/bind.c + - new bindable variable, `bind-tty-special-chars', bound to value of + _rl_bind_stty_chars + +doc/bash.1,lib/readline/doc/{readline.3,rluser.texi} + - documented new readline variable `bind-tty-special-chars' + +builtins/pushd.def + - make the first check for option `--' skip the rest of option + checking + + 10/16 + ----- +lib/readline/shell.c + - change sh_set_lines_and_columns to prefer setenv, which has + predictable memory allocation behavior, to putenv, which does not + + 10/19 + ----- +variables.c + - change push_exported_var so that a tempenv variable has to have the + export attribute set (which they all do -- something to look at) and + the `propagate' attribute set to be propagated down to the next + scope + +execute_cmd.c + - change execute_builtin so that if CMD_COMMAND_BUILTIN is set in the + passed flags argument, call pop_scope with a value that says the + builtin is not special, since `command' means that preceding variable + assignments don't persist in the environment. Fixes problem with + variable assignments preceding command preceding special builtin + keeping those variable assignments around (when in posix mode) + + 10/20 + ----- +lib/sh/shquote.c + - new function, sh_mkdoublequoted, brackets a given string with + double quotes and returns a new string. Flags argument, if non- + zero, means to quote embedded double quotes with backslashes + +externs.h + - new extern declaration for sh_mkdoublequoted + +parse.y + - use sh_mkdoublequoted after calling localeexpand() + +lib/sh/strtrans.c + - change ansicstr to understand that (flags & 4) != 0 means to remove + backslash from unrecognized escape sequences + +general.c + - fix logic problem in assignment() that caused non-variable-starter + characters to be allowed, resulting in things like `1=xxx' creating + a variable `1' in the hash table + + 10/21 + ----- +bashline.c + - don't call programmable_completions with an assignment statement + argument + + 10/22 + ----- +lib/readline/rltty.c + - in prepare_terminal_settings, turn echoing on (readline_echoing_p) + if get_tty_settings fails because the input is not a terminal + + 10/24 + ----- +lib/readline/util.c + - include rlmbutil.h for multibyte definitions + - new function, _rl_walphabetic, wide char version of rl_alphabetic + +lib/readline/mbutil.c + - new function, _rl_char_value(buf, ind), returns value of (possibly + multibyte) character at buf[ind] + +lib/readline/rlmbutil.h + - extern defines for _rl_walphabetic and _rl_char_value for when + multibyte chars are not being used + - new wrapper definitions for _rl_find_next_mbchar (MB_NEXTCHAR) and + _rl_find_prev_mbchar (MB_PREVCHAR) that try to avoid unneeded + function calls + +lib/readline/text.c + - fix rl_foward_word to work with multibyte characters (or in a + multibyte locale) using above utility functions + - fix rl_backward_word to work with multibyte characters (or in a + multibyte locale) using above utility functions + + 10/26 + ----- +parse.y + - fix parse_matched_pair so that it doesn't swallow \ when + parsing a $'...' construct (call shell_getc with different arg) + + 10/28 + ----- +lib/glob/glob.c + - after some (compiled-in) threshold, glob_vector will stop using + alloca to allocate `struct globval's and will switch to using + malloc, with appropriate cleanup before returning + +subst.c + - don't expand tildes after `=' in expand_word_internal, even if the + W_TILDEEXP flag is set, unless it's the first tilde in a word + marked W_ASSIGNMENT + + 10/31 + ----- +lib/readline/text.c + - make sure rl_point doesn't go below 0 in rl_delete_horizontal_space + (from SUSE, but not sent in) + +shell.c + - make sure shell_is_restricted skips over a single leading `-' in + the shell name (from SUSE, but not sent in) + +lib/readline/display.c + - disable `fast redisplay' at the end of the line if in a locale that + supports multibyte characters (from SUSE, but not sent in) + +lib/readline/histexpand.c + - fix a problem with finding the delimiter of a `?' substring when + compiled for multibyte characters (from SUSE, but not sent in) + + 11/1 + ---- +lib/readline/display.c + - correct some assignments to _rl_last_c_pos: when in a multibyte + locale, it's used as an absolute cursor position; when not using + multibyte characters, it's a buffer offset. I should have caught + this when the multibyte character support was donated + + 11/5 + ---- +general.c + - change `assignment()' to accept `+=' assignment operator + +arrayfunc.[ch] + - bind_array_variable and assign_array_element both take a new `flags' + argument + - assign_array_var_from_string, assign_array_from_string, and + assign_array_var_from_word_list now all take a new `flags' argument + - change assign_array_var_from_word_list to understand how to append + to an array variable + - change assign_array_var_from_string to understand how to append + to an array variable. It does not unset the previous value if + appending, allowing both old values to be changed and new ones to + be added + +subst.h + - new flag #defines to use for evaluating assignment statements + +{subst,variables}.c, builtins/{declare,read}.def + - change callers of assign_array_element and bind_array_variable + - change do_compound_assignment to understand assignment flags + - change do_assignment_internal to set assignment flags and pass them + to underlying functions + +pcomplete.c,builtins/{declare,read}.def + - fix callers of assign_array_var_from_string, assign_array_var_from_word_list + +variables.[ch] + - make_variable_value now takes a new `flags' argument + - make_variable_value now understands how to append to a particular + variable, using the old value + - bind_variable_value now takes a new `flags' argument + - change make_variable_value to understand ASS_APPEND flag + - bind_variable now takes a new `flags' argument + - bind_variable_internal now takes a new `flags' argument + +arrayfunc.c + - change callers of make_variable_value to add flags arg + +builtins/declare.def + - change callers of bind_variable_value to add flags arg + +{execute_cmd,mailcheck,pcomplete,shell,subst,variables}.c,parse.y +builtins/{cd,command,declare,getopts,read,set,setattr}.def + - change callers of bind_variable to add flags arg + +variables.c + - change callers of bind_variable_internal + - change bind_variable_internal to pass assignment flags on to + make_variable_value + - change assign_in_env to treat `var+=value' like `var=value' + +arrayfunc.c + - break code that actually constructs the new value and assigns it + to a particular array index out into a new functions: + bind_array_var_internal. This fakes out make_variable_value by + passing a dummy SHELL_VAR * so it can do proper appending and other + += processing + - changes to assign_array_var_from_string to accept and process as if + they were `standalone' assignment statements array assignment words + of the form [ind]+=val + + 11/7 + ---- +builtins/declare.def + - added support for `declare [flags] var+=value'. `Flags' are applied + before the assignment is performed, which has implications for things + like `-i' -- if -i is supplied, arithmetic evaluation and increment + will be performed + +builtins/setattr.def + - add support for `+=' assignment for rest of `assignment builtins': + export, readonly + + 11/12 + ----- +lib/readline/display.c + - make sure prompt_physical_chars and prompt_invis_chars_first_line + are reset to 0 if the prompt string passed to rl_expand_prompt is + NULL or empty + + 11/14 + ----- +{configure,config.h}.in + - check for `raise', define HAVE_RAISE if available + +lib/intl/dcigettext.c + - make sure `raise' is defined if HAVE_RAISE is not before + eval-plurah.h is included + +lib/malloc/trace.c + - put extern declaration for imalloc_fopen inside the MALLOC_TRACE + #ifdef + + 11/16 + ----- +lib/intl/Makefile.in + - make sure SHELL is defined to cpp + +lib/intl/dcigettext.c + - make sure we use getcwd() even if HAVE_GETCWD is not defined after + including config.h; if SHELL is defined, #define HAVE_GETCWD + + 11/18 + ----- +trap.[ch] + - new function, int signal_in_progress(int sig), returns TRUE if the + trap handler for signal SIG is currently executing + + 11/19 + ----- +redir.c + - slightly change do_redirection_internal to set the close-on-exec + flag for file descriptors > 2 used to save file descriptors < 2 + using explicit redirections (e.g., `exec 3>&1'). This keeps file + descriptors pointing to pipes from being left open but doesn't + change the shell's file descriptor semantics + + 11/20 + ----- +doc/{bash.1,bashref.texi} + - correct some minor typos, forwarded from doko@debian.org + + 11/22 + ----- +doc/bash.1,lib/readline/doc/{readline.3,rluser.texi} + - documented detail that yank-last-arg and yank-nth-arg use the history + arg expansion code (and, as a result, are subject to restrictions + of the history-comment character) + + 11/23 + ----- +execute_cmd.c + - changes so that BASH_COMMAND preserves its value into a DEBUG trap: + for commands, arithmetic for command expressions, select commands, + case commands, (( commands, [[ commands, simple commands + + 11/24 + ----- +doc/{bash.1,bashref.texi} + - changed description of `set' builtin slightly so that it is clear + that only variables are displayed in posix mode and that read-only + variables can't be reset by simply sourcing the output of `set' + +lib/sh/strftime.c + - don't try to redefine `inline' if it's already defined + + 11/26 + ----- +execute_cmd.c + - fix execute_function to check funcname_a after function execution, + since FUNCNAME can be changed or unset within a function + + 11/27 + ----- +builtins/evalfile.c + - make same changes as 11/26, this time to _evalfile + +execute_cmd.c + - change execute_function to run the return trap after a function + completes execution even if the shell is compiled without DEBUGGER + defined + +trap.c + - change reset_or_restore_signal_handlers so that the RETURN trap is + not inherited by command substitution when DEBUGGER is not defined + + 11/30 + ----- +lib/readline/misc.c + - fix memory leaks in _rl_free_history_entry and rl_maybe_replace_line + caused by not freeing `timestamp' member of history entry + - make sure timestamp is initialized to NULL in rl_maybe_save_line + + 12/1 + ---- +execute_cmd.c + - fix execute_function so a function calling `return' will run the + RETURN trap, if one's defined + +doc/{bash.1,bashref.texi} + - fix description of RETURN trap in various places to indicate that it's + only inherited by shell functions if function tracing is on globally + or has been enabled for that function + - fix documentation to indicate that the DEBUG and RETURN traps are + inherited under the same conditions + +execute_cmd.c + - a function does not inherit the RETURN trap if a DEBUG trap is + currently running + + 12/2 + ---- +lib/glob/xmbsrtowcs.c + - change xmbsrtowcs to handle the one case where malloc can fail + (though it should not matter) -- don't try to free a null pointer + + 12/9 + ---- +subst.c + - fix get_var_and_type to handle var[@], where `var' is a scalar + variable, identically to var -- all calling expansions can now + handle var[@] like var. Bug reported by agriffis@gentoo.org + + 12/10 + ----- +lib/readline/bind.c + - make new-style "\M-x" keybindings obey `convert-meta' settings + (bug reported by twaugh@redhat.com) + + 12/14 + ----- +builtins/set.def + - added description of `-' option to help text + +builtins/shopt.def + - fix bug that caused `gnu_errfmt' to not be compiled in unless + READLINE is defined + + 12/16 + ----- +subst.c + - fixed a typo in string_extract_verbatim in first call to MBLEN + (used `slen - 1' instead of `slen - i') + + 12/17 + ----- +subst.c + - avoid some calls to strlen if the value is only being used for + ADVANCE_CHAR and MB_CUR_MAX == 1 (since ADVANCE_CHAR doesn't need + it unless multibyte characters are possible) + - change string_extract_verbatim so it takes the length of the string + as a parameter, so we don't have to recompute the length of the same + string over and over again when doing word splitting (that kills if + it's a long string) + + 12/18 + ----- +subst.c + - in string_list_dollar_star, make sure to null-terminate the + separator if the character is longer than one byte + + 12/22 + ----- +doc/{bash.1,bashref.texi} + - changed text in quoting section explaining that double quotes do + not prevent history expansion from taking place, and that backslashes + escaping ! are not removed + + 12/28 + ----- +shell.c + - set gnu_error_format to 1 if running under emacs. This should allow + the emacs `next-error' stuff to work, at least for interactive shells + +parse.y + - change yy_stream_get to set interrupt_immediately before calling + getc_with_restart when the shell is interactive. This avoids the + synchronization problem caused by the call to QUIT in read_a_line, + which results in the first character after a SIGINT/^C to be + dropped + + 12/30 + ----- +builtins/mkbuiltins.c + - changes to write long documentation to arrays as a single string by + default, rather than an array of strings -- enabled by default + - new option, -S, to restore old behavior of writing multiple strings + for long documentation + - changes to avoid filenames written when the separate-filenames option + (-H) has been supplied being run through gettext + +configure.in + - new cofiguration option, --enable-single-help-strings (on by default), + causes help text to be stored as a single string (or smaller set than + one string per line) + +builtins/Makefile.in + - pass `-S' to mkbuiltins if single-help-strings is turned off + +doc/bashref.texi + - documented new `single-help-strings' configure option + + 1/3/2005 + -------- +jobs.c + - make wait_for return a non-zero status if the job or processed + waited for is suspended. Returns 128 + stop signal. This fixes + the problem with `echo one && sleep 5 && echo two' displaying + `two' after the sleep is suspended + + 1/5 + --- +print_cmd.c + - change indirection_level_string so the code duplicates the first + character of $PS4 to indicate the indirection level, rather than + the first byte + + 1/8 + --- +variables.c + - new special variable hook function for COMP_WORDBREAKS; sets + rl_completer_word_break_characters back to NULL when the variable + is unset + - change bind_variable_value to understand dynamic variables with + assign_function set, and handle them correctly. If the variable is + being appended to, use make_variable_value to create the new + value + - change bind_variable_internal to understand dynamic variables with + assign_function set, and handle them the same way + - RANDOM and LINENO now get the integer attribute, so appending works + as expected + - ditto for HISTCMD, MAILCHECK, OPTIND + +lib/readline/display.c + - change _rl_make_prompt_for_search to set prompt_physical_chars + appropriately + - rl_save_prompt and rl_restore_prompt save and restore + prompt_prefix_length + - change redraw_prompt to use rl_save_prompt and rl_restore_prompt + - change rl_restore_prompt to set the `save' variables back to + NULL/0 so code can check whether or not the prompt has been saved + - change rl_message and rl_clear_message to save and restore the + prompt if the caller has not already done it (using a simple + semaphore-like variable) + - change rl_message to call expand_prompt, so that local_prompt and + local_prompt prefix are set before calling the redisplay functions, + in case the prompt is longer than a screenwidth (fixes bug + reported to debian by epl@unimelb.edu.au) + +lib/readline/doc/rltech.texi + - make sure to note that rl_save_prompt should be called before + rl_message, and rl_restore_prompt before rl_clear_message + +pcomplete.c + - make sure to save and restore the parser state around the call to + execute_shell_function in gen_shell_function_matches. Fixes bug + reported by a050106.1.keeLae3x@captaincrumb.com (cute) + +lib/readline/readline.c + - fix _rl_dispatch_subseq in the case where we're recursing back up + the chain (r == -2) and we encounter a key shadowed by a keymap, + but originally bound to self-insert. Calling rl_dispatch with + ANYOTHERKEY as the first argument will call rl_insert, but with + ANYOTHERKEY (256) as the char to insert. Use the shadow keymap + and set things up to dispatch to rl_insert with the shadowed key + as the argument. Fixes the bug reported by Thomas Glanzmann + (sithglan@stud.uni-erlangen.de) + + 1/13 + ---- +command.h + - new word flag: W_HASQUOTEDNULL + +make_cmd.c + - new function to allocate a WORD_DESC * without doing anything with a + containing string: alloc_word_desc + +make_cmd.h + - extern declaration for alloc_word_desc + +dispose_cmd.c + - new function to just free a WORD_DESC * without freeing the contained + string: dispose_word_desc + +dispose_cmd.h + - extern declaration for dispose_word_desc + +subst.c + - change some places to use alloc_word_desc + - make same changes to word_list_quote_removal as were made to + word_list_split + - set W_HASQUOTEDNULL when a word is created with w->word[0] == + CTLNUL and w->word[1] == '\0' + +subst.c + - parameter_brace_expand_word now returns a WORD_DESC * -- changed + callers to understand + - parameter_brace_expand_indir now returns a WORD_DESC * -- changed + callers to understand + - parameter_brace_expand_rhs now returns a WORD_DESC * -- changed + callers to understand + - remove W_HASQUOTEDNULL from a word's flags when remove_quoted_nulls + is called on the word's enclosed string + + 1/15 + ---- +subst.c + - param_expand now returns a WORD_DESC * -- changed callers to + understand + - parameter_brace_expand now returns a WORD_DESC * -- changed + callers to understand + - in expand_word_internal, only call remove_quoted_nulls after a word + is returned with W_HASQUOTEDNULL + - changes to pass W_HASQUOTEDNULL flag out of expand_word_internal; + changed callers to call remove_quoted_nulls only if return value has + W_HASQUOTEDNULL set. This is a mostly-complete fix for the + long-standing CTLNUL confusion between a quoted null expansion and + the expansion of a variable with a literal '\177' in its value + - change string_list_dollar_at to compute the separator character the + same way as string_list_dollar_star: using the already-computed + values generated in setifs() + - when expanding unquoted $*, if $IFS is empty, check whether or not + we're eventually going to split the results (e.g., on the rhs of an + assignment statement) and concatenate the positional parameters as + if the expansion were within double quotes if we're not going to + split + +tests/iquote.tests + - test cases based on old bug reports about the quoted-null vs. 0177 + problem the recent code fixes + + 1/16 + ---- +dispose_cmd.c + - set w->word to 0 before putting a WORD_DESC * back in the cache in + dispose_word_desc; changed callers to delete those assignments + +variables.c + - change assign_random and get_random_value so that the random number + generator only gets re-seeded once in a subshell environment, and + assigning a value to RANDOM counts as seeding the generator. This + makes the sequences a little more predictable + + 1/20 + ---- +lib/readline/history.c + - fix replace_history_entry, remove_history to return NULL if + passed index is < 0 + + 1/22 + ---- +lib/sh/netconn.c + - fix isnetconn() to understand that getpeername can return ENOTCONN + to indicate that an fd is not a socket + +configure.in + - set BUILD_DIR to contain backslashes to escape any spaces in the + directory name -- this is what make will accept in targets and + prerequisites, so it's better than trying to use double quotes + - set SIZE to the appropriate value if some cross-compiling tool + chain is being used; `size' by default (can be overridden by + SIZE environment variable) + +Makefile.in + - use $(SIZE) instead of size; set SIZE from configure + + 1/31 + ---- +arrayfunc.c + - in array_value_internal, return NULL right away if the variable's + value is NULL, instead of passing a null string to add_string_to_list + + 2/1 + --- +jobs.h + - new struct to hold stats and counters for child processes and jobs + - change some uses of global and static variables to use members of + new struct (struct jobstats) + + 2/2 + --- + +jobs.[ch] + - change PRUNNING to PALIVE + - new define INVALID_JOB + - new macro get_job_by_jid(ind), currently expands to jobs[ind] + - new define J_JOBSTATE, operates on a JOB * like JOBSTATE operates on + a job index + - new function, reset_job_indices, called from delete_job if + js.j_lastj or js.j_firstj are removed + - change various functions to keep counters and stats in struct jobstats + +pcomplete.c, builtins/common.c, builtins/{exit,fg_bg,jobs,kill,wait}.def + - change global variables (e.g., job_slots) to struct members + (e.g., js.j_jobslots) + - use INVALID_JOB define where appropriate + - use get_job_by_jid and J_JOBSTATE where appropriate + +trap.c + - change reset_or_restore_signal_handler to not free the exit trap + string if the function pointer is reset_signal, which is used when + the trap strings shouldn't be freed, like in command substitution + + 2/4 + --- +jobs.c + - new function, realloc_jobs_list, copies jobs array to newly-allocated + memory shrinking (or growing) size to have next multiple of JOB_SLOTS + greater than js.j_njobs + - change compact_jobs_list to just call reap_dead_jobs and then + realloc_jobs_list, simplifying it considerably + - discard_pipeline now returns `int': the number of processes freed + - slightly changed the logic deciding whether or not to call + compact_jobs_list: now non-interactive shells will compact the + list if it reaches MAX_JOBS_IN_ARRAY in size + +parse.y + - move test for backslash-newline after pop_string in shell_getc so + that things like + + ((echo 5) \ + (echo 6)) + + work right + + 2/8 + --- +jobs.h + - new structs for holding status of exited background processes, as + POSIX specifies + - new job flag: J_ASYNC + +jobs.c + - new functions to manipulate struct holding status of exited + background processes + - new members in struct jobstats to hold pointer to last created job + and last created asynchronous job + - initialize js.c_childmax in initialize_job_control + - if the `async' arg to stop_pipeline is non-null, set the J_ASYNC + flag in the job struct + - set js.j_last_made_job and js.j_last_asynchronous_job in + stop_pipeline + - new function: find_last_proc, returns the PROCESS * to the last proc + in a job's pipeline + - changed find_last_pid to call find_last_proc + - change delete_job to call bgp_add on the last proc of the job being + deleted + - change delete_all_jobs and wait_for_background_pids to call bgp_clear + + 2/9 + --- +jobs.c + - change wait_for_single_pid to look for pid in bgpids.list (using + bgp_search()) if find_pipeline returns NULL + + 2/10 + ---- +support/shobj-conf + - change the solaris-gcc stanza so that it auto-selects the appropriate + options for ld depending on which `ld' gcc says it's going to run + + 2/11 + ---- +jobs.h + - add support for PS_RECYCLED as a process state, add PRECYCLED macro + to test it. Change PALIVE and PRUNNING macros to not count processes + in PS_RECYCLED state + +execute_cmd.c + - restore use of last_pid as sentinel value; use NO_PID as sentinel + only if RECYCLES_PIDS is defined + +jobs.c + - change find_job to return a pointer to the PROCESS the desired pid + belongs to, analogous to find_pipeline returning pointer to JOB + - change find_job callers to add extra argument + - change running_only arguments to find_pipeline and find_job to + alive_only, since we don't want recycled pids returned here and it + better describes the result + - new function find_process, calls find_pipeline and searches the + returned pipeline for the PROCESS * describing the desired pid + - in make_child, if fork() returns the same pid as the value of + last_asynchronous_pid when RECYCLES_PIDS is defined, avoid pid + aliasing by resetting last_asynchronous_pid to 1 + - use PRUNNING instead of child->running, since we, for the most + part, don't want to consider recycled pids (e.g., in make_child()) + - call find_process instead of find_pipeline in waitchld() + - use PEXITED(p) instead of testing p->running == PS_DONE + - in make_child, call bgp_delete to remove a just-created pid from the + last of saved pid statuses + - in add_process, check whether or not pid being added is already in + the_pipeline or the jobs list (using find_process) and mark it as + recycled if so + - This set of fixes mostly came from Pierre Humblet + to fix pid aliasing and reuse problems on + cygwin + +variables.c + - set $_ from the environment if we get it there, set to $0 by + default if not in env + +doc/{bashref.texi,bash.1} + - a couple of clarifying changes to the description of $_ based on + comments from Glenn Morris + + 2/15 + ---- +shell.c + - use strstr instead of strmatch when checking whether $EMACS contains + `term' -- simpler and faster + + 2/18 + ---- +builtins/cd.def + - implement posix requirement that `pwd -P' set $PWD to a directory + name containing no symlinks + - add new function, setpwd(), just sets (and changes exported value) + of PWD + +doc/bashref.texi + - add note to posix mode section about pwd -P setting $PWD + +doc{bash.1,bashref.texi} + - added note that BASH_ARGC and BASH_ARGV are only set in extended + debug mode + - expand description of extdebug option to include everything changed + by extended debug mode + + 2/19 + ---- +pathexp.h + - new flag macro, FNMATCH_IGNCASE, evaluates to FNM_CASEFOLD if the + match_ignore_case variable is non-zero + +execute_cmd.c + - new variable, match_ignore_case + - change call to strmatch() in execute_case_command so it includes + FNMATCH_IGNCASE + +test.c + - change call to strmatch() in patcomp() so that pattern matching + calls for [[ ... ]] obey the match_ignore_case variable + +lib/sh/shmatch.c + - if match_ignore_case is set, enable REG_ICASE in the regexp match + flags + +builtins/shopt.def + - new settable option, `nocasematch', controls the match_ignore_case + variable. Currently alters pattern matching for case and [[ ... ]] + commands (==, !=, and =~ operators) + +doc/{bashref.texi,bash.1} + - updated descriptions of [[ and case to include reference to + nocasematch option + + 2/22 + ---- +builtins/mkbuiltins.c + - add `times' to the list of posix special builtins + + 2/23 + ---- +builtins/cd.def + - posix mode no longer turns on effect of -P option on $PWD if a + directory is chosen from CDPATH + +doc/bashref.texi + - clarified that in posix mode, reserved words are not alias expanded + only in a reserved word context + - removed item about cd, $CDPATH, and -P from posix mode section + + 2/24 + ---- +builtins/reserved.def + - minor cleanups to the description of `if' + + 3/2 + --- +subst.c + - change list_string and get_word_from_string to explicitly treat an + IFS character that is not space, tab, or newline *and any adjacent + IFS white space* as a single delimiter, as SUSv3/XPG6 says + +builtins/read.def + - check whether or not the number of fields is exactly the same as + the number of variables instead of just assigning the rest of the + line (minus any trailing IFS white space) to the last variable. + This parses a field and checks whether or not it consumes all of + the input (including any trailing field delimiters), falling back + to the previous behavior if it does not. This is what POSIX.2 + specifies, I believe (and the consensus of the austin-group list). + This requires a few tests in read.tests to be changed: backslashes + escaping IFS whitespace characters at the end of input cause the + whitespace characters to be preserved in the value assigned to the + variable, and the trailing non-whitespace field delimiter issue + + 3/7 + --- +configure.in + - add -D_POSIX_SOURCE to the LOCAL_CFLAGS for Interix + + 3/8 + --- +bashline.c + - make bash_directory_expansion a void function, since it doesn't have + any return value + + 3/9 + --- +builtins/read.def + - when testing for a pipe, use `fd' instead of hard-coding 0, since we + can read from other file descriptors now + +lib/sh/zread.c + - in zsyncfd, only set lind and lused to 0 if the lseek succeeds. + If the lseek fails, we might steal input from other programs, but + a failed lseek won't cause us to erroneously discard input + + 3/11 + ---- +builtins/evalstring.c + - don't allow parse_and_execute to short-circuit and call exec() if + the command's return value is being inverted + + 3/15 + ---- +builtins/printf.def + - new macro PC to call putchar and increment number of chars printed - + fixes bug in computation of value for %n format char + - `tw' is now a global var so printstr can modify it using PC() + - convert PF macro to use asprintf into a local buffer + Preparation for printf -v var + - add code to add the text printed to a `variable buffer' if -v option + supplied. The buffer grows as needed + - printf now takes a `-v var' option to put the output into the variable + VAR rather than sending it to stdout. It does not: + print partial output on error (e.g., format string error) + handle NULs in the variable value, as usual + + 3/16 + ---- +parse.y + - fix bug in prompt string decoding that caused a core dump when PS1 + contained \W and PWD was unset (null pointer deref) + +builtins/printf.def + - changed -v var behavior so it stores partial output into the named + variable upon an error + + 3/24 + ---- +lib/readline/bind.c + - bool_to_int now takes a `const char *' argument + +support/{printenv,recho,zecho}.c + - include config.h + - include "bashansi.h" for appropriate extern function declarations + +configure.in + - on MacOS X 10.4, compensate for loader not allowing static library + to override existing system dynamic library when compiling -dynamic + (affects readline and history libraries); so use absolute pathname + instead of -lreadline as library name + +lib/glob/{glob,sm_loop,smatch}.c + - make sure to cast arguments to (char *) or (unsigned char *) as + appropriate to avoid gcc4 warnings + +lib/glob/smatch.c + - collsym (single-byte version) now takes a (CHAR *) first argument to + match callers; cast argument to strncmp appropriately + +lib/sh/snprintf.c + - fix ldfallback and dfallback to handle width and precision specs in + the format passed to sprintf() + - fix STAR_ARGS macro to deal with negative field widths and precisions + + 3/25 + ---- +builtins/printf.def + - since a negative precision in a "x.x[fFgGeE]" format specifier should + be allowed but treated as if the precision were missing, let it + through + +lib/sh/snprintf.c + - fix * code to deal with a negative precision by treating it as if + the `.' and any digit string in the precision had not been specified + - fix format parsing code to deal with a negative inline precision, + e.g., "%4.-4f" by treating it as if the `'. and any digit string in + the precision had not been specified + - a `+' in a format specifier should only act as a flag if it comes + before a `.' (otherwise it is ignored) + +lib/readline/vi_mode.c + - new function, rl_vi_rubout, to rl_rubout as rl_vi_delete is to + rl_delete; saves deleted text for possible reinsertion as with any + vi-mode `text modification' command (fixes problem with `X' reported + by beat.wieland@gmx.ch) + +lib/readline/vi_keymap.c + - bind `X' in vi command mode to rl_vi_rubout + +lib/readline/funmap.c + - add a bindable `vi-rubout' command, runs rl_vi_rubout + +lib/readline/text.c + - rewrote internals of _rl_rubout_char to make structure cleaner + +lib/readline/{complete,text}.c + - changed code to remove #ifdef HANDLE_MULTIBYTE where possible + + 3/28 + ---- +lib/readline/examples/rl.c + - include instead of posixstat.h if READLINE_LIBRARY not + defined + +subst.c + - fix mbstrlen to treat invalid multibyte sequences as sequences of + single-byte characters + + 4/8 + --- +configure.in + - default SIZE to `:' if cross-compiling and an appropriate size for + the target is not found + + 4/11 + ---- +subst.c + - change match_upattern and match_wpattern to check whether or not the + supplied pattern matches anywhere in the supplied string, prefixing + and appending the pattern with `*' if necessary. If it doesn't we + can short-circuit immediately rather than waste time doing up to + N-1 unsuccessful calls to strmatch/wcsmatch (which kills for long + strings, even if the pattern is short) + + 4/12 + ---- +configure.in + - make sure the special case for MacOS X 10.4 only kicks in if the + `--with-installed-readline' option isn't supplied + +lib/readline/{callback,readline,signals}.c + - make sure rl_prep_term_function and rl_deprep_term_function aren't + dereferenced if NULL (as the documentation says) + +builtins/mkbuiltins.c + - don't bother with the special HAVE_BCOPY code; just use straight + assignments + +builtins/ulimit.def + - use _POSIX_PIPE_BUF in pipesize() if it's defined and PIPE_BUF is + not + + 4/13 + ---- +execute_cmd.c + - add cm_function_def to the list of control structures for which + child processes are forked when pipes come in or out + + 4/14 + ---- +builtins/read.def + - make sure the ^As added for internal quoting are not counted as + characters read when -n is supplied + + 4/20 + ---- +redir.c + - fix redir_open so that the repeat open on failure that AFS support + adds restores the correct value of errno for any error message + + 4/26 + ---- + +Makefile.in + - make sure mksignames and mksyntax are invoked with the $(EXEEXT) + extension + + 4/28 + ---- +lib/readline/readline.h + - new state variable: RL_STATE_CALLBACK, means readline is using the + callback interface + +lib/readline/callback.c + - set RL_STATE_CALLBACK in rl_callback_handler_install, unset in + rl_callback_handler_remove + + 4/29 + ---- +config-top.h + - DONT_REPORT_SIGPIPE is now on by default, since it apparently + interferes with scripts + +configure.in + - arrange things so PGRP_PIPE is defined on Linux-2.4+ and version 3 + kernels (ones that apparently schedule children to run before their + parent) + + 4/30 + ---- +builtins/caller.def + - add call to no_options, so it can handle `--' option + +doc/{bash.1,bashref.texi} + - note explicitly that test, :, true, and false don't understand -- + as meaning the end of options + + 5/7 + --- +support/shobj-conf + - darwin 8 needs the same LDFLAGS setting as darwin 7 + +parse.y + - in save_parser_state, make sure we cast the return value from + xmalloc() to the right type + - remove casts to (char *) in calls to yyerror() + +lib/readline/signals.c + - make SIGQUIT and SIGALRM code conditional on their definition + - use raise() to send a signal if we don't have kill() + +lib/readline/display.c + - some MS-DOS and MINGW changes from the cygwin and mingw folks + +config.h.in + - add HAVE_PWD_H for + - add HAVE_FCNTL, HAVE_KILL for respective system calls + - add HAVE_GETPW{ENT,NAM,UID} for passwd functions + +configure.in + - add check for + - add checks for fcntl, kill system calls + - add checks for getpw{ent,nam,uid} C library functions + - pass a flag indicating we're cross compiling through to + CFLAGS_FOR_BUILD in Makefile.in + +lib/readline/complete.c + - guard inclusion of with HAVE_PWD_H + - don't provide a missing declaration for getpwent if we don't have it + - guard calls to {get,end}pwent with HAVE_GETPWENT + +lib/readline/shell.c + - guard inclusion of with HAVE_PWD_H + - guard inclusion of with HAVE_FCNTL_H + - don't provide a missing declaration for getpwuid if we don't have it + - guard calls to getpwuid with HAVE_GETPWUID + - don't bother with body of sh_unset_nodelay_mode if we don't have + fcntl + +lib/tilde/tilde.c + - guard inclusion of with HAVE_PWD_H + - guard calls to getpw{nam,uid} with HAVE_GETPW{NAM,UID} + - guard calls to {get,end}pwent with HAVE_GETPWENT + +Makefile.in,builtins/Makefile.in + - @CROSS_COMPILE@ is substituted into CFLAGS_FOR_BUILD (equal to + -DCROSS_COMPILING if bash is being cross-compiled) + + 5/9 + --- +aclocal.m4 + - print version as `0.0' in RL_LIB_READLINE_VERSION if the + `rl_gnu_readline_p' variable isn't 1 (accept no imitations) + + 5/11 + ---- +lib/readline/rlprivate.h + - definition of a readline `search context', to be use for incremental + search initially and other types of search later. Original from + Bob Rossi as part of work on incremental searching problems when + using callback interface + +lib/readline/isearch.c + - functions to allocate and free search contexts + - function to take a search context and a character just read and + `dispatch' on it: change search parameters, add to search string, + search further, etc. + - isearch is now completely context-driven: a search context is + allocated and passed to the rest of the functions + + 5/12 + ---- +lib/readline/isearch.c + - an additional `isearch cleanup' function that can be called from + the callback interface functions when the search is to be terminated + - an additional `isearch callback' function that can be called from + rl_callback_read_char when input is available + - short-circuit from rl_search_history after initialization if + the callback interface is being used + +lib/readline/callback.c + - in rl_callback_read_char(), if RL_STATE_ISEARCH is set, call + _rl_isearch_callback to read the character and dispatch on it. + If RL_STATE_ISEARCH is unset when that call returns, and there is + input pending, call rl_callback_read_char() again so we don't + have to wait for new input to pick it up + +support/shobj-conf,configure.in + - add support for dragonfly bsd, the same as freebsd + + 5/13-5/15 + --------- +lib/readline/callback.c + - support for readline functions to `register' a function that will + be called when more input is available, with a generic data + structure to encapsulate the arguments and parameters. Primarily + intended for functions that read a single additional character, + like quoted-insert + - support for callback code reading numeric arguments in a loop, + using readline state and an auxiliary variable + - support for callback code performing non-incremental searches using + the same search context struct as the isearch code + +lib/readline/{callback,display}.c + - if a callback function sets `_rl_redisplay_wanted', the redisplay + function will be called as soon as it returns + +lib/readline/input.c + - changes to _rl_read_mbchar to handle reading the null multibyte + character and translating it into '\0' + +lib/readline/misc.c + - break rl_digit_loop() into component functions that can be called + individually from the callback code more easily + - share some of the functions with rl_digit_loop1() in vi_mode.c + +lib/readline/readline.h + - change the version #defines to reflect readline 5.1 + +lib/readline/search.c + - break code into smaller functions that can be composed to work with + the callback code more easily + +lib/readline/text.c + - in rl_quoted_insert(), don't mess around with the tty signals if + running in `callback mode' + +lib/readline/vi_mode.c + - changed set-mark, goto-mark, change-char, and char-search to work + when called by callback functions + + 5/17 + ---- + +lib/readline/rlprivate.h + - new struct declaration for a `reading key sequence' context + +lib/readline/readline.c + - new variable, _rl_dispatching_keymap, keeps track of which keymap + we are currently searching + - functions to allocate and deallocate contexts for reading multi-char + key sequences + + 5/18 + ---- +lib/readline/rlprivate.h + - new struct defining a context for multiple-key key sequences (the + base case is escape-prefixed commands) + +lib/readline/readline.c + - change structure of _rl_dispatch_subseq to allow for callback code + to use it - rudimentary support for supporting the existing + recursion using a stack of contexts, each with a reference to the + previous + - fix so that ^G works when in callback mode + +lib/readline/callback.c + - call the appropriate multiple-key sequence callback if the state is + set + + 5/19 + ---- +lib/readline/readline.c + - broke code from _readline_internal_char after call to rl_dispatch + out into separate function: _rl_internal_char_cleanup, callable by + other parts of the code + - change _rl_internal_char_cleanup to unset _rl_want_redisplay after + it calls (*rl_redisplay_func) + +lib/readline/callback.c + - call _rl_internal_char_cleanup from rl_callback_read_char when + appropriate + + 5/24 + ---- +lib/readline/callback.c + - use _rl_dispatch_callback and a chain of _rl_keyseq_contexts to + simulate the recursion used to decode multicharacter key sequences + (even things like ESC- as meta-prefix) + - call setjmp in rl_callback_read_char to give things like rl_abort + a place to jump, since the saved location in readline() will not + be valid + - keep calling _rl_dispatch_callback from rl_callback_read_char while + we are still decoding a multi-key key sequence + - keep calling readline_internal_char from rl_callback_read_char while + we are reading characters from a macro + +lib/readline/macro.c + - use a slightly different strategy upon encountering the end of a macro + when using the callback interface: when the last character of a + macro is read, and we are reading a command, pop the macro off the + stack immediately so the loop in rl_callback_read_char terminates + when it should + +lib/readline/readline.c + - if longjmp() is called and we end up at the saved location while + using the callback interface, just return -- don't go back into a + blocking read + - new function to dispose a chain of rl_keyseq_cxts + - only read new input in _rl_dispatch_callback if the KSEQ_DISPATCHED + flag is not set in the current keyseq context -- if it is, we are + traversing the chain back up and should use what we already saved + - use -3 as a magic value from _rl_dispatch_subseq to indicate that + we're allocating a new context and moving downward in the chain + (a special return value for the benefit of _rl_dispatch_callback) + +lib/readline/rlprivate.h + - new extern declaration for _rl_keyseq_chain_dispose + + 6/1 + --- +builtins/read.def + - fixed a bug that occurred when reading a set number of chars and + the nth char is a backslash (read one too many). Bug reported by + Chris Morgan + +execute_cmd.c + - fix execute_builtin so the `unset' builtin also operates on the + temporary environment in POSIX mode (as well as source and eval), + so that unsetting variables in the temporary environment doesn't + leave them set when unset completes. Report by Eric Blake + + +array.c + - fix from William Park for array_rshift when shifting right on an + empty array -- corrects calculation of array->max_index + +builtins/exec.def + - if an exec fails and the execfail option is set, don't call + restart_job_control unless the shell is interactive or job_control + is set + +jobs.c + - add a run-time check for WCONTINUED being defined in header files + but rejected with EINVAL by waitpid(). Fix from Maciej Rozycki + + + 6/20 + ---- +bashhist.c + - make sure calls to sv_histchars are protected by #ifdef BANG_HISTORY + - ditto for calls to history_expand_line_internal + + 6/23 + ---- +doc/bashref.texi + - remove extra blank lines in @menu constructs + +variables.c + - assign export_env to environ (extern char **) every time it changes + (mostly in add_to_export_env define), so maybe getenv will work on + systems that don't allow it to be replaced + + 6/29 + ---- +bashline.c + - in bash_directory_completion_hook, be careful about not turning `/' + into `//' and `//' into `///' for benefit of those systems that treat + `//' as some sort of `network root'. Fix from Eric Blake + + +lib/readline/complete.c + - in to_print, do the right thing after stripping the trailing slash + from full_pathname: // doesn't turn into /, and /// doesn't become + //. Fix from Eric Blake + + 6/30 + ---- +lib/malloc/trace.c + - include if it's available for a definition of size_t + +jobs.c + - in wait_for, if a child process is marked as running but waitpid() + returns -1/ECHILD (e.g., when the bash process is being traced by + strace), make sure to increment c_reaped when marking the child as + dead + - in without_job_control, make sure to close the pgrp pipe after + calling start_pipeline + + 7/1 + --- +Makefile.in + - only remove pathnames.h when the other files created by running + configure are removed (e.g., Makefile). Fix from William Park + +lib/sh/shquote.c + - since backslash-newline disappears when within double quotes, don't + add a backslash in front of a newline in sh_double_quote. Problem + reported by William Park + +jobs.c + - in notify_of_job_status, don't print status messages about + terminated background processes unless job control is active + +bashhist.c + - new variable, hist_last_line_pushed, set to 0 in really_add_history + (used by `history -s' code) + +bashhist.h + - new extern declaration for history -s + +builtins/history.def + - don't remove last history entry in push_history if it was added by + a call to push_history -- use hist_last_line_pushed as a sentinel + and set it after adding history entry. This allows multiple + calls to history -s to work right: adding all lines to the history + rather than deleting all but the last. Bug reported by Matthias + Schniedermeyer + - pay attention to hist_last_line_pushed in expand_and_print_history() + so we don't delete an entry pushed by history -s + + 7/4 + --- +print_cmd.c + - fix print_arith_for_command to not print so many blanks between + expressions in ((...)) + +command.h + - new word flag: W_DQUOTE. Means word should be treated as if double + quoted + +make_cmd.c + - add W_DQUOTE to word flags in make_arith_for_expr + +parse.y + - add W_DQUOTE to word flags for (( ... )) arithmetic commands + +subst.c + - don't perform tilde expansion on a word with W_DQUOTE flag set + - don't perform process substitution on a word with W_DQUOTE flag set + +arrayfunc.c + - expand an array index within [...] the same way as an arithmetic + expansion between (( ... )) + +lib/readline/input.c + - use getch() instead of read() on mingw + +lib/readline/readline.c + - add a few key bindings for the arrow keys on mingw + +lib/readline/rldefs.h + - if on mingw, define NO_TTY_DRIVER + +lib/readline/rltty.c + - compile in the stub functions for _rl_{disable,restore}_tty_signals + if on mingw + - compile in stub function for rl_restart_output on mingw + - make sure enough functions and macros are defined to compile if + NO_TTY_DRIVER is defined (lightly tested - builds on MacOS X, at + least) + + 7/7 + --- +command.h + - add a `flags' member to the PATTERN_LIST structure + +make_cmd.c + - intialize the `flags' member of a PATTERN_LIST when it's created + +builtins/psize.c + - protect extern declaration of errno with usual #ifdef errno + +configure.in, variables.c + - changes for QNX 6.x + + 7/9 + --- +parse.y + - fix parse_matched_pair to handle single and double quoted strings + inside old-style command substitution (``) since they can each + quote the ` and embedded $-expansions. Report by Eric Blake + + +{configure,Makefile}.in + - TILDE_LIB is now substituted into Makefile by configure + +configure.in + - if configuring --with-installed-readline on cygwin, set TILDE_LIB + to the empty string to avoid multiply-defined symbols. Cygwin + doesn't allow undefined symbols in dynamic libraries. Report by + Eric Blake + + 7/11 + ---- +input.c + - in duplicate_buffered_stream, don't call free_buffered_stream if the + two buffered streams share the same b_buffer object (e.g., if they + had already been duplicated with a previous call). Fixes Debian bug + reported by eero17@bigfoot.com + + 7/12 + ---- +shell.c + - make set_shell_name more resistant to a NULL argument + - in bind_args, use < instead of != when counting the arguments and + making the arg list + - in main(), make sure arg_index is not initialized to a value greater + than argc + + 7/14 + ---- +lib/readline/display.c + - in expand_prompt, don't set the location of the last invisible + char if the sequence is zero length (\[\]) + + 7/15 + ---- +doc/{bash.1,bashref.texi} + - document that the shell uses $TMPDIR when creating temporary files + + 7/20 + ---- +[bash-3.1-alpha1 frozen] + + 7/29 + ---- +builtins/evalstring.c + - make sure that parse_and_execute saves and restores the value of + loop_level, so loops in sourced scripts and eval'd strings don't + mess up the shell's parser state + +bashline.c + - change command_subst_completion_function to suppress appending + any character to a unique completion, instead of a space, unless + the last word in the quoted command substitution completes to a + directory name. In that case we append the expected slash + + 8/1 + --- +builtins/printf.def + - make sure variables are initialized if their values are tested later + +[bash-3.1-alpha1 updated and re-frozen] + + 8/2 + --- +variables.c + - make sure to call stifle_history with an `int' instead of an intmax_t. + Sometimes it makes a difference + + 8/3 + --- +[bash-3.1-alpha1 released] + +support/mksignames.c + - add `SIGSTKFLT' (RHE3) + - add `SIGXRES' (Solaris 9) + + 8/4 + --- +builtins/ulimit.def + - fix typo to make `x' the right option for locks + - add new options to short help synopsis + +variables.c + - use get_variable_value instead of direct reference to value_cell + in make_variable_value when appending to the current value, so + references to array variables without subscripts will be equivalent + to element 0 + +lib/readline/text.c + - rewrote rl_change_case to correctly change the case of multibyte + characters where appropriate + + 8/5 + --- +configure.in + - remove call to obsolete macro AC_ACVERSION + - remove special calls to AC_CYGWIN and AC_MINGW32; AC_CANONICAL_HOST + takes care of those cases + +general.h + - include `chartypes.h' for definition of ISALPHA + - fix definitions of ABSPATH and RELPATH for cygwin + - fix definition of ISDIRSEP for cygwin to allow backslash as a + directory name separator + + 8/9 + --- +builtins/setattr.def + - when setting a variable from the temporary environment in + set_var_attribute (e.g., `LC_ALL=C export LC_ALL'), make sure to + call stupidly_hack_special_variables after binding the variable in + the current context + +builtins/printf.def + - make sure to call stupidly_hack_special_variables if using `printf -v' + to put formatted output in a shell variable + + 8/11 + ---- +support/shobj-conf + - new variable: SHLIB_LIBPREF, prefix for shared library name (defaults + to `lib' + - new variable: SHLIB_DLLVERSION, used on Cygwin to set the library + version number + - new variable: SHLIB_DOT, separator character between library name and + suffix and version information (defaults to `.') + - new stanza for cygwin to generate windows-compatible dll + + 8/14 + ---- +variables.c + - new special variable function for Cygwin, so the export environment + is remade when HOME is changed. The environment is the only way to + get information from the shell to cygwin dlls, for instanace, when + bash is compiled to use an already-installed libreadline + +variables.h + - new extern declaration for sv_home + + 8/15 + ---- +lib/readline/display.c + - call init_line_structures from rl_redisplay if vis_lbreaks == 0 + to avoid consequences of a poorly-timed SIGWINCH + + 8/16 + ---- +subst.c + - fix logic for performing tilde expansion when in posix mode (don't + rely on W_TILDEEXP flag always being set, because it won't be when + expanding the RHS of assignment statement). Use W_TILDEEXP only + when deciding to expand a word marked as W_ASSIGNMENT that doesn't + precede a command name + + 8/17 + ---- +execute_cmd.c + - in execute_function, when subshell == 1, don't short-cut by using + the command contained in the group command -- if you do, any + redirections attached to the group command (function) don't get + executed + +general.h + - new #define, FS_READABLE, indicates file is readable by current + user + +findcmd.c + - rewrote file_status to use S_xxx POSIX file mode bits and to add + support for FS_READABLE (affects ./source and searching $PATH for + scripts whose names are supplied as arguments on the command line) + - change find_path_file to look for readable files -- source requires + it + - change find_in_path_element to do the right thing when FS_READABLE + is supplied as a flag + +doc/bashref.texi + - remove note about posix non-compliance in `.': we now require and + look for readable files when searching $PATH + + 8/20 + ---- +subst.c + - fix setifs to handle case where passed variable is non-zero but + v->value == 0 (as in an unset local variable); treat IFS as unset + in this case + +jobs.c + - in kill_pid, if asked to killpg a process or pgrp whose pgrp is + recorded as the same as the shell's, just call killpg and let the + chips fall where they may -- there may be other processes in that + pgrp that are not children of the shell, so killing each process + in the pipeline will not do a complete job, and killpg'ing each + such process will send too many signals in the majority of cases + +builtins/cd.def + - in posix mode, pwd needs to check that the value it prints and `.' + are the same file + +builtins/read.def + - if reading input from stdin in a non-interactive shell and calling + `read', call sync_buffered_stream to seek backward in the input + stream if necessary (XXX - should we do this for all shell builtins?) + + 8/23 + ---- +builtins/cd.def + - in posix mode, if canonicalization of the absolute pathname fails + because the path length exceeds PATH_MAX, but the length of the passed + (non-absolute) pathname does not, attempt the chdir, just as when + not in posix mode + +builtins/type.def + - don't have describe_command call sh_makepath if the full path found + is already an absolute pathname (sh_makepath will stick $PWD onto the + front of it) + + 8/24 + ---- + +jobs.c + - in posix mode, don't have start_job print out and indication of + whether the job started by `bg' is the current or previous job + - change start_job to return success if a job to be resumed in the + background is already running. This means that bg won't fail when + asked to bg a background job, as SUSv3/XPG6 requires + - new function, init_job_stats, to zero out the global jobstats struct + +{jobs,nojobs}.c + - change kill_pid to handle pids < -1 by killing process groups + +jobs.h + - extern declaration for init_job_stats + +lib/readline/history.c + - check whether or not the history list is null in remove_history + +builtins/history.def + - delete_last_history is no longer static so fc builtin can use it + +builtins/fc.def + - use free_history_entry in fc_replhist instead of freeing struct + members individually + - call delete_last_history from fc_replhist instead of using inline + code + - if editing (-l not specified), make sure the fc command that caused + the editing is removed from the history list, as POSIX specifies + +builtins/kill.def + - just call kill_pid with any pid argument and let it handle pids < -1 + This is the only way to let kill_pid know whether a negative pid or + a job spec was supplied as an argument to kill + +builtins/fg_bg.def + - force fg_bg to return EXECUTION_SUCCESS explicitly if called by bg + and start_job returns successfully + - bg now returns success only if all the specified jobs were resumed + successfully + +execute_cmd.c + - call init_job_stats from initialize_subshell to zero out the global + job stats structure + + 8/25 + ---- +bashline.c + - change vi_edit_and_execute_command to just call vi when in posix + mode, instead of checking $FCEDIT and $EDITOR + +lib/readline/search.c + - if in vi_mode, call rl_free_undo_list in make_history_line_current + to dispose of undo list accumulated while reading the search string + (if this isn't done, since vi mode leaves the current history + position at the entry which matched the search, the call to + rl_revert_line in rl_internal_teardown will mangle the matched + history entry using a bogus rl_undo_list) + - call rl_free_undo_list after reading a non-incremental search string + into rl_line_buffer -- that undo list should be discarded + +lib/readline/rlprivate.h + - add UNDO_LIST * member to search context struct + +lib/readline/isearch.c + - initialize UNDO_LIST *save_undo_list member of search context struct + + 8/27 + ---- +lib/readline/bind.c + - change rl_parse_and_bind to strip whitespace from the end of a + variable value assignment before calling rl_variable_bind + +doc/bash.1,lib/readline/doc/{rluser.texi,readline.3} + - clarified the language concerning parsing values for boolean + variables in assignment statements + + 8/28 + ---- +lib/sh/pathphys.c + - fix small memory leak in sh_realpath reported by Eric Blake + + 8/31 + ---- +doc/bashref.texi + - add additional notes to posix mode section + + 9/3 + --- +parse.y + - if $'...' occurs within a ${...} parameter expansion within + double quotes, don't single-quote the expanded result -- the double + quotes will cause it to be expanded incorrectly + + 9/4 + --- +builtins/fc.def + - if STRICT_POSIX is defined, the posix mode default for the editor to + use is $FCEDIT, then ed + +shell.c + - if STRICT_POSIX is defined, initialize `posixly_correct' to 1 + +config.h.in + - add #undef STRICT_POSIX + + 9/5 + --- +configure.in + - add new option argument, --enable-strict-posix-default, configures + bash to be posix-conformant (including defaulting echo to posix + conformance) by default + +builtins/echo.def + - if STRICT_POSIX is defined, default echo to xpg-style + +doc/bashref.texi + - describe the --enable-strict-posix-default option to configure + + 9/10 + ---- +builtins/mkbuiltins.c + - change to not generate N_(""), because the translated empty string is + special to GNU gettext + + 9/13 + ---- +lib/readline/complete.c + - a negative value for rl_completion_query_items means to not ask + +lib/readline/doc/{{rltech,rluser}.texi,readline.3} + - documented new semantics for rl_completion_query_items/ + completion-query-items + + 9/14 + ---- +bashline.c + - bind M-TAB in emacs mode to dynamic-complete-history even if the + current binding is `tab-insert' (which is what it is by default), + not just if it's unbound + + 9/15 + ---- +eval.c + - call QUIT before calling dispose_command on current_command after + the `exec_done' label. If we dispose current_command first, the + longjmp might restore the value of current_command after we've + disposed it, and the subsequent call to dispose_command from the + DISCARD case will free memory twice + + 9/16 + ---- +lib/sh/strto[iu]max.c + - make sure the function being declared is not a cpp define before + defining it -- should fix problems on HP-UX + + 9/19 + ---- +Makefile.in + - make sure the binaries for the tests are at the front of $PATH + + 9/22 + ---- +parse.y + - new flag for parse_matched_pair: P_COMMAND, indicating that the + text being parsed is a command (`...`, $(...)) + - change calls to parse_matched_pair to include P_COMMAND where + appropriate + - if P_COMMAND flag is set and the text is unquoted, check for comments + and don't try to parse embedded quoted strings if in a comment (still + not exactly right yet) + + 9/24 + ---- +builtins/history.def + - if running history -n, don't count these new lines as history lines + for the current session if the `histappend' shell option is set. + If we're just appending to the history file, the issue that caused + history_lines_this_session to be recalculated doesn't apply -- the + history file won't be missing any entries + +lib/readline/isearch.c + - fix C-w handler for isearch string reader to handle multibyte chars + +lib/readline/rlmbutil.h + - new defines for _rl_to_wupper and _rl_to_wlower + +lib/readline/text.c + - use _rl_to_wupper and _rl_to_wlower as appropriate + + 9/26 + ---- +execute_cmd.c + - in shell_execve, if the exec fails due to E2BIG or ENOMEM, just print + the appropriate error message instead of checking out any interpreter + specified with #! + + 9/30 + ---- +bashhist.c + - make $HISTCMD available anytime remember_on_history is non-zero, + which indicates that we're saving commands to the history, and + let it evaluate to 1 if we're not + + 10/4 + ---- +lib/sh/snprintf.c + - in floating(), make sure d != 0 before calling chkinfnan -- gcc on the + version of Solaris 9 I have translates 0 to -inf on the call + +[bash-3.1-beta1 frozen] + + 10/6 + ---- +jobs.c + - set the_pipeline to NULL right away in cleanup_the_pipeline, and + dispose a copy of the pointer so we don't mess with the_pipeline + while we're in the process of destroying it + - block and unblock SIGCHLD around manipulating the_pipeline in + cleanup_the_pipeline + + 10/7 + ---- +[bash-3.1-beta1 released] + +lib/readline/isearch.c + - when switching directions, make sure we turn off the SF_REVERSE + flag in the search context's flags word if we're going from reverse + to forward i-search + +lib/readline/bind.c + - new function, rl_variable_value, returns a string representing a + bindable readline variable's value + - new auxiliary function, _rl_get_string_variable_value, encapsulates + everything needed to get a bindable string variable's value + - rewrote rl_variable_dumper to use _rl_get_string_variable_value + +lib/readline/readline.h + - new extern declaration for rl_variable_value + +lib/readline/doc/rltech.texi + - documented rl_variable_value + +bashline.c + - in command_word_completion_function, if readline sets + rl_completion_found_quote, but doesn't set rl_completion_quote_character, + we have an embedded quoted string or backslash-escaped character in + the passed text. We need to dequote that before calling + filename_completion_function. So far, this is in place only for + absolute program names (those containing a `/') + - in command_word_completion_function, use rl_variable_value to decide + whether or not we should ignore case, and use strncasecmp instead of + strncmp where appropriate + + 10/11 + ----- +builtins/fc.def + - fixed a typo when using POSIX_FC_EDIT_COMMAND + +redir.h + - new flag values for redirections: RX_INTERNAL and RX_USER (currently + unused) + +redir.c + - add_undo_redirect and add_undo_close_redirect now set RX_INTERNAL + flag when making new redirects + - in do_redirection_internal, only set file descriptors > 2 to CLEXEC + if they're marked as RX_INTERNAL + + 10/12 + ----- +jobs.c + - in wait_for_single_pid, if in posix mode, remove the waited-for pid + from the list of background pids, forgetting it entirely. POSIX + conformance tests test for this. + +lib/readline/{readline.h,vi_mode.c} + - new state flag, RL_STATE_VICMDONCE, set after entering vi command + mode the first time; reset on each call to readline() + + 10/13 + ----- +lib/readline/undo.c + - in rl_revert_line, make sure that revert-line in vi mode leaves + rl_point set to 0 no matter the state of the line buffer + +lib/readline/vi_mode.c + - when entering vi_command mode for the first time, free any existing + undo list so the previous insertions won't be undone by the `U' + command. This is how POSIX.2 says `U' should work (and the test + suite tests for it) + +lib/readline/bind.c + - change rl_parse_and_bind so only `set' commands involving boolean + readline variables have trailing whitespace stripped from the value + string + + 10/16 + ----- +lib/glob/sm_loop.c + - fix patscan() to correctly scan backslash-escaped characters + + 10/18 + ----- +lib/sh/{winsize.c,Makefile.in},{jobs,nojobs}.c,Makefile.in,externs.h + - moved get_new_window_size from jobs.c/nojobs.c to new file, + lib/sh/winsize.c, made function global + +{jobs,nojobs,sig}.c,{jobs,sig}.h + - moved SIGWINCH handling code to sig.c rather than duplicate it in + jobs.c and nojobs.c + - call set_sigwinch_handler from sig.c code rather than job control + signal initialization + +sig.[ch] + - new variable, sigwinch_received, acts like interrupt_state for + SIGWINCH, set by sigwinch_sighandler. sigwinch_sighandler no longer + calls get_new_window_size + +parse.y + - add call to get_new_window_size if sigwinch_received at top of + shell_getc + + 10/19 + ----- +lib/malloc/malloc.c + - to avoid orphaning memory on free if the right bucket is busy, use a + new function xplit(mem, bucket) to split the block into two or more + smaller ones and add those to the right bucket (appropriately marking + it as busy) + - audit bsplit(), bcoalesce(), and xsplit() for proper use of busy[], + since they're dealing with two separate buckets + + 10/22 + ----- +subst.c + - new flag for string_extract: EX_REQMATCH, means to return an error + if a matching/closing character is not found before EOS + - new static flag variables: extract_string_error and extract_string_fatal + - change expand_word_internal to check for new error returns from + string_extract and return errors if appropriate + + 10/23 + ----- +builtins/cd.def + - make sure we free TDIR in change_to_directory after calling + set_working_directory (which allocates new memory) and other places + we short-circuit and return + + 10/24 + ----- +subst.c + - modified fix from 10/22 to allow bare ` to pass through (for + some backwards compatibility and more correctness) + + 10/27 + ----- +conftypes.h + - make MacOS X use the RHAPSODY code that gets HOSTTYPE, et al. + at build rather than configure time, to support universal binaries + (fix from llattanzi@apple.com) + + 10/30 + ----- +builtins/evalstring.c + - make sure we don't turn on CMD_NO_FORK in parse_and_execute if + we're running a trap command on signal receipt or exit + +execute_cmd.c + - in shell_execve, improve the error message a little bit if the + interpreter name in a #! exec header ends with a ^M (as in a DOS- + format file) + + 11/1 + ---- +lib/readline/vi_mode.c + - fix vi-mode `r' command to leave the cursor in the right place + +[bash-3.1-rc1 frozen] + + 11/5 + ---- +execute_cmd.c + - make sure a DEBUG trap doesn't overwrite a command string passed to + make_child in execute_simple_command + +bashline.c + - rearrange some code in bash_quote_filename so filenames with leading + tildes containing spaces aren't tilde-expanded before being + returned to the caller + + 11/6 + ---- +lib/readline/display.c + - when deciding where to move the cursor in rl_redisplay and needing + to move the cursor back after moving it vertically and compensate + for invisible characters in the prompt string, make sure that + _rl_last_c_pos is treated as an absolute cursor position in a + multibyte locale and the wrap offset (number of invisible characters) + is added explicitly when deciding how many characters to backspace + + 11/10 + ----- +lib/readline/terminal.c + - _rl_set_screen_size now interprets a lines or columns argument < 0 + as an indication not to change the current value + + 11/11 + ----- + +lib/readline/terminal.c + - new function, rl_reset_screen_size, calls _rl_get_screen_size to + reset readline's idea of the terminal size + - don't call _rl_get_screen_size in _rl_init_terminal_io if both + _rl_screenheight and _rl_screenwidth are > 0 + - don't initialize _rl_screenheight and _rl_screenwidth to 0 in + _rl_init_terminal_io; let caller take care of it + - set _rl_screenheight and _rl_screenwidth to 0 before calling + _rl_init_terminal_io + +lib/readline/readline.h + - new extern declaration for rl_reset_screen_size + +lib/readline/doc/rltech.texi + - documented rl_reset_screen_size + +variables.c + - if readline is being used, compile in a special var function for + assignments to LINES and COLUMNS that calls rl_set_screen_size or + rl_reset_screen_size as appropriate. Only do this in posix mode + and only when STRICT_POSIX is defined at compile time + - new semaphore variable, winsize_assignment, set while doing an + assignment to LINES or COLUMNS + - new variable, winsize_assigned, says LINES or COLUMNS was assigned + to or found in the environment + - if in the middle of an assignment to LINES or COLUMNS, make + sh_set_lines_and_columns a no-op + +lib/sh/winsize.c + - get_new_window_size now takes two int * arguments, to return the + screen dimensions + +externs.h + - change extern declaration for get_new_window_size + +{jobs,nojobs}.c, parse.y + - change callers of get_new_window_size + + 11/12 + ----- +lib/readline/terminal.c + - new variable, rl_prefer_env_winsize, gives LINES and COLUMNS + precedence over values from the kernel when computing window size + +lib/readline/readline.h + - extern declaration for rl_prefer_env_winsize + +lib/readline/doc/rltech.texi + - document rl_prefer_env_winsize + + 11/13 + ----- +lib/readline/rltty.c + - change rl_prep_terminal to make sure we set and reset the tty + special characters in the vi insertion keymap if in vi mode. This + matters if we get accept-line for the previous line while in vi + command mode + + 11/14 + ----- +builtins/pushd.def + - make sure any call to cd_builtin includes a leading `--' from the + argument list (or constructs one) + + 11/16 + ----- +pcomplete.c + - fix small memory leak in gen_wordlist_matches + +[bash-3.1-rc2 frozen] + + 11/21 + ----- +[bash-3.1-rc2 released] + + 11/23 + ----- +lib/readline/display.c + - changes to rl_redisplay to compensate for update_line updating + _rl_last_c_pos without taking invisible characters in the line into + account. Important in multibyte locales where _rl_last_c_pos is an + absolute cursor position + - changes to _rl_move_cursor_relative to account for _rl_last_c_pos + being an absolute cursor position in a multibyte character locale + - rewrote _rl_move_cursor_relative to make it a little simpler + + 11/29 + ----- +lib/readline/display.c + - changes to rl_redisplay and update_line for update_line to communicate + upward that it took the number of invisible characters on the current + line into account when modifying _rl_last_c_pos + - in update_line, adjust _rl_last_c_pos by wrap_offset before calling + _rl_move_cursor_relative, so we pass correct information about the + true cursor position + + 12/1 + ---- +configure.in + - changed release status to `release' + +[bash-3.1 frozen] + + 12/8 + ---- +[bash-3.1 released] + + 12/9 + ---- +doc/{bash.1,version.texi},lib/readline/doc/version.texi + - remove `beta1' from man page footer and texinfo documents + +variables.c + - make sure winsize_assignment is protected by #ifdef READLINE, so + minimal shell will compile + +builtins/read.def + - make sure error cases free memory and run any unwind-protects to + avoid memory leaks + + 12/10 + ----- +execute_cmd.c + - change execute_command_internal to set $PIPESTATUS for ((...)) and + [[ ... ]] commands + +doc/{bash.1,bashref.texi,version.texi} + - add documentation for ulimit -[iqx] and bump revision date + + 12/12 + ----- +parse.y + - make sure parse_compound_assignment saves and restores the + PST_ASSIGNOK parser state flag around its calls to read_token. + Fixes bug reported by Mike Frysinger + + 12/13 + ----- +parse.y + - change parse_compound_assignment to save and restore the value of + last_read_token. Not sure why it was set unconditionally in the + first place after parsing the complete compound assignment + + 12/14 + ----- +lib/readline/text.c + - don't use return value of rl_kill_text (which always succeeds and + returns the number of characters killed) in rl_delete as an indication + of success or failure + - ditto for return value of rl_delete_text + +lib/readline/readline.c + - don't return the value of the called readline function as the return + value from _rl_dispatch_subseq; -1 means something different to the + callers (return 0 all the time to indicate that a readline function + was found and dispatched). Fix from Andreas Schwab for + bug in callback interface first reported by Mike Frysinger + +execute_cmd.c + - fixed a typo in execute_case_command + + 12/15 + ----- +aclocal.m4 + - add check for wctype() to BASH_CHECK_MULTIBYTE, define HAVE_WCTYPE + +config.h.in + - add HAVE_WCTYPE #define + +config-bot.h + - add HAVE_WCTYPE to the set of checks for HANDLE_MULTIBYTE. This + should catch the deficient NetBSD multibyte support + + 12/16 + ----- +parse.y + - use CTLESC instead of literal '\001' when decode_prompt_string + prefixes RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE + + 12/20 + ----- +lib/readline/display.c + - don't treat RL_PROMPT_START_IGNORE specially inside a sequence of + ignored characters + - keep track of the start of the current sequence of ignored + characters; make sure that an empty sequence of such characters + really is an empty sequence, not one that happens to end with '\001' + (RL_PROMPT_START_IGNORE) + + 12/21 + ----- +subst.c + - change expand_word_internal to process rest of `tilde-word' as a + regular part of the word if tilde expansion leaves the tilde-word + unchanged. This means that ~$USER expands to ~chet, which seems + more intuitive, and is effectively what bash-3.0 did + + 12/23 + ----- +subst.c + - when making a local array variable in do_compound_assignment, make + sure that we don't use a variable of the same name from a previous + context + +doc/bash.1 + - documented expansions for word and patterns in case statement + +builtins/ulimit.def,doc/{bashref.texi,bash.1} + - added new -e and -r (nice and rtprio) options to ulimit; documented + them + + 12/26 + ----- +variables.c + - use `hmax' instead of `num' in sv_histsize to avoid integer overflow + problems with intmax_t + +builtins/read.def + - add unwind-protect to restore rl_attempted_completion_function in + case of a timeout + +{bashline,variables}.c + - move initialization of HISTSIZE from initialization path to + load_history, so it can be overridden by a value assigned in a + startup file + +lib/readline/misc.c + - add a missing `return r' so that rl_digit_loop returns a meaningful + value + +lib/readline/{bind,callback,display,isearch,rltty,search,text,vi_mode}.c + - minor cleanups to satisfy compiler warnings, mostly removing unused + variables + + 12/27 + ----- +support/Makefile.in + - add LIBS_FOR_BUILD support; defaults to ${LIBS} + +Makefile.in + - add LIBS_FOR_BUILD with no default value; use when linking programs + using CC_FOR_BUILD (e.g., bashversion) + + 12/28 + ----- +lib/readline/bind.c + - fix rl_translate_keyseq bad translation of \M-\C-x sequences + +execute_cmd.c + - in execute_arith_command, if the expression expands to more than one + word, make sure we join the words into a single string and pass the + entire thing to evalexp() + +expr.c + - new functions: _is_arithop(c), returns true if C is a valid single- + character arithmetic operator; _is_multiop(c), returns true if C is + a token corresponding to a valid multi-character arithmetic operator + - if we encounter a character that isn't a valid arithmetic + operator, throw an error. Try to be intelligent about what type of + error message to print + +subst.c + - new function, expand_arith_string, calls expand_string_if_necessary; + used where an arithmetic expression needs to be expanded + +subst.h + - new extern declaration for expand_arith_string + +arrayfunc.c + - in array_expand_index, call expand_arith_string to expand the + subscript in a fashion consistent with other arithmetic expressions + +subst.c + - fix parameter_brace_patsub so that we don't try to anchor the pattern + at the beginning or end of the string if we're doing global + replacement -- that combination doesn't doesn't make sense, and + the changed behavior is compatible with ksh93 + +doc/{bash.1,bashref.texi} + - changed description of pattern substitution to match the new + semantics + +tests/new-exp.tests + - change tests to remove all ${pat//#rep} and ${pat//%rep} + expansions, since they don't mean the same thing anymore + + 12/29 + ----- +support/signames.c + - new file, initialize_signames() function from old mksignames.c. This + file builds the signal_names array + +support/mksignames.c + - strip out initialize_signames(), move to signames.c. This file only + writes signames.h + - set up to only write a stub signames.h if CROSS_COMPILING is defined, + with extern declaration for initialize_signames + - if not cross compiling, #define initialize_signames to nothing + +Makefile.in + - mksignames is now linked from mksignames.o and buildsignames.o + - add rules to build signames.o, assuming we're building it as part + of the shell (cross-compiling) + +trap.c + - call initialize_signames from initialize_traps + +configure.in + - set SIGNAMES_O to nothing (normal) or signames.o (cross-compiling), + substitute into Makefile + - don't set SIGNAMES_H if cross-compiling any more + + 12/30 + ----- +command.h + - new word flag: W_NOPROCSUB, inhibits process substitution on a word + +subst.c + - change expand_word_internal to suppress process substitution if the + word has the W_NOPROCSUB flag + +shell.c + - --wordexp turns on W_NOPROCSUB in addition to W_NOCOMSUB + +subst.c + - change string_list_dollar_at and string_list_dollar_star so that + MB_CUR_MAX is used to size an array only when using gcc, since gcc + can handle non-constant array sizes using a mechanism like alloca. + Other compilers, e.g. Sun's compiler, do not implement that + extension + + 12/31 + ----- +builtins/mkbuiltins.c + - when cross-compiling, don't include , since it's for the + target rather than the host system. Instead, choose a reasonable + set of default #defines based on a minimal POSIX system + +jobs.c + - change find_process to handle a NULL return value from find_pipeline + - return immediately from delete_job if jobs[index] is already NULL or + if it has a null pipeline associated with it + - in delete_job, if find_last_proc returns NULL, don't try to call + bgp_delete + + 1/7/2006 + -------- +doc/bash.1 + - patch from Tim Waugh to replace some literal single quotes with + \(aq, the groff special character for it + +jobs.c + - in realloc_jobs_list, make sure to zero out slots after j_lastj + in the new list + + 1/9 + --- +support/mksignames.c + - make sure to include to get right value of NSIG from + (usually) + + 1/10 + ---- +parse.y + - when calling parse_matched_pair on a $(...) command substitution, + don't pass the P_DQUOTE flag so that single quotes don't get + stripped from $'...' inside the command substitution. Bug report + and fix from Mike Stroyan + +jobs.c + - start maintaining true count of living children in js.c_living + - call reset_current in realloc_jobs_list, since old values for current + and previous job are most likely incorrect + - don't allocate a new list in realloc_jobs_list if the old size and + new size are the same; just compact the existing list + - make sure realloc_jobs_list updates value of js.j_njobs + - add some more itrace messages about non-null jobs after j_lastj in + jobs array + + 1/11 + ---- +bashjmp.h + - new value for second argument to longjmp: SIGEXIT. Reserved for + future use + + 1/12 + ---- +jobs.c + - add logic to make_child to figure out when pids wrap around + - turn second argument to delete_job into flags word, added flag to + prevent adding proc to bgpids list + + 1/13 + ---- +lib/readline/vi_mode.c + - move code that moves forward a character out of rl_vi_append_mode + into a separate function, _rl_vi_append_forward + - change _rl_vi_append_mode to save `a' as the last command, so it + can be redone properly + - new function _rl_vi_backup, moves point back a character taking + multibyte locales into account + - change rl_vi_redo to handle redoing an `a' command specially -- + it should be redone like `i' but after moving forward a character + - change rl_vi_redo to use _rl_vi_backup to move point backward + after redoing `i' or `a' + +jobs.c + - new function, delete_old_job (pid), checks whether or not PID is in + a job in the jobs list. If so, and the job is dead, it just removes + the job from the list. If so, and the job is not dead, it zeros + the pid in the appropriate PROCESS so pid aliasing doesn't occur + - make_child calls delete_old_job to potentially remove an already-used + instance of the pid just forked from the jobs list if pids have + wrapped around. Finally fixes the bug reported by Tim Waugh + + +trap.c + - new define, GETORIGSIG(sig), gets the original handling for SIG and + sets SIG_HARD_IGNORE if that handler is SIG_IGN + - call GETORIGSIG from initialize_traps, get_original_signal, and + set_signal + +jobs.c + - in wait_for, if the original SIGINT handler is SIG_IGN, don't set + the handler to wait_sigint_handler. This keeps scripts started in + the background (and ignoring SIGINT) from dying due to SIGINT while + they're waiting for a child to exit. Bug reported by Ingemar + Nilsson + +lib/readline/vi_mode.c + - don't save text to buffer unless undo pointer points to a record of + type UNDO_INSERT; zero it out instead. This fixes bug reported by + Craig Turner with redoing `ctd[ESC]' (empty + insert after change to) + +shell.c + - change set_shell_name so invocations like "-/bin/bash" are marked as + login shells + +doc/bash.1 + - add note about destroying functions with `unset -f' to the section + on shell functions + +lib/readline/terminal.c + - if readline hasn't been initialized (_rl_term_autowrap == -1, the + value it's now initialized with), call _rl_init_terminal_io from + _rl_set_screen_size before deciding whether or not to decrement + _rl_screenwidth. Fixes bug from Mike Frysinger + + 1/14 + ---- +lib/readline/input.c + - allow rl_set_keyboard_input_timeout to set the timeout to 0, for + applications that want to use select() like a poll without any + waiting + +lib/readline/doc/rltech.texi + - documented valid values for timeout in rl_set_keyboard_input_timeout + +jobs.c + - in stop_pipeline, don't have the parent shell call give_terminal_to + if subshell_environment contains SUBSHELL_ASYNC (no background + process should ever give the terminal to anything other than + shell_pgrp) + - in make_child, don't give the terminal away if subshell_environment + contains SUBSHELL_ASYNC + + 1/15 + ---- +subst.c + - in parameter_brace_expand, if extracting ${#varname}, only allow + `}' to end the expansion, since none of the other expansions are + valid. Fixes Debian bug reported by Jan Nordhorlz + + 1/17 + ---- +parse.y + - in parse_matched_pair, protect all character tests with the MBTEST + macro + - in parse_dparen, take out extra make_word after call to alloc_word_desc + (mem leak) + + 1/18 + ---- +parse.y + - in parse_matched_pair, add P_ALLOWESC to flags passed to recursive + parse_matched_pair call when encountering a single or double quote + inside a ``-style command substitution + +execute_cmd.c + - add call to QUIT at beginning of execute_command_internal; better + responsiveness to SIGINT + + 1/21 + ---- +lib/readline/bind.c + - change rl_invoking_keyseqs_in_map to honor the setting of + convert-meta when listing key bindings, since if convert-meta is off, + using '\M-' as the prefix for bindings in, for instance, + emacs-escape-keymap, is wrong. This affects `bind -p' output + - change rl_untranslate_keyseq to add '\e' instead of '\C-[' for + ESC + +execute_cmd.c + - add call to QUIT at end of execute_command + + 1/23 + ---- +lib/readline/display.c + - changed two places in update_line where a check of whether the cursor + is before the last invisible character in the prompt string to + differentiate between the multibyte character case (where + _rl_last_c_pos is a physical cursor position) and the single-byte + case (where it is a buffer index). This prevents many unnecessary + \r-redraw the line sequences. Reported by Dan Jacobson. + + 1/24 + ---- +quit.h + - wrap QUIT macro in do...while(0) like other compound statement + macros + - CHECK_TERMSIG define (placeholder for now); future use will be to + handle any received signals that should cause the shell to + terminate (e.g., SIGHUP) + +{input,jobs,nojobs}.c + - add calls to CHECK_TERMSIG where appropriate (reading input and + waiting for children) + - include quit.h if necessary + + 1/25 + ---- +parse.y + - undo change that makes `)' in a compound assignment delimit a token. + It messes up arithmetic expressions in assignments to `let', among + other things + +sig.h,{jobs,nojobs,sig,trap}.c,builtins/trap.def + - rename termination_unwind_protect to termsig_sighandler + +sig.c + - split termsig_sighandler into two functions: termsig_sighandler, which + runs as a signal handler and sets a flag noting that a terminating + signal was received, and termsig_handler, which runs when it is `safe' + to handle the signal and exit + - new terminate_immediately variable, similar to interrupt_immediately + - termsig_sighandler calls termsig_handler immediately if + terminate_immediately is non-zero + +quit.h + - change CHECK_TERMSIG macro to check terminating_signal and call + termsig_handler if it's non-zero + - add same check of terminating_signal and call to termsig_handler to + QUIT macro + +{jobs,nojobs}.c + - change call to termsig_sighandler to call termsig_handler directly, + as was intended + +parse.y,builtins/read.def + - set terminate_immediately to non-zero value when reading interactive + input, as is done with interrupt_immediately + + 1/26 + ---- +doc/{bash.1,bashref.texi} + - reworded the POSIX standard references to remove mention of POSIX.2 + or 1003.2 -- it's all the 1003.1 standard now. Recommended by + Arnold Robbins + + 1/27 + ---- +lib/readline/complete.c + - move call to filename dequoting function into + rl_filename_completion_function; call only if directory completion + hook isn't set. This means that directory-completion-hook now needs + to dequote the directory name. We don't want to dequote the directory + name before calling the directory-completion-hook. Bug reported by + Andrew Parker + +bashline.c + - add necessary directory name dequoting to bash_directory_expansion + and bash_directory_completion_hook + +lib/readline/doc/rltech.texi + - add note to description of rl_directory_completion_hook that it + needs to dequote the directory name even if no other expansions are + performed + + 1/28 + ---- +braces.c + - make sure that we skip over braces that don't start a valid matched + brace expansion construct in brace_expand -- there might be a valid + brace expansion after the unmatched `{' later in the string + - brace_gobbler now checks that when looking for a `}' to end a brace + expansion word, there is an unquoted `,' or `..' that's not inside + another pair of braces. Fixes the a{b{c,d}e}f problem reported by + Tim Waugh + +builtins/declare.def + - when not in posix mode, and operating on shell functions, typeset + and declare do not require their variable operands to be valid + shell identifiers. The other `attribute' builtins work this way. + Fixes inconsistency reported by Mike Frysinger + +{configure,config.h}.in + - add test for setregid, define HAVE_SETREGID and HAVE_DECL_SETREGID + as appropriate + - add test for eaccess, define HAVE_EACCESS if found + +lib/sh/eaccess.c + - new file, with sh_stat and sh_eaccess functions, moved from test.c + - renamed old sh_eaccess as sh_stataccess, since it uses the stat(2) + information to determine file accessibility + - new function, sh_euidaccess, to call when uid != euid or gid != egid; + temporarily swaps uid/euid and gid/egid around call to access + - rewrote sh_eaccess to call eaccess, access, sh_euidaccess or + sh_stataccess as appropriate. access(2) will take into account + things like ACLs, read-only file systems, file flags, and so on. + +lib/sh/Makefile.in,Makefile.in + - add necessary entries for eaccess.[co] + +test.c + - change calls to test_stat to call sh_stat + +{test,general}.c + - change calls to test_eaccess to call sh_eaccess + +externs.h + - new extern declaration for sh_eaccess + +test.[ch] + - remove test_stat and test_eaccess + + 1/29 + ---- +braces.c + - make change from 1/28 dependant on CSH_BRACE_COMPAT not being + defined (since old bash behavior is what csh does, defining + CSH_BRACE_COMPAT will produce old bash behavior) + + 1/30 + ---- +bashline.c + - last argument of bash_default_completion is now a flags word: + DEFCOMP_CMDPOS (in command position) is only current value + - attempt_shell_completion now computes flags before calling + bash_default_completion + - if no_empty_command_completion is set, bash does not attempt command + word completion even if not at the beginning of the line, as long + as the word to be completed is empty and start == end (catches + beginning of line and all whitespace preceding point) + + 2/4 + --- +lib/readline/display.c + - change _rl_make_prompt_for_search to use rl_prompt and append the + search character to it, so the call to expand_prompt in rl_message + will process the non-printing characters correctly. Bug reported + by Mike Stroyan + + 2/5 + --- +lib/readline/display.c + - fix off-by-one error when comparing against PROMPT_ENDING_INDEX, + which caused a prompt with invisible characters to be redrawn one + extra time in a multibyte locale. Change from <= to < fixes + multibyte locale, but I added 1 to single-byte definition of + PROMPT_ENDING_INDEX (worth checking) to compensate. Bug reported + by Egmont Koblinger + + 2/8 + --- +lib/readline/terminal.c + - call _emx_get_screensize with wr, wc like ioctl code for consistency + - new function, _win_get_screensize, gets screen dimensions using + standard Windows API for mingw32 (code from Denis Pilat) + - call _win_get_screensize from _rl_get_screen_size on mingw32 + +lib/readline/rlconf.h + - define SYS_INPUTRC (/etc/inputrc) as system-wide default inputrc + filename + +support/shobj-conf + - changes to make loadable builtins work on MacOS X 10.[34] + +builtins/pushd.def + - changes to make it work as a loadable builtin compiled with gcc4 + + 2/9 + --- +lib/readline/bind.c + - add SYS_INPUTRC as last-ditch default (if DEFAULT_INPUTRC does not + exist or can't be read) in rl_read_init_file + +lib/readline/doc/rluser.texi + - add description of /etc/inputrc as ultimate default startup file + + 2/10 + ---- +lib/readline/bind.c + - fix problem with rl_function_of_keyseq that returns a non-keymap + bound to a portion of the passed key sequence without processing + the entire thing. We can bind maps with existing non-map + functions using the ANYOTHERKEY binding code. + +variables.c + - shells running in posix mode do not set $HOME, as POSIX apparently + requires + + 2/15 + ---- +braces.c + - mkseq() now takes the increment as an argument; changed callers + + 2/16 + ---- +builtins/hash.def + - print `hash table empty' message to stdout instead of stderr + + 2/17 + ---- +lib/readline/readline.c + - when resetting rl_prompt in rl_set_prompt, make sure rl_display_prompt + is set when the function returns + + 2/18 + ---- +lib/readline/display.c + - further fixes to _rl_make_prompt_for_search from Eric Blake to deal + with multiple calls to expand_prompt + + 2/21 + ---- +builtins/hash.def + - don't print `hash table empty' message in posix mode + + 2/27 + ---- +lib/glob/sm_loop.c + - change extmatch() to turn off FNM_PERIOD in flags passed to recursive + calls to gmatch() when calling it with a substring after the start + of the string it receives. Changed `+', `*', `?, `@', and `!' cases + to do the right thing. Fixes bug reported by Benoit Vila + + +braces.c + - add QUIT; statements to mkseq to make large sequence generation + interruptible + + 2/28 + ---- +lib/glob/glob.c + - initialize nalloca in glob_vector + + 3/1 + --- +lib/glob/glob.c + - in glob_vector, when freeing up the linked list after some error, + make sure to set `tmplink' to 0 if `firstlink' is set to 0, else we + get multiple-free errors + + 3/5 + --- +trap.c + - inheritance of the DEBUG, RETURN, and ERR traps is now dependent + only on the `functrace' and `errtrace' shell options, as the + documentation says, rather than on whether or not the shell is in + debugging mode. Reported by Philip Susi + +parse.y + - in parse_matched_pair, don't recursively parse ${...} or other + ${...} constructs inside `` + - in parse_matched_pair, remove special code that recursively parses + quoted strings inside `` constructs. For Bourne shell compatibility + + 3/6 + --- +builtins/pushd.def + - let get_directory_stack take take an `int flags' argument and convert + $HOME to ~ if flags&1 is non-zero + +builtins/common.h + - change extern declaration for get_directory_stack + +variables.c + - call get_directory_stack with an arg of 0 to inhibit converting + $HOME to ~ in the result. Fixes cd ${DIRSTACK[1]} problem + reported by Len Lattanzi (cd fails because + the tildes won't be expanded after variable expansion) + +jobs.c + - changed hangup_all_jobs slightly so stopped jobs marked J_NOHUP + won't get a SIGCONT + +general.c + - changed check_binary_file() to check for a NUL byte instead of a + non-printable character. Might at some point want to check + entire (possibly multibyte) characters instead of just bytes. Hint + from ksh via David Korn + + 3/7 + --- +builtins/reserved.def + - changed runs of spaces to tabs in variables help text to make + indentation better when displayed + +builtins/mkbuiltins.c + - changes to avoid the annoying extra space that keeps gettext from + being passed an empty string + + 3/9 + --- +lib/glob/glob.c + - make sure globbing is interrupted if the shell receives a terminating + signal + + 3/14 + ---- +lib/readline/search.c + - call rl_message with format argument of "%" in _rl_nsearch_init + to avoid `%' characters in the prompt string from being interpreted + as format specifiers to vsnprintf/vsprintf + + 3/19 + ---- +parse.y, eval.c, input.h + - change execute_prompt_command to execute_variable_command; takes the + variable name as a new second argument + + 3/25 + ---- +bashline.c + - command_word_completion_function keeps track of when it's searching + $PATH and doesn't return directory names as matches in that case. + Problem reported by Pascal Terjan + - command_word_completion_function returns what it's passed as a + possible match if it's the name of a directory in the current + directory (only non-absolute pathnames are so tested). + + 3/27 + ---- +subst.c + - expand_arith_string takes a new argument: quoted. Either 0 (outside + subst.c) or Q_DOUBLE_QUOTES (substitution functions); changed callers + +subst.h + - changed extern declaration for expand_arith_string + +arrayfunc.c + - changed call to expand_arith_string in array_expand_index + + 3/31 + ---- +lib/readline/histfile.c + - change read_history_range to allow windows-like \r\n line endings + +execute_cmd.c + - add new variable, line_number_for_err_trap, currently set but not + used + + 4/2 + --- +lib/sh/strtrans.c + - add code to echo -e and echo with xpg_echo enabled to require + a leading 0 to specify octal constants + + 4/3 + --- +subst.c + - slight change to wcsdup() replacement: use memcpy instead of wcscpy + +parse.y + - before turning on W_COMPASSIGN, make sure the final character in the + token is a `(' (avoids problems with things like a=(4*3)/2) + + 4/4 + --- +lib/sh/snprintf.c + - in number() and lnumber(), turn off PF_ZEROPAD if explicit precision + supplied in format + - change number() and lnumber() to correctly implement zero-padding + specified by a non-zero `.precision' part of the format + +subst.c + - new flag for extract_delimited_string: EX_COMMAND. For $(...), so + we can do things like skip over delimiters in comments. Added to + appropriate callers + - changes to extract_delimited_string to skip over shell comments when + extracting a command for $(...) (EX_COMMAND is contained in the + flags argument) + + 4/5 + --- +subst.c + - first argument to skip_single_quoted is now a const char * + - new function, chk_arithsub, checks for valid arithmetic expressions + by balancing parentheses. Fix based on a patch from Len Lattanzi + + 4/6 + --- +{configure,config.h}.in + - add separate test for isnan in libc, instead of piggybacking on + isinf-in-libc test + +lib/sh/snprintf.c + - separate the isnan replacement function so it's guarded by its own + HAVE_ISNAN_IN_LIBC define + +lib/sh/wcsdup.c + - new file, contains replacement wcsdup library function from subst.c + with change back to using wcscpy + +Makefile.in,lib/sh/Makefile.in + - make sure wcsdup.c is compiled and linked in + +subst.c + - wcsdup now found in libsh; removed static definition + + 4/10 + ---- +lib/readline/callback.c + - loop over body of rl_callback_read_char as long as there is additional + input rather than just calling readline_internal_char, which does + not handle multi-character key sequences or escape-prefixed chars + +lib/readline/macro.c + - make sure we turn off RL_STATE_MACROINPUT when the macro stack is + empty if we are reading additional input with RL_STATE_MOREINPUT + +support/shobj-conf + - Mac OS X no longer likes the `-bundle' option to gcc when creating a + dynamic shared library + + 4/11 + ---- +lib/tilde/tilde.c + - don't try to dereference user_entry if HAVE_GETPWENT isn't defined + +lib/readline/input.c + - make sure chars_avail is not used without being assigned a value in + rl_gather_tyi + - use _kbhit() to check for available input on Windows consoles, in + rl_gather_tyi and _rl_input_available + + 4/21 + ---- +lib/readline/display.c + - calculate (in expand_prompt) and keep track of length of local_prompt + in local_prompt_len; use where appropriate + - when using o_pos to check whether or not we need to adjust + _rl_last_c_pos after calling update_line, assume that it's correct + (a buffer index in non-multibyte locales and a cursor position in + multibyte locales) and adjust with wrap_offset as appropriate + - in update_line, set cpos_adjusted to 1 after calling + _rl_move_cursor_relative to move to the end of the displayed prompt + string + - in _rl_move_cursor_relative, check that the multibyte display + position is after the last invisible character in the prompt string + before offsetting it by the number of invisible characters in the + prompt (woff) + + 4/26 + ---- +lib/readline/doc/{rluser.texi,readline.3} + - make sure to note that key bindings don't allow any whitespace + between the key name or sequence to be bound and the colon + + 4/28 + ---- +lib/readline/display.c + - in update_line, make sure we compare _rl_last_c_pos as strictly less + than PROMPT_ENDING_INDEX, since it's 0-based, to avoid multiple + prompt redraws + + 5/4 + --- +parse.y + - in decode_prompt_string, only prefix the expansion of \[ or \] + with CTLESC if the corresponding readline escape character is + CTLESC (coincidentally the same as \[) or CTLNUL. Bug report sent + by Mike Frysinger prompted the discovery + +aclocal.m4 + - slight change to test for /dev/fd to compensate for a linux + failing; suggested by Mike Frysinger + + 5/9 + --- +arrayfunc.c + - broke assign_array_var_from_string into two functions: + expand_compound_array_assignment and assign_compound_array_list; + assign_array_var_from_string just calls those functions now + +arrayfunc.h + - new extern declarations for expand_compound_array_assignment and + assign_compound_array_list + +subst.c + - in do_compound_assignment, call expand_compound_array_assignment + before creating the local variable so a previous inherited + value can be used when expanding the rhs of the compound assignment + statement + + 5/11 + ---- +doc/{bash.1,bashref.texi} + - clarifed `trap' description to make it clear that trapped signals + that are not set to SIG_IGN are reset when a subshell is created + + 5/18 + ---- +locale.c + - change reset_locale_vars to call setlocale (LC_ALL, "") if LANG + is unset or NULL + - if LANG is unset or NULL, reset the export environment before + calling setlocale in reset_locale_vars, and trust that it will + change the environment setlocale() inspects + + 5/21 + ---- +lib/readline/history.c + - new function, HIST_ENTRY *alloc_history_entry (char *string, char *ts); + creates a new history entry with text STRING and timestamp TS (both + of which may be NULL) + - new function, HIST_ENTRY *copy_history_entry (HIST_ENTRY *hist), + which copies the line and timestamp entries to new memory but just + copies the data member, since that's an opaque pointer + - new function, void replace_history_data (int which, histdata_t *old, histdata_t *new) + which replaces the `data' member of specified history entries with + NEW, as long as it is OLD. WHICH says which history entries to + modify + - add calls to replace_history_data in rl_free_undo_list and + rl_do_undo + +lib/readline/undo.c + - new function, alloc_undo_entry (enum undo_code what, int start, int end, char *text) + takes care of allocating and populating a struct for an individual + undo list entry + - new function: _rl_copy_undo_entry(UNDO_LIST *entry) + - new function: _rl_copy_undo_list(UNDO_LIST *head) + +lib/readline/rlprivate.h + - new extern declarations for _rl_copy_undo_{entry,list} + +execute_cmd.c + - change execute_cond_node so that quoting the rhs of the =~ + operator forces string matching, like the == and != operators + + 5/23 + ---- +redir.c + - add_undo_redirect now takes as an additional argument the type of + redirection we're trying to undo + - don't add a "preservation" redirection for fds > SHELL_FD_BASE if + the redirection is closing the fd + + 5/24 + ---- +subst.c + - make sure that parameter_brace_substring leaves this_command_name + set to either NULL or its previous value after setting it so that + arithmetic evaluation errors while expanding substring values + contain meaningful information + + 6/9 + --- +execute_cmd.c + - make sure that SUBSHELL_ASYNC and SUBSHELL_PIPE are set as flag bits + in subshell_environment, rather than setting only a single value + - change execute_subshell_builtin_or_function to give the `return' + builtin a place to longjmp to when executed in a subshell or pipeline + (mostly as the last command in a pipeline). Bug reported by + Oleg Verych + - in execute_simple_command, make sure to call execute_disk_command + with the_printed_command_except_trap to keep DEBUG trap command + strings from overwriting the command strings associated with jobs + and printed in job control messages. Bug reported by Daniel Kahn + Gillmor + +[bash-3.2-alpha frozen] + + 6/22 + ---- +syntax.h + - add new CBLANK (for [:blank:] class) flag value for syntax table and + shellblank(c) character test macro + +mksyntax.c + - add support for setting CBLANK flag in the syntax table depending on + whether or not isblank(x) returns true for character x + +locale.c + - change locale_setblanks to set or unset CBLANK flag for each + character when locale changes + +parse.y + - change call to whitespace(c) in lexical analyzer (read_token()) to + call shellblank(c) instead, so locale-specific blank characters are + treated as white space. Fixes bug reported by Serge van deb Boom + + +print_cmd.c + - when printing redirections, add a space between <, >, and <> and the + following word, to avoid conflicts with process substitution. Bug + reported by Ittay Dror + + 6/26 + ---- +configure.in + - set CROSS_COMPILE to the empty string by default, so we don't inherit + a random value from the environment. Bug reported by + Lee Revell + + 6/29 + ---- +lib/glob/xmbsrtowcs.c + - make sure destp is non-null before assigning a 0 to *destp in + xdupmbstowcs. Fix from Louiwa Salem + +execute_cmd.c + - fix execute_in_subshell to make sure asynchronous isn't set to 0 + before subshell_environment is set appropriately and + setup_async_signals is run. Based on report by Louiwa Salem + + +lib/readline/bind.c + - in rl_generic_bind(), make sure that the keys array is freed before + an error return. Fix from Louiwa Salem + + 7/1 + --- +builtins/read.def + - make sure all editing code is protected with #ifdef READLINE, esp. + unwind-protect that restores the default completion function + +lib/readline/display.c + - make sure to set local_prompt_len in rl_message() [in bash-3.2-alpha] + + 7/5 + --- +builtins/printf.def + - add more of echo's write error handling to printf. Suggested by + martin.wilck@fujitsu-siemens.com + + 7/7 + --- +lib/readline/display.c + - save and restore local_prompt_len in rl_{save,restore}_prompt + [in bash-3.2-alpha] + + 7/8 + --- +[bash-3.2-alpha released] + + 7/9 + --- +lib/readline/display.c + - make sure that _rl_move_cursor_relative sets cpos_adjusted when it + offsets `dpos' by wrap_offset in a multi-byte locale. Bug reported + by Andreas Schwab and Egmont Koblinger + +subst.c + - make sure that the call to mbstowcs in string_extract_verbatim is + passed a string with enough space for the closing NUL. Reported + by Andreas Schwab + + 7/18 + ---- +lib/readline/{display,terminal}.c + - remove #ifdefs for HACK_TERMCAP_MOTION so we can use + _rl_term_forward_char in the redisplay code unconditionally + +lib/readline/rlprivate.h + - new extern declaration for _rl_term_forward_char + +lib/readline/display.c + - in _rl_move_cursor_relative, use `dpos' instead of `new' when + deciding whether or not a CR is faster than moving the cursor from + its current position + - in _rl_move_cursor_relative, we can use _rl_term_forward_char to + move the cursor forward in a multibyte locale, if it's available. + Since that function doesn't have a handle on where the cursor is in + the display buffer, it has to output a cr and print all the data. + Fixes rest of problem reported by Egmont Koblinger + - change variable denoting the position of the cursor in the line buffer + from c_pos (variable local to rl_redisplay) to cpos_buffer_position + (variable local to file) for future use by other functions + + 7/25 + ---- +lib/malloc/{stats,table}.h + - include for prototypes for memset, strlen + +lib/termcap/{termcap,tparam}.c + - include and provide macro replacement for bcopy if + necessary + + 7/27 + ---- +lib/readline/histexpand.c + - add support for `<<<' here-string redirection operator to + history_tokenize_word. Bug reported by agriffis@gentoo.org + +externs.h + - don't add prototype for strerror() if HAVE_STRERROR defined + + 7/29 + ---- +subst.c + - in list_string, use `string' instead of `s' -- s is not initialized + + 8/9 + --- +subst.c + - fix parameter_brace_expand to set W_HASQUOTEDNULL in the WORD_DESC it + returns if the result of parameter_brace_substring is a quoted null + ("\177"). Fixes bug reported by Igor Peshansky + + 8/16 + ---- +lib/readline/readline.h + - new #define, READERR, intended to be used to denote read/input errors + +lib/readline/input.c + - in rl_getc, if read() returns an error other than EINTR (after the + EWOULDBLOCK/EAGAIN cases are handled), return READERR rather than + converting return value to EOF if readline is reading a top-level + command (RL_STATE_READCMD) + +lib/readline/readline.c + - if rl_read_key returns READERR to readline_internal_char[loop], + abort as if it had read EOF on an empty line, without any conversion + to newline, which would cause a partial line to be executed. This + fixes the bug reported by Mathieu Bonnet + +aclocal.m4 + - when testing for validity of /dev/fd/3, use /dev/null instead of + standard input, since the standard input fails with linux and `su'. + Bug reported by Greg Shafer + + 8/17 + ---- +Makefile.in + - switch the TAGS and tags targets so TAGS is the output of `etags' and + tags is the output of `ctags'. Suggested by Masatake YAMATO + + 8/25 + ---- +execute_cmd.c + - change code to match documentation: set BASH_COMMAND (which takes its + value from the_printed_command_except_trap) only when not running a + trap. Rocky says the debugger is ok with this, and this is what his + original diffs did + + 8/29 + ---- +variables.c + - change set_if_not to create shell_variables if it is NULL, since + -o invocation options can cause variables to be set before the + environment is scanned + +[bash-3.2-beta frozen] + + 9/5 + --- +[bash-3.2-beta released] + + 9/8 + --- +variables.c + - change dispose_used_env_vars to call maybe_make_export_env + immediately if we're disposing a temporary environment, since + `environ' points to the export environment and getenv() will use + that on systems that don't allow getenv() to be replaced. This + could cause the temporary environment to affect the shell. Bug + reported by Vasco Pedro + +builtins/echo.def,doc/{bash.1,bashref.texi} + - clarify that `echo -e' and echo when the `xpg_echo' shell option is + enabled require the \0 to precede any octal constant to be expanded. + Reported by Vasco Pedro + + 9/12 + ---- +builtins/printf.def + - make sure `%q' format specifier outputs '' for empty string arguments + Bug reported by Egmont Koblinger + +make_cmd.c + - change make_here_document to echo lines in here-doc if set -v has + been executed. Reported by Eduardo Ochs + +aclocal.m4 + - change BASH_CHECK_MULTIBYTE: + o replace check for wctomb with check for wcrtomb + o add checks for wcscoll, iswctype, iswupper, iswlower, + towupper, towlower + o add call to AC_FUNC_MBRTOWC to check for mbrtowc and mbstate_t + define HAVE_MBSTATE_T manually + o add checks for wchar_t, wctype_t, wint_t + +config.h.in + - add defines for wcscoll, iswctype, iswupper, iswlower, towupper, + towlower functions + - replace define for wctomb with one for wcrtomb + - add defines for wchar_t, wint_t, wctype_t types + +config-bot.h, lib/readline/rlmbutil.h + - add check for HAVE_LOCALE_H before defining HANDLE_MULTIBYTE + - add checks for: ISWCTYPE, ISWLOWER, ISWUPPER, TOWLOWER, TOWUPPER + - add checks for: WCTYPE_T, WCHAR_T, WCTYPE_T + + 9/13 + ---- +lib/readline/display.c + - when displaying prompts longer than the screenwidth in rl_redisplay, + and looking for the index of the last character whose buffer index + is <= the screen width to set up the inv_lbreaks array, make sure to + catch the case where the index == the screen width (an off-by-one + error occurs otherwise with prompts one character longer than the + screen width). Bug reported by Alexey Toptygin + +configure.in + - change DEBUGGER_START_FILE to start with ${ac_default_prefix}/share, + like bashdb installs itself. Reported by Nick Brown + + + 9/14 + ---- +lib/readline/display.c + - make multibyte code that computes the buffer indices of line breaks + for a multi-line prompt dependent on MB_CUR_MAX, so we don't take + the function call hit unless we're in a locale that can have + multibyte characters + + 9/19 + ---- +subst.c + - make dequote_list extern so other parts of the shell can use it + +subst.h + - extern declaration for dequote_list + +builtins/read.def + - call dequote_list before assigning words read to array variable if + we saw an escape character. Old code left spurious CTLESCs in the + string after processing backslashes. Bug reported by Daniel Dawson + + + 9/21 + ---- +[bash-3.2 frozen] + + 10/9 + ---- +support/shobj-coonf + - change -fpic to -fPIC for FreeBSD systems (needed for SPARC at least) + + 10/11 + ----- +[bash-3.2 released] + + 10/12 + ----- +parse.y + - change parse_matched_pair to make sure `` command substitution does + not check for shell comments while parsing. Bug reported against + bash-3.2 by Greg Schaefer + + 10/14 + ----- +parse.y + - add new parser_state flag: PST_REGEXP; means we are parsing a + regular expression following the =~ conditional operator + - cond_node sets PST_REGEXP after reading the `=~' operator + - change read_token to call read_token_word immediately if the + PST_REGEXP bit is set in parser_state + - change read_token_word to skip over `(' and `|' if PST_REGEXP is + set, since those characters are legitimate regexp chars (but still + parse matched pairs of parens) + + 10/16 + ----- +builtins/ulimit.def + - add -e and -r to $SHORT_DOC usage string + +po/ru.po + - fix encoding; Russian text in the file is actually encoded in KOI8-R + + 10/23 + ----- +shell.c + - make sure that the call to move_to_high_fd in open_shell_script + passes 1 for the `check_new' parameter so open high file descriptors + don't get closed and reused. Bug reported by Mike Stroyan + + +doc/bashref.texi + - fixes for typos and misspellings sent in by Brian Gough + + 10/24 + ----- +support/shobj-conf + - make netbsd shared library creation like openbsd's until I hear + differently (called using `gcc -shared') + + 10/26 + ----- +subst.c + - fix bug in parameter_brace_patsub so if the first character of the + expanded pattern is a `/', it is not taken as a global replacement + specifier. Bug reported on forums.nekochan.net + + 10/27 + ----- +builtins/printf.def + - if we need an extern declaration for asprintf, make sure we include + stdarg.h or varargs.h, whichever is appropriate + - if we do not have asprintf, add an extern declaration using + stdarg format. This fixes the bugs with %G on IRIX reported by + Matthew Woehlke and Stuart Shelton + + + +lib/sh/snprintf.c + - add note to not call log_10 with 0 argument -- we don't want to do + what real log10 does (-infinity/raise divide-by-zero exception) + - make sure numtoa (used by dtoa) takes the precision into account + when computing the fractional part with an argument of `0.0' + - make sure `g' and `G' formats don't print radix char if there are + no characters to be printed after it (change to floating()) + - change callers of log_10 (exponent, 'g' and 'G' cases in + vsnprintf_internal) to not call it with 0 for argument. This fixes + the hang reported on IRIX by Matthew Woehlke + and Stuart Shelton + + 10/28 + ----- +builtins/{caller,pushd}.def + - changed longdoc strings in loadable builtin section to be single + strings, as put in the build directory builtins.c file, to aid + translators + + 11/1 + ---- +execute_cmd.c + - reset subshell_environment to 0 after make_child() call in + execute_null_command. Fix provided by Roy Marples + + + 11/7 + ---- +lib/tilde/tilde.c +lib/readline/{util,undo,callback,input,isearch,kill}.c + - make sure that memory allocated with xmalloc is freed with xfree + + 11/9 + ---- +lib/readline/display.c + - make sure that _rl_redisplay_after_sigwinch clears the last displayed + line instead of the current line (instead of assuming that the + cursor is on the last line). Fixes bug reported by Egmont + Koblinger + + 11/10 + ----- +lib/readline/display.c + - make sure that _rl_col_width is never called with MB_CUR_MAX == 1, + since it doesn't count invisible characters and they are not + compensated for. Added a warning in _rl_col_width if called when + MB_CUR_MAX == 1. Bug reported and solution suggested by Eric + Blake + + 11/11 + ----- +lib/readline/display.c + - make sure _rl_wrapped_line is initialized to inv_lbsize int chars. + inv_lbsize and vis_lbsize are the same at that point, but it makes + the intent clearer. Fix from jan.kratochvil@redhat.com. + - in rl_redisplay, make sure we call memset on _rl_wrapped_line with + its full initialized size: inv_lbsize*sizeof(int). Fix from + jan.kratochvil@redhat.com. + - wrap the invisible and visible line variables and _rl_wrapped_line + into line_state structures, which can be swapped more efficiently. + Have to watch the wrapped_line field, since there's now one for + each struct. Changes from jan.kratochvil@redhat.com. + +lib/readline/complete.c + - in stat_char, check for `//server' on cygwin and return `/', since + it will always behave as a directory. Fix from Eric Blake + +lib/readline/histfile.c + - Cygwin's mmap() works in recent versions, so don't #undef HAVE_MMAP. + Recommendation from Eric Blake + +lib/readline/rlwinsize.h + - make sure tcflow() is defined on SCO Unix. Fix from William Bader + +aclocal.m4 + - add check for localeconv to AM_INTL_SUBDIR macro + +config.h.in + - add HAVE_LOCALECONV + +lib/sh/snprintf.c + - add check for HAVE_LOCALECONV for GETLOCALEDATA macro + +general.[ch] + - first argument to legal_number is now `const char *' + + 11/14 + ----- +lib/readline/{readline,rlprivate}.h + - move rl_display_prompt declaration from rlprivate.h to readline.h + +lib/readline/util.h + - new function: rl_free(void *mem), for use by users of readline dlls + on Windows + +lib/readline/readline.h + - new extern declaration for rl_free + +lib/readline/doc/rltech.texi + - document rl_free and rl_display_prompt for use by application writers + + 11/15 + ----- +aclocal.m4 + - change tests for /dev/fd and /dev/stdin to use constructs of the form + (exec test ... ) instead of test ... to avoid bash's /dev/fd and + /dev/stdin emulation + + 11/16 + ----- +jobs.c + - in delete_job, reset_current was being called before the job slot + was cleared -- moved after job_slots[job] was set to NULL. Fixes + bug reported by Dan Jacobson + + 11/19 + ----- +findcmd.c + - when the checkhash option is set, fix the check for the hashed + pathname being an existing executable file. Old code required a + hash table deletion and re-addition. Bug reported by Linda + Walsh + + 11/21 + ----- +subst.c + - in pos_params, handle case of `start' == 0 by making the list of + positional parameters begin with $0 + - in parameter_brace_substring, increment `len' if start == 0, since + we will be adding $0 to the beginning of the list when we process it + +doc/{bash.1,bashref.texi} + - document new behavior of `0' offset when using substring expansion + with the positional parameters + +support/shobj-conf + - changes to shared object creation for loadable builtins on Mac OS X + 10.4 to use libtool instead of ld by specifying -dynamiclib + argument and changing options to be appropriate for libtool. This + winds up creating a dynamic shared library instead of an executable + + 11/24 + ----- +{jobs,nojobs}.c + - don't set last_asynchronous_pid to the child's pid in the child + for asynchronous jobs (for compatibility -- all other posix shells + seem to do it this way). This means that (echo $! )& echo $! should + display two different pids. Fix from discussion on the + austin-group-l list + +builtins/mkbuiltins.c + - change builtins.c file generation so short doc strings are marked for + gettext and available for subsequent translation. Suggestion by + Benno Schulenberg + +builtins/{bind,cd,hash,inlib,printf,pushd,test,times,ulimit}.def +lib/malloc/malloc.c +{shell,subst}.c + - fix a few strings that were not marked as translatable. Fix from + Benno Schulenberg + +lib/readline/misc.c + - new function, _rl_revert_all_lines(void). Goes through history, + reverting all entries to their initial state by undoing any undo + lists. + +lib/readline/rlprivate.h + - extern declaration for _rl_revert_all_lines + +rldefs.h + - add #undef HAVE_STRCOLL if STRCOLL_BROKEN is defined, prep to move + from config.h.in. Problem reported by Valerly Ushakov + + + 11/25 + ----- +lib/readline/readline.c + - call _rl_revert_all_lines from readline_internal_teardown if the + variable _rl_revert_all_at_newline is non-zero + - declare _rl_revert_all_lines initially 0 + + 11/27 + ----- +doc/{bash.1,bashref.texi} + - make sure to be explicit that `typeset +r' cannot remove the readonly + attribute from a variable + + 11/28 + ----- +lib/sh/zmapfd.c + - new file, implements zmapfd(), which takes a file and returns its + contents in a string + +externs.h + - extern declaration for zmapfd + + 11/29 + ----- +builtins/evalfile.c + - in _evalfile, use zmapfd to read the contents of the file into a + string, rather than using the size reported by stat and reading that + many characters, if the file is not a regular file (for things like + named pipes, stat reports the size as 0) + + 12/3 + ---- +lib/sh/snprintf.c + - make sure number() sets the FL_UNSIGNED flag for %x and %X, so + fmtulong treats them as unsigned numbers. Fixes bug reported by + James Botte + + 12/13 + ----- +lib/readline/util.c + - new function, _rl_ttymsg, for internal warning messages -- does + redisplay after printing message + - new function, _rl_errmsg, for internal warning/error messages -- + does not do redisplay after printing message + +lib/readline/rlprivate.h + - new extern declaration for _rl_ttymsg, _rl_errmsg + +lib/readline/{bind,callback,complete,display,rltty}.c + - use _rl_ttymsg/_rl_errmsg instead of direct writes to stderr + +lib/sh/tmpfile.c + - in get_tmpdir(), make sure that $TMPDIR names a writable directory; + otherwise skip it. This catches names longer than PATH_MAX, but in + case it doesn't test that the length does not exceed PATH_MAX. Fixes + heap overrun bug reported by Eric Blake + + 12/16 + ----- +builtin/{set,declare,shopt,trap,wait,bind,complete,enable,fc,history,read,setattr}.def +doc/{bash.1,bashref.texi} + - improvements and clarifications to the help text associated with + several builtins, in some cases bringing them into line with the + man page text. From Benno Schulenberg + +doc/{bash.1,bashref.texi} + - add `E' and `T' to the synopsis of the set builtin. + From Benno Schulenberg + +builtins/{break,exit,fg_bg,hash,jobs,type,ulimit}.def +builtins/{common,evalfile}.c +{error,expr,jobs,mksyntax,nojobs,shell,subst,version,siglist}.c + - add gettextizing marks to untranslated strings + From Benno Schulenberg + + 12/19 + ----- +builtins/common.c + - change display_signal_list (used by `trap -l' and `kill -l') to use + five columns instead of 4 to display signal names + +builtins/help.def + - use the true terminal width instead of assuming 80 when displaying + help topics, leaving two characters of whitespace between horizontal + descriptions instead of 1 + - change to print in columns with entries sorted down rather than across + (that is, like `ls' rather than `ls -x'). Change inspired by Benno + Schulenberg + +jobs.h + - give values to the JOB_STATE enumerations so they can be used as + bitmasks, too + + 12/22 + ----- +doc/{bash.1,bashref.texi} + - change description of `set' to make it clearer that you can use + `+' to turn off options + - clarify in the description of word splitting that sequences of + IFS whitespace at the beginning or end of the string are ignored + + 12/26 + ----- +doc/bashref.texi + - move `shopt' builtin to its own section; change internal references + from `Bash Builtins' to the new shopt builtin + - new section for builtins that modify shell behavior in `Shell + Builtin Commands'; move set and shopt to new section. Changes + inspired by Benno Schulenberg + +{redir,subst}.c + - add MT_USETMPDIR flag to calls to sh_mktmpfd and sh_mktmpname. Bug + reported by Eric Blake + +{configure,Makefile}.in + - changes so that the pathname for DEBUGGER_START_FILE is substituted + into pathnames.h at make time (allowing more flexibility in setting + `prefix' or `datadir') instead of at configure time. Suggested by + Nick Brown + +shell.c + - declaration for have_devfd; initialized from HAVE_DEV_FD + - declaration for check_jobs_at_exit; initialized to 0 + - declaration for autocd; initialized to 0 + +variables.c + - new dynamic variable, BASHPID, always set from return value from + getpid() (changes even when $$ doesn't change). Idea from Bruce + Korb + +builtins/exit.def + - if check_jobs_at_exit is non-zero, list jobs if there are any stopped + or running background jobs; don't exit shell if any running jobs + +execute_cmd.c + - in execute_simple_command, if the first word of a simple command is + a directory name (after looking for builtins, so `.' isn't caught) + that isn't found in $PATH, and `autocd' is non-zero, prefix a "cd" + to the command words + +builtins/shopt.def + - new `checkjobs' option, changes value of check_jobs_at_exit + - new `autocd' option, changes value of autocd + +pcomplete.c + - add COMP_TYPE, set to rl_completion_type, to list of variables set + by bind_compfunc_variables and unset by unbind_compfunc_variables + +doc/{bash.1,bashref.texi} + - document BASHPID + - document new shopt `checkjobs' option + - document new shopt `autocd' option + - document COMP_TYPE completion variable + + 12/29 + ----- +aclocal.m4 + - in BASH_SYS_SIGLIST, check HAVE_DECL_SYS_SIGLIST instead of the + obsolete and no-longer-supported SYS_SIGLIST_DECLARED + + 12/30 + ----- +lib/readline/vi_mode.c + - add ` (backquote) to the list of vi motion characters + - in rl_vi_delete_to, rl_vi_change_to, and rl_vi_yank_to, don't delete + character under the cursor if the motion command moves the cursor + backward, so add F and T to the commands that don't cause the + mark to be adjusted + - add ` to the characters that don't cause the mark to be adjusted + when used as a motion command, since it's defined to behave that way + - when a motion character that may adjust the mark moves point + backward, don't adjust the mark so the character under the cursor + isn't deleted + +lib/readline/complete.c + - add variable rl_sort_completion_matches; allows application to + inhibit match list sorting + - add variable rl_completion_invoking_key; allows applications to + discover the key that invoked rl_complete or rl_menu_complete + +lib/readline/readline.h + - extern declarations for rl_completion_invoking_key and + rl_sort_completion_matches + +lib/readline/doc/rltech.texi + - documented rl_completion_invoking_key and rl_sort_completion_matches + +pcomplete.c + - export variable COMP_KEY to completion functions; initialized from + rl_completion_invoking_key; unset along with rest of completion + variables + +doc/{bash.1,bashref.texi},lib/readline/doc/rluser.texi + - document COMP_KEY + +[many files] + - changes to make variables and function parameters `const' for better + text sharing. Changes originally from Andreas Mohr + + + 1/4/2007 + -------- +lib/intl/Makefile.in + - use cmp before copying libgnuintl.h to libintl.h -- maybe save a few + rebuilds + +lib/builtins/Makefile + - fixes to build LIBINTL_H if necessary, dependency on this for + mkbuiltins.o prevented `make -j 6' from working correctly + + 1/8 + --- +subst.c + - new function, fifos_pending(), returns the count of FIFOs in + fifo_list (process substitution) + +subst.h + - extern declaration for fifos_pending() + +execute_cmd.c + - in execute_simple_command, if CMD_NO_FORK is set before we call + execute_disk_command, make sure there are no FIFOs in the expanded + words (from process substitution) and turn off CMD_NO_FORK if there + are, so they can get unlinked when the command finishes + + 1/10 + ---- +subst.c + - read_comsub now takes a flags parameter and returns appropriate W_* + flags in it + - command_substitute now returns a WORD_DESC *, with the string it used + to return as the `word' and `flags' filled in appropriately + +subst.h + - changed extern declaration for command_substitute + +{pcomplete,subst}.c + - changed callers of command_substitute appropriately + +subst.c + - string_extract_verbatim now takes an additional int flags argument; + changed callers + + 1/11 + ---- +support/texi2html + - fix problem that caused index links to not be generated if the first + index node had a name different than the node name + +doc/bashref.texi + - encapsulated all indexes into a single `Indexes' appendix; works + around bug fixed in texi2html + + 1/12 + ---- +subst.c + - add call to sv_histtimefmt in initialize_variables so HISTTIMEFORMAT + from the environment is honored. Fix from Ark Submedes (heh) + + +lib/readline/histfile.c + - make sure that the first character following the history comment + character at the beginning of a line is a digit before interpreting + it as a timestamp for the previous line + +doc/{bash.1,bashref.texi},lib/readline/doc/hsuser.texi + - added detail to make it clear exactly how history timestamps are + saved to and read from the history file + +subst.c + - change quote_escapes to add CTLESC before spaces if IFS is null, + just in case we have to split on literal spaces later on (e.g., in + case of unquoted $@). Corresponding changes to dequote_escapes. + Fixes a couple of problems reported by Brett Stahlman + + + 1/14 + ---- +subst.c + - make same change to read_comsub to add CTLESC before ' ' if $IFS is + null, since we will split on literal spaces later + + 1/15 + ---- +array.c + - new function, array_quote_escapes (ARRAY *a), calls quote_escapes + on each element of the array in the same way array_quote calls + quote_string + - call array_quote_escapes if match is not quoted in array_patsub + - array_slice is now used, so remove the #ifdef INCLUDE_UNUSED define + - change structure of array_subrange to call array_slice to create a + new array with the desired subset of elements, then call array_quote + or array_quote_escapes as necessary, like array_patsub. Convert to + a string by calling array_to_string on the sliced-out array + +array.h + - new extern declaration for array_quote_escapes + +subst.c + - since array_patsub now calls quote_escapes as necessary, callers + don't need to call it after array_patsub returns. Fixes first bug + reported by Brett Stahlman + - since array_subrange now calls quote_escapes as necessary, callers + don't need to call it after array_patsub returns. Same fix as + for array_patsub + + 1/31 + ---- +configure.in + - add -DSOLARIS to LOCAL_CFLAGS for solaris x + +config-bot.h + - don't #undef HAVE_GETCWD if GETCWD_BROKEN and SOLARIS are both + defined. Solaris's loopback mount implementation breaks some of the + file system assumptions the replacement getcwd uses. + +builtins/common.c + - if GETCWD_BROKEN is defined, call getcwd with PATH_MAX for the size + argument, so it will allocate a buffer for the current working dir + with that size, instead of one that's `big enough' + +config.h.in + - add #undef PRI_MACROS_BROKEN for AIX 4.3.3 + +pathexp.h + - new flag value for quote_string_for_globbing: QGLOB_REGEXP (quoting + an ERE for matching as a string) + +pathexp.c + - change quote_string_for_globbing to understand QGLOB_REGEXP + +execute_cmd.c + - change execute_cond_node to pass 2 (regexp match), 1 (shell pattern + match), or 0 (no matching) to cond_expand_word + +subst.c + - change cond_expand_word to translate SPECIAL==2 into passing + QGLOB_REGEXP to quote_string_for_globbing + +locale.c + - by default, if all else fails, set shell's idea of locale to "" + instead of its idea of `default_locale' -- the library functions + behave better with that value + + 2/2 + --- +builtins/printf.def + - if PRI_MACROS_BROKEN is defined, #undef PRIdMAX (AIX 4.3.3 broken) + + 2/3 + --- +Makefile.in,{builtins,doc}/Makefile.in,lib/*/Makefile.in + - add assignment for datarootdir as per GNU coding standards + +Makefile.in,builtins/Makefile.in,lib/intl/Makefile.in,po/Makefile.in.in + - use @localedir@ instead of $(datadir)/locale in assignment + + 2/13 + ---- +jobs.c + - fix compact_jobs_list to not return js.j_lastj, since that is in use + and should not be overwritten. Fix from Len Lattanzi + + + 2/16 + ---- +lib/readline/text.c + - change rl_forward_char to allow moving to the end of the line when + using the arrow keys in vi insertion mode, rather than having the + behavior identical between vi command and insertion modes. Change + suggested by Hugh Sasse + + 2/19 + ---- +CWRU/audit-patch + - patch from Steve Grubb of RedHat to make bash + audit root's behavior by logging commands using his audit + framework. Enabled if the shell's name is `aubash'. + + 3/8 + --- +jobs.c + - use WSTATUS (p->status) instead of bare p->status. Fix from + Jim Brown + + 3/9 + --- +lib/readline/{complete,input,isearch,misc,readline,text,vi_mode}.c + - make sure cases where rl_read_key returns -1 (usually due to EIO + because the controlling tty has gone away) are handled correctly. + Prompted by report from Thomas Loeber + + 3/10 + ---- +sig.c + - new function, top_level_cleanup, callable from contexts where some + cleanup needs to be performed before a non-fatal call to + jump_to_top_level + +sig.h + - new extern declaration for top_level_cleanup + +builtins/common.c + - add calls to top_level_cleanup before calls to jump_to_top_level + in a builtin command context (no_args(), get_numeric_arg()). Fixes + bug reported by Ian Watson + +lib/readline/display.c + - in _rl_move_cursor_relative, use `new' when comparing against + the last invisible character in the prompt, since they both denote + buffer indices when in a multibyte locale, whereas `dpos' is a + display position + + 3/13 + ---- +lib/readline/complete.c + - set rl_completion_append_character to the default (' ') in + set_completion_defaults(). Fixes bug reported by David Emerson + + + 3/23 + ---- +builtins/evalfile.c + - make sure read() returns a value >= 0 before using it as an index + into string[] + - use a variable of type `ssize_t' for return value from read() + - only try to read the entire contents of a regular file in one shot + if the file size is less than SSIZE_MAX. These fix problems + reported by hooanon05@yahoo.co.jp. + +include/typemax.h + - define SSIZE_MAX as 32767 if it's not defined + +lib/readline/display.c + - in rl_redisplay() and update_line(), if redrawing the prompt because + it contains invisible characters, make sure we redraw the character + indicating a modified history line and take it into account when + computing _rl_last_c_pos + - in update_line, if deleting characters and redrawing the new text, + make sure we adjust _rl_last_c_pos by wrap_offset in a multibyte + locale if the text we're drawing starts before or at the last + invisible character in the prompt string. Fixes bug reported on + bug-readline by J Pelkey + +parse.y + - when adding at CTLESC character to the current token, do not + escape it with CTLESC if pass_next_character indicates that the + CTLESC was escaped by a backslash. Fixes bug reported by + Paul Bagshaw . + + 3/25 + ---- +lib/readline/text.c + - in rl_forward_char, short-circuit the loop if in emacs mode and + rl_point == rl_end. Fixes problem with multibyte locales + reported by Len Lattanzi + + 3/29 + ---- +command.h + - new flag for subshell_environment: SUBSHELL_PROCSUB, for process + substitution + +subst.c + - add SUBSHELL_PROCSUB to subshell_environment in process_substitute + + 3/30 + ---- +doc/Makefile.in + - fix installation of bash.info to understand that it is in the build + directory, not the source directory + +mailcheck.c + - new function, init_mail_dates, calls remember_mail_dates only if + there are no mailboxes in `mailfiles' + - new function, init_mail_file, initializes a FILEINFO, using the + last time mail was checked as the mtime and atime (or the time the + shell was started if last_time_mail_checked is uninitialized) + - call init_mail_file instead of update_mail_file in add_mail_file, + called from remember_mail_dates (which is supposed to initialize + the list of mail files) + - new convenience functions, alloc_mail_file and dispose_mail_file to + allocate and free FILEINFO structs + +mailcheck.h + - extern declaration for init_mail_dates + +shell.c + - call init_mail_dates instead of remember_mail_dates + + 4/4 + --- +builtins/read.def + - changes to print $PS2 when a line is continued with a backslash in + an interactive shell. This is as POSIX requires + + 4/5 + --- +subst.c + - make sure quote_escapes is only ever called when the word to be + escaped is not marked as double-quoted -- cleaner, and allows us + to make certain assumptions + + 4/6 + --- +subst.c + - change all EX_* defines to begin with SX_ + - new flag, SX_NOCTLESC, obeyed by string_extract_verbatim, tells it + to not obey CTLESC quoting + - change quote_escapes to not quote CTLESC with CTLESC if one of the + chars in $IFS is CTLESC, since the return value from quote_string + will be passed to word splitting and filename generation + - change read_comsub to do the same thing for unquoted command + substitutions + - change list_string to pass SX_NOCTLESC if CTLESC is one of the + chars in $IFS, so it will split on CTLESC instead of using it as a + quote character + + 4/7 + --- +subst.c + - slight change to string_extract_verbatim to allow CTLESC to quote + CTLNUL even if SX_NOCTLESC is set in the flags passed, to protect + the CTLNULs from future calls to remove_quoted_nulls. Only + matters when $IFS contains CTLESC + - changes to cope with $IFS containing CTLNUL in the same way as the + CTLESC changes + +builtins/read.def + - changes to cope with $IFS containing CTLNUL in the same way as the + CTLESC changes + + 4/16 + ---- +lib/sh/strftime.c + - a couple of fixes to the `%z' code + +eval.c + - add an fflush after printing the auto-logout message + + 4/24 + ---- +subst.c + - add call to top_level_cleanup in exp_jump_to_top_level to get things + like unwind-protects and the loop levels cleaned up + +{arrayfunc,expr,variables}.c + - add calls to top_level_cleanup before jump_to_top_level() + + 4/27 + ---- +builtins/complete.def + - make sure the `command' argument to the -C option is printed with + single quotes, since multi-word commands will require them. Bug + reported by martin@snowplow.org + +execute_cmd.c + - change execute_builtin_or_function and execute_subshell_builtin_or_function + to call fflush(stdout) after the builtin or function returns, to + make sure that all output is flushed before the call returns. It + matters on cygwin. Fix suggested by Eric Blake + +redir.c + - in do_redirection_internal, if the file descriptor being acted upon + is the same one used by the stdout stream, call fflush(stdout) to + make sure all output is flushed before changing the underlying fd + out from underneath stdio. Fix suggested by Eric Blake + + + 4/30 + ---- + +builtins/common.c + - new function, sh_chkwrite(int), fflushes stdout and checks for error; + printing an error message and returning a new exit status if there's + an error on stdout. Takes exit status as argument; returns new exit + status (EXECUTION_FAILURE if write error) + +builtins/common.h + - new extern declaration for sh_chkwrite + +builtins/{alias,cd,complete,echo,fc,history,pushd,shopt,times,trap,type,ulimit,umask}.def + - change to use sh_chkwrite to report write errors + +builtins/fc.def + - if an error occurs while writing commands from the history to a file + to be executed, report a write error and return failure without + attempting to execute any commands + + 5/1 + --- +builtins/{bind,declare,set,setattr}.def + - change to use sh_chkwrite to report write errors + + 5/2 + --- +lib/readline/input.c + - fix off-by-one errors in _rl_get_char (pop_index) and rl_stuff_char + (push_index) that caused the 511th character in the buffer to be + discarded. Fixes bug reported by Tom Bjorkholm + + 5/8 + --- +subst.c + - fix parameter_brace_remove_pattern to pass getpattern() newly-allocated + memory. If word expansions (particularly brace expansions) are + required, the expansion code will free the string passed to + expand_word_internal, and we don't want to free unallocated memory + (patstr++) or have duplicate frees (patstr). Fixes bug reported on + Red Hat bugzilla + + 5/9 + --- +lib/readline/signals.c + - fix bug in rl_set_signals that caught SIGINT twice and didn't catch + SIGTERM. Bug reported by Ed Kwan + + 5/18 + ---- +jobs.c + - change compact_jobs_list to return 1 if js.j_lastj == 0 and there is + a job in jobs[0]; compact_jobs_list should never return an index + already occupied + - change reset_job_indices to avoid infinite looping when js.j_firstj + == 0 or js.j_firstj == js.j_jobslots upon function entry. Fixes + bug reported by osicka@post.cz + + 5/20 + ---- + +execute_cmd.c + - new variable, executing_builtin, keeps track of number of "levels" + of builtins being executed; incremented by execute_builtin; saved + and restored by execute_simple_command + +subst.c + - new variable, assigning_in_environment, set and unset around calls + to assign_in_env by the expansion code + +variables.c + - use executing_builtin and assigning_in_environment to decide whether + or not to look into temporary_env when calling find_variable_internal. + Fixes problem reported by Kevin Quinn + + 5/22 + ---- +redir.c + - change add_undo_redirect to differentiate between file descriptors + greater than SHELL_FD_BASE (currently 10) used internally to save + others and then being the targets of user redirection and fds that + are just the target of user redirections. The former need to have + an `exec undo' redirect added to undo it in case exec throws away + redirections; the latter does not. We use the close-on-exec flag + for this: if it's set, we assume that the file descriptor is being + used internally to save another. Fixes problem reported by Ian + Jackson + +shell.c + - new function, init_interactive_script(), does interactive initialization + for a script run with `bash -i script' -- does everything the same + as init_interactive except set `interactive == 1', which causes the + shell to read from the standard input, after calling + init_noninteractive + - call init_interactive_script if a script is run as `bash -i script'. + Fixes problem reported by Joseph Michaud + + 5/24 + ---- +builtins/printf.def + - change vbadd to only call FASTCOPY if the passed buffer length is + > 1 + - if the `-v' option is supplied and `vbuf' is already non-null from a + previous `printf -v var' call, set vbuf[0]=0 explicitly instead of + relying on vbadd to do it -- vbadd may not be called. + - fix PRETURN macro to set vbuf[0] == 0 if vbuf is not freed. These + should fix problem reported by Elmar Stellnberger + +lib/readline/display.c + - fix update_line to deal with the case where col_lendiff > 0 (meaning + the new string takes up more screen real estate than the old) but + lendiff < 0 (meaning that it takes fewer bytes to do so). This can + happen when a multibyte prompt string is replaced with a longer one + containing only single-byte characters (e.g., when doing a reverse + i-search). Fixes gentoo bug reported by Peter Volkov + + +builtins/read.def + - make sure we only print $PS2 if the standard input is a terminal + - new function, read_mbchar, to read a multibyte character so we + can make sure we read entire multibyte chars when `read -n' is + used, rather than bytes. Only called when -n is supplied. + Fixes problem reported by Stanislav Brabec + + 5/25 + ---- +externs.h + - new #defines for third argument to named_function_string: + FUNC_MULTILINE (don't suppress newlines) and FUNC_EXTERNAL (convert + to external display form) + +subst.h + - new extern declaration for remove_quoted_escapes + +subst.c + - remove_quoted_escapes is now global + +print_cmd.c + - in named_function_string, if FUNC_EXTERNAL is in the flags argument, + call remove_quoted_escapes to convert from internal to external form. + Fixes bug reported by Bo Andresen + +variables.c,builtins/{declare,setattr,type}.def + - use FUNC_MULTILINE in calls to named_function_string as appropriate + - add FUNC_EXTERNAL to calls to named_function_string as appropriate + + 5/27 + ---- +{make_cmd,variables}.c + - changes to enable the shell to compile when debugger support is + configured out (function_def hash table and access functions). Fixes + bug reported by Horst Wente + +builtins/help.def + - fix bug in `help' two-column printing to avoid referencing + shell_builtins[num_shell_builtins] + +error.c + - in get_name_for_error, use dollar_vars[0] if the name returned from + looking in $BASH_SOURCE[0] is the empty string as well as if it's + null + + 5/31 + ---- +arrayfunc.c + - change array_value_internal to set *RTYPE to 1 if the reference is + array[*] and 2 if the reference is array[@] + +subst.c + - in parameter_brace_expand_word, set the flags returned by the word + desc to include W_HASQUOTEDNULL if array_value returns QUOTED_NULL + for an array reference like x[*] and the word is quoted. Fixes bug + reported by Christophe Martin + + 6/1 + --- +jobs.c + - several changes to preserve errno if tcgetpgrp/tcgetattr/tcsetattr + fail, for subsequent error messages + - change initialize_job_control to turn off job control if the terminal + pgrp == -1 or is not equal to shell_pgrp (with an error message) + - in initialize_job_control, if the shell has been forced interactive + with -i, make sure stderr is hooked to a tty before using it as + the controlling terminal. If it's not, try to open /dev/tty and + assign it to shell_tty. Fixes problems reported by Derek Fawcus + + + 6/13 + ---- +support/shobj-conf + - changes to support shared object and shared library creation on AIX + 5.x and later versions. From Niklas Edmundsson + + 6/17 + ---- +builtins/mkbuiltins.c + - new array of builtins, posix_builtins, containing builtins listed + as special to the command search order by POSIX + - add POSIX_BUILTIN to the builtin flags if the builtin name is one + that's special to the posix command search order + +builtins.h + - new define, POSIX_BUILTIN, means that a builtin is special to the + posix command search order + + 6/22 + ---- +lib/readline/display.c + - new macro, WRAP_OFFSET, intended to replace W_OFFSET. Takes prompt + strings longer than one physical line with invisible characters on + the second line into account when calculating the number of + invisible characters on the current screen line + - use WRAP_OFFSET where appropriate (update_line, _rl_move_cursor_relative) + - change update_line to deal with adjusting _rl_last_c_pos in a + multibyte environment when the prompt has invisible chars on the + second line and redisplay has output the invisible characters + - change _rl_move_cursor_relative to adjust _rl_last_c_pos in a + multibyte environment when the prompt has invisible chars on the + second line and the redisplay draws the invisible character. Fixes + redisplay bug reported by Andreas Schwab + + + 7/11 + ---- + +lib/readline/rltty.c + - enable flush-output code for systems other than AIX 4.1. Problem + reported by Jan Kratochvil + + 7/12 + ---- +lib/readline/display.c + - set prompt_invis_chars_first_line from the portion of the prompt + following the final newline, instead of from the prefix. Fixes + bug reported on the Ubuntu bug list by dAniel hAhler + + + 7/13 + ---- +variables.c + - use native __QNX__ and __QNXNTO__ cpp defines instead of qnx and + qnx6, respectively. Patch from Sean Boudreau + +lib/sh/getcwd.c + - #undef HAVE_LSTAT on qnx, so it uses stat instead. Patch from + Sean Boudreau + + 7/21 + ---- +builtins/common.c + - change sh_invalidnum to be a little smarter about octal and hex + numbers and change the message appropriately. Bug originally + reported on coreutils list by Jürgen Niinre + + 7/26 + ---- +test.c + - make sure the string passed to test_unop has only a single character + following the `-'. Fixes bug reported by Michael A. Smith + + +parse.y + - better input validation: make sure a word looks like a conditional + unary operator (-X) before calling test_unop + + 7/28 + ---- +trap.c + - in trap_handler, if it's called directly from the signal handler + (e.g., SIGINT sighandler, set by set_sigint_handler), but the + trap disposition has been reset to the default between the + assignment and receipt of the signal, check that the signal is + trapped and issue a warning if the shell was compiled with + debugging enabled. Fixes bug reported by Fergus Henderson + + + 8/1 + --- +lib/readline/{util,histexpand}.c + - fixes for small memory leaks from Michael Snyder + + 8/18 + ---- +Makefile.in + - add dependency on builtins/builtext.h to nojobs.o list. Fixes + `make -j 5' issue reported by Chris MacGregor + +examples/loadables/Makefile.in + - add @LDFLAGS@ to SHOBJ_LDFLAGS assignment -- experimental. Suggested + by Mike Frysinger + +examples/loadables/{basename,cut,dirname,finfo,head,ln,logname,mkdir,pathchk,print,printenv,push,realpath,rmdir,sleep,tee,truefalse,tty,uname,unlink,whoami}.c + - fix up some includes. Fix from Mike Frysinger + + 8/21 + ---- +histexpand.c + - fix another memory leak in history_find_word. Bug report originally + from Michael Snyder ; test case suggested by Jim + Blandy + + 8/26 + ---- +subst.c + - change to do_assignment_internal to make an assignment to a variable + with the `noassign' internal attribute not a variable assignment + error. + - fix do_assignment_internal so assignment to a `noassign' variable + does not cause it to suddenly become visible if it's currently + invisible + + 9/3 + --- +stringlib.c + - change strsub to check whether or not temp is non-null before + trying to null-terminate it. Also make sure temp is allocated + even if the pattern and replacement strings are empty, and set + to a copy of string (like ${foo//}) + Bug report from Timo Lindfors + + 9/10 + ---- +{config.h,Makefile,configure}.in,aclocal.m4 + - new tests for fpurge and __fpurge + +lib/sh/fpurge.c, externs.h + - new file, fpurge(3) implementation with external decl in externs.h + +builtins/common.c + - add call to fpurge(stdout) to sh_chkwrite + +{redir,execute_cmd}.c + - add call to fpurge(stdout) after fflush(stdout) before changing + stdout file descriptor and after a builtin or function executes + + 9/12 + ---- +expr.c + - make sure noeval is set to 0 when a longjmp occurs, since it will + not be reset otherwise, and it can be set to 1 while processing + a {pre,post}-increment or {pre,post}-decrement token + - set noeval to 0 at the beginning of evalexp, since it's never + called recursively + + 9/14 + ---- +config-top.h + - new builder-modifiable define: DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS + Turning it on will cause errors from EPIPE to not be reported by + the normal shell write error message mechanism + +builtins/common.c + - if DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS is defined, don't print an + error message from sh_wrerror if errno == EPIPE. Suggestion from + Petr Sumbera + + 9/19 + ---- +{jobs,nojobs}.c,jobs.h + - add code to retry fork() after EAGAIN, with a progressively longer + sleep between attempts, up to FORKSLEEP_MAX (16) seconds. Suggested + by Martin Koeppe + + 9/21 + ---- +version.c + - change copyright year to 2007 + + 9/25 + ---- +pathexp.c + - change quote_string_for_globbing to add a backslash in front of a + backslash appearing in the pathname string, since the globbing + code will interpret backslashes as quoting characters internally. + Bug reported by on the debian list + (443685) + + 10/8 + ---- +lib/readline/display.c + - in update_line, make sure _rl_last_c_pos is > 0 before setting + cpos_adjusted (or we actually moved the cursor to column 0 in + _rl_move_cursor_relative). Fixes redisplay bug with prompt with + only invisible characters reported by dAniel hAhler + + + 10/10 + ----- +lib/readline/display.c + - in rl_redisplay, when calculating the new physical cursor position + in a multibyte locale (`tx'), do not call rl_backspace if tx ends + up < 0. Rest of fix for bug reported by dAniel hAhler + + + 10/12 + ----- +lib/sh/getcwd.c + - fix memory overwrite problem that's possible if buf is NULL and + passed size is greater than the pathname length. Reported by + Ian Campbell + +builtins/ulimit.def + - change the multiplier for the -c and -f options (`blocks') to 512, + the traditional value (and the one POSIX specifies). Bug reported + by Pete Graner + +braces.c + - pass process substitution through unchanged the same as command + substitution. Prompted by suggestion from Stephane Chazelas + + +lib/readline/input.c + - in rl_unget_char, fix off-by-one error when resetting pop_index if + it's < 0. Bug reported by Uwe Doering + +builtins/type.def + - change exit status of `type' to not successful if any of the + requested commands are not found. Reported by Stephane Chazleas + + +pcomplete.c + - change command_line_to_word_list to use rl_completer_word_break_characters + instead of the shell metacharacters to split words, so programmable + completion does the same thing readline does internally. Reported + by Vasily Tarasov + + 10/16 + ----- +bashline.c + - When completing a command name beginning with a tilde and containing + escaped specical characters, dequote the filename before prefixing + it to the matches, so the escapes are not quoted again. Reported + by neil@s-z.org + + 10/17 + ----- +expr.c + - in readtok(), don't reset lasttp if we've consumed the whitespace + at the end of the expression string. Fixes error message problem + reported by + + 11/1 + ---- +builtins/printf.def + - change asciicode() to return intmax_t; add multibyte character + support instead of assuming ASCII (depending on behavior of system + multibyte support functions). Fixes bug reported by Rich + Felker + + 11/5 + ---- +execute_cmd.c + - if redirections attached to a compound command fail, make sure to + set last_command_exit_value when returning EXECUTION_FAILURE. + Fixes bug reported separately by Andreas Schwab + and Paul Eggert + + 11/9 + ---- +builtins/read.def + - make sure the return value from get_word_from_string is freed if + non-null. Fixes memory leak bug reported by Lars Ellenberg + + + 11/10 + ----- +variables.c + - use getpid() as value of seeded_subshell to avoid problems with + random number generator not getting re-seeded correctly when + subshells are created. Fix from Tomas Janousek + +lib/readline/display.c + - in update_line(), when outputting characters at the end of the line, + e.g., when displaying the prompt string, adjust _rl_last_c_pos by + wrap_offset if the text we're drawing begins before the last + invisible character in the line. Similar to fix from 5/24. Fixes + bug reported by Miroslav Lichvar + + 11/14 + ----- +subst.c + - fix $[ expansion case to deal with extract_arithmetic_subst + returning NULL (if the `]' is missing) and return the construct + unchanged in that case. Fixes tab completion bug reported by + Heikki Hokkanen (debian bug 451263) + +lib/readline/mbutil.c + - fix _rl_find_next_mbchar_internal to deal with invalid multibyte + character sequences when finding non-zero-length chars. Fixes + bug reported by Morita Sho + + 11/15 + ----- +variables.c + - add new function `seedrand' to seed the bash random number + generator from more random data. Suggestion from Steve Grubb + + - replace the rng in brand() with a slightly better one from FreeBSD + (filtered through Mac OS X 10.5). Replacement suggested by + Steve Grubb + + 11/21 + ----- +configure.in + - darwin 9 also requires linking against libreadline.a and + libhistory.a because of Apple's questionable decision to ship a + libreadline "replacement" that doesn't provide all functions + +doc/{bash.1,bashref.texi} + - slight change to the text describing the effect of set -e when + in a || or && list + + 12/5 + ---- +jobs.c + - fix raw_job_exit_status to correct mixing of int/WAIT values (need + to return a WAIT) + - arrange so that children run as part of command substitutions also + set the SIGINT handler to wait_sigint_handler, since they effectively + don't do job control + - in wait_for, if a child run as part of a command substitution exits + due to SIGINT, resend the SIGINT to the waiting shell with kill(2). + This makes sure the exit status propagates + +doc/{bash.1,bashref.texi} + - tighten up the language describing when bash tries to see if its + stdin is a socket, so it can run the startup files. Suggested by + Vincent Lefevre + +eval.c + - in the DISCARD case of a longjmp to top_level, make sure + last_command_exit_value is set to EXECUTION_FAILURE if it's 0, + but leave existing non-zero values alone + +subst.c + - in command_substitute, don't reset pipeline_pgrp in the child + process -- this means that second and subsequent children spawned by + this comsub shell get put into the wrong process group, not the + shell's. Fix for bug reported by Ingo Molnar + + 12/6 + ---- +support/shobj-conf + - make sure the cases for darwin8.x (Mac OS X 10.4.x) are extended to + darwin9.x (Mac OS X 10.5.x). Fixes problem originally reported + against readline-5.2 by schneecrash@gmail.com + + 12/8 + ---- +subst.c + - make sure to add the results of (successful) tilde expansion as a + quoted string, to inhibit pathname expansion and word splitting. + From recent Austin Group interpretation. + +include/shtty.h, lib/sh/shtty.c + - add ttfd_onechar, ttfd_noecho, ttfd_eightbit, ttfd_nocanon, and + ttfd_cbreak to set tty attributes associated with a particular + file descriptor (which is presumed to point to a terminal). Support + for fix for bug reported by b_bashbug@thebellsplace.com + +lib/readline/display.c + - make sure we only use rl_invis_chars_first_line when the number of + physical characters exceeds the screen width, since that's the + only time expand_prompt sets it to a valid value + + 12/12 + ----- +builtins/set.def + - change set_minus_o_option to return EX_USAGE if an invalid option + name is supplied. All callers can handle it. + - change set_builtin to return what set_minus_o_option returns if it's + not EXECUTION_SUCCESS. This allows EX_USAGE errors to abort a + shell running in posix mode + + 12/14 + ----- +builtins/read.def + - generalize the calls to the tty attribute functions to maintain a + local copy of the terminal attributes and use the fd supplied as + the argument to the -u option (default 0). Fix for bug reported + by b_bashbug@thebellsplace.com + +doc/bashref.texi, lib/readline/doc/{history,rlman,rluser,rluserman}.texi + - Slight changes to conform to the latest FSF documentation standards. + Patch from Karl Berry + + 12/20 + ----- +execute_cmd.c + - after calling clear_unwind_protect_list, make sure we reset + parse_and_execute_level to 0, since there's nothing left to + restore it if top_level_cleanup tests it. Fixes bug reported + by Len Lattanzi + + 12/31 + ----- +lib/sh/getcwd.c + - new function, _path_checkino, checks whether the inode corresponding + to the path constructed from the first two arguments is the same as + the inode number passed as the third argument + - if BROKEN_DIRENT_D_INO is defined, meaning the d_ino/d_fileno + member of struct dirent doesn't contain valid values, use + _path_checkino instead of directly comparing against d_fileno. + Fixes Interix problem reported by Michael Haubenwallner + + + 1/7/2008 + -------- +array.c + - fix array_subrange to separate elements in returned string with + first char of $IFS if QUOTED is non-zero, since this indicates + the caller used ${array[@]:foo}. Fixes bug reported by Lea + Wiemann + + 1/8 + --- +subst.c + - new function returning a string containing the first character of + $IFS: char *ifs_firstchar(int *) + +subst.h + - extern declaration for ifs_firstchar() + +array.c + - call ifs_firstchar() to get first character of $IFS when needed + (array_subrange() and array_patsub()) + + 1/11 + ---- +lib/readline/display.c + - use sentinel variable set at end of init_line_structures to decide + whether to call it from rl_redisplay, since early SIGWINCH on + Mac OS X that hits during this function can cause _rl_wrapped_line + to be referenced before initialization. Fix for bug reported by + Len Lattanzi + +subst.[ch] + - skip_to_delim is now compiled into the shell all the time, not just + when readline is linked in + +subst.c + - use skip_to_delim to find the `/' denoting the end of a pattern + in pattern substitution, since it knows more shell syntax than + quoted_strchr and understands multibyte characters. Fixes bug + reported by Dmitry V Golovashkin + + 1/15 + ---- +subst.c + - add `flags' argument to skip_to_delim telling it whether or not to + set no_longjmp_on_fatal_error; set this flag when calling from the + readline completion code + +subst.h + - update extern declaration for skip_to_delim + + 1/17 + ---- +subst.c + - expand_prompt_string takes a third argument: the initial flags for + the WORD + +subst.h + - change extern declaration for expand_prompt_string to add third arg + +bashline.c + - pass W_NOCOMSUB as third argment to expand_prompt_string when + calling from bash_directory_completion_hook, since we don't want + to do command substitution from the completion code + +parse.y + - change call to expand_prompt_string + + 1/18 + ---- +doc/Makefile.in + - added an `install_builtins' rule to install the builtins.1 man page, + preprocessing it with sed to force `.so man1/bash.1', which some + versions of man require. Suggestion from Peter Breitenlohner + + - new target `install_everything' that will install normal documentation + and builtins man page + - changed uninstall target to remove bash_builtins page from man + directory + +lib/readline/vi_mode.c + - new function, rl_vi_insert_mode, which calls rl_vi_start_inserting + to make sure the value of `last command to repeat' is set correctly. + Fix from Thomas Janousek + - add support for redoing inserts made with the `I' command. Fix + from Thomas Janousek + - add support for redoing inserts made with the `A' command + +lib/readline/readline.h + - new extern declaration for rl_vi_insert_mode + +lib/readline/{misc,readline,vi_mode,vi_keymap}.c + - change calls to rl_vi_insertion_mode to rl_vi_insert_mode + + 1/19 + ---- +builtins/read.def + - change timeout behavior when not reading from a tty device to save + any partial input in the variable list, but still return failure. + This also causes variables specified as arguments to read to be + set to null when there is no input available. Fix inspired by + Brian Craft + + 1/21 + ---- +builtins/fc.def + - change computation of last_hist to use remember_on_history instead + of a hard-coded `1'. This keeps fc -l -1 in PROMPT_COMMAND from + looking too far back + + 1/25 + ---- +lib/readline/complete.c + - fix fnwidth to use string[pos] instead of *string when testing the + current character for a control character or rubout + + 2/2 + --- +general.c + - change posix_initialize to turn off source/. searching $PWD when + the file sourced is not found in $PATH. Fixes bug reported by + Paolo Bonzini and Eric Blake + + 2/9 + --- +builtins/*.def + - changes to text and formatting suggested by Jan Schampera + + + 2/16 + ---- +bashline.c + - change command_word_completion_function to use the word completion + found by readline, which matters only when ignoring case is on + and the completion found in the file system differs in case from + the text the user typed (this is what readline does for normal + filename completion). Fixes issue reported by Jian Wang + . + + 2/18 + ---- +builtins/source.def + - if the filename passed as an argument contains a `/', don't search + $PATH. Not sure why it wasn't like this before + + 2/21 + ---- +lib/readline/terminal.c + - change rl_crlf so that the MINT system on ATARI systems adds a + carriage return before the \n + + 2/22 + ---- +doc/{bash.1,bashref.texi} + - added text to the EXIT STATUS section noting that exit statuses + fall between 0 and 255, inclusive + +support/mkversion.sh + - output a #define for DEFAULT_COMPAT_LEVEL (${major}${minor}; e.g. 32) + to version.h + +version.c + - int variable, shell_compatibility_level, set to DEFAULT_COMPAT_LEVEL + by default + +builtins/shopt.def + - new shopt variable, compat31, sets shell_compatibility_level to 31 + (or back to default if unset) + +execute_cmd.c + - in execute_cond_node, restore bash-3.1 behavior of quoted rhs of + regexp matches if shell_compatibility_level == 31 + + 2/28 + ---- +lib/readline/rltty.c + - set readline_echoing_p = 1 if tcgetattr fails and sets errno to + EINVAL, as Linux does when the fd is a pipe. Reported by Mike + Frysinger + + 3/6 + --- +{MANIFEST,Makefile.in},lib/sh/{casemod,uconvert,ufuncs}.c + - new library sources from bash-4.0-devel tree + +lib/sh/spell.c + - moved cdspell() here from builtins/cd.def, renamed dirspell() + +externs.h + - new declarations for extern functions from new library files + - new extern declaration for lib/sh/spell.c:dirspell() + +builtins/cd.def + - call extern library function dirspell(); remove static cdspell() + +builtins/read.def + - when read times out, make sure input_string is null-terminated before + assigning any partial input read to the named variables + + 3/10 + ---- +lib/glob/xmbsrtowcs.c + - cut the number of memory allocations in xdupmbstowcs by not keeping + track of the indices if the caller hasn't asked for it + + 3/17 + ---- +builtins/fc.def + - make sure the adjustment to i in fc_gethnum uses the same formula + fc_builtin uses to calculate last_hist + - make sure that every time fc_gethnum is called, the fc command last + in the history list has not yet been deleted, since fc_gethnum + assumes that it has not. Fix from John Haxby + +lib/readline/complete.c + - new private library function, _rl_reset_completion_state(), used to + reset any completion state internal to the library when a signal + is received + - call _rl_reset_completion_state() before returning from + rl_complete_internal + +lib/readline/rlprivate.h + - new extern declaration for _rl_reset_completion_state + +lib/readline/signals.c + - call _rl_reset_completion_state from rl_signal_handler on SIGINT. + This fixes one of the problems identified by Mika Fischer + + +pcomplete.c + - programmable_completions now saves pointer to the compspec it's + working with in new global variable CURCS + - new function, pcomp_set_readline_variables, that sets or unsets + readline variables based on a passed flags value (COPT_FILENAMES, + etc.) + - new function, pcomp_set_compspec_options, to set or unset bits in + the options word of a passed compspec (default CURCS) + - only call bash_dequote_filename (via rl_filename_dequoting_function) + from pcomp_filename_completion_function if the readline state + word indicates word completion is in progress + +pcomplete.h + - new extern declaration for curcs + - new extern declaration for pcomp_set_readline_variables + - new extern declaration for pcomp_set_compspec_options + +bashline.c + - fix bash_dequote_filename to implement shell quoting conventions: + 1. Inhibit backslash stripping within single quotes + 2. Inhibit backslash stripping within double quotes only if + the following character is one of the special ones + - call pcomp_set_readline_variables from attempt_shell_completion + instead of doing the equivalent inline + + 3/18 + ---- +bracecomp.c + - make sure we sort array of matches in byte order (using strcmp). so + the brace calculations work correctly even when the locale orders + characters like aAbBcC...zZ. Fixes bug reported by Torsten Nahm + + + 3/20 + ---- +lib/readline/{rltty,signals}.c + - move block_sigint and release_sigint from rltty.c to signals.c; add + _rl_ prefix to make them public to the library; change callers. + From Jan Kratochvil + +lib/readline/rlprivate.h + - new extern declarations for _rl_block_sigint and _rl_release_sigint + +lib/readline/display.c + - add calls to _rl_block_sigint and _rl_release_sigint to rl_redisplay, + since it maniupluates global data structures. Fix from Jan + Kratochvil + +builtins/printf.def + - change calls to asprintf and manually adding to vbuf to use calls + to vsnprintf against vbuf directly -- if the number of characters + to be written overflows the buffer, realloc the buffer and use + vsnprintf again. This should reduce the memory used by printf. + Idea from Yuya Katayama + +lib/readline/doc/rltech.texi + - documented rest of readline's state flags, including RL_STATE_CALLBACK + - documented rl_save_state and rl_restore_state + + 3/27 + ---- +lib/readline/{rlprivate.h,{display,readline,rltty,terminal,text}.c} + - rename readline_echoing_p to _rl_echoing_p for namespace consistency + +lib/readline/{rlprivate.h,{callback,readline,util}.c} + - rename readline_top_level to _rl_top_level for namespace consistency + +builtins/ulimit.def + - new -b (socket buffer size) and -T (number of threads) options + +array.c + - fix bug in calculation of the array element assignment string length: + use length of `is' instead of `indstr'. Reported as ubuntu bug + #202885 by John McCabe-Dansted + +builtins/setattr.def + - new function, show_all_var_attributes, displays attributes and + values for all shell variables (or shell functions) in a reusable + format + +builtins/common.h + - new extern declaration for show_all_var_attributes + +builtins/declare.def + - change `declare -p' to print out all variable attributes and values, + and `declare -fp' to print out all function attributes and + definitions. Inspired by request from John Love-Jensen + + +doc/{bash.1,bashref.texi} + - document new -b and -T options to ulimit + - tighten up language describing AND and OR lists + - add description of new behavior of `declare -p' + + 3/28 + ---- +pcomplete.c + - rename curcs -> pcomp_curcs + - new global completion variable, pcomp_curcmd, the current command + name being completed + +builtins/complete.def + - new builtin, compopt, allows completion options for command names + supplied as arguments or the current completion being executed to + be modified. Suggested by Mika Fischer + + 3/30 + ---- +doc/{bash.1,bashref.texi},lib/readline/doc/rluser.texi + - document new compopt builtin + + 4/5 + --- +support/shobj-conf + - change solaris10 stanza to use -fPIC to fix 64-bit sparc_v9/solaris10 + compilations. Fix from Fabian Groffen + +builtins/read.def + - added `-i text' option, inserts `text' into line if using readline. + Suggested by many, used some ideas from Kevin Pulo + +doc/{bash.1,bashref.texi} + - document new `-i text' option to read builtin + + 4/7 + --- +lib/readline/bind.c + - new settable variable, `history-size', sets the max number of + entries in the history list + +doc/bash.1,lib/readline/doc/{rluser.texi,readline.3} + - document new `history-size' settable readline variable + + 4/8 + --- +builtins/complete.def + - change build_actions calling sequence to take a struct with `other' + (non-action) flag arguments (-p, -r) + - add support for `-E' option to build_actions and complete builtin -- + modifies or displays (internal) `_EmptycmD_' completion spec + +bashline.c + - change attempt_shell_completion to try programmable completion on an + `empty' command line and return the results + +doc/bash.1,lib/readline/doc/rluser.texi + - documented new `-E' option to `complete' + + 4/9 + --- +bashhist.c + - new variable, `enable_history_list', used to reflect setting of + `-o history' option + - change bash_history_{enable,disable,reinit} to set enable_history_list + as well as remember_on_history + +builtins/set.def + - use `enable_history_list' instead of `remember_on_history' to keep + value of `-o history' option + +builtins/evalstring.c + - instead of unwind-protecting remember_on_history, use a function to + restore it to the value of `enable_history_list' after + parse_and_execute runs the commands in the string. This allows + history to be turned off in a startup file, for instance. Problem + reported by Dan Jacobson + + 4/11 + ---- +bashline.c + - limited support for completing command words with globbing characters + (only a single match completed on TAB, absolute or relative + pathnames supported, no $PATH searching, some support for displaying + possible matches, can be used with menu completion). + Suggested by Harald Koenig + +print_cmd.c + - change redirection printing to output r_err_and_out as `&>file', + since the man page says that's the preferred form + + 4/12 + ---- +builtins/*.def + - change long doc so the first line is a short description + - add `Exit Status:' section to each longdoc describing exit values + +builtins/help.def + - new `-d' option to print short description of each utility + - new `-m' option to print description of each builtin in a + pseudo-manpage format (inspired by ksh93) + +doc/{bash.1,bashref.texi} + - document new `-d' and `-m' options to `help' + +builtins/mapfile.def + - new builtin, `mapfile', imported from bash-4.0-devel branch + +tests/{mapfile.{data,right,tests},run-mapfile} + - tests for `mapfile' builtin + +doc/{bash.1,bashref.texi} + - added description of `mapfile' builtin + +MANIFEST,Makefile.in,builtins/Makefile.in + - added entries for mapfile source files + +arrayfunc.[ch] + - new function, bind_array_element, to support mapfile builtin + + 4/20 + ---- +expr.c + - fix operator precendence in expcond(): term after the `:' is + a conditional-expression, not a logical-OR-expression (using C + terminology). Bug reported by + + 4/22 + ---- +bashintl.h + - new P_ define for using ngettext to decide on plural forms + (currently unused) + + 4/25 + ---- +execute_cmd.c + - in execute_disk_command, if the command is not found, search for + a shell function named `command_not_found_handle' and call it + with the words in the command as arguments. Inspired by Debian + feature. + +doc/{bash.1,bashref.texi} + - document new command_not_found_handle behavior in COMMAND EXECUTION + section + +configure.in + - change default version to bash-4.0-devel + + 4/28 + ---- +variables.c + - change push_func_var and push_exported_var to call + stupidly_hack_special_variables if the temporary variable is going + to be disposed. This undoes any internal changes caused by a local + variable assignment in the environment or in a shell function. Bug + reported by Morita Sho in + http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=478096 + + 5/3 + --- +builtins/fc.def + - fixed a problem caused by change of 1/21 to use remember_on_history, + since it's turned off by parse_and_execute(), but can cause the + last command in history to be deleted and leave last_hist pointing + beyond the end of the history list. edit_and_execute_command can + do this. + +bashline.c + - new define, RL_BOOLEAN_VAR_VALUE, to take a readline boolean variable + and get its value as 0 or 1 (consider making readline global) + - put tty back into canonical mode before calling parse_and_execute in + edit_and_execute_command and then back into raw mode after it + returns. Fixes problem identified by . + + 5/4 + --- +lib/glob/glob.c + - code to support `globstar' option: GX_GLOBSTAR and two internal + flags. Changes to skipname, glob_vector, mbskipname, glob_filename. + New function finddirs(). + +lib/glob/glob.h + - new defines to support globstar code + +builtins/shopt.def + - new shell option, `globstar', enables special handling of `**' in + glob patterns -- matches all directories recursively + +pathexp.h + - extern declaration for glob_star + +pathexp.c + - break inline code out of quote_globbing_chars into a separate + function to decide whether a character is a globbing char: + glob_char_p + - change shell_glob_filename to call glob_filename with the + GX_GLOBSTAR flag if glob_star is set + +doc/{bash.1,bashref.texi} + - document new `globstar' shell option + +arrayfunc.c + - new function, broken out of quote_array_assignment_chars: + quote_assign; extended from old code to make sure that globbing + chars and chars in $IFS are quoted when displaying assignment + statements, especially in compound array assignments + + 5/5 + --- +bashline.c + - new variable, dircomplete_spelling, controls spelling correction + of directory names when doing filename completion + - change bash_directory_completion_hook to incorporate spelling + correction if initial canonicalization of directory name fails + +builtins/shopt.def + - new shell option, `dirspell', enables and disables spelling + correction of directory names during word completion + +builtins/read.def + - support for fractional timeout values (ival.uval); uses uconvert + and falarm/setitimer + +config.h.in + - new `HAVE_SETITIMER' define + +configure.in + - look for setitimer(2), define HAVE_SETITIMER if found + +doc/{bash.1,bashref.texi} + - document new `dirspell' shopt option + - document new fractional values to `read -t timeout' + + 5/6 + --- +assoc.[ch] + - new files, basic support for associative array implementation + +general.h + - new extern declarations for sh_openpipe, sh_closepipe, trim_pathname + +general.c + - new functions: sh_openpipe to create a pipe and move the file + descriptors to a high range; sh_closepipe, to close pipe fds and + clean up, and trim_pathname, to replace portions of a pathname + with `...' (for prompting) + +jobs.c + - don't set last_asynchronous_pid in child shell (messes up $!, among + other things) + +parse.y,parser.h + - moved definitions of parser flags to parser.h + +array.c + - imported array_modcase (case-changing operations on arrays) from + 4.0-devel branch + +array.h + - new extern declaration for array_modcase + +lib/readline/complete.c + - new variable, rl_menu_completion_entry_function, generator for + rl_menu_complete + - new menu completion `browsing' implementation, with several + improvements over the old code. Inspired by Sami Pietila + + +lib/readline/readline.h + - extern declaration for rl_menu_completion_entry_function + + 5/8 + --- +lib/readline/complete.c + - add support for a third argument to fnprint and print_filename, + which supports replacing a specified portion of the pathnames + printed when displaying possible completions with a `...' (or + `___', if the prefix would be confused with a portion of the + filename) + - new variable, _rl_completion_prefix_display_length, sets the + number of characters in a common prefix to be replaced with an + ellipsis when displaying possible completions + - add support to _rl_display_match_list to find the length of the + common prefix of all items being displayed, and passing that + value to print_filename for possible replacement with an ellipsis + if that length is longer than _rl_completion_prefix_display_length + +lib/readline/bind.c + - add support for retrieving value of history-size variable to + _rl_get_string_variable_value + - new bindable variable, completion-prefix-display-length. When + displaying possible completions, matches with a common prefix + longer than this value have the common prefix replaced with an + ellipsis + - support for retrieving value of completion-prefix-display-length + variable to _rl_get_string_variable_value + - new bindable variable, revert-all-at-newline: if enabled, causes + all changes in history lines to be undone before readline returns + after processing a newline + +doc/bash.1,lib/readline/doc/{readline.3,rluser.texi} + - document new `completion-prefix-display-length' variable + - document new `revert-all-at-newline' variable + +execute_cmd.c + - change execute_builtin to not inherit the `-e' flag into commands + executed by the `command' or `source/.' builtins if we are supposed + to be ignoring the return value. This is like `eval'. Fixes bug + reported by Hiroshi Fujishima + + 5/10 + ---- +variables.c + - when reading the initial environment, don't create variables with + names that are not valid shell identifiers. Fixes bug reported by + Stephane Chazleas + + 5/13 + ---- +subst.c + - fix string_quote_removal to gracefully handle the case where a + backslash is the final character in the string (leaves the backslash + in place). Fixes bug reported by Ian Robertson + + + 5/16 + ---- +support/checkbashisms + - Perl script that purports to check for bash-specific features in a + shell script. Lifted from Debian via ubuntu + + 5/20 + ---- +lib/readline/display.c + - in update_line, when deciding whether or not to adjust _rl_last_c_pos + in a multibyte environment after printing the last line of a multiline + prompt with invisible characters on the first and last lines, use + the number of inivisible chars on the first line in the calculation + deciding whether or not we're past the last invisible character and + need to adjust the cursor position. Old code used the number of + invisible chars on the last prompt line. Fixes bug reported by + stuff@slinkp.com. + - in update_line, when fixing _rl_last_c_pos after drawing the first + line of the prompt, use the number of invisible chars on the first + line as the offset, instead of the total number of invisible chars + - use prompt_multibyte_characters, the number of multibyte chars in + the prompt string, to short-circuit some relatively expensive + multibyte text processing in rl_redisplay + + 5/21 + ---- +variables.c + - new function, reinit_special_variables(), a hook for special + vars that need their hook functions called when they're unset as + a result of the shell reinitializing itself to run a script + +shell.c + - shell_reinitialize now calls reinit_special_variables + - shell_reinitialize now calls bashline_reset + +variables.h + - new extern declaration for reinit_special_variables + +bashline.c + - new function, bashline_reset(), called when the shell reinitializes + in shell_reinitialize. Right now, just resets + bash_readline_initialized to 0. + +bashline.h + - new extern declaration for bashline_reset() + + 5/23 + ---- +bashhist.c + - new function, bash_clear_history, clears the history and resets any + associated internal bash state + +bashhist.h + - extern declaration for bash_clear_history + +builtins/history.def + - call bash_clear_history instead of clear_history for `history -c'. + Fixes part of problem reported by Scott McDermott + + - decrement history_lines_this_session in delete_histent, called for + `history -d' + +builtins/history.def,bashhist.[ch] + - move delete_histent() to bashhist.c; rename to bash_delete_histent + - move delete_last_history() to bashhist.c; rename to + bash_delete_last_history() + + 5/25 + ---- +braces.c + - add another parameter to mkseq(), the number of digits to put into + each member of a numeric sequence (width), changes to determine + any zero-padding go into expand_seqterm + - changes to expand_seqterm to allow user-specified increments + +bashline.[ch],shell.c,sig.c + - switched names of bashline_reinitialize and bashline_reset to better + reflect their functions + - when searching $PATH for directories to use for command completion, + make sure to free `current_path' before going out of scope + - new bindable function `dabbrev-expand', which is more or less + menu completion using dynamic history completion as the generator + - changes to bash_execute_unix_command to set variables for the + executed command like programmable completion: READLINE_LINE + (rl_line_buffer) and READLINE_POINT (rl_point) + - change to bash_execute_unix_command to allow the executed command + to change the readline line buffer by modifying the value of + READLINE_LINE and to change rl_point by modifying the value of + READLINE_POINT + +common.h + - new SEVAL_ defines for later parse_string changes from 4.0-devel + branch + +command.h + - new defines for new &>> r_append_err_and_out redirection + +builtins/evalstring.c + - new function, parse_string, parses a command from a passed string + and returns the number of characters consumed. For satisfying + Posix rules when parsing command substitutions, from bash-4.0-devel + branch + - split out common prolog code from parse_string and + parse_and_execute into a separate function called from both + +parse.y + - small changes to add symbols needed for parse_string + - parser change to add `|&' as synonym for `2>&1 |'; translation is + performed at parse time so |& never shows up in output of + print_command, for instance. Picked up from zsh, merged in from + bash-4.0-devel branch + +parse.y,{redir,copy_cmd,dispose_cmd,make_cmd,print_cmd}.c + - implement new &>> r_append_err_and_out (like >>foo 2>&1); merged + in from bash-4.0-devel branch + +doc/{bash.1,bashref.texi},lib/readline/doc/rluser.texi + - document new optional increment in brace expansion + - document new zero-padded fixed-width integer brace expansion + - document new `dabbrev-expand' bindable readline command + - document new effects of `bind -x' setting and reading the values of + READLINE_LINE and READLINE_POINT + - document new |& synonym for `2>&1 |' pipeline operator + + 5/26 + ---- +parse.y - recognize new ;& and ;;& case action list terminator tokens and + implement them in the grammar, setting CASEPAT_FALLTHROUGH and + CASEPAT_TESTNEXT flags as appropriate + +print_cmd.c + - print new ;& and ;;& case clause action list terminators as + appropriate + +execute_cmd.c + - implement new case clause action list terminators: + ;& - fall through to actions associated with next pattern list + ;;& - fall through to tests in next pattern list + +doc/{bash.1,bashref.texi} + - document new ;& and ;;& case clause action list terminators + + 5/28 + ---- +jobs.c + - change waitchld so it treats SIGCHLD like SIGINT if `wait' is being + executed, and allows wait to jump out before running any trap set + on SIGCHLD. Fixes debian bug #483016 reported by Miroslav Rudisin + + - run_sigchld_trap is no longer static, so the trap code in trap.c + can call it + - change run_sigchld_trap to call set_impossible_sigchld_trap instead + of just using a call to restore_default_signal + +jobs.h + - new extern declaration for run_sigchld_trap + +trap.c + - fix run_pending_traps to run a SIGCHLD trap if the trap handler isn't + set to IMPOSSIBLE_TRAP_HANDLER + - in trap_handler, don't reset the SIGCHLD trap handler to trap_handler + if MUST_REINSTALL_SIGHANDLERS is defined + - new function, set_impossible_sigchld_handler, sets the trap string + associated with SIGCHLD to IMPOSSIBLE_TRAP_HANDLER; used as a sentinel + by run_sigchld_trap and maybe_set_sigchld_handler + - change maybe_set_sigchld_handler to set the SIGCHLD trap string only + if the current value is IMPOSSIBLE_TRAP_HANDLER. This ensures that + any traps on SIGCHLD set in a SIGCHLD handler will persist. Fixes + debian bug #483016 reported by Miroslav Rudisin + + +trap.h + - new extern declaration for set_impossible_sigchld_trap + + 5/31 + ---- +parse.y + - new function: parse_comsub(), parses $(...) by parsing command + between parens and making sure the next token is `)'. From + the bash-4.0-devel branch + - new function: xparse_dolparen, helper function for parsing + command substitutions in $(...). Called from subst.c to extract + a command substitution during word expansion. From bash-4.0-devel + branch + - new function: rewind_input_stream(). Rewinds bash_input.location.string + back to where it was before the shell parsed a $() command + substitution. From bash-4.0-devel branch + - changes to parse_matched_pair to combine most of the flag variables + (was_dollar, in_comment, and so on) into a local flags word + + 6/2 + --- +parse.y + - call trim_pathname, which retains only the last $PROMPT_DIRTRIM + directories and replaces the intervening characters with `...', + when expanding \w and \W + +doc/{bash.1,bashref.texi} + - document the effect of setting PROMPT_DIRTRIM + + 6/3 + --- +builtins/ulimit.def + - make the multiplier (block size) for -c and -f 512 bytes only if in + Posix mode and 1024 bytes otherwise (as in previous versions). Uses + POSIXBLK and BLOCK_SIZE defines to parameterize size based on value + of posixly_correct + +doc/bashref.texi + - document this addition to posix mode + +builtins/common.c + - change get_numeric_arg to have a calling sequence and return value + more closely mimicking general.c:legal_number(), with the addition + of a flags word + - add extra value for `fatal' argument to get_numeric_arg to force it + to return failure to the caller rather than longjmping + +builtins/common.h + - change prototype declaration for get_numeric_arg + +builtins/{break,shift}.def + - change calls to get_numeric_arg to deal with new semantics and calling + sequence + +builtins/history.def + - display_history now returns an int + - change calling sequence for get_numeric_arg in display_history + - display_history now returns failure to the caller if get_numeric_arg + detects an invalid number, rather than jumping back to the top level + - use value returned by display_history as return status of history + builtin, filtered through sh_chkwrite + - history no longer aborts compound commands on invalid arguments. + fixes problem reported by Chu Li + +{braces,subst}.c + - extract_command_subst now takes a third flags argument; passed flags + are ORd into flags passed to other functions; changed callers + +subst.h + - move SX_* defines here from subst.c so parse.y:xparse_dolparen can + see them and behave appropriately + - extract_command_subst now takes a third flags argument; change + prototype + +subst.c + - change extract_command_subst to call xparse_dolparen when extracting + a $() construct + - change calls to extract_delimited_string to extract_command_subst + as appropriate + - if command_substitute returns a NULL word desc, don't call + dispose_word_desc on it + +parse.y + - change xparse_dolparen to use the SX_* flags now in subst.h + + 6/16 + ---- +subst.c + - in quote_list, set W_HASQUOTEDNULL flag in the word if quote_string + turns "" into CTLNUL + - in dequote_list, turn off W_HASQUOTEDNULL flag in the word if + dequote_string turns CTLNUL into "" + - new function, string_list_pos_params, encapsulates everything + needed to turn the positional parameters or an array indexed with + '@' or '*' into a string, including taking care of quoting and + using the first char of $IFS, when used in another expansion like + pattern removal or pattern substitution + - change list_remove_pattern, pos_params, pos_params_pat_subst to + call string_list_pos_params. Fixes problems reported by + Stephane Chazelas + + 6/22 + ---- +variables.h + - include assoc.h for associative arrays + - defines for case-modifying expansions and associative array variables + - sh_var_assign_func_t functions now take an extra char * parameter + + 6/25 + ---- +variables.c + - change declarations and definitions of sh_var_assign_func_t functions + to add the extra char * parameter: null_assign, null_array_assign, + assign_seconds, assign_random, assign_lineno, assign_subshell, + assign_dirstack + - change calls to var->assign_func to add extra char * argument + - broke part of body of dispose_variable out into a new function, + dispose_variable_value, which knows how to free all kinds of shell + variable data + - changes to deal with variables with the internal `nofree' attribute + +arrayfunc.c + - change calls to var->assign_func to add extra char * argument + - bind_array_var_internal now takes an extra `char *key' argument + - additions for associative array implementation; from bash-4.0-devel + tree + +arrayfunc.[ch],subst.c + - expand_compound_array_assignment now takes the variable as the first + argument (SHELL_VAR *); changed function definition and callers + +builtins/set.def + - changes to handle associative arrays in `unset' + +{execute_cmd,command}.h + - definitions for coproc implementation; from bash-4.0-devel tree + +variables.c + - new functions for associative arrays: make_new_assoc_variable, + make_local_assoc_variable + + 6/26 + ---- +variables.c + - more infrastructure for associative arrays; from bash-4.0-devel tree + - infrastructure for handling assignments to variables with + case-modifying attributes; from bash-4.0-devel tree + +config.h.in + - add #defines controlling case-modifying variable attributes and word + expansions + +configure.in + - add enable options for case-modifying variable attributes and word + expansions (--enable-casemod-attributes and --enable-casemod-expansions, + respectively); from bash-4.0-devel tree + +execute_cmd.c + - add code to fix_assignment_words to handle assignment statements to + "assignment builtins" that seem to be associative arrays. Imperfect + +subst.c + - array_remove_pattern now takes a SHELL_VAR * as its first argument + instead of an ARRAY *; from the bash-4.0-devel tree + - changes to array_length_reference for associative arrays; from the + bash-4.0-devel tree + - changes to get_var_and_type for associative arrays; from the + bash-4.0-devel tree + - changes to parameter_brace_substring for associative arrays; from the + bash-4.0-devel tree + - changes to param_expand for associative arrays; from the + bash-4.0-devel tree + +builtins/declare.def + - changes for associative arrays: new `-A' option, changes to make + local and global associative array variables; from the bash-4.0-devel + tree + + 6/27 + ---- +execute_cmd.c + - in execute_command_internal, when short-circuiting execution + because `breaking' or `continuing' is non-zero, preserve the exit + status by returning `last_command_exit_value' instead of an + unconditional EXECUTION_SUCCESS. Fixes bug reported by Roman + Rakus + + 6/28 + ---- +variables.c + - fix get_var_and_type to appropriately handle references like + ${varname[0]}, where `varname' is a scalar variable + +make_cmd.[ch],parse.y + - make_here_document now takes a second argument: the current line + number; changed caller (gather_here_documents) + +builtins/setattr.def + - added support for associative arrays and the `-A' variable attribute + option; from the bash-4.0-devel tree + +subst.c + - change code that transforms `declare -A xxx=(yyy)' to perform the + internal `declare -A xxx' before doing the variable assignment, + because associative arrays have to be declared before being assigned + to as such; uses new function make_internal_declare + + 6/30 + ---- +subst.[ch] + - dequote_escapes is now external; add declaration in subst.h + - remove_quoted_nulls is now external; add declaration in subst.h + +array.[ch] + - new functions for completeness: array_dequote, array_dequote_escapes, + array_remove_quoted_nulls + - array_subrange now calls array_remove_quoted_nulls for "${array[*]}". + Fixes bug reported by Vitor De Araujo + - array_patsub now calls array_remove_quoted_nulls for "${array[*]}" + - array_modcase now calls array_remove_quoted_nulls for "${array[*]}" + - array_patsub now handles the mflags&MATCH_QUOTED case appropriately + (that implies "${array[@]}") + +subst.c + - new functions for case-modifying word expansion suppport: + pos_params_casemod, parameter_brace_casemod; from bash-4.0-devel branch + +assoc.c + - new functions for completeness: assoc_remove_quoted_nulls + - assoc_patsub now calls assoc_remove_quoted_nulls for "${assoc[*]}" + - assoc_modcase now calls assoc_remove_quoted_nulls for "${array[*]}" + - assoc_patsub now handles the mflags&MATCH_QUOTED case appropriately + (that implies "${assoc[@]}") + + 7/1 + --- +assoc.[ch] + - new function, assoc_subrange: takes a hash table, converts it to a + word list, and performs the subrange and indexing on that list + - new functions for completeness: assoc_dequote, assoc_dequote_escapes + +subst.c + - verify_substring_values now takes the variable SHELL_VAR * as its + new first argument; changed callers + - change verify_substring_values to handle associative arrays using the + number of elements as the upper bound + - brought in code to do case-modifying word expansions from + bash-4.0-devel branch, conditional on CASEMOD_EXPANSIONS + +input.c + - if the read(2) in getc_with_restart returns -1/EAGAIN, turn off + non-blocking mode on the file descriptor and try again. Fixes + problem reported by Glynn Clements + + 7/2 + --- +doc/{bash.1,bashref.texi} + - documented new case-modifying word expansions + +make_cmd.c + - change make_here_document to display a warning message including the + start line of a here document if it ends up delimited by EOF. + Addresses issue raised by Richard Neill + +subst.c + - in do_assignment_internal, make sure the `invisible' attribute is + unset before returning success + + 7/3 + --- +config-top.h + - add `CASEMOD_CAPCASE' define to include or exclude the ~[~] word + expansion and the `capcase' variable attribute (declare -c) + +builtins/declare.def + - add support for manipulating the case-modifying attributes (new + declare -clu); from bash-4.0-devel branch + +builtins/setattr.def + - add support for reporting case-modifying attributes (-clu attributes); + from bash-4.0-devel branch + +doc/{bash.1,bashref.texi} + - specify that the read builtin timing out results in a return value + greater than 128 + - document new `-l' and `-u' options to declare/typeset/local. Leave + `-c' undocumented for now + + 7/4 + --- +make_cmd.[ch] + - make_coproc_command: construct a coproc; from bash-4.0-devel tree + +dispose_cmd.c + - dispose coproc command; from bash-4.0-devel tree + +copy_cmd.c + - copy a coproc command; from bash-4.0-devel tree + +print_cmd.c + - print a coproc command; from bash-4.0-devel tree + +shell.c + - dispoe the current coproc on shell exit; from bash-4.0-devel tree + +redir.c + - when closing redirects as part of user redirections, check whether + or not active coprocess fds are being closed and close the coproc + if so; from bash-4.0-devel tree + +config.h.in + - add define for COPROCESS_SUPPORT to include coprocesses + +configure.in + - add support for configuring coprocesses into and out of the build + +jobs.c + - in waitchld, check whether or not a coproc processs has exited; + from the bash-4.0-devel tree + + 7/5 + --- +doc/bashref.texi + - document new --enable-coprocesses option that includes coprocess + support + +execute_cmd.c + - add functions for coprocess support, including execute_coproc and + code to call it when command->type == cm_coproc; from + bash-4.0-devel tree + +lib/sh/fdprintf.c + - new library function fdprintf(int fd, const char *format, ...); + printf to a file descriptor + +{configure,config.h}.in + - support for detecting fdprintf and compiling in replacement + +Makefile.in,lib/sh/Makefile.in + - add rules to include fdprintf.o + +doc/{bash.1,bashref.texi} + - documented coprocesses and `coproc' reserved word + + 7/7 + --- +subst.c + - fix array_length_reference to use MB_STRLEN instead of STRLEN, so + multibyte characters in array values are computed correctly. Fixes + bug reported by Wang Xin + + 7/10 + ---- +jobs.c + - new function, maybe_give_terminal_to (old, new, flags), sets the + terminal pgrp to NEW if and only if it's currently set to OLD + - call maybe_give_terminal_to when the parent sets the terminal pgrp + to the pipeline pgrp in stop_pipeline, so we don't give the + terminal to the new job's pgrp unless it's currently owned by the + shell. Fixes race condition described by Joe Peterson + , where parent bash may change tty pgrp after a + grandchild (interactive bash child of su) has changed it to + something else. The call to maybe_give_terminal_to makes explicit + a previously-implicit assumption + +aclocal.m4 + - remove dependency on writable /tmp by creating directories in + build directory + +shell.c + - make changes to how bash sets no_line_editing and running_under_emacs + to deal with various emacs terminal emulators; use better check + for `eterm', since bash sends $PWD to eterm with control sequences + that confuse other programs. Problem reported by Micah Cowan + + + + 7/12 + ---- +print_cmd.c + - break code that prints here-documents into two functions: + print_heredoc_header, which prints the operator and delimiter, and + print_heredoc_body, which prints the body text and closing delimiter + - change print_redirection to call print_heredoc_{header,body} + - sentinel variable, printing_connection, used when printing a command + of type `connection' (|, &&, ||, etc.) + - change print_redirection_list to save any here documents it finds + while printing a connection and save them in `deferred_heredocs' + - new function, print_deferred_heredocs, called from print_redirection + in the cm_connection case, calls print_heredoc_header for all the + here documents, then prints the operator (|, &&, ||, etc.), then + the here-document body. This preserves syntactic correctness; the + old code printed the control operator after the body of the here + document. Fixes bug reported by + + 7/16 + ---- +locale.c + - in set_locale_var, print a warning message if setlocale() fails any + time it's called -- required some code restructuring + + 7/19 + ---- +support/shobj-conf + - support for mingw32, contributed by Carlo Bramix + + + 7/23 + ---- +execute_cmd.c + - added support (currently unused) to manage a list of coprocs + + 7/25 + ---- +bashline.c + - add extern declarations for literal_history and force_append_history + +builtins/shopt.def + - include "bashhist.h" instead of having extern declarations for the + appropriate history variables + +parser.h + - new parser_state value: PST_HEREDOC, set when reading body of here- + document in parse.y:read_secondary_line + +parse.y + - set PST_HEREDOC bit in parser_state when reading a secondary line + for the body of a here-document + - change read_secondary_line to save lines in the body of a here- + document in the shell history list if remember_on_history is + set. Fixes bug reported by Gene Golub + + 8/4 + --- +configure.in + - changed to 4.0-alpha + +lib/readline/readline.h + - changed constants to reflect readline-6.0 version + + 8/11 + ---- +lib/readline/signals.c + - make sure we don't use SIGWINCH without checking whether or not it's + defined. Fix from Pedro Alves + + 8/12 + ---- + +COPYING + - updated to GPLv3; edits in every file with a copyright or license + declaration to update to gpl3 + +version.c + - update extended version info to latest gnu standard + + 8/17 + ---- +subst.c + - change exp_jump_to_top_level to only call top_level_cleanup if + parse_and_execute_level is 0. If it's not, the longjmp to + parse_and_execute will run the unwind-protect stack. Fixes bug + most recently reported by Roman Rakus + + 8/18 + ---- +support/config.{guess,sub} + - updated to newer versions from autoconf-2.62 distribution + + 8/20 + ---- +subst.c + - fixed parameter_brace_substring to differentiate between indexed and + associative arrays when computing second offset, instead of + assuming indexed array + + 8/21 + ---- +support/xcase.c + - simple program to convert input from lower to uppercase and vice + versa. Now used by coproc test suite, since `tr -u' is not + portable. + + 8/22 + ---- +doc/bash.1 + - fixed description of the bindable edit-and-execute commands to note + they check $VISUAL first, instead of $FCEDIT. Fixed bug reported + by + +[bash-4.0-alpha frozen] + + 8/28 + ---- +[bash-4.0-alpha released] + + 9/1 + --- +builtins/evalstring.c + - fixed typo in parse_string (ostring used uninitialized). Bug + reported by Andreas Schwab + +subst.c + - fix return value of parameter_brace_expand to set the + W_HASQUOTEDNULL flag in the returned WORD_DESC * if the return value + from parameter_brace_remove_pattern is a quoted null string. Fixes + bug reported by Andreas Schwab + - set the W_HASQUOTEDNULL flag in the return value from + parameter_brace_expand if the return value from parameter_brace_patsub + is a quoted null string + + 9/6 + --- +builtins/read.def + - change read -t 0 to return success if there is input available to be + read -- allows scripts to poll for input. Uses input_avail libsh + function + + 9/9 + --- +externs.h + - fix extern fpurge declaration -- use HAVE_DECL_FPURGE instead of + NEED_FPURGE_DECL, since the former is set by `configure' + +jobs.h + - add extern declaration for close_pgrp_pipe + - add a new job state JNONE (-1) to the enum + +jobs.c + - include execute_cmd.h for extern declarations for coproc functions + +subst.c + - include builtins/builtext.h for extern declarations for functions + implementing builtins (e.g., declare_builtin) + +arrayfunc.c + - include "pathexp.h" for extern declaration for glob_char_p + +braces.c + - add extern declaration for `asprintf' + +lib/readline/rlprivate.h + - add extern declarations for _rl_trace, _rl_tropen + +lib/sh/zgetline.c + - add extern declarations for zread, zreadc + +lib/sh/mktime.c + - include "bashansi.h" for string function declarations + +builtins/common.h + - add extern declaration for parse_string + +trap.c + - include jobs.h for extern declaration for run_sigchld_trap + +general.c + - fix call to strtoimax in legal_number; if ep == string when function + returns, the number was not converted, even if errno is not set. + Fix from Paul Jarc + + 9/11 + ---- +[prayers for the victims of 9/11/2001] + +builtins/return.def + - call no_options, as Posix requires. This also has the effect of + disallowing negative return values unless they're prefixed by `--' + + 9/13 + ---- +builtins/bind.def + - add an error message when bind is used without line editing active, + instead of just returning an error status + +variables.c + - make sure make_local_variable never creates visible variables with + a value, whether or not a variable with the same name existed in a + previous context. This is consistent with ksh93. Fix from + + + 9/16 + ---- +execute_cmd.c + - add call to CHECK_TERMSIG in shell_execve after the call to execve + returns. Recommended by Roman Rakus + - add QUIT check in execute_connection after executing first command + in a `&' connection + + 9/22 + ---- +execute_cmd.c + - new semaphore variable, executing_list, incremented every time a + list (command1;command2 or command1 || command2 or command1 && + command2) is executed; used as sentinel for rest of shell + +sig.c,builtins/evalstring.c + - set executing_list to 0 when throwing execution back to top level; + make sure to unwind-protect it in appropriate places + +jobs.c + - if a pipeline is killed by SIGINT while executing a list (when + executing_list is non-zero), make sure the shell acts as if an + interrupt occurred. The behavior is dependent on the shell + compatibility level being > 32 (bash-4.0 and above) + + 9/23 + ---- +redir.c + - don't bother reporting an error with a file descriptor, even if + the errno is EBADF, if the redirection error (e.g., NOCLOBBER) + can't have anything to do with the fd. Fixes bug reported by + "David A. Harding" , debian bug #499633. + + 9/24 + ---- +builtins/declare.def + - make `declare [option] var' (and the `typeset' equivalent) create + invisible variables, instead of assigning the null string to a + visible variable. Fixes bug reported by Bernd Eggink + + 9/25 + ---- +builtins/common.[ch] + - new function, builtin_warning(), like builtin_error but for warning + messages + +builtins/bind.def + - experimental: print a warning, but go on, if line editing not active + when bind is invoked. Suggested by Rocky Bernstein + + + 10/3 + ---- +test.c + - use same_file instead of directly comparing st_dev and st_ino when + comparing files in filecomp(). From mingw32 patches submitted + by Hector Chu + + 10/4 + ---- + +redir.c + - in redirection_error(), use `error' instead of errno when comparing + against EBADF. From mingw32 patches submitted by Hector Chu + + +shell.c + - in unset_bash_input(), reset bash_input.type to st_none after + closing the default buffered fd. From mingw32 patches submitted + by Hector Chu + +builtins/cd.def + - ignore CDPATH when in privileged mode. Suggested by Paul Jarc + + +variables.c + - change sv_globignore to only act if privileged mode is not enabled. + Suggested by Paul Jarc + +doc/bash.1,bashref.texi + - document new treatment of CDPATH and GLOBIGNORE when privileged + mode is enabled + +builtins/read.def + - change prompt printing to occur after terminal is set to no-echo + mode. Based on suggestion from Stephane Chazelas + + +lib/readline/signals.c + - new variables to keep track of special characters corresponding to + SIGINT, SIGQUIT, and SIGTSTP + - new variable to keep track of whether tty is echoing control + characters corresponding to SIGINT, SIGQUIT, and SIGTSTP + - new function, _rl_echo_signal_char(int sig) to display the tty + special char generating SIGINT, SIGQUIT, or SIGTSTP. Based on + idea and code from Joe Peterson + - call rl_echo_signal_char in rl_signal_handler: if the terminal + settings indicate it, readline will echo characters that generate + keyboard signals + +lib/readline/rltty.c + - set _rl_intr_char, _rl_quit_char, and _rl_susp_char to special + characters that generate signals from keyboard + - set _rl_echoctl if ECHOCTL tty flag is set + +lib/readline/rlprivate.h + - extern declarations for _rl_intr_char, _rl_quit_char, and + _rl_susp_char + - extern declaration for _rl_echoctl + +lib/readline/readline.h + - extern declaration for rl_echo_signal_char() + +lib/readline/doc/rltech.texi + - document rl_echo_signal_handler(): available for applications + that install their own signal handlers + + 10/5 + ---- +execute_cmd.c + - fix errexit logic to not cause the shell to exit when a command in + a pipeline fails. Fixes bug reported by Marcin Owsiany + + + 10/14 + ----- +builtins/evalstring.c + - don't short-circuit execution in parse_and_execute if we want to + run an exit trap. Fixes bug reported by Steffen Kiess + + + 10/18 + ----- +parse.y + - fix error production to only call YYACCEPT if the shell is currently + interactive and not in parse_and_execute (so parser errors in + things like eval will correctly set $?). Fixes bug reported by + marco-oweber@gmx.de + +execute_cmd.c + - make sure variable name errors in execute_for_command and non- + identifier function names in execute_intern_function set the + return status to EX_BADUSAGE (2), not EX_USAGE (258) + +parser.h + - new parser state, PST_REPARSE + +parse.y + - turn PST_REPARSE on in parse_string_to_word_list + - in parse_matched_pair, if parsing a single-quoted string and + PST_REPARSE is set, don't requote CTLESC or CTLNUL. Fixes bug with + compound array assignment using $'\x7f' reported by Antonio Macchi + + + 10/23 + ----- +configure.in + - define LOCAL_LDFLAGS as `-z interpose' on Solaris 8, 9, and 10 to + allow the bash malloc to interpose the libc malloc when called by + library functions pre-bound to the libc malloc. Suggested by + Serge Dussud + + 10/26 + ----- +doc/bash.1 + - add single-sentence descriptions to rest of parameter expansions. + Suggested by Ken Irving + + 10/27 + ----- +subst.c + - rearrange code in skip_to_delims to allow quote characters and other + shell expansion characters to be delimiters + - add new flags value for inverting search: skip to the next character + NOT in the set of delimiters passed as an argument + +subst.h + - define for new SD_INVERT flag value for skip_to_delims + + 10/28 + ----- +bashline.c + - new bindable functions: shell-forward-word and shell-backward-word. + Like forward-word and backward-word, but understand shell quoting + and use shell metacharacters and whitespace as delimiters. + Suggested by Andre Majorel + - new bindable functions: shell-kill-word and shell-backward-kill-word. + Like kill-word and backward-kill-word, but understand shell quoting + and use shell metacharacters and whitespace as delimiters. + Suggested by Andre Majorel + +doc/bash.1,lib/readline/doc/rluser.texi + - documented shell-forward-word and shell-backward-word + - documented shell-kill-word and shell-backward-kill-word + + 11/1 + ---- +redir.c + - add extra argument to add_undo_redirect: fdbase. FD used to save + a file descriptor must be > fdbase if fdbase >= SHELL_FD_BASE. A + value of -1 for fdbase means to just use SHELL_FD_BASE. Fixes bug + with 0<&10 reported by Clark Jian Wang + + 11/5 + ---- +unwind_prot.c + - new function: have_unwind_protects(); returns 1 if unwind_protect_list + is not empty + +unwind_prot.h + - extern declaration for have_unwind_protects + +builtins/evalstring.c + - in parse_and_execute_cleanup, make sure that we don't call + run_unwind_frame and expect it to decrement parse_and_execute_level + if there's no unwind_protect_list, since there's a while loop in + throw_to_top_level that calls parse_and_execute_cleanup as long as + parse_and_execute_level is non-zero + + 11/9 + ---- +variables.c + - fix the assign function for COMP_WORDBREAKS to allocate new memory + to store as the variable's value, to avoid freeing memory twice + if the variable is unset after rl_completer_word_break_characters + is freed and reallocated. Fix from Mike Stroyan + + 11/20 + ----- +general.c + - new 'file_exists(fn)' primitive; just calls stat(2) + +general.h + - new extern declaration for file_exists + +bashline.c + - add `~' to rl_filename_quote_characters so make_quoted_replacement + will call bash_quote_filename for words containing `~'. Then + bash_quote_filename can make choices based on that + - change quote_word_break_chars to backslash-quote the tilde in a + filename with a leading tilde that exists in the current directory, + since we want to inhibit tilde expansion in this case + +execute_cmd.c + - call file_isdir from shell_execve instead of stat(2) directly + +bashhist.c + - use file_exists and file_isdir primitives instead of calling stat + + 11/21 + ----- +redir.c + - When undoing saving of non-standard file descriptors (>=3) using + file descriptors >= SHELL_FD_BASE, we set the saving fd to be + close-on-exec and use a flag (RX_SAVCLEXEC) to decide how to set + close-on-exec when the fd is restored. Set flag in add_undo_redirect, + check in do_redirection_internal. Fixes problem reported by Andreas + Schwab + + 11/26 + ----- +subst.c + - fix param_expand to have expansions of $@ and $* exit the shell if + there are no positional parameters and `set -u' is enabled. Fixes + bug reported by Dan Jacobson + + 11/27 + ----- +lib/readline/display.c + - fix update_line to not call space_to_eol if current cursor position + (_rl_last_c_pos) indicates that we're already at end of line. + Partial fix for bug reported by Mike Frysinger + - in update_line, don't call insert_some_chars if that will start + before the last invisible character in the prompt string and not + draw the entire prompt string. More of the partial fix for bug + reported by Mike Frysinger + - fix update_line to adjust _rl_last_c_pos by wrap_offset when adding + characters beginning before the last invisible character in the + prompt. New code is same as previously existed in a different code + path. Rest of fix for bug from Mike Frysinger + - fix assignment of newline breaks (inv_lbreaks) to correctly account + for prompts longer than two screen lines containing invisible + characters. The assumption is that part of the invisible characters + are on the first line (prompt_invis_chars_first_line) and the + remainder are on the last (wrap_offset - prompt_invis_chars_first_line). + Fix is in rl_redisplay. part of fix for bug reported by + "Wesley J. Landaker" in + http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=265182 + [TENTATIVE] + - fix _rl_move_cursor_relative to correctly offset `dpos' by `woff' + when there are invisible characters on lines after the second by + using (_rl_screenwidth*_rl_last_v_pos) when seeing whether or not + we just wrote some invisible characters. Rest of fix for bug + reported in http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=265182 + [TENTATIVE] + + 12/11 + ----- +sig.c + - reset the execution context before running the exit trap in + termsig_handler + +general.c + - set and unset terminate_immediately like interrupt_immediately in + bash_tilde_expand + +builtins/read.def + - change terminate_immediately to a counter instead of a flag, as + interrupt_immediately is used + +lib/readline/display.c + - slight change to fix from 11/27 to deal with prompts longer than a + screen line where the invisible characters all appear after the + line wrap. Fixes bug reported by Andreas Schwab + +builtins/{echo,printf}.def + - increment terminate_immediately at entry; decrement before returning. + Fix for bug reported by Ralf.Wildenhues@gmx.de + + 12/16 + ----- +subst.c + - fix off-by-one error in /dev/fd version of add_fifo_list; make + sure we add to totfds when it is == fd, not just when fd > totfds. + Fixes bug reported by marciso@gmail.com + +[bash-4.0-beta2 frozen] + + 12/29 + ----- +doc/{bash.1,bashref.texi} + - document more clearly that when not in Posix mode, command + substitution does not inherit the -e option. From bug report from + Freddy Vulto + +{execute_cmd,sig,builtins/evalstring}.c + - sentinel variable to keep track of whether or not we're supposed to + ignore the failure status of a command executed in a command + substitution even if the `-e' option is set: comsub_ignore_return + - increment and decrement comsub_ignore_return in execute_simple_command + before calling expand_words + - in parse_and_execute, if comsub_ignore_return is non-zero and the + SUBSHELL_COMSUB bit is set in subshell_environment, enable the + CMD_IGNORE_RETURN flag in every command executed from the passed + string. Fixes problem reported by Freddy Vulto + - make sure to reset comsub_ignore_return every time we throw to the + top level, like executing_list flag + + 1/2/2009 + -------- +parse.y + - fix to rewind_input_stream to handle case of $(...) command + substitution followed by a quoted literal newline. Report and fix + from Andreas Schwab + + 1/7 + --- + +subst.c + - fix match_wpattern and match_upattern to prefix a `*' to the + pattern even if it starts with a `*(' (if extglob is enabled) + before checking whether or not it can match anywhere in the + string. Fixes bug reported by os@sernet.de. + +[bash-4.0-rc1 frozen] + + 1/9 + --- +locale.c + - since setlocale() doesn't set errno to anything meaningful, + don't include the strerror() result in the error message if + it fails + - make sure the error messages printed when setlocale fails are + localizable + + 1/11 + ---- +lib/readline/histexpand.c + - make sure that every time history_no_expand_chars is tested, we + also call the history_inhibit_expansion_function if it's set. + Fixes bug reported by Yang Zhang + + 1/12 + ---- +trap.c + - make sure to call parse_and_execute with the SEVAL_RESETLINE bit + set in the flags so it will reset the line number when running + the trap commands. Partial fix for bug reported by + peter360@fastmail.us + + 1/14 + ---- +builtins/reserved.def + - document `coproc' so it can be used with `help' builtin. Pointed + out by Pierre Gaston + +lib/sh/casemod.c + - added two new flags: CASE_UPFIRST and CASE_LOWFIRST to casemod + the first character of the passed string and pass the rest + through unchanged. Fixes bug reported by Jan Schampera + + +externs.h + - new defines for CASE_UPFIRST and CASE_LOWFIRST + +subst.c + - use CASE_UPFIRST for ^ and CASE_LOWFIRST for , casemod operators + +builtins/mapfile.def + - call zreset() before calling first zgetline(), to clean out any + remaining data in local buffer used by zreadc. Fixes bug + reported by Pierre Gaston + + 1/15 + ---- +lib/sh/zread.c + - renamed zreadintr to zreadretry -- not perfect, but better + - new functions: zreadintr, which just calls read so it can be + interruptible, and zreadcintr, which is like zreadc but uses + zreadintr to fill the buffer + +lib/sh/zgetline.c + - in zgetline, when zread/zreadc return <= 0, make sure line is + non-null before assigning to line[nr] + +builtins/mapfile.def + - return an error right away if the supplied array variable name + refers to a readonly or noassign array + - set interrupt_immediately so calls to zgetline can be + interrupted. Fixes bug reported by Pierre Gaston + + - if interactive, pass the SEVAL_INTERACT and SEVAL_NOHIST flags + to parse_and_execute when calling callbacks. Fixes bug reported + by Pierre Gaston + - add `readarray' as a synonym for mapfile + +doc/{bash.1,bashref.texi} + - document behavior of mapfile builtin adding index of array element + to be assigned as additional argument to callback string. Reported + by Pierre Gaston + - document readarray as synonym for mapfile + +builtins/common.c + - new error function, sh_ttyerror(set), prints an error message having + to do with setting or getting terminal attributes + +builtins/read.def + - print error message if read fails to set terminal attributes + + 1/16 + ---- +execute_cmd.c + - new function, coproc_reap, calls coproc_dispose if sh_coproc is + marked as COPROC_DEAD + - new function, cpl_reap, disposes coprocs marked as COPROC_DEAD + from coproc list + - change coproc_pidchk to just mark the coproc as dead instead of + calling coproc_dispose, so we don't call unsafe functions from + a signal handler. Fixes bug reported by Andreas Schwab + + +execute_cmd.h + - new extern declaration for coproc_reap + +command.h + - new flags for c_flags member of a struct coproc + +{jobs,nojobs}.c + - add call to coproc_reap in cleanup_dead_jobs, which will do the + right queueing or blocking of SIGCHLD + +trap.c + - modify change from 1/12 to not reset the line number when running + the DEBUG and RETURN traps + + 1/18 + ---- +lib/sh/casemod.c + - change default operations to work on entire passed string instead + of breaking into words at non-alpha-numerics. Use new + CASE_USEWORDS flag to enable by-word behavior. Fixes bug reported + by Jan Schampera + +builtins/printf.def + - in vbprintf, bracket each call to vsnprintf (which uses the args + passed to vbprintf) with SH_VA_START and va_end, so we can + reninitialize the argument list for each call. This is actually + what the C standard requires. Fixes bug that caused printf -b + to `ignore' first % format specifier if it came first in the + string. Reported by David Leverton + +builtins/mapfile.def + - start the line count at 1, since it doesn't get incremented before + (or after) reading the first line, so things like + `mapfile -n 5 -c 1 -C 'echo foo' array < file' work right and call + the callback after the first line is read. Fixes bug reported by + Pierre Gaston + + 1/22 + ---- +lib/readline/complete.c + - set _rl_interrupt_immediately non-zero before reading from the file + system or calling an application-defined completion function + +lib/readline/signals.c + - renamed rl_signal_handler to _rl_handle_signal; new version of + rl_signal_handler that just calls _rl_handle_signal (for now) + - new function _rl_signal_handler that calls _rl_handle_signal without + any checking + +lib/readline/rlprivate.h + - new extern declaration for _rl_signal_handler + - new define, RL_CHECK_SIGNALS, checks whether or not _rl_caught_signal + is set and calls _rl_signal_handler if so + +lib/readline/{bind,input,readline}.c + - add RL_CHECK_SIGNALS in appropriate places + +lib/readline/signals.c + - change rl_signal_handler to set a flag and return rather than + run through the entire signal handling process. If + _rl_interrupt_immediately is set, call the signal handling code + right away instead of setting the flag. Initial fix for crash + bug reported by Roman Rakus + +aclocal.m4 + - new macro, BASH_TYPE_SIG_ATOMIC_T, tests for sig_atomic_t in + , defines as int if not defined + +configure.in + - call BASH_TYPE_SIG_ATOMIC_T + - call AC_C_VOLATILE + +config.h.in + - empty define for sig_atomic_t + - empty define for volatile + + 1/27 + ---- +subst.c + - audit calls to add_character and change to add_ifs_character (which + quotes characters in $IFS). Affects primarily `:', `=', and `~'. + Fixes bug reported by Jan Schampera ; fix + suggested by Stephane Chazelas + + 2/1 + --- +configure.in + - call AC_C_RESTRICT + +config.h.in + - add empty defintion for `restrict' + +pcomplete.c + - use unwind_protects around call to execute_shell_function in + gen_shell_function_matches to prevent data corruption if + throw_to_top_level is called. Bug report and fix from + werner@suse.de. + +execute_cmd.c + - don't clamp CPU usage at 100% in print_formatted_time. Bug reported + by Linda Walsh + + 2/5 + --- +locale.c + - in set_locale_var, set errno to 0 before calling setlocale(), and + print strerror (errno) if setlocale fails and errno ends up non-zero + + 2/6 + --- +configure.in + - backed out of solaris change from 10/23/2008 (adding `-z interpose' + to LDFLAGS) due to solaris updates to fix a linker problem. + Updatted by Serge Dussud + + 2/12 + ---- +execute_cmd.c + - change execute_connection so failure of a pipeline will cause the + shell to exit if -e is on. From discussion on austin-group + mailing list + - change execute_command_internal so failure of a user-specified + subshell will cause the shell to exit if -e is on. From discussion + on austin-group mailing list + + 2/13 + ---- +doc/{bash.1,bashref.texi} + - clarified description of set -e option to accurately reflect current + implementation + + 2/19 + ---- +print_cmd.c + - fix print_deferred_heredocs to not print a space if the separator + string is null + - change print_deferred_heredocs to set `was_heredoc' after printing + something + - change connection printing code to only print the `;' separator + if we haven't just printed a here-document + - change connection printing code to print any deferred here + documents after the rhs of the connection. Fixes bug reported by + Bo Andresen + +[bash-4.0 frozen] + + 2/20 + ---- + +[bash-4.0 released] + + 2/22 + ---- + +parse.y + - fix parse_comsub to not test a character for being a possible shell + metacharacter if LEX_PASSNEXT flag is set. Fixes bug reported by + Mike Frysinger + +pcomplete.c + - add call to save_parser_state (accidentally dropped from patch) to + gen_shell_function_matches. Fixes bug with bash_completion and + file/directory completion reported by phil@Arcturus.universe + +Makefile.in + - fix assignment to LDFLAGS_FOR_BUILD to match those in subdir + Makefiles. Fixes bug reported by Mike Frysinger + +builtins/mapfile.def + - make sure the callback quantum (-c option argument) is > 0. Fixes + bug reported by Stephane Chazleas + + 2/23 + ---- +parse.y + - fix save_token_state and restore_token_state to save and restore + current_token. Fixes bug reported by Bernd Eggink + + +builtins/exit.def + - check jobs[i] before checking whether or not it's running when + the checkjobs option is set and we're looking for running jobs + at exit. Fixes bug reported by Mike Frysinger + + 2/24 + ---- +siglist.c + - include bashintl.h for definition of _. Fixes bug reported by + Greg Wooledge + + 2/25 + ---- +subst.c + - new function, skip_matched_pair. Similar to skip_to_delim and + the extract_XXX family + - move skipsubscript here from arrayfunc.c; re-implement in terms of + skip_matched_pair. Fixes bugs reported by + +arrayfunc.c + - remove skipsubscript; moved to subst.c + +parse.y + - change reset_parser to set current_token to '\n'. Rest of fix for + bug reported by Bernd Eggink ; earlier fix on + 2/23 + + 2/26 + ---- +builtins/declare.def + - when given something like array[x]=y (which sets making_array_special + to 1), don't convert an associative array to an indexed array (line + 493). Part of fix for bug reported by Pierre Gaston + + - if offset == 0, indicating that we do not have a valid assignment, + make sure any `name' containing a `[' is a valid array reference + before trying to go on. Not doing this leads to creating crazy + variables like `name[foo[bar]=bax'. Rest of fix for bug reported + by Pierre Gaston + +assoc.c + - change assoc_to_assign to single-quote the array keys if `quoted' is + non-zero. Makes things easier to read with weird characters in the + key + +parse.y + - fix parse_comsub to not set LEX_HEREDELIM when it sees "<<<". Fixes + bug reported by Mike Frysinger + + 2/27 + ---- +parse.y + - fix report_syntax_error to set last_command_exit_value to + EX_BADUSAGE (2) instead of EX_USAGE (258), since there's nothing + that will translate that to something < 128 before reading the + next command. Partial fix for bug reported by Mike Frysinger + + +sig.c + - fix sigint_sighandler to set last_command_exit_value to sig+128 + before calling throw_to_top_level. Rest of fix for bug reported + by Mike Frysinger + +jobs.c + - if fork() fails, set last_command_exit_value to 126 before calling + throw_to_top_level + +execute_cmd.c + - defer calling unlink_fifo_list in parent branch of + execute_disk_command if we're executing in a shell function + - change execute_function to call unlink_fifo_list before returning + if it's the top-level function + + 3/2 + --- +builtins/read.def + - if read times out, make sure we remove the top element from the + unwind-protect stack (the free of input_string) and run the rest, + to reset the tty and readline and alarm states. Then we jump to + assigning the variables to any partial input. Fixes bug reported + by Christopher F. A. Johnson + + 3/3 + --- +parse.y + - break comment checking code into a common COMMENT_BEGIN define so + we can use it in multiple places in parse_comsub + - in parse_comsub, don't alter the LEX_RESWDOK flag if we read a + `#' and we're checking comments, even though `#' isn't a `shell break' + character. Fixes bug reported by Mike Frysinger + +braces.c + - in expand_seqterm, decrease the total length of the rhs by the length + of any (optional) increment, so we don't end up with unwanted zero + padding because the rhs length is wrong. Fixes bug reported by + Carl Albing + + 3/4 + --- +doc/{bash.1,bashref.texi} + - changes to clean up some of the language describing the effects of + terminal process groups on the ability to read from and write to + the terminal + + 3/5 + --- +support/shobj-conf + - add host_vendor to string tested in switch to handle things like + gentoo/freebsd + - beginning with version 7, FreeBSD no longer has /usr/bin/objformat + or a.out binaries and libraries. It's always ELF. Fix from + Timothy Redaelli + +parse.y + - in parse_comsub, allow comments if we are ready to read a + reserved word (tflags & LEX_RESWDOK), haven't read anything from + one yet (lex_rwlen == 0) and the current character is a '#' + + 3/6 + --- +parse.y + - new lex flag for parse_comsub: LEX_INWORD. Turn it off when + we see a shell break character; turn it on or keep it on when + not a break character. Keep track of word length (reset to 0 + when we turn on LEX_INWORD when it was off). + - don't use COMMENT_BEGIN in parse_comsub any more; test + whether or not LEX_INWORD is set and lex_wlen == 0 in addition + to tests for LEX_RESWDOK and lex_rwlen. Comments are valid + when at the start of a word + - move LEX_PASSNEXT code to the top of parse_comsub, so the rest + of the function doesn't have to check for the flag at different + places + + 3/7 + --- +parse.y + - in parse_comsub, when looking for a reserved word (LEX_RESWDOK + non-zero), and in a case statement, we can see either an esac + or a pattern list. We handle an esac separately. We should + turn off LEX_RESWDOK if we see anything but a newline, since + we'll be reading a pattern list. Other part of fix for bug + reported by Mike Frysinger (rest of fix + on 3/3) + + 3/10 + ---- +{.,lib/readline}/doc/fdl.texi + - updated to FDL version 1.3 + + 3/11 + ---- +parse.y + - when using the |& construct with a simple command preceding it, add + the implicit redirection to the simple command's redirection list, + since the redirections associated with the command struct are never + executed. Fixes bug reported by Matt Zyzik + + 3/14 + ---- +execute_cmd.c + - in execute_case_command, if ;& is used with no following pattern + list, make sure we don't reference a NULL pointer. Bug report and + fix from Clark Jian Wang + +parse.y + - make parser_state global, so other files can use it + - command_word_acceptable now returns non-zero if PST_REDIRLIST bit + set in parser_state, so we accept assignment statements and + perform alias expansion. Fix for bug reported by Vincent + Lefevre (2/24/2009) + +parser.h + - add PST_REDIRLIST flag, notes that parser is currently parsing a + redirection list preceding a simple command + +make_cmd.c + - make_simple_command now turns on PST_REDIRLIST in parser_state when + creating a new simple command + - make_simple_command turns off PST_REDIRLIST in parser_state if it + adds a non-redirection to the command it's building + - clean_simple_command turns off PST_REDIRLIST to make sure it's off + +subst.c + - new flag for param_expand: PF_IGNUNBOUND, means to not exit if the + variable is unbound even if `set -u' is enabled + - change param_expand to not call err_unboundvar if the `pflags' + argument has the PF_IGNUNBOUND bit set + - parameter_brace_expand_word now takes an extra `pflags' argument to + pass down to param_expand; changed callers + - changed call to parameter_brace_expand_word in parameter_brace_expand + to add PF_IGNUNBOUND flag so ${@:-foo} doesn't cause the shell to + exit (but ${@} does) when there are no positional parameters. Fixes + Debian bug 519165 from Dan Jacobson + +parse.y + - add code to parse_comsub to allow here-documents within command + substitutions to be delimited by the closing right paren, with the + usual warning about here documents delimited by EOF on execution. + Fixes regression from bash-3.2 noted in Red Hat bugzilla 485664 by + Ralf Corsepius + + 3/15 + ---- +subst.c + - string_list_dollar_at now checks for Q_PATQUOTE, which getpattern() + uses to denote Q_DOUBLE_QUOTES (?). Fixes a=abcd echo "${a#$*}" + when IFS= and args are `a b' as noted by Stephane Chazleas + + - param_expand now checks for Q_PATQUOTE and treats it identically + to Q_DOUBLE_QUOTES when expanding $* + - expand_word_unsplit now sets W_NOSPLIT in the flags of the word it + passes to expand_word_internal if $IFS is NULL + - expand_word_leave_quoted now sets expand_no_split_dollar_star and + the W_NOSPLIT bit in the word flags before calling + expand_word_internal if $IFS is NULL, just like expand_word_unsplit. + It is now virtually identical to expand_word_unsplit. Rest of fix for + problems reported by Stephane Chazleas + + 3/20 + ---- +trap.c + - in _run_trap_internal, don't pass SEVAL_RESETLINE as flag to + parse_and_execute if running the ERR trap (further modification + of change from 1/12) + +execute_cmd.c + - in execute_simple_command, set line_number to line_number_for_err_trap + before calling run_error_trap. Part of fix for bug reported by + Brian J. Murrell + - change other places calling run_error_trap() to set and use + line_number_for_err_trap + + 3/21 + ---- +builtins/fc.def + - Even though command substitution through parse_and_execute turns + off remember_on_history, command substitution in a shell when + set -o history has been enabled (interactive or not) should use it + in the last_hist calculation as if it were on. Same calculation + in fc_gethnum and fc_builtin. Fixes bug reported by + Ian Kelling + +sig.c + - change termsig_sighandler to terminate immediately if it gets called + twice with the same signal before termsig_handler gets called. This + fixes the `looping on SIGSEGV' phenomenon reported by Linux users. + +parse.y + - in read_secondary_line, don't try to add NULL lines to the history + list. Report and patch from Lubomir Rintel + + 3/22 + ---- +sig.c + - Augment change from 3/21 with explicit check for signals we *don't* + want this to happen for. Patch from Lubomir Rintel + + 3/28 + ---- +array.c + - in array_reference, return NULL immediately if the desired index + is larger than the maximum + - add cache of last array referenced and last array element referenced; + use in array_reference to optimize case of sequential access; + invalidated where necessary in other functions + - array_rshift needs to set max_index to 0 if the array was empty + before shifting in the new element 0 + - array_shift needs to use element_index(a->head->prev) to set the + max_index, not a simple decrement, to deal with sparse arrays + + 4/1 + --- +bashline.c + - in bash_dequote_filename, return right away after copying the + backslash if the last character in the string to be expanded + is a backslash. The old code copied an extra NUL and overwrote + the bounds checking. Fixes bug reported by Shawn Starr + https://bugzilla.redhat.com/show_bug.cgi?id=488649 + + 4/3 + --- +subst.c + - in pat_subst.c, make sure to copy one character from the input + string in the case of a null pattern match, since we substitute + on the null match and then increment past the current character. + Not doing this means that each character of the original string + is replaced because of the null matches. Fixes debian bug + reported bhy Louis-David Mitterrand + http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=522160 + +lib/sh/winsize.c + - incorporate contents of readline/rlwinsize.h to get all the various + system dependencies right when trying to find TIOCGWINSZ. Fixes + bug reported by Dan Price + + 4/6 + --- +doc/{bash.1,bashref.texi} + - fix description of conditional `>' and `<' to remove statement that + the comparison pays attention to the current locale -- it has + always used strcmp + +lib/glob/glob.c + - fixed a bug in glob_filename that caused glob_dir_to_array to be + called to prepend a (globbed) directory name onto the results from + glob_vector, which, if we were globbing `**', glob_vector has + already done. Effect is to have the directory name(s) on there + twice. Fixes "dir*/**" bug reported by Matt Zyzik + + + 4/8 + --- +doc/{bash.1,bashref.texi} + - fix short syntax summary of for command to reflect full bash + syntax (which is a superset of Posix syntax). Fixes bug reported + by Reuben Thomas + + 4/10 + ---- +{expr,subst}.c + - make sure last_command_exit_value is set to EXECUTION_FAILURE + before calling err_unboundvar, in case set -e is enabled and + the shell exits from there. Fixes bug reported by Freddy + Vulto and Piotr Zielinski + + + 4/11 + ---- +jobs.c + - in restore_pipeline, don't call discard_pipeline with a NULL + argument + +trap.c + - in run_debug_trap, make sure to save and restore the pipeline, + pipeline_pgrp, and state of the pipeline around running the debug + trap, then remove any job created by running the debug trap from + the jobs table when it completes. Fixes for two bugs reported + by lex@upc.ua + + 4/12 + ---- +lib/readline/signals.c + - new functions to block and release SIGWINCH like the SIGINT blocking + and releasing functions + +lib/readline/rlprivate.h + - new extern declarations for _rl_block_sigwinch and _rl_release_sigwinch + +lib/readline/display.c + - block SIGWINCH during redisplay like SIGINT. Should fix bug reported + by Nicolai Lissner + + 4/13 + ---- +lib/readline/readline.h + - new readline state variable: RL_STATE_REDISPLAYING + +lib/readline/display.c + - in rl_redisplay, don't block SIGWINCH during redisplay; just set + the REDISPLAYING state + +lib/readline/terminal.c + - in rl_resize_terminal, don't call rl_redisplay_after_sigwinch() if + we're already in the middle of redisplay (RL_STATE_REDISPLAYING). + Fix for bug reported by Nicolai Lissner + + 4/15 + ---- +parse.y + - fix parse_comsub to add check for \n when seeing whether the current + character can change to a state where a reserved word is legal, + since it is not a shell meta character. Fixes bug reported by + Bernd Eggink . + + 4/17 + ---- +jobs.c + - new functions to save and restore the pgrp_pipe (since there's only + one): save_pgrp_pipe and restore_pgrp_pipe + +trap.c + - run_debug_trap now saves and restores the pgrp_pipe before and + after calling the debug trap + - run_debug_trap now makes sure the terminal is owned by the pipeline + pgrp after the debug trap runs. Rest of fix for bug reported by + Oleksly Melnyk (lex@upc.ca) + + 4/19 + ---- +include/posixselect.h + - new include file, encapsulates select(2) includes and defines for + bash and readline. Inspired by patch from Mike Frysinger + + +lib/sh/input_avail.c + - include "posixselect.h" + +lib/readline/{input,parens}.c + - include "posixselect.h" instead of using inline includes + - use new USEC_TO_TIMEVAL define to make sure that values for timeouts + greater than one second are handled properly + +lib/sh/fpurge.c + - updated implementation, taken from gnulib + + 4/21 + ---- +lib/glob/glob.c + - in finddirs, don't try to free a return value of glob_error_return + from glob_vector. Bug and fix from werner@suse.de + +lib/readline/signals.c + - in rl_echo_signal_char, check that SIGQUIT and SIGTSTP are defined + before trying to use them. Bug report and fix from Volker Grabsch + + + 4/24 + ---- +aclocal.m4 + - add conditional inclusion of to BASH_CHECK_TYPE + +bashtypes.h,lib/sh/strto[iu]max.c + - include if present for any existing declaration of + intmax_t and uintmax_t. Fixes Interix problem reported by + Markus Duft + +lib/sh/strindex.c,externs.h,builtins/common.h + - renamed strindex to strcasestr to agree with other implementations + (e.g., BSD, MacOS X, gnulib); changed callers + +lib/sh/{strindex.c,Makefile.in},Makefile.in + - renamed strindex.c to strcasestr.c + +configure.in + - add strcasestr to call to AC_REPLACE_FUNCS, take advantage of + existing libc implementations + +config.h.in + - add define for HAVE_STRCASESTR + +lib/sh/mbscmp.c + - fix mbscmp to return correct values when the strings do not contain + valid multibyte characters. Ideas from gnulib + +xstrchr.c + - only compare current character against C if mblength == 1 + +{shell,variables}.c + - changed some xstrchr calls back to strchr when the arguments cannot + contain multibyte characters + +lib/sh/{xstrchr.c,Makefile.in},Makefile.in + - renamed xstrchr to mbschr; renamed file to mbschr.c + +aclocal.m4 + - change BASH_CHECK_MULTIBYTE to use AC_REPLACE_FUNCS(mbschr) + +externs.h + - extern declarations for mbscmp and mbschr, conditional on the usual + HAVE_MBSCMP and HAVE_MBSCHR defines + +general.h,{alias,arrayfunc,bashline,general,execute_cmd,subst}.c + - changed calls to xstrchr to mbschr + +doc/bash.1 + - use `pathname expansion' consistently, not `filename expansion' or + `filename generation' + +doc/bashref.texi + - use the phrase `filename expansion' consistently (since this is + what the Gnu people prefer) instead of `pathname expansion' or + `filename generation' + +aclocal.m4,config.h.in + - check for mbscasecmp in BASH_CHECK_MULTIBYTE, define HAVE_MBSCASECMP + if found + +lib/sh/{mbscasecmp.c,Makefile.in} + - new file, case-insensitive multibyte string comparison + +externs.h + - extern declaration for mbscasecmp + + 4/25 + ---- +lib/readline/display.c + - in _rl_move_cursor_relative, don't adjust dpos by woff if it's + already less than woff (don't want it less than 0) + - in _rl_move_cursor_relative, short-circuit right away if the cursor + is at columns 0 and `new' is 0 (doesn't matter if it's a multibyte + locale or not, or whether there are invisible chars in the prompt) + - in _rl_move_cursor_relative, go ahead and adjust dpos if + prompt_physical_chars >= _rl_screenwidth (previous check was just > ) + Fixes bug reported by Andreas Schwab + + 4/28 + ---- +lib/glob/glob.c + - in glob_vector, don't add an empty pathname ("") if we're adding the + currect directory to the dirlist and GX_NULLDIR is set -- we can just + ignore it, since the passed directory name (".") was created by + the caller. Fixes bug reported by Matt Zyzik + + 5/5 + --- +subst.c + - make expansion of $@ and $* when set -u is in effect and there are + no positional parameters be a non-fatal error. This is the + consensus of the austin group, though it is not historical practice. + Message from Geoff Clare <20090505091501.GA10097@squonk.masqnet> of + 5 May 2009 and http://austingroupbugs.net/view.php?id=155 + + + 5/20 + ---- +lib/glob/glob.c + - tentative fix to glob_filename to compensate for glob_vector putting + null pathname at front of result vector when dflags&GX_NULLDIR. + Current fix manually removes empty string element from front of + result vector; a better fix would be to use a flag so glob_vector + doesn't add it at all. Augments patch from 4/28, which appears to + have broken some things. Fixes bug reported by Matt Zyzik + + + 5/22 + ---- + +lib/glob/glob.c + - better fix for glob_filename; supersedes patch of 5/20. Now the + code does not set GX_ADDCURDIR if directory_len == 0 and the + function has not been called recursively ((flags & GX_ALLDIRS) == 0). + Better fix for bug reported by Matt Zyzik + +Makefile.in + - fix build race condition that occurs in some makes caused by + libreadline.a and libhistory.a containing some of the same files + (e.g., xmalloc.o) and conflicting when trying to build both at + the same time. Reported by Mike Frysinger + + 5/25 + ---- +lib/readline/vi_mode.c + - fix _rl_vi_initialize_line so that the loop counter is not + unsigned (it doesn't matter, but it eliminates a compiler warning). + Bug reported by Dave Caroline + + 5/26 + ---- +doc/{bash.1,bashref.texi} + - add text to the description of array variables making it clear + that an array variable is not considered set until a subscript + has been assigned a value + + 5/29 + ---- +lib/readline/text.c + - fix rl_change_case to handle case where mbrtowc doesn't find a + valid multibyte character + +lib/readline/vi_mode.c + - fix _rl_vi_change_mbchar_case to handle case where mbrtowc doesn't + find a valid multibyte character + +lib/sh/casemod.c + - fix sh_modcase to handle case where mbrtowc doesn't find a valid + multibyte character + +lib/readline/mbutil.c + - fix _rl_find_next_mbchar_internal to not call mbrtowc at the end of + the string, since implementations return different values -- just + break the loop immediately + +lib/readline/display.c + - fix rl_redisplay to make same sort of cursor position adjustments + based on multibyte locale and _rl_last_c_pos when performing + horizontal scrolling rather than line wrapping. Probably still + more to do. Fixes bug reported by jim@jim.sh + + 6/5 + --- +doc/{bash.1,bashref.texi} + - added some more explanation of the inheritance of the ERR trap at + the suggestion of Thomas Pospisek + +findcmd.c + - use eaccess(2) if available in file_status to take other file + access mechanisms such as ACLs into account. Patch supplied + by werner@suse.de + + 6/12 + ---- +xmalloc.c + - also calculate lowest brk() value the first time xmalloc/xrealloc + (and their sh_ counterparts) are called + - error messages consolidated into a single function (allocerr/ + sh_allocerr) to avoid string duplication + + 6/16 + ---- +variables.c + - changes to allow variables.c to be compiled if ALIAS is not defined. + Bug and fix from John Gatewood Ham + +lib/sh/getcwd.c + - fix so systems defining BROKEN_DIRENT_D_INO have the necessary + defines. Fix from Jay Krell + +configure.in + - add -D_ALL_SOURCE to interix CFLAGS for struct timezone definition. + Bug and fix from John Gatewood Ham + + 6/29 + ---- +variables.c + - change initialize_shell_variables to add environment variables with + invalid names to the variables hash table, but marking them as + invisible and imported + - new function, export_environment_candidate. Used when creating the + export environment for commands to include variables with invalid + names inherited from the initial environment. Apparently this + behavior is widespread + - change make_var_export_array to use export_environment_candidate + rather than visible_and_exported to test variables for inclusion + in the export environment + + 7/1 + --- +builtins/read.def + - fix a memory leak where the number of fields is not the same as + the number of variables passed to `read'. Bug report from + werner@suse.de + +builtins/command.def + - move section of code that sets PATH from -p option before the + verbose-handling section, so command -v and command -V honor + the PATH set by command -p. Bug report and fix from + ohki@gssm.otsuka.tsukuba.ac.jp + + 7/9 + --- +subst.c + - change brace_expand_word_list to defer brace expansion on compound + array assignments that are arguments to builtins like `declare', + deferring the expansion until the assignment statement is processed. + Fixes inconsistency reported by agriffis@n01se.net + + 7/16 + ---- +bashline.c + - fix bash_execute_unix_command to set rl_point correctly based on + READLINE_POINT. The old method of using save_point will not + work because maybe_make_readline_line will change rl_point. Bug + reported by Henning Bekel + +trap.c + - fix _run_trap_internal and run_pending_traps to save and restore + value of subst_assign_varlist so the dispose_words on it doesn't + leave dangling pointers after the trap handler runs. Fixes bug + reported by Marc Herbert + + 7/22 + ---- +subst.c + - fix off-by-one error in pos_params when computing positional + parameters beginning with index 0. Bug and fix from Isaac Good + + + 7/24 + ---- +lib/readline/display.c + - add code to _rl_move_cursor_relative and _rl_col_width to short- + circuit a few special cases: prompt string and prompt string plus + line contents, both starting from 0. Saves a bunch of calls to + multibyte character functions using already-computed information. + As a side effect, fixes bug reported by Lasse Karkkainen + + +subst.c + - fixed a problem in split_at_delims that could leave *cwp set to -1 + if the line ends in IFS whitespace and SENTINEL is one of those + whitespace characters. Fixes problem with setting COMP_CWORD for + programmable completion reported by Ville Skytta + +bashline.c + - change bash_execute_unix_command to clear the current line (if the + terminal supplies the "ce" attribute) instead of moving to a new + line. Inspired by report from Henning Bekel + +builtins/printf.def + - changes to allow printf -v var to assign to array indices, the way + the read builtin can. Suggested by Christopher F. A. Johnson + + +lib/readline/complete.c + - fix rl_old_menu_complete and rl_menu_complete to appropriately set + and unset RL_STATE_COMPLETING while generating the list of matches. + Fixes debian bug #538013 reported by Jerome Reybert + + + 7/25 + ---- +execute_cmd.c + - change execute_builtin to temporarily turn off and restore the ERR + trap for the eval/source/command builtins in the same way as we + temporarily disable and restore the setting of the -e option. + Fixes bug reported by Henning Garus + + 7/27 + ---- +shell.c + - add fflush(stdout) and fflush(stderr) to exit_shell before closing + any file descriptors at exit time (e.g., coproc pipes) + + 7/30 + ---- +lib/readline/complete.c + - new function rl_backward_menu_complete, just passes negative count + argument to rl_menu_complete + - change rl_menu_complete to act appropriately if rl_last_command is + rl_backward_menu_complete, so we can cycle forward and backward + through the list of completions + +lib/readline/doc/{readline.3,rluser.texi},doc/bash.1 + - document new "menu-complete-backward" bindable readline function. + Suggested by Jason Spiro + +lib/readline/vi_keymap.c + - add binding of C-n to menu-complete and C-p to menu-complete-backward + in vi-insert keymap, as suggested by Jason Spiro + + +pcomplete.c + - fixed a bug in programmable_completions: the options it returned from + the compspec it found were set before generating the completions, + which meant that any changes made by "compopt" were overridden and + only in effect for the duration of the executing shell function + rather than the entire completion. Fixes bug reported by Ville + Skytta + + 7/31 + ---- +lib/readline/keymaps.c + - fixed memory leak in rl_discard_keymap by freeing storage associated + with hierarchical keymaps + - new convenience function, rl_free_keymap, that calls rl_discard_keymap + and frees the keymap passed as an argument + +lib/readline/util.c + - new bindable keymap function, _rl_null_function, to be used internally + +lib/readline/rlprivate.h + - extern declaration for _rl_null_function + +lib/readline/bind.c + - fix rl_generic_bind in the case where we are trying to override a + keymap with a null function (e.g., when trying to unbind it). We + can't use a NULL function pointer in ANYOTHERKEY since that's + indistinguishable from the keymap not having been overridden at all. + We use _rl_null_function instead, which simply does nothing. We + could add an rl_ding to it later. Fixes problem with hitting ESC + repeatedly while in vi command mode reported by James Rowell + + +builtins/bind.def + - call rl_bind_keyseq instead of rl_set_key for -r option + +lib/readline/readline.c + - Set vi_movement_keymap[ESC] to _rl_null_function after binding the + arrow keys in bind_arrow_keys() to allow vi-mode users to hit ESC + multiple times in vi command mode while still allowing the arrow + keys to work + + 8/2 + --- +bashline.c + - fix clear_hostname_list by setting hostname_list_initialized to 0 + after freeing all list members. Fixes bug reported by Freddy + Vulto + +lib/readline/display.c + - in update_line, if we copy data from one line to another because we + are wrapping a multibyte character from, say, the first line to the + second, we need to update OMAX and the line indices to account for + the moved data. Bug report and fix from Martin Hamrle + + + 8/3 + --- +pcomplete.h + - defines for EMPTYCMD ("_EmptycmD_") and DEFAULTCMD ("_DefaultCmD_") + +builtins/complete.def + - change compopt_builtin to make -E work on the "empty" command + completion + - fix print_compitem and print_compopts to replace EMPTYCMD with -E + - added -D (default) option to complete/compgen/compopt. No supporting + code yet + +doc/bash.1,lib/readline/doc/rluser.texi + - document new -D, -E options to compopt + - document new -D option to complete/compgen + +shell.h + - new define, EX_WEXPCOMSUB, value of 125 + - new define, EX_RETRYFAIL, value of 124 (for programmable completion) + +subst.c + - use EX_WEXPCOMSUB instead of literal 125 as exit status when a shell + invoked to run wordexp(3) with the -n option supplied attempts a + command substitution + +pcomplete.c + - new define, PCOMP_RETRYFAIL, used to indicate a "failure, retry with + next completion" status to the programmable completion code + + 8/4 + --- +pcomplete.c + - changed gen_shell_function_matches to take an extra parameter + indicating whether the specified shell function was not found or + returned the special "fail/retry" status, and, if it was either, + to not bother returning any matches list + - changed gen_compspec_completions to take an extra parameter to pass + through the "found" status from gen_shell_function_completions + - new function gen_progcomp_completions to take care of searching for + and evaluating a compspec for a particular word, saving its status, + and returning to its caller (programmable_completions) whether or + not to retry completion. This function also checks whether a + retry changed the compspec associated with a command and short- + circuits the retry if it has not + - changed programmable_completions to try default completion (if set) + if a specific completion was not found for a command + - changed programmable_completions to implement "fail/retry" semantics + for a shell function that returns 124 and changes the compspec + associated with the command. All based on proposal and changes from + Behdad Esfahbod (Red Hat bugzilla 475229) + +doc/bash.1,lib/readline/doc/rluser.texi + - documented new dynamic programmable completion functionality + + 8/5 + --- +stringlib.c + - first argument to substring() is now `const char *' + +externs.h + - changed extern declaration for substring() + +subst.c + - skipsubscript now takes a third FLAGS argument, passes to + skip_matched_pair + - skip_matched_pair now interprets flags&1 to mean not to parse + matched pairs of quotes, backquotes, or shell word expansion + constructs + +{subst,general,expr}.c + - changed skipsubscript() callers + +assoc.c + - changed assoc_to_assign to double-quote the key if it contains any + shell metacharacters + +arrayfunc.c + - use skipsubscript in quote_assign rather than quote any glob + characters in the subscript of an array assignment + - in assign_compound_array_list, call skipsubscript with a flags + argument of 1 if assigning an associative array to avoid trying + to re-parse quoted strings + +redir.c + - set expanding_redir before expanding body of here documents and + here strings to avoid looking for variables in temporary env + + 8/7 + --- +lib/readline/readline.c + - in _rl_dispatch_callback, return value of -3 means that we have + added to a key sequence, but there are previous matches in the + sequence. Don't call _rl_subseq_result if we get a -3 from a + previous context in the chain; just go back up the chain. Report + and fix from + +bashline.c + - fixes to history_completion_generator and bash_dabbrev_expand to + make dabbrev-expand inhibit suppressing of appending space char + to matches. Have to do it with the generator too because + rl_menu_complete turns off suppressing the appended space in + set_completion_defaults(). Suggestion from Dan Nicolaescu + + - suppress completion match sorting in bash_dabbrev_expand by + setting rl_sort_completion_matches = 0. Suggestion from Dan + Nicolaescu + - don't qsort history match list in build_history_completion_array + if dabbrev_expand_active == 1 + - start the loop in build_history_completion_array that gathers words + from history for possible completions from the end of the list + rather than the beginning. It doesn't matter where you start if + the results are sorted, and dabbrev-expand is supposed to offer + the most recent completions first + + 8/12 + ---- +execute_cmd.c + - change to execute_command_internal to make [[ ... ]] conditional + command subject to settings of `set -e' and the ERR trap + + 8/14 + ---- +execute_cmd.c + - change to execute_command_internal to make (( ... )) arithmetic + command subject to settings of `set -e' and the ERR trap + +lib/readline/text.c + - new bindable function, rl_skip_csi_sequence, reads the characters + that make up a control sequence as defined by ECMA-48. Sequences + are introduced by the Control Sequence Indicator (CSI) and + contain a defined set of characters. Insert, End, Page Up and so + on are CSI sequences. Report and code from Andy Koppe + + +lib/readline/readline.h + - extern declaration for rl_skip_csi_sequence + +lib/readline/funmap.c + - new bindable command "skip-csi-sequence", runs rl_skip_csi_sequence + +doc/bash.1,lib/readline/doc/{readline.3,rluser.texi} + - documented new bindable command "skip-csi-sequence", unbound by + default + +builtins/evalfile.c + - fix _evalfile to remove embedded null bytes from the file read + into the string. Report and proposed fix from Roman Rakus + + +{configure,config.h}.in + - check for syslog(3), define HAVE_SYSLOG + - check for syslog.h, define HAVE_SYSLOG_H + +config-top.h + - new define SYSLOG_HISTORY, disabled by default + +config-bot.h + - if HAVE_SYSLOG or HAVE_SYSLOG_H are not defined, undef SYSLOG_HISTORY + +bashhist.c + - if SYSLOG_HISTORY is defined, call bash_syslog_history with the + line added to the history in bash_add_history. + - new function, bash_syslog_history(line), sends line to syslog at + user.info. The line is truncated to send no more than 600 + (SYSLOG_MAXLEN) bytes to syslog. Feature requested by many, and + required by some national laws + +sig.c + - in termsig_handler, resend SIGHUP to children if subshell_environment + indicates we're a shell performing command or process substitution + +jobs.c + - add CHECK_TERMSIG calls to wait_for in addition to the ones in + waitchld() + +builtins/shopt.def + - new functions set_bashopts, parse_bashopts, and initialize_bashopts + to manage new environment variable $BASHOPTS, like $SHELLOPTS but + for shopt options + - change toggle_shopts to call set_bashopts after setting options, so + $BASHOPTS reflects new values + +shell.c + - call initialize_bashopts after calling initialize_shell_options at + shell startup + +configure.in + - new configure `enable' option --enable-exended-glob-default, to + set the initial default value of the `extglob' shell option + +config.h + - new define, EXTGLOB_DEFAULT, controlled by the `extended-glob-default' + configure option + +pathexp.c + - initialize extended_glob variable to EXTGLOB_DEFAULT + +doc/{bash.1,bashref.texi} + - document new $BASHOPTS variable and its behavior + +doc/bashref.texi + - document new --enable-extended-glob-default configure option + + 8/16 + ---- +print_cmd.c + - new variables: xtrace_fd and xtrace_fp, the file descriptor and + FILE * to which we send `set -x' tracing output. If fd == -1 + then fp == STDERR, the default mode + - new function xtrace_init, sets xtrace_fd == -1 and xtrace_fp = stderr + - new function xtrace_set (fd, fp), sets xtrace_fd and xtrace_fp + to the arguments + - new function xtrace_reset, handles closing old xtrace fd/fp and + moving them back to -1/stderr + - new function xtrace_fdchck, calls xtrace_reset if the fd passed as + an argument is xtrace_fd + - change xtrace functions to fprintf to xtrace_fp instead of stderr + +shell.c + - call xtrace_init() very early in main() + +variables.c + - new special variable, BASH_XTRACEFD, holds file descriptor used for + set -x trace output. Inspired by suggestion from Bruce Korb + + +doc/{bash.1,bashref.texi} + - added description of new BASH_XTRACEFD variable + +redir.c + - add calls to xtrace_fdchk to the redirections that close file + descriptors, so we notice if we close BASH_XTRACEFD and compensate + accordingly (same places that call coproc_fdchk()) + + 8/18 + ---- +lib/readline/text.c + - change to _rl_replace_text to add error checks: start must be <= + end, and we don't call rl_insert_text if passed the empty string + +config.h.in + - add define for HAVE_ICONV, already found by intl autoconf macros + - add define for HAVE_LOCALE_CHARSET + +aclocal.m4 + - add check for locale_charset() to BASH_CHECK_MULTIBYTE + +lib/sh/fnxform.c + - new file with two public function: fnx_tofs and fnx_fromfs. + Primarily intended for use on MacOS X, they use iconv to convert + between whatever the current locale encoding is and "UTF-8-MAC", + a special encoding on OS X in which all characters are + decomposed unicode, as the HFS+ filesystem stores them. These + functions return a pointer to a local buffer, allocated once and + resized as necessary, to avoid too many allocations; callers + should not free the return value, since it may be the string + passed + +Makefile.in + - make sure LIBICONV is set by autoconf (@LIBICONV@) and added to + list of link libraries + +externs.h + - new extern declarations for fnx_fromfs and fnx_tofs + +lib/glob/glob.c + - convert the filename read using readdir() in glob_vector() using + fnx_fromfs and use that value in the call to strmatch. This + ensures that we're using the precomposed Unicode value of the + filename rather than the native decomposed form. Original bug + report from Len Lattanzi ; fix inspired by + Guillaume Outters + + 8/19 + ---- +lib/readline/complete.c + - new completion hook: rl_filename_rewrite_hook, can rewrite or modify + filenames read from the filesystem before they are compared to the + word to be completed + +lib/readline/readline.h + - extern declaration for rl_filename_rewrite_hook + +lib/readline/doc/rltech.texi + - document rl_filename_rewrite_hook + +bashline.c + - new function, bash_filename_rewrite_hook, assigned to + rl_filename_rewrite_hook. Calls fnx_fromfs to convert from + filesystem format to "input" format. This makes completing + filenames with accented characters work on Mac OS X + + 8/20 + ---- +lib/readline/bind.c + - new bindable variable "skip-completed-text", bound to + _rl_skip_completed_text. If enabled, it means to note when + completing before the end of a word and skipping over characters + after rl_point that match in both the completion to be inserted + and the word being completed. It means that completing + `Makefile' with the cursor after the `e' results in `Makefile' + instead of `Makefilefile'. Inspired by an idea from Jared + Yanovich from back in 2004 + +lib/readline/rlprivate.h + - extern declaration for _rl_skip_completed_text + +lib/readline/complete.c + - implement semantics of _rl_skip_completed_text in insert_match: + skip characters in `replacement' that match chars in rl_line_buffer + from the start of the word to be completed + + 8/21 + ---- +error.c + - change parser_error to set last_command_exit_value to 2 before + calling exit_shell (if set -e is enabled), so any exit or ERR + trap gets the right value of $?. Suggestion from Stefano + Lattarini + +braces.c + - fix expand_seqterm so that a non-zero-prefixed term that's longer + than a zero-prefixed term determines the length of each term + in the brace-expanded sequence. This means that things like + {01..100} will have three digits in all the elements of the + expanded list. Fixes bug reported by Jeff Haemer + + + 8/24 + ---- +{arrayfunc,variables}.c + - when inserting a value into an associative array using syntax like + T=v where T is an already-declared associative array using key "0", + make sure the key is in newly-allocated memory so it can be freed + when the variable is unset. Fixes bug reported as redhat 518644 + by Jon Fairbairn + + 8/26 + ---- +lib/readline/funmap.c + - add "old-menu-complete" binding for rl_old_menu_complete + +lib/readline/readline.h + - add extern declaration for rl_old_menu_complete + +subst.c + - fix memory leak when processing ${!prefix@}. Need to dispose all + words in the word list created from all matching variable. Fixes + bug reported by muszi@muszi.kite.hu. + + 8/29 + ---- +execute_cmd.c + - add fflush(stdout) and fflush(stderr) to child coproc code before + calling exit after execute_in_subshell + + 8/31 + ---- +lib/readline/{{bind,readline}.c,rlprivate.h} + - new bindable variable, "echo-control-characters", enabled by default. + This controls whether or not readline honors the tty ECHOCTL bit + and displays characters corresponding to keyboard-generated signals. + Controlled by _rl_echo_control_chars variable, declared in readline.c + +lib/readline/signals.c + - if _rl_echo_control_chars == 0, don't go through _rl_echo_signal_char + + +lib/readline/doc/{readline.3,rluser.texi} + - document "echo-control-characters" bindable variable + + 9/1 + --- +lib/readline/histexpand.c + - hist_string_extract_single_quoted now takes an additional argument: + a flags word. The only defined value (flags & 1) allows backslash + to quote the single quote. This is to inhibit history expansion + inside $'...' containing an escaped single quote. + - change history_expand to call hist_string_extract_single_quoted + with flags == 1 if it sees $'. Fixes bug reported by Sean + Donner + + 9/2 + --- +builtins/printf.def + - add a call to sh_wrerror if ferror() succeeds in the PRETURN macro, + to print an error message in the case that the final fflush fails + (for instance, because it attempts to write data that didn't have a + trailing newline). Fixes bug reported by Stefano Lattarini + + + 9/7 + --- +arrayfunc.c + - some fixes to assign_compound_array_list to avoid null pointer + dereferences pointed out by clang/scan-build + +lib/glob/glob.c + - fixes to udequote_pathname and wdequote_pathname to avoid possible + null pointer dereferences pointed out by clang/scan-build + +lib/readline/undo.c + - fix to _rl_copy_undo_list (function unused) to avoid deref of + uninitialized pointer pointed out by clang/scan-build + +general.c + - fix string_to_rlimtype so it works if passed a null pointer (though + it never is) + +builtins/mapfile.def + - fix to mapfile() to avoid possible null pointer dereference pointed + out by clang/scan-build + +variables.c + - fix to valid_exportstr to avoid possible null pointer dereferences + pointed out by clang/scan-build + +bashline.c + - fix to bash_execute_unix_command to avoid possible null pointer + dereference if READLINE_LINE or READLINE_POINT is not bound + + 9/11 + ---- +[Prayers for the victimes of 9/11/2001] + +command.h + - add `rflags' member to struct redirect to hold private flags and + state information + - change redirector to a REDIRECTEE instead of int to prepare for + possible future changes + +{copy_cmd,dispose_cmd,make_cmd,print_cmd,redir}.c + - changes resulting from type change of `redirector' member of struct + redirect: change x->redirector to x->redirector.dest and add code + where appropriate to deal with x->redirector.filename + +make_cmd.h + - change extern declaration for make_redirection + +make_cmd.c + - first argument of make_redirection is now a `REDIRECTEE' to prepare + for possible future changes. First arg is now assigned directly to + redirector member instead of assigning int to redirector.dest + +{make_cmd,redir}.c,parse.y + - changes resulting from type change of first argument to + make_redirection from int to REDIRECTEE. In general, changes are + using REDIRECTEE sd and assigning old argument to sd.dest, then + passing sd to make_redirection + +make_cmd.[ch],parse.y + - add fourth argument to make_redirection: flags. Sets initial value + of `rflags' member of struct redirect + - changed all callers of make_redirection to add fourth argument of 0 + + 9/15 + ---- +parse.y + - change read_token_word to return REDIR_WORD for tokens of the form + {var} where `var' is a valid shell identifier and the character + following the } is a `<' or `>' + - add REDIR_WORD versions of all input and output file redirections + and here documents + +print_cmd.c + - change input and output file redirection direction and here + document cases of print_redirection to print a varname + specification of the form {var} when appropriate. Still need + to fix rest of cases + +redir.c + - implement REDIR_VARASSIGN semantics for file input and output + redirections and here documents + + 9/16 + ---- +parse.y + - added REDIR_WORD versions of remaining redirection constructs except + for err_and_out ones + +redir.c + - handle REDIR_VARASSIGN semantics for rest of redirection constructs + - accommodate REDIR_VARASSIGN when translating redirections + - new function, redir_varvalue, does variable lookup for {v} when + redirection needs the value (e.g., r_close_this) + +print_cmd.c + - fix rest of cases to print {varname} when REDIR_VARASSIGN is set in + redirect->rflags + +doc/{bash.1,bashref.texi} + - document new {varname} REDIR_VARASSIGN form of redirections + +tests/vredir.{right,tests},vredir[1-5].sub + - tests for new {varname} REDIR_VARASSIGN form of redirections + + 9/18 + ---- +subst.c + - new flags argument to split_at_delims: these flags are ORd with + SD_NOJMP and passed to skip_to_delim + - change skip_to_delim to honor new SD_NOQUOTEDELIM flag by not + checking whether or not single and double quotes are delimiters + if it's set in passed flags until after skipping quoted strings. + +subst.h + - change extern declaration for split_at_delims + - new define for SD_NOQUOTEDELIM flag + +pcomplete.c + - pass SD_NOQUOTEDELIM in flags argument to split_at_delims so single + and double quotes, even though they're in + rl_completer_word_break_characters, don't act as word delimiters + for programmable completion. Fixes bug reported by Freddy + Vulto + +lib/glob/glob.c + - in glob_filename, after recursively scanning a directory specified + with `**', turn off GX_ALLDIRS|GX_ADDCURDIR before calling + glob_vector on the rest of the pathname, since it may not apply to + the rest of the pattern. Turned back on if the filename makes it + appropriate. Fixes bug reported by Anders Kaseorg + +redir.c + - change execute_null_command to fork a child to execute if any of + the commands redirections have the REDIR_VARASSIGN flag set, since + those commands are not supposed to have side effects + +test.c + - < and > binary operators will obey the locale by using strcoll if + the TEST_LOCALE flag is passed to binary_test + +test.h + - new define for TEST_LOCALE + +execute_cmd.c + - execute_cond_node sets TEST_LOCALE so [[ str1 < str2 ]] (and >) + obey the locale. Fixes bug/incompatibility reported by Greg + Wooledge + +doc/{bash.1,bashref.texi} + - documented [[ command new locale-sensitive treatment of < and > + + 9/24 + ---- +configure.in + - add "darwin10" cases like darwin8 and darwin9 to handle linking with + included readline and history libraries + + 9/26 + ---- +lib/readline/display.c + - modify change of 7/24 to use prompt_physical_chars instead of + prompt_visible_length to account for visible multibyte characters in + the line (usually in the prompt). Fixes debian bug #547264 + reported by Pietro Battiston + - add flags argument to _rl_col_width; changed callers. flags > 0 + means that it's ok to use the already-computed prompt information; + flags == 0 means that we're expanding the prompt and we should not + short-circuit + +parse.y + - in decode_prompt_string, when expanding \w and \W on Mac OS X, + use fnx_fromfs to convert from "filesystem" form to "input" form. + This makes $PWD with multibyte characters work in the prompt + string on Mac OS X + +lib/sh/fnxform.c + - in fnx_fromfs and fnx_tofs, use templen instead of outlen as last + argument in calls to iconv, since outlen is used to keep track of + the size of the buffer, and iconv potentially modifies its + `outbytesleft' argument + + 9/29 + ---- +subst.c + - make skip_to_delim understand how to skip over process substitution + constructs the way it skips $(...) command substitution + + 9/30 + ---- +lib/readline/terminal.c + - don't set the `terminal has meta key' flag if the `MT' capability is + available; that means something completely different + + 10/1 + ---- +builtins/help.def + - make sure width is at least 7, since we pass `width/2 - 3' to strncpy + as the length argument. Terminal widths <= 6 are converted to 80. + Fixes bug reported by Chris Hall + +configure.in + - changed version to 4.1-alpha + +subst.h + - new flag for skip_to_delim: SD_NOSKIPCMD, which means to not skip + over embedded command and process substitutions, but rather to look + for delimiters within them + +subst.c + - implement semantics of SD_NOSKIPCMD in skip_to_delim + +bashline.c + - call skip_to_delim with SD_NOSKIPCMD from find_cmd_start, so + programmable completion can use the completion defined for `b' for + command lines like "a $(b c". Fixes inconsistency/bug reported by + Freddy Vulto + +parser.h + - replace unused PST_CMDTOKEN parser state value with PST_EXTPAT, + means currently parsing an extended glob pattern (extglob) + +parse.y + - fix cond_node() so that extended_glob is set before parsing the + rhs of the `==' or `!=' operators. For ksh93 compatibility. + - reset extended_glob to global value (saved in parse_cond_command()) + in reset_parser() + + 10/5 + ---- +jobs.c + - change waitchld() to only interrupt the wait builtin when the shell + receives SIGCHLD in Posix mode. It's a posix requirement, but + makes easy things hard to do, like run a SIGCHLD trap for every + exiting child. Change prompted by question from Alex Efros + + +doc/bashref.texi + - document new posix mode behavior about SIGCHLD arriving while the + wait builtin is executing when a trap on SIGCHLD has been set + + 10/6 + ---- +lib/readline/histexpand.c + - fix hist_expand to keep from stopping history expansion after the + first multibyte character (a `break' instead of a `continue'). + Fixes debian bug (#549933) reported by Nikolaus Schulz + + + 10/8 + ---- +builtins/read.def + - implement new `-N nchars' option: read exactly NCHARS characters, + ignoring any delimiter, and don't split the result on $IFS. + Feature requested by Richard Stallman + +doc/{bash.1,bashref.texi} + - document new `read -N' option + + 10/9 + ---- +lib/readline/bind.c + - new bindable variable, "enable-meta-key", controls whether or not + readline enables any meta modifier key the terminal claims to + support. Suggested by Werner Fink + +lib/readline/doc/{readline.3,rluser.texi},doc/bash.1 + - document new readline "enable-meta-key" bindable variable + + 10/10 + ----- +trap.c + - new function, free_trap_string(), does what it says and turns off + SIG_TRAPPED flag without changing signal disposition + +[bash-4.1-alpha frozen] + + 10/16 + ----- +builtins/mapfile.def + - return an error if the variable passed is not an indexed array. + Fixes bug reported by Nick Hobson + - change help text to make it clear that an indexed array is required + +doc/{bash.1,bashref.texi} + - changed description of mapfile to note that the array variable + argument must be an indexed array, and mapfile will return an + error if it is not + +subst.c + - change expand_string_unsplit and expand_string_leave_quoted to + add the (previously unused) W_NOSPLIT2 flag to the created word + - change expand_word_internal to understand W_NOSPLIT2 to mean that + we're not going to split on $IFS, so we should not quote any + characters in IFS that we add to the result string. Fixes bug + reported by Enrique Perez-Terron + - change cond_expand_word similarly. Fixes rest of bug reported by + Enrique Perez-Terron + +parse.y + - save and restore value of last_command_subst_pid around call to + expand_prompt_string in decode_prompt_string. Fixes bug that causes + $? to be set wrong when using a construct like false || A=3 when + set -x is enabled and $PS4 contains a command substitution. Reported + by Jeff Haemer + + 10/17 + ----- +execute_cmd.c + - in execute_in_subshell, make sure we set setjmp(return_catch) before + running the command, in case the command or its word expansion + calls jump_to_top_level. Fixes bug reported by Nils Bernhard + + +subst.c + - new PF_NOSPLIT2 flag for param_expand + - parameter_brace_expand takes a new `pflags' argument, before the + `output' parameters; passes to param_expand as necessary + - change parameter_brace_expand to call parameter_brace_expand_word + with the PF_NOSPLIT2 flag if the pflags argument to + parameter_brace_expand has it set + +parse.y + - change report_syntax_error to set last_command_exit_value to + EX_BADSYNTAX if parse_and_execute_level is > 0, indicating a + syntax error while we're executing a dot script, eval string, + trap command, etc. + +builtins/evalstring.c + - in parse_and_execute, if parse_command() returns non-zero, + indicating a parse error, print a warning message if the conditions + would require a posix-mode shell to abort (parse error in a `.' + script or eval string) + + 10/19 + ----- +builtins/evalfile.c + - even if the `check binary' flag is not passed to _evalfile, return an + error after reading 128 null characters if called by `source', on + the assumption that it's probably a binary file. [This will be in + bash-4.1-beta] + + 10/24 + ----- +[bash-4.1-alpha released] + +bashline.c + - don't call command_substitution_completion_function if we're + completing a substring delimited by a single quote. Fixes bug + reported by bash-bugs@atu.cjb.net + +lib/readline/complete.c + - make sure _rl_skip_completed_text defaults to 0, as the + documentation states (incorrect in bash-4.1-alpha) + - in insert_match, skip over a close quote in the replacement text if + the character at point when completion is invoked is a single + quote. Fixes complaint from bash-bugs@atu.cjb.net + + 10/26 + ----- +shell.c + - in main, make sure "$EMACS" is non-null before calling strstr on its + value. Fixes Red Hat bug 530911 submitted by Mitchell Berger + +builtins/mapfile.def + - don't save callback commands in shell history. Suggested by + Jan Schampera + +mailcheck.c + - in file_mod_date_changed, make sure the modification time is later + than the saved modification date, not just that it's not equal. + Fix from Evgeniy Dushistov + - in file_access_date_changed, make sure the access time is later + than the saved access time, not just that it's not equal + + 10/27 + ----- +builtins/shopt.def + - added new `compat40' compatibility variable, with associated changes + to shell_compatibility_level(), since the default compatibility level + is now 41 + +test.c + - make the < and > operators to [[ use strcoll() only if the shell + compatibility level is greater than 40 (it is 41 by default in + bash-4.1) + + 10/28 + ----- +support/shobj-conf + - decrease the default version of FreeBSD that creates shared libraries + to 4.x. Advice from Peter Jeremy + + 11/2 + ---- +parse.y + - change parse_comsub to free `heredelim' and set it to 0 whenever the + comsub scanner finds the end of a here document. Really need to + implement a stack of here doc delimiters like in the parser (can we + use redir_stack here, too?) + - fix parse_comsub to not attempt to read another here doc delimiter + after seeing a shell break character (that is not newline) if we + already have one. Fixes Debian bash bug #553485, submitted by + Samuel Hym + + 11/3 + ---- +variables.c + - fix bind_variable_internal to call a variable's dynamic 'set function' + with the right arguments depending on whether it's an associative + array, an indexed array, or a scalar. Fixes Ubuntu bug #471504 + https://bugs.launchpad.net/ubuntu/+source/bash/+bug/471504 reported + by AJ Slater + +[bash-4.1-beta frozen] + + 11/11 + ----- +builtins/printf.def + - in getintmax(), in the case of a conversion error, return the partial + value accumulated so far, which is suppose to be what + strtoimax/strtoll/strtol returns + + 11/17 + ----- +[bash-4.1-beta released] + + 11/18 + ----- +builtins/{common.h,shopt.def},shell.c + - changed shopt variable "set functions" to take the option name as + the first argument; changed function prototypes and callers + +builtins/shopt.def + - change set_compatibility_level() to turn off other compatNN options + when one is set -- enforce mutual exclusivity. Fixes problem noted + by Jan Schampera + + 11/19 + ----- +lib/readline/rltty.c + - make sure prepare_terminal_settings() tests for the presence of + ECHOCTL before using it. Fixes bug reported by Joachim Schmitz + + +config-top.h + - new WORDEXP_OPTION define (off by default) + +shell.c + - don't include the --wordexp option or the supporting function + (run_wordexp) if WORDEXP_OPTION is not defined. Suggested by + Aharon Robbins + +execute_cmd.c + - in execute_cond_node, turn on comsub_ignore_return if the flags + indicate we're ignoring the return value before calling + cond_expand_word. Fixes bug reported by Anirban Sinha + + + 11/20 + ----- +lib/sh/snprintf.c,builtins/printf.def + - change check for HAVE_ASPRINTF and HAVE_SNPRINTF to check if value + is 1 or 0 rather than whether they are defined or not. This allows + a value of 0 to enable function replacement + +configure.in,aclocal.m4 + - new autoconf macro, BASH_FUNC_SNPRINTF, checks for snprintf present + and working as C99 specifies with a zero length argument. Idea + from Greg Wooledge + - new macro BASH_FUNC_VSNPRINTF, does same thing for vsnprintf + + 11/25 + ----- +subst.c + - in command_substitute, only tell parse_and_execute to reset the line + number in an interactive shell if sourcelevel == 0 -- we'll use the + line numbers from the sourced file + +execute_cmd.c + - in execute_simple_command, only subtract function_line_number from + line_number if sourcelevel == 0. If sourcing, we'll use the line + numbers from the sourced file. Fixes bug reported by Hugo + Mildenberger + +builtins/declare.def + - in declare_internal, call bind_assoc_variable instead of + bind_array_variable in the case of declare -A foo=bar. Fixes bug + reported by Bernd Eggink . + + 11/27 + ----- +lib/readline/util.c + - change declaration for _rl_walphabetic to use prototype, assuming + that any system with multibyte characters has a compiler that can + handle prototypes. Fix for AIX compilation problem reported by + Nick Hillman + + 11/28 + ----- +execute_cmd.c + - make funcnest file-scope static and unwind-protect its value in + execute_function, so it can be used as a real measure of function + call nesting + +general.c + - fix off-by-one error in trim_pathname that caused it to short-circuit + when PROMPT_DIRTRIM == number of directories - 1. Fixes bug + reported by Dennis Williamson + + 11/29 + ----- +jobs.c + - when fork() returns -1/EAGAIN, call waitchld(-1, 0) so the shell can + reap any dead jobs before trying fork again. Currently disabled + until bash-4.2 development starts + +lib/readline/complete.c + - when incrementing _rl_interrupt_immediately, make sure it's greater + than 0 before decrementing it. In practice, not a problem, but + the right way to do it. Suggested by Jan Kratochvil + + +lib/readline/signals.c + - make sure rl_signal_handler doesn't set rl_caught_signal if + _rl_interrupt_immediately is set, so RL_CHECK_SIGNALS doesn't + cause it to be processed twice. Suggested by Jan Kratochvil + + - if the callback interface is being used, use the code path that + immediately handles signals. This restores the readline-5.2 + behavior. Fixes GDB readline bug reported by Jan Kratochvil + + + 12/18 + ----- +[bash-4.1-rc1 released] + + 12/22 + ----- +config-top.h + - don't have SYSLOG_HISTORY enabled by default + +lib/sh/Makefile.in + - add explicit dependency on pathnames.h for parallel make support + +externs.h + - add extern declaration for xtrace_fdchk + +lib/sh/snprintf.c + - add local prototype declarations for isinf, isnan if we are providing + local definitions + +lib/sh/fnxform.c + - add extern declaration for get_locale_var if HAVE_LOCALE_CHARSET not + defined + +execute_cmd.c + - define NEED_FPURGE_DECL so we pick up any extern declaration for + fpurge (e.g., if the system doesn't provide it) + +builtins/shopt.def + - correct prototype and declaration for set_shellopts_after_change so + it's the correct type for shopt_set_func_t + - add new function shopt_enable_hostname_completion that is the correct + type for shopt_set_func_t; just calls enable_hostname_completion and + returns its result + + 12/26 + ----- +doc/{bash.1,bashref.texi} + - add \E and \" escape sequences to ANSI-C quoting description. + Suggested by Aharon Robbins + + 12/29 + ----- +doc/bash.1 + - make sure shell and environment variable names are always in + `small caps' bold. Suggested by Aharon Robbins + + 12/30 + ----- +{execute_cmd.c,parse.y,Makefile} + - changes for building minimal configuration from Matthias Klose + + +[bash-4.1 frozen] + + 12/31 + ----- +[bash-4.1 released] + + 1/5/2010 + -------- +doc/bashref.texi + - document compat32 and compat40 shopt options. Omission pointed out + by Dilyan Palauzov + + 1/6 + --- +lib/readline/complete.c + - use `convfn' (converted filename) instead of entry->d_name (filename + read from file system) when adding partial or full completions to + the command line. Bug and fix from Guillaume Outters + + + 1/7 + --- +builtins/printf.def + - fix prototype in extern declaration for vsnprintf. Fix for bug + reported by Yann Rouillard + + 1/9 + --- +parse.y + - fix shell_getc to handle alias expansions containing quoted + newlines. Problems in bash-4.1 with aliases containing quoted + newlines in the middle of and at the end of their expansion. + Fix for bug reported by Jonathan Claggett + + - change mk_alexpansion to not append a space to an alias + expansion ending with a newline. Works with shell_getc + + 1/11 + ---- +lib/glob/Makefile.in + - add dependencies on shell.h and pathnames.h. From Mike Frysinger + + + 1/15 + ---- +doc/{bash.1,{bashref,version}.texi},lib/readine/doc/rluser.texi + - some typo fixes from Aharon Robbins + - added descriptions of ENV, COPROC, and MAPFILE variables + - added descriptions of READLINE_LINE and READLINE_POINT + + 1/21 + ---- +arrayfunc.c + - free `akey', the word-expanded index into the assoc array to avoid + mem leak in array_value_internal + - free index into assoc array in unbind_array_element + - change array_value_internal to take an additional argument: an + arrayind_t *. If not null, an index to an indexed array is + returned there. If not an indexed array or subscript is @ or + *, the value is unchanged + + 1/22 + ---- +builtins/ulimit.def + - include if we found it during configure and we don't + have resources. Fixes omission reported by Joachim Schmitz + + +{configure,config.h}.in + - check for , define HAVE_ULIMIT_H if found + +lib/sh/oslib.c + - include for extern declaration for kill(2) if + HAVE_KILLPG not defined + +jobs.c + - if HAVE_KILLPG is not defined, add an extern prototype decl for + killpg() + + 1/24 + ---- +print_cmd.c + - when printing here-string redirections, don't quote the string. The + original quotes, if any, are still in place and don't need to be + requoted. Fixes bug reported by Arfrever Frehtes Taifersar Arahesis + + +subst.c + - fix array_length_reference to return 0 for variables that have not + been assigned a value. Fixes bug reported by Mart Frauenlab + , but is not backwards compatible + +arrayfunc.[ch] + - change array_value to take a new arrayind_t *indp parameter like + get_array_value; changed extern prototype declaration + +subst.c + - changed callers of array_value to add extra parameter + +expr.c + - change expr_streval to set a new `lvalue' parameter with information + about the string being evaluated: string, value, array index (if + any), variable evaluated (if set). + - saving and restoring current context now saves and restores the + current `lvalue' + - new function expr_bind_array_element, binds an array element with an + already-computed index to a specified value + - anywhere we set the current token to a string (STR), save and set + the current lvalue + - change calls to expr_bind_variable to check whether or not the + current lvalue indicates an indexed array was evaluated, and, if so, + call expr_bind_array_element using the already-computed index + (curlval.ind). Fixes problems with dynamic variables (e.g., RANDOM) + in array indices with {pre,post}-{inc,dec}rement and op= + operators reported by + + 1/25 + ---- +expr.c + - fix subexpr() to initialize curlval and lastlval when resetting all + of the rest of the expression-parsing variables + + 1/26 + ---- +builtins/setattr.def + - in show_var_attributes, if the variable is not set (value == 0), + don't print `name=""', just print `name'. Pointed out by + Mart Frauenlab + +arrayfunc.c + - fix array_keys to return NULL if the variable is not set or + invisible. Pointed out by Mart Frauenlab + - change array_value_internal to return NULL for variable which has + not been set + + 1/30 + ---- +bashline.c + - in command_word_completion_function, don't call glob_pattern_p + on hint -- use the already-computed `globpat'. At this point, + hint might contain an already-dequoted globbing character, but + glob_matches will be NULL. Fixes bug reported by + coyote@wariat.org.pl + + 2/5 + --- +builtins/exec.def + - set extern variable "exec_argv0" to the argument to -a + +shell.c + - if exec_argv0 is set, set dollar_vars[0] to it and set it to NULL, + assuming it was set by `exec -a'. `exec -a foo' now sets $0 to + foo in an executable shell script without a leading `#!' (fixes + longstanding bug) + + 2/8 + --- +variables.c + - in push_func_var, if a variable is in a special builtin's temporary + environment and needs to be propagated because we're in Posix mode, + or we just need to propagate a variable, and we are executing in a + function without any local variables (so the function-local variable + context has no variable hash table), make sure we create a hash + table so we have a place to save the variable to be propagated. + Fixes bug reported by Crestez Dan Leonard . + + 2/18 + ---- +builtins/hash.def + - change add_hashed_command to remove the command being looked up from + the hash table before trying to add it. That way, if it's not found, + there won't be anything remaining in the hash table + + 2/26 + ---- +trap.[ch] + - move IMPOSSIBLE_TRAP_HANDLER define to trap.h so other parts of the + shell can use it + +parse.y + - change yy_readline_get to use IMPOSSIBLE_TRAP_HANDER instead of NULL + as a sentinel value for the SIGINT signal handler + - make sure yy_readline_get resets interrupt_immediately to 0 after + calling readline() using the same criteria it used to set it to 1 + before the call -- make the code symmetric. Suggested by Werner + Fink + +builtins/read.def + - move assignment to `retval' before decrement of interrupt_immediately + and terminate_immediately and call to discard_unwind_frame + - move assign_vars label before decrement of interrupt_immediately and + terminate_immediately so those variables get reset appropriately + if read -t times out + +subst.h + - new define for Q_DOLBRACE, indicates double-quoted ${...} + +subst.c + - in parameter_brace_expand, before calling parameter_brace_expand_rhs, + add Q_DOLBRACE to `quoted' if we're within double quotes. + - in expand_word_internal, if the Q_DOLBRACE flag is set, remove a + backslash escaping a }. Result of a Posix discussion on the + austin-group list + + 2/27 + ---- +variables.c + - new functions to save and restore the PIPESTATUS variable's internal + array: save_pipestatus_array and restore_pipestatus_array + +variables.h + - new extern declarations for save_pipestatus_array and + restore_pipestatus_array + +trap.c + - in run_pending_traps, _run_trap_internal, and run_exit_trap, save + and restore $PIPESTATUS while traps are running. Fixes bug + reported by Florian Bruhin + +parse.y + - use save_pipestatus_array and restore_pipestatus_array in + save_parser_state and restore_parser_state, respectively, replacing + inline code + +lib/readline/histfile.c + - fix callers of history_filename to be prepared to cope with it + returning NULL + - change history_filename to return NULL if $HOME is not set, rather + than trying to write the history file in the current directory. + This is the default directory, used only if the application does + not specify a history filename. Changed due to long-ago (unsent) + bug report from OpenBSD + +{Makefile,config.h,configure}.in,externs.h,lib/sh/{dprintf.c,Makefile.in} + - change fdprintf to dprintf, which is the Posix standard interface, + look for it with configure, replace it if not available + + 2/28 + ---- +command.h + - add new subshell flag, SUBSHELL_RESETTRAP. Indicates to the trap + builtin that the shell is executing a command substitution and + should free the trap strings we left unfreed by reset_signal_handlers() + +trap.c + - free_trap_string() and free_trap_strings() are now compiled in + +builtins/trap.def + - if changing a signal disposition and the SUBSHELL_RESETTRAP flag is + set in subshell_environment, free the trap strings left unfreed by + reset_signal_handlers + +subst.c + - in command_substitute, set the SUBSHELL_RESETTRAP flag. This change + is for Austin Group Posix interpretation 53 + (http://austingroupbugs.net/view.php?id=53) + + 3/7 + --- +lib/sh/{Makefile.in,strchrnul.c},Makefile.in + - implementation of strchrnul, from gnulib + +configure.in,config.h.in + - look for strchrnul and compile in version in lib/sh/strchrnul.c if + not available + - look for mbsnrtowcs and define HAVE_MBSNRTOWCS if available + +lib/sh/xmbsrtowcs.c + - new function, xdupmbstowcs2, fast version of xdupmbstowcs used when + mbsnrtowcs is available and the indices are not required. Called + from xdupmbstowcs as required. Initial patch from + <0xe2.0x9a.0x9b@gmail.com> + + 3/22 + ---- +print_cmd.c + - call print_deferred_heredocs virtually every time a recursive call + to make_command_string_internal is made so here documents get + printed correctly when they are attached to commands inside compound + commands such as for and while. Fixes bug reported by Mike + Frysinger + + 3/25 + ---- +builtins/printf.def + - fix have_precision case in PF macro to call printf with precision + instead of fieldwidth argument. Fixes bug reported by Rob Robason + + + 3/26 + ---- +trap.[ch] + - new function, signal_is_hard_ignored, returns true if the shell + inherited SIG_IGN as a signal's disposition + - new function, set_original_signal (sig, handler), provides interface + for rest of shell to set original_signals[sig] = handler + +execute_cmd.c + - execute_disk_command needs to call reset_terminating_signals in the + child process before resetting traps with restore_original_signals + +builtins/trap.def + - call initialize_terminating_signals before calling display_traps for + trap -p or trap without any other arguments. Possible future use + +lib/readline/complete.c + - rl_filename_completion_function needs to call + rl_filename_dequoting_function with `dirname' (which has already + been tilde-expanded) instead of `users_dirname', because it calls + opendir with `dirname'. Fixes bug reported by Stefan H. Holek + + + 3/27 + ---- +sig.c + - experimental change to set_signal_handler: when setting the SIGCHLD + handler, set the SA_RESTART flag so that interruptible system calls + get restarted after a child dies. Fixes bug reported by Tomas + Trnka , but needs further evaluation + +lib/sh/eaccess.c + - eaccess(2) apparently does only half the job: it does not check that + the permission bits on a file actually allow, for instance, execution. + Need to augment with a call to sh_stataccess if eaccess returns + success on FreeBSD. Fixes FreeBSD problem reported by Johan Hattne + + + 3/28 + ---- +parse.y,bashline.c,externs.h + - history_delimiting_chars now takes a const char * as an argument: + the line being added to the history. Changed callers + +parse.y + - bash_add_history should not add a semicolon separator if the current + history entry already ends in a newline. It can introduce syntax + errors (e.g., when it results in a null command before a close brace). + Fixes bug reported by Andreas Schwab + +parse.y + - history_delimiting_chars needs to return a newline instead of a + semicolon if it thinks the current line starts a here document + (if it contains `<<'). Also keeps track of the fact with a new + static variable, LAST_WAS_HEREDOC, so it can return the right + sequence of newlines later for the here-document body. Fixes bug + reported by Andreas Schwab + + 3/29 + ---- +lib/sh/eaccess.c + - if the system has faccessat, sh_eaccess will now use it in + preference to all other options + + 3/30 + ---- +subst.h + - new string_extract and extract_dollar_brace_string flag value: + SX_POSIXEXP, set if the shell is expanding one of the new Posix + pattern removal word expansions + +parser.h + - new definitions for "word expansion state", shared between parse.y + and subst.c + +subst.c + - include parser.h + + 4/9 + --- +builtins/declare.def + - make sure declare_internal calls bind_assoc_variable with newly- + allocated memory for the key argument when using an implicit key + of "0". Bug report and fix from Andreas Schwab + + + 4/14 + ---- +lib/readline/input.c + - restructure the rl_event_hook loop in rl_read_key to call the + event hook after rl_gather_tyi() returns and rl_get_char has + a chance to collect the input. Previous behavior was to call + the event hook before attempting to read input. Problem + reported by Anant Shankar + + 4/15 + ---- +builtins/fc.def + - fc_builtin needs to check whether the calculation of last_hist + leaves hlist[last_hist] == 0, and keep decrementing it until it + leaves a non-null history entry or goes < 0. Currently only + does this if saved_command_line_count > 0, indicating we're + trying to edit a multi-line command. Fixes bug reported by + Roman Rakus + + 4/17 + ---- +subst.c + - new process substitution helper functions: + unlink_fifo - closes a single FD or FIFO + num_fifos - returns number of open FDs or active FIFOs + copy_fifo_list - returns a bitmap of open FDs or active FIFOs + by index into appropriate list (dev_fd_list or fifo_list) + close_new_fifos - take a bitmap saved by copy_fifo_list and + call unlink_fifo on any FD or FIFO open at the time of the + call that is not marked as active in list + +execute_cmd.c + - execute_builtin_or_function: use new framework to close process + substitution FDs or FIFOs created by a shell builtin or shell + function. Fixes bug reported by Charles Duffy + +doc/{bash.1,bashref.texi} + - document 'C and "C constants for printf builtin + + 4/22 + ---- +lib/readline/complete.c + - new function to return screenwidth for use when displaying possible + matches: complete_get_screenwidth; changed uses of _rl_screenwidth + to use complete_get_screenwidth(). + - change complete_get_screenwidth to query (readline-private) + _rl_completion_colums, $COLUMNS, then _rl_screenwidth in that order + - change rl_display_match_list to deal with limit < 0 (which implies + that cols == 0) when _rl_screenwidth > 0 + +lib/readline/bind.c + - new bindable variable: completion-display-width, controls the + number of columns used when displaying completions with new + sv_compwidth function to call when value is set or unset + +lib/readline/doc/{readline.3,rltech.texi} + - documented completion-display-width variable + + 4/23 + ---- +execute_cmd.c + - change execute_in_subshell to reset trap handlers without freeing + the trap strings and set SUBSHELL_RESETTRAP. In line with Austin + Group interp #53 (trap in a subshell). + - ditto for execute_simple_command where it can be determined that + the shell is going to run a builtin or function in a subshell + +trap.c + - new function, get_all_original_signals, retrieves the original + signal disposition for all signals + +trap.h + - extern declaration for get_all_original_signals + +builtins/trap.def + - change showtrap to display signals that are "hard ignored" as + trap commands to ignore them, even though that trap command would + be a no-op. Partial fix for feature request from Siddhesh + Poyarekar + - change trap_builtin to call get_all_original_signals before displaying + traps. This will show inherited ignored signals. Rest of feature + request from Siddhesh Poyarekar + +lib/readline/histexpand.c + - fix history_tokenize_word so that it understands $(...) and the + <(...) and >(...) expansions as a single word + - change history_tokenize_word so that it understands extended shell + globbing patterns as a single word. Code is very similar to + $(...) code above. Bug reported by Rajeev V. Pillai + + + 4/24 + ---- +lib/readline/vi_mode.c + - add checks to rl_vi_char_search to make sure we've already done a + search if the command is `;' or `,', and return immediately if we + have not. Fixes bug reported by Eric Ho + +lib/readline/text.c + - make sure `dir' is in the valid range before searching in + _rl_char_search_internal. Range checks in the code depend on it + being non-zero + + 5/3 + --- +lib/readline/complete.c + - in rl_complete_internal, if show-all-if-ambiguous or + show-all-if-unmodified are set (what_to_do == '!' or '@', + respectively), and the common match prefix is shorter than the + text being completed, inhibit inserting the match. + The guess is that replacing text with a shorter match will not + be wanted + + 5/20 + ---- +lib/sh/unicode.c + - new file, with unicode character conversion-related code. Will be + used to implement \u and \U escapes where appropriate, and for + other unicode-related functions in the future + + 5/21 + ---- +builtins/printf.def + - add code to handle \u and \U escapes in format strings and arguments + processed by the %b format specifier + +lib/sh/strtrans.c + - add code to handle \u and \U escapes as unicode characters, works for + both `echo -e' and $'...' + +doc/{bash.1,bashref.texi} + - document new \u and \U escape sequences for $'...' and echo (printf + defers to the system's man page or Posix) + + 5/24 + ---- +execute_cmd.c + - change execute_disk_command to return a status, instead of just + leaving it in `last_command_exit_value', since the parent's return + value is sometimes used (e.g., when a restricted shell refuses to + run a command with a `/'). Fixes bug reported by David Pitt + + + 5/25 + ---- +bashline.c + - change bash completion functions to save and restore the value of + rl_ignore_some_completions_function, and set it to the bash default + of filename_completion_ignore where appropriate. Fixes bug + reported by Henning Bekel + +variables.c + - new convenience function: find_global_variable (name). Looks for + NAME in the global variables table, skipping any local and + temporary environment variables + +builtins/declare.def + - add new -g option to declare/typeset/local, forces variables to be + created or modified at the global scope when executing inside a + shell function. Requested by many, most recently by + konsolebox@gmail.com + + 5/27 + ---- +test.c + - added new `-v var' unary test operator; returns TRUE if var is set + (i.e., has been assigned a value). Works in both test builtin and + [[ conditional command + +doc/{bash.1,bashref.texi} + - documented new `-v var' unary conditional operator + +tests/test.tests + - added tests for new -v var operator + +builtins/kill.def + - change kill builtin so -PID (pgrp specification) following a + -s sig or -n sig option is not interpreted as a signal specification. + Fixes bug reported by Roman Rakus + +builtins/evalstring.c + - in parse_and_execute, if parse_command() returns non-zero, + indicating a parse error, exit the shell if the conditions require + a posix-mode non-interactive shell to abort (parse error in a `.' + script or eval string). Bash-4.1 only printed a warning. This is + from Austin Group interp 114 + +doc/bashref.texi + - add note to the posix mode section of the texinfo manual noting + the changed behavior for `.' and `eval' + +parse.y + - change time_command_acceptable to allow TIME token to appear after + BANG token (to allow `! time foo', which is supposed to be valid) + - change pipeline_command production to allow multiple instances of + `!' (which toggle inverting the return status) and `time' (which + have no effect) + +execute_cmd.c + - In posix mode, `time' without a following pipeline prints the + elapsed user, system, and real time for the shell and its + children since the shell was invoked. + It's like `times' but obeys the setting of TIMEFORMAT. A future + revision of Posix will require this + +doc/{bashref.texi,bash.1} + - document new posix mode use of `time' + +parse.y + - add production to pipeline_command that permits `!' by itself to + be equivalent to `false' (and, with the changes above, permits + `! !' to be roughly equivalent to `true'). A future revision of + Posix will require this + + 5/28 + ---- +parse.y + - fix \W prompt expansion to use memmove instead of strcpy, since the + source and target strings overlap (though you think it wouldn't + matter, since the overlapping regions are never touched at the same + time). Fixes bug reported by Stéphane Jourdoi + + +parse.y + - Posix interp 217 states that $(( must be parsed first as an + arithmetic expansion, so avoid attempting to parse it as a nested + command substitution. Fixes bug reported by several, most recently + + +subst.c + - change extract_delimited_string to process nested $( as a possible + command substitution, but only if already parsing an arithmetic + expansion. Rest of fix for Posix interp 217 + - change parameter_brace_expand_rhs to make the := expansion operator + perform quote removal and both assign the result to the variable and + return it as the result of the expansion, rather than assign the + value after quote removal but return the value before quote removal. + Posix interp 221 + - introduce new internal quoting flag: Q_DOLBRACE. Denotes a double- + quoted ${...} expansion. In this case, Posix interp 221 requires + that a backslash quoting an embedded `}' be removed, even though it's + not one of the characters marked as special inside double quotes. + Set in parameter_brace_expand, used by expand_word_internal. + +parse.y + - introduce new parsing state, P_DOLBRACE, set when parsing a ${...} + expansion + - set a "dolbrace operator state" in parse_matched_pair to decide + whether the lexer is reading the param, op, or word in + ${paramOPword}. Will be used to decide whether or not to treat + single quotes specially in a double-quoted "${...} + + 5/29 + ---- +parse.y + - change parse_matched_pair so that a single quote appearing in a + double-quoted ${...} expansion is not special unless the expansion + operator is `#[#]' or `%[%]'. Posix interp 221 + +subst.c + - change string_extract_double_quoted so that a single quote appearing + in a double-quoted ${...} expansion is not special unless the + expansion operator is `#[#]' or `%[%]'. Posix interp 221 + +doc/bashref.texi + - document posix-mode effects of Posix interp 221 + - add section describing GNU parallel as requested by Stallman + +lib/readline/complete.c + - broke code that compares filenames read from the file system (and + possibly converted) to words being completed out into a separate + function: complete_fncmp + - augment complete_fncmp to treat hyphen and underscore as equivalent + when comparing filenames if _rl_completion_case_map is set + +lib/readline/rlprivate.h + - new extern declaration for _rl_completion_case_map + +lib/readline/util.c + - change _rl_strnicmp to return the difference between the characters, + like strcasecmp, and not modify the pointers it is passed + - change _rl_stricmp to not modify the pointers it is passed + +lib/readline/bind.c + - new bindable variable, "completion-case-map", toggles value of + _rl_completion_case_map + +lib/readline/doc/{rluser.texi,readline.3} + - document new bindable readline variable "completion-case-map" + +execute_cmd.c + - change execute_function to reset funcnest and jump back to top level + if funcnest exceeds funcnest_max + - use funcnest_max as a max function nesting level, if set to numeric + value greater than 0 (defaults to 0, so inactive) + +variables.c + - new variable FUNCNEST, controls funcnest_max value if set to numeric + value > 0 +sig.c + - reset funcnest to 0 when throw_to_top_level occurs + +doc/{bash.1,bashref.texi} + - document FUNCNEST variable and its effect on function execution + +lib/readline/funmap.c + - add new bindable command names to avoid case-insensitive matching + problems between, for instance, vi-fword and vi-fWord: + + vi-forward-word + vi-forward-bigword + vi-backward-word + vi-backward-bigword + vi-end-word + vi-end-bigword + + Suggested in a different form in 2006 (!) by Servatius Brandt + + +builtins/mapfile.def + - run_callback now takes a new third argument: curline, the line + currently being read and about to be assigned + - the callback function/command now takes an additional argument: + the line to be assigned to the array index. Feature suggested by + Dennis Williamson + +doc/{bash.1,bashref.texi} + - document new additional `line' argument to mapfile callback + + 5/30 + ---- +builtins/printf.def + - add new %(fmt)T format specifier, where FMT is a strftime format. + Argument is number of seconds since the epoch, with -1 meaning + current time (roughly date +%s) and -2 meaning shell start time + (roughly $SECONDS, unless it's been assigned a value or unset). + Fieldwidth and precision are preserved, strftime result is printed + as with %[-][[fieldwidth][.[precision]]]s + +doc/{bash.1,bashref.texi} + - document new %(datefmt)T printf format specifier and special + arguments + +builtins/hash.def + - don't permit programs with slashes to be entered into the hash table + at all, even with the -p option. Inconsistency pointed out by + Jan Schampera + +builtins/shopt.def + - add `compat41' option in preparation for bash-4.2 + + 6/6 + --- +lib/readline/vi_mode.c + - finish restructuring rl_vi_domove and the functions that call it so + it works in callback mode, including numeric arguments. Requested + a long time ago by Bob Rossi + +lib/readline/callback.c + - arrange to call appropriate callback when readline state indicates + RL_STATE_VIMOTION, so vi motion commands like `cw' and `d2w' are + handled in callback mode + +lib/sh/wcswidth.c + - replacement wcswidth implementation + +aclocal.m4 + - add REPLACE_FUNCS(wcswidth) to BASH_CHECK_MULTIBYTE + +execute_cmd.c + - fix select_query and print_index_and_element to compute correct + display width of select list elements in presence of multibyte + characters. Bug reported by Bernd Eggink + +builtins/cd.def + - add posix-mandated -e option; currently ignored in most circumstances + +doc/{bash.1,bashref.texi} + - document new `cd -e' option + + 6/12 + ---- +arrayfunc.c + - change array_value_internal to treat negative subscripts to indexed + arrays, offset from array_max_index(x) + 1, so foo[-1] is the last + element of $foo + +subst.c + - Change verify_substring_values to allow negative length specifications + when using string variables or array members. Negative lengths + mean to return characters from OFFSET until (${#var} - N) for + {var:offset:-N}. Feature requested by Richard Neill + + +doc/{bash.1,bashref.texi} + - document new behavior of negative subscripts to indexed arrays + - document new behavior of negative LENGTH in substring expansion + +configure.in + - change version to bash-4.2-devel + +variables.c + - make sure initialize_shell_variables calls sv_xtracefd if + BASH_XTRACEFD is inherited in the shell environment. Fixes but + reported by + + 6/13 + ---- +lib/readline/complete.c + - change get_y_or_n to always return 1 when in callback mode, so we + don't do a blocking read. Have to wait until readline-7.0 to add + a state so we can use callbacks, since that will change public + interface + + 6/17 + ---- +subst.c + - fix memory leak in parameter_brace_expand: when performing pattern + removal with parameter_brace_remove_pattern, make sure `name' is + freed. Fixes bug reported by oyvindh@dhampir.no + + 6/23 + ---- +{parse.y,subst.c} + - make the ${param//pat/rep}, ${param^pat}, and ${param,pat} expansions + require single quotes and double quotes to match when within double + quotes. This way every expansion except the Posix ones behaves as + bash has always behaved + +subst.c + - change remove_upattern and remove_wpattern to return their first + argument if nothing matches, change callers to allocate memory + appropriately + - change remove_pattern to short-circuit and return copy of PARAM + if remove_wpattern returns its first argument (indicating no match) + rather than convert back to multibyte string, allocating new memory + twice and calling wcsrtombs + + 6/24 + ---- +execute_cmd.c + - add missing initializers for sh_coproc to eliminate a compiler + warning. Patch from Werner Fink + + 6/27 + ---- +parse.y + - add `TIMEIGN' token to handle `time -p -- ...'. Pointed out by + Laszlo Ersek on austin-group list + + 6/28 + ---- +jobs.c + - treat a shell with (subshell_environment&SUBSHELL_PIPE) != 0 like + a command substitution in wait_for and act like we received a + SIGINT if a job we're waiting for dies of SIGINT. Fixes bug + reported by Ilya Basin + + 7/2 + --- +jobs.c + - if fork() fails in make_child, try to reap some dead children before + retrying + +execute_cmd.c + - change execute_pipeline to run the last command of a non-asynchronous + pipeline in the current shell environment if the `lastpipe' shell + option is enabled and job control is not active. Code from + Werner Fink + +parse.y + - Posix says (issue 267) that time is not recognized as a keyword + if the next token begins with a `-' + +doc/{bash.1,bashref.texi} + - changed the descriptions of BASH_SOURCE, BASH_LINENO, and FUNCNAME + as proposed in Ubuntu bug 591677. + - document new `lastpipe' shell option that runs last command of a + pipeline in the current shell environment + - document new posix-mode behavior with `time -p' + + 7/5 + --- +aclocal.m4 + - new autoconf test WEXITSTATUS_OFFSET, bit offset in status word + returned by wait() of the process's exit status + +jobs.[ch] + - change stop_pipeline to return the actual index of the job just + created and added to the jobs table, instead of the current job + - job_exit_status and job_exit_signal are now global functions, with + extern declarations in jobs.h + - append_process: new utility function for use by the lastpipe code, + takes info, creates a PROCESS from them, and adds it to the end of + the passed job id's pipeline. lastpipe code uses it to add a dummy + process for the last command in the pipeline + - freeze_jobs_list: new utility function so rest of shell can freeze + the jobs list. Used by the lastpipe code + +execute_cmd.c + - changes to lastpipe code to make `pipefail' option, $PIPESTATUS, and + $? work correctly. Uses append_process and job_exit_status + + 7/10 + ---- +subst.c + - when performing pattern substitution word expansions, a `&' in the + replacement string is replaced by the text matched by the pattern. + The `&' can be quoted with a backslash to inhibit the expansion. + CURRENTLY DISABLED + + 7/13 + ---- +pcomplib.[ch] + - new member for struct compspec: lcommand. for future use + + 7/15 + ---- +parse.y + - fix problem in parse_comsub where extra space was added to here-doc + delimiter if the first word in the comsub contained a `/'. Fixes + bug reported by Alex Khesin + + 7/20 + ---- +parse.y + - change reserved_word_acceptable to return success if the last two + tokens read were `function WORD'. Allows function definitions like + function good [[ -x foo ]];. Fixes bug reported by Linda Walsh + + +doc/{bash.1,bashref.texi} + - change function definition meta-syntax to make it clearer, rather + than let the text note the optional portions + + 7/24 + ---- +bashhist.c + - change bash_history_inhibit_expansion() to suppress history expansion + for $! parameter expansion. Fixes debian bug #589745 submitted by + Frank Heckenbach + +lib/readline/terminal.c + - change rl_resize_terminal to always fetch the new terminal size and + only force the redisplay if _rl_echoing_p is non-zero. Fixes bug + reported by Balazs Kezes + + 7/25 + ---- +lib/readline/xfree.c + - new file, contains definition of xfree moved from xmalloc.c + + 7/28 + ---- +variables.c + - check suspect return values from bind_variable before trying to use + the returned SHELL_VAR *. Changes to: initialize_shell_variables, + bind_int_variable, FIND_OR_MAKE_VARIABLE. Fixes bug reported by + Roman Rakus + + 7/31 + ---- +lib/readline/rltty.c + - fix rl_prep_terminal and rl_deprep_terminal to use fileno(stdout) + if rl_instream is NULL. Fixes bug reported by Otto Allmendinger + otto.allmendinger@googlemail.com + + 8/2 + --- +lib/sh/casemod.c + - if the passed string is NULL or empty, return it immediately. Fixes + bug reported by Dennis Williamson + +subst.c + - fix pat_subst to cope with the passed string being NULL + +arrayfunc.h + - added flag values for array_value_internal and its callers; converted + array_value_internal `allow_all' parameter into a general flags word + - get_array_value now takes a flags value + - changed array_value internal to use *indp as an index to use if the + AV_USEIND flag is set, rather than recomputing it + +subst.c + - get_var_and_type takes two new parameters: a flags word and an index + that represents an already-computed index for an array reference + (just indexed arrays so far). Index is used and passed to array_value + if flags includes AV_USEIND + - parameter_brace_expand_word takes a new argument: the already- + computed index; returns W_ARRAYIND if word expanded is being used + as an array index + - changed parameter_brace_casemod, parameter_brace_patsub, + parameter_brace_substring, parameter_brace_remove_pattern to take new + flags and index arguments from parameter_brace_expand_word. They + pass the new parameters along to get_var_and_type to use an + already-computed array index if necessary. Fixes bug where array + indexes are computed twice reported by Andrew Benton + + +doc/bash.1,lib/readline/doc/{history.3,hsuser.texi} + - modified description of history event designators to clarify that + all non-absolute event designators are relative to the current + position in the history list. Question raised by Frank + Heckenbach as debian bash bug 590012 + + 8/5 + --- +subst.c + - remove code that does not add a quoted null when the input string + is partially quoted; subsequent word splitting may require it. + Fixes bug reported by Eric Blake + + 8/12 + ---- +lib/glob/gmisc.c + - move match_pattern_wchar and match_pattern_char to new file in + glob library + - new functions: wmatchlen(pat, max) and umatchlen(pat, max), computes + number of characters PAT will match. Returns the number of chars + that will be matched or -1 if the match length is indeterminate + (i.e., contains a `*') + +subst.c + - use umatchlen/wmatchlen in match_upattern/match_wpattern to bound + the number of match attempts in large strings to (usually) one, + depending on match length. Fixes performance problems with + pattern substitution in large strings noted by Yi Yan + . Can be applied to remove_[uw]pattern also + + 8/13 + ---- +bashhist.c + - in maybe_append_history, change check for history_lines_this_session + so that we append the lines to the file if it's equal to the value + returned by where_history(). This means that without this change, + the history won't be appended if all the lines in the history list + were added in the current session since the last time the history + file was read or written. Fixes bug reported by Bruce Korb + + +shell.h,parse.y + - add prompt_string_pointer to the parser_state struct saved and + restored by {save,restore}_parser_state. Fixes both bugs exposed + by bash_completion and completion of open backquotes reported by + Egmont Koblinger + +subst.h + - new flag for skip_to_delim: SD_EXTGLOB. Skip extended globbing + patterns while looking for ending delimiter + +subst.c + - when passed the SD_EXTGLOB flag, skip_to_delim skips over extended + globbing patterns (when extended_glob is set) while looking for a + character in the delimiter set + +pathexp.c + - split_ignorespec: new function to replace calls to extract_colon_unit + in setup_ignore_patterns. uses skip_to_delim with the SD_EXTGLOB + flag to skip over extended globbing patterns in variables like + HISTIGNORE and GLOBIGNORE. Fixes bug reported by Dimitar DIMITROV + and Greg Wooledge + + 8/28 + ---- +lib/readline/rlprivate.h + - add members to search_cxt to save _rl_keymap + - new flag for isearch context: SF_CHGKMAP, set if we changed the + keymap while reading a character for the search string that + translated to a command + +lib/readline/isearch.c + - save current readline keymap in cxt->keymap and cxt->okeymap + in _rl_scxt_alloc + - in _rl_isearch_dispatch, only check for cxt->lastc as a member of + cxt->search_terminators if it's > 0 (i.e., not an isearch opcode) + + 9/3 + --- +support/signames.c + - add Solaris SIGJVM1 and SIGJVM2. Update from Stefan Teleman + + +shell.c + - instead of closing all fds 3-20 at shell startup, just set them to + be close-on-exec. Report from Rainer Mülle + +lib/readline/isearch.c + - in _rl_isearch_dispatch, if the current character maps to ISKMAP, + move to the indicated keymap (using cxt->keymap) and go on to + read another character. Fixes problem reported by Davor + Cubranic + - in _rl_isearch_dispatch, after translating key to possible opcode, + restore _rl_keymap from cxt->okeymap if necessary + - in _rl_isearch_dispatch, use key sequences that map to default + functions that ^G, ^W, and ^Y map to as equivalent to those chars + +lib/readline/complete.c + - new variable, _rl_menu_complete_prefix_first, zero by default + - change menu_complete to display common prefix (matches[0]) first + before cycling through rest of match list if + _rl_menu_complete_prefix_first is non-zero. Suggested by Sami + Pietila + +lib/readline/bind.c + - new bindable readline variable, "menu-complete-display-prefix", + controls setting of _rl_menu_complete_prefix_first + +doc/{bash.1,bashref.texi},lib/readline/doc/{readline.3,rluser.texi} + - added description of menu-complete-display-prefix bindable + readline variable + + 9/17 + ---- +configure.in + - remove AM_PATH_LISPDIR call since we don't use that bash debugger + any more. Suggested by Mike Frysinger + + 10/6 + ---- +findcmd.c + - change executable_file to set errno to EISDIR if the passed name + is a directory + +builtins/exec.def + - change exec_builtin to report appropriate error message if the + file argument is a directory. Noted by Eric Blake + in a message to austin-group + +builtins/source.def + - change source_builtin to make sure the shell exits if the file is + not found when in a non-interactive shell running in posix mode + and source_searches_cwd == 0 (as posix mode makes it by default). + Pointed out in http://thread.gmane.org/gmane.comp.shells.dash/291/focus=392 + by Jilles Tjoelker + +execute_cmd.c + - set executing_command_builtin in execute_builtin if the builtin is + command_builtin. Unwind-protected in execute_function_or_builtin + (like executing_builtin variable). Available for rest of shell + +builtins/{source.def,evalfile.c} + - make sure that non-interactive posix mode shells exit if the file + argument to `.' is not found only if they are not being executed + by the command builtin (executing_command_builtin == 0). This is + how `command' can cancel effects of special builtin exit properties + in the case of `dot file not found' + + 10/13 + ----- +lib/sh/strtrans.c + - pass \c through unchanged if not escaping for `echo -e' and they are + the final two characters in the string + + 10/15 + ----- +subst.c + - extract_dollar_brace_string: fix problem with single quotes + in unquoted ${...} for Posix compliance + + 10/16 + ----- +builtins/exec.def + - catch return value from shell_execve; don't print duplicate error + message if return value is EX_NOTFOUND. Make sure exit status + from exec is 127 if command is not found + +execute_cmd.c + - fix typo (`saved_redirects' should be `saved redirects') in + execute_function_or_builtin `command exec' case. Typo caused + too much of the unwind-protect stack to be discarded + - in same execute_function_or_builtin case, don't discard the + `saved redirects' frame unconditionally; only discard it if + saved_redirects is non-null in the `command exec' case. Fixes + sh -c 'command exec; exit 1' hanging bug uncovered by FreeBSD + sh test cases + + 10/18 + ----- +subst.c + - when in posix mode, shell should not exit if a variable assignment + error (e.g., assigning to readonly variable) occurs preceding a + command that is not a special builtin. Fixes bug uncovered by + FreeBSD sh test cases + - when in posix mode, the ${!?} and ${!#} expansions are not indirect + expansions, but posix word expansions involving the `!' variable + +parse.y + - fix parse_comsub so that it does not skip backslash-newline when + parsing a comment + + 10/19 + ----- +subst.c + - fix parameter_brace_expand so that an attempt to use the % or # + expansions on an unset variable with -u set will cause a non- + interactive shell to abort. Posix change + - fix parameter_brace_expand so that an attempt to use pattern + substitution or case modification expansions on an unset variable + with -u set will cause and unbound variable error and make a + non-interactive shell abort + - change parameter_brace_expand_length to return INTMAX_MIN if a + positional parameter is unset and -u is set + - if parameter_brace_expand_length returns INTMAX_MIN when -u is set, + treat it as an unbound variable error and make a non-interactive + shell abort. Posix change + - change parameter_brace_expand_length to return INTMAX_MIN if an + implicit reference to array[0] is made ${#array} and array[0] is + not set when -u is set + + 10/20 + ----- +builtins/cd.def + - Posix 2008 says that if no matching directories are found in $CDPATH, + use the directory name passed as an operand and go on. Posix change + +doc/bashref.texi + - change Posix mode section with latest additions and removals + + 11/4 + ---- +lib/readline/complete.c + - fix rl_menu_complete and rl_old_menu_complete to keep incrementing + match_list_index by match_list_size as long as it's < 0. Fixes + bug reported by jeenuv@gmail.com + +braces.c + - make mkseq() take intmax_t arguments for sequence start and end + and make sure it's passed intmax_t values. Fixes bug reported by + Pete Gregory + +sig.c + - if termsig_handler is called when terminate_immediately == 1, + assume we're being called as a signal handler and set + history_lines_this_session to 0 to inhibit history file being + written on shell exit. Fixes long-standing bug most recently + observed by Andreas Schwab + + 11/5 + ---- +redir.c + - add_undo_close_redirect now returns int, 0 on success, non-zero on + failure. Currently always succeeds + - new macro REDIRECTION_ERROR to make do_redirection_internal return + value of errno + - change do_redirection_internal to call REDIRECTION_ERROR after + saving file descriptor and make do_redirection_internal return error + if add_undo_redirect or add_undo_close redirect fails. This makes + failure to save a file descriptor a redirection error and the shell + behaves appropriately. Fixes bug reported by Eric Blake + + +bashline.c + - modify bash_forward_shellword to correctly handle quoted strings, + especially if point is in a quoted string when function is invoked. + Fixes bug reported by Daniel Colascione + +configure.in + - change version to 4.2-alpha + + 11/7 + ---- +lib/readline/text.c + - in rl_insert, if we're not in the multibyte code path, don't try to + optimize and insert all of the available typeahead input if we're + reading input from a macro. Fixes bug reported by Andre Majorel + + +lib/readline/text.c + - break out multibyte guts of rl_forward_char into a separate function + _rl_forward_char_internal that does nothing but calculate the new + value of point + - change rl_forward_char to call _rl_forward_char_internal instead of + having equivalent code inline + +lib/readline/rlprivate.h + - new extern declaration for _rl_forward_char_internal + +lib/readline/vi_mode.c + - change _rl_vi_append_forward to call _rl_forward_char_internal to + set rl_point, instead of calling rl_forward_char. When at the end + of the line, rl_forward_char will ring the bell. Fixes debian + bash bug 601042, reported by Alan J. Greenberger + + 11/14 + ----- +subst.c + - fix match_upattern to use correct test to immediately break out of + loop (when potential match length is greater than number of chars + remaining in the string) in MATCH_ANY case + + 11/15 + ----- +subst.c + - include "typemax.h" to make sure we have a definition of INTMAX_MIN + + 11/16 + ----- +lib/sh/unicode.c + - make sure `localconv' isn't declared on machines without iconv + - add stub_charset for systems that don't have locale_charset: looks + up LC_CTYPE, returns everything after last `.', "UTF-8" if the + value is exactly "UTF-8", and "ASCII" otherwise + + 11/20 + ----- +lib/readline/vi_mode.c + - in rl_domove_motion_callback, make sure to use m->key instead of + key, which is not initialized and should not be used. Bug report + from Andreas Schwab + - in rl_vi_domove, make assignment to `m' explicit instead of + relying on evaluation order semantics, since the C standard leaves + them unspecified. Bug report from Andreas Schwab + + + 11/21 + ----- +lib/sh/shquote.c + - sh_single_quote and sh_double_quote now take a const char * + argument. Fixes problem pointed out by Joachim Schmitz + + +externs.h + - change extern declarations for sh_single_quote and sh_double_quote + +lib/sh/strchrnul.c + - make sure that return value is cast to (char *) if we're using a + part of the passed (const char *) argument. Fixes problem pointed + out by Joachim Schmitz + +lib/glob/gmisc.c + - fix a typo that mixed up defines for LPAREN and RPAREN. Bug and + fix from Andreas Schwab + - use WLPAREN and WRPAREN in multibyte character environments + - fixed typos using L'cc' in a non-wide-char environment + +lib/readline/complete.c + - fix rl_filename_completion_function to dequote users_dirname if + there is a filename dequoting function (as well as dirname), since + users_dirname gets tacked back onto the beginning of the possible + completions and then requoted. Bug reported by Andreas Schwab + + + 11/22 + ----- +lib/readline/parens.c + - the `blink-matching-paren' variable should default to off + + 11/23 + ----- +subst.h + - add extern declaration for close_new_fifos() + +lib/sh/fnxform.c + - fix curencoding to return the character past the `.', not a string + beginning with `.' + +lib/sh/unicode.c + - fix stub_charset to do the same cut-off at `@' as curencoding(). + These two functions should be combined + +builtins/printf.def + - document new %(datefmt)T modifier in help text + + 11/24 + ----- +parse.y + - fix `W' case in decode_prompt_string: memmove was copying one too + few bytes and missed the closing NUL. Bug report from Tim Mooney + + + 11/26 + ----- +subst.c + - in expand_word_internal, don't add quoted nulls to partially- + quoted strings if the word will not be subjected to word splitting + later (which will remove the quoted null). Fixes bug reported by + Rocky Bernstein + + 11/28 + ----- +subst.c + - change multibyte case of match_pattern to revert to match_upattern + if neither the pattern nor the string has any multibyte characters + +alias.c + - fix tests of backslash-escaped characters in skipquotes, skipws, + rd_token to check for backslash at EOS and not go past the end. + Fixes debian bug 603696 reported by Tim Small + +include/shmbchar.h + - new file, mbchar.h from gnulib minus the include + +lib/sh/shmbchar.c + - new file, mbchar.c from gnulib with additions + - moved mbstrlen from subst.c to here, changed initialization of mbs + - change mbstrlen to use is_basic to avoid calls to mbrlen for ASCII + chars; code hints from gnulib + - don't copy mbs and mbsbak if we're not calling mbrlen + + 11/29 + ----- +lib/glob/smatch.c + - change xstrmatch to use internal_strmatch() if the pattern and + string don't have any multibyte characters + + 11/30 + ----- +include/shmbutil.h + - change ADVANCE_CHAR and ADVANCE_CHAR_P macros to use is_basic and + only call mbrlen and copy state and state_bak if is_basic returns + false (non-ASCII). Called all over the place. + - change rest of macros except BACKUP_CHAR and BACKUP_CHAR_P in the + same way + + 12/2 + ---- +subst.c + - audit all calls to string_list and make sure caller can handle a + NULL return value. Fixes bug reported by David Rochberg + + +general.h + - change sh_wassign_func_t to take an additional argument: an int + flags word + +subst.c + - change do_word_assignment to take an additional argument to match + wassign_func_t; change callers + - change call to (*assign_func) in expand_word_list_internal to match + new wassign_func_t prototype + - (*assign_func) passes 1 as additional arg if the simple command is + a builtin or function, in which case the assignment to the + temporary env should take effect + +variables.c + - change assign_in_env to take an additional argument to match + wassign_func_t; change callers + - move call to sv_ifs from dispose_temporary_env to + dispose_used_env_vars; we don't need to do it if called from + merge_temporary_env + + 12/3 + ---- +variables.c + - change dispose_temporary_env to maintain a list (tempvar_list) of + variables that need to be handled specially. If a variable that + gets freed by push_temp_var or propagate_temp_var is one of the + variables that the shell handles specially (IFS, LANG, etc.), it's + stored on the list. For each variable in this list, + dispose_temp_var calls stupidly_hack_special_variables. + - assign_in_env calls stupidly_hack_special_variables if flags arg + is non-zero, so variable assignments affect current shell + execution environment if a builtin or function is being executed. + Fixes bug reported by Bruno Haible + + 12/5 + ---- +subst.c + - use mbsmbchar on both string and pattern in match_pattern instead + of strlen and mbstrlen; only go through the strings once + + 12/6 + ---- +lib/readline/kill.c + - in rl_yank_last_arg, only switch directions if the `count' + argument is < 0, not < 1. This makes explicit count arguments of + 0 work as expected. Fixes bug reported by Dennis Williamson + + +doc/bash.1,lib/readline/doc/{readline.3,rluser.texi} + - fix documentation for yank-last-arg to make it clear how the count + argument is set and how second and subsequent calls treat any + numeric argument + +doc/{bash.1,bashref.texi} + - slight changes to the description of test + - change \(bv to `|'; it seems that many `internationalized' versions + of groff don't render that as a vertical bar. Fixes Debian bug + 603805 + + 12/10 + ----- +configure.in + - changed release status to 4.2-beta + + 12/14 + ----- +[bash-4.2-beta frozen] + + 12/18 + ----- +redir.c + - change REDIRECTION_ERROR macro to accept a third argument: an + additional file descriptor to close before returning and error (pass + -1 to do nothing) + - change calls to REDIRECTION_ERROR to close appropriate file + descriptors. Fixes bug reported by Andreas Schwab + + - make sure to close any file descriptors opened for REDIR_VARASSIGN + before returning an error + + 12/19 + ----- +expr.c + - move processing of unary `-' and `+' to exp1 from exp0 to avoid + precedence problems. Fixes bug reported by <12bric@gmail.com> + + 12/22 + ----- +lib/sh/fpurge.c + - updated version from gnulib, inlined gnulib stdio-impl.h + + 12/24 + ----- +doc/bash.1 + - change the description of while and until to use `list-1' and + `list-2', similar to the Posix description. Suggested by + Jeff Haemer + + 12/27 + ----- +execute_cmd.c + - slight changes to execute_command_internal and how it captures the + exit status of (command) and shell control structures with pipes to + avoid multiple variable assignments to last_command_exit_value + - change to execute_simple_command so that parent branches of shells + forked to execute commands in pipelines don't change $? to 0 + (if (pipe_out != NO_PIPE) result = last_command_exit_value). Fixes + bug reported by Damien Nadà + + 12/28 + ----- +configure.in + - changed version to bash-4.2-rc1 + + 1/2/2011 + -------- +lib/readline/complete.c + - fix rl_filename_completion_function to dequote and save users_dirname + before calling any function to transform the directory name passed + to opendir(). Fix from Andreas Schwab + +lib/readline/doc/ + - make sure to note that rl_directory_completion_hook cannot modify + the directory name argument if it returns 0 + +bashline.c + - make sure that bash_directory_completion_hook consistently returns + non-zero whenever it modifies its directory name argument + +lib/readline/terminal.c + - don't bother with the declarations (extern or not) for PC, BS, and + UP if NCURSES_VERSION is defined, since ncurses defines local + versions of those symbols in the library. Fixes bug most recently + reported by Kevin Scott against Mac OS X + +include/filecntl.h + - make sure O_TEXT and O_BINARY are defined to avoid Windows-specific + (or cygwin-specific) code. This and the following changes from + Eric Blake for current cygwin systems + +input.h + - add a B_TEXT flag to note when the underlying file descriptor is + opened in O_TEXT mode + +lib/sh/tmpfile.c + - make sure temporary files are opened in binary mode (O_BINARY) on + systems where it matters + +input.c + - make sure to set the B_TEXT flag if the file descriptor has O_TEXT + in its flags (returned by fcntl) + - change b_fill_buffer to compensate for lseek() and read() returning + different offsets on files opened in O_TEXT mode + - cygwin now is able to lseek on files and set the unbuffered and text + flags appropriately, so can use the general test for a seekable fd + - now that cygwin uses O_TEXT or O_BINARY appropriately, we no longer + have to manually translate \r\n to \n + +redir.c + - remove the Cygwin-1.1 code from here_document_to_fd; cygwin is now + up to version 1.7 and can unlink an open file descriptor + - make sure temporary files used for here documents are opened in + binary mode (O_BINARY) on systems where it matters + +execute_cmd.c,parse.y + - make sure error messages use all printable characters in filenames + and strings + +{builtins/evalfile,shell,subst}.c + - remove cygwin-specific calls to setmode to force file descriptors + into text mode, since we're using text or binary mode according to + the mode of the mount point + +execute_cmd.c + - when creating pipes and making them stdin and stdout, make sure to + tell stdio that the mode of the underlying file descriptor may have + changed from text to binary + +subst.c + - when creating pipes for command substitution, make sure to + tell stdio that the mode of the underlying file descriptor may have + changed from text to binary + + 1/3 + --- +doc/{bash.1,bashref.texi} + - changes to the readonly documentation suggested by Jan Schampera + + + 1/4 + --- +builtins/read.def + - change bind_read_variable to consistently return NULL if there is some + kind of variable assignment error (e.g., assigning to a readonly or + noassign var) + - change read builtin to only call stupidly_hack_special_variables if + bind_read_variable returns non-NULL + - change read_builtin to return EXECUTION_FAILURE if there is an + assignment error (e.g., assigning to a readonly or noassign var). + Fixes bug reported by Jan Schampera + + 1/5 + --- +builtins/{help.def,common.c} + - change uses of a builtin's `short_doc' member to go through gettext + for possible translation before being displayed. Suggestion from + + + 1/6 + --- +shell.h + - new exit status define: EX_MISCERROR (2) + +builtins/getopts.def + - change getopts_bind_variable to return error if an attempt is made + to assign to a variable with the `noassign' attribute + - change getopts_bind_variable to return EX_MISCERROR if attempt is + made to assign to readonly or noassign variable + +builtins/cd.def + - change setpwd to return an int and return failure when PWD is + readonly; success otherwise + - change bindpwd to return failure if setpwd returns EXECUTION_FAILURE. + Inspired by message from Eric Blake + - change pwd builtin to return failure if PWD is readonly (and setpwd + returns EXECUTION_FAILURE) + + 1/8 + --- +lib/sh/eaccess.c + - on FreeBSD and Solaris, check the result of access(2) with mode X_OK + for root by checking sh_stataccess(). Same code as was added to + check result of eaccess(). Fixes Solaris 11 problem reported by + + + 1/10 + ---- +builtins/set.def + - add description of `--' to help text + +[bash-4.2-rc1 released] + + 1/14 + ---- +lib/readline/readline.h + - fix/update description of rl_directory_rewrite_hook + +lib/readline/complete.c + - if there are no directory rewrite or completion hooks, set dirname + to a duplicate copy of users_dirname instead of calling the + dequoting function again + +bashline.c + - use rl_directory_rewrite_hook instead of rl_directory_completion_hook + to avoid changing the directory name the user typed, other than + dequoting it. Fixes bug introduced by changes to directory + completion hook, pointed out first by William Bader + + + 1/16 + ---- +lib/sh/strftime.c + - portability and other (int->long) updates from Aharon Robbins + + +configure.in + - change release level to rc2 + + 1/17 + ---- +execute_cmd.c + - short-circuit select builtin if read_builtin returns anything but + EXECUTION_SUCCESS, not just EXECUTION_FAILURE. Fixes bug reported + by Pierre Gaston + + 1/19 + ---- +execute_cmd.c + - change execute_simple_command to save and restore the values of + executing_builtin and executing_command_builtin before discarding + the unwind-protect frame. Bug and fix from Werner Fink + + + 1/24 + ---- +variables.c + - change brand to set rseed to a known, constant value if it's 0, + so the sequence is known. Fixes issue reported by Olivier + Mehani + + 2/2 + --- +braces.c + - make sure to pass an `int' argument to asprintf in mkseq. Fixes + bug reported by Mike Frysinger + + 2/5 + --- +lib/glob/gmisc.c + - fix wmatchlen and umatchlen to initialize all state variables. Fix + from Andreas Schwab + +jobs.c + - change wait_for to call restore_sigint_handler right after exiting + the wait loop, instead of right before function returns. Reduces + the window for a SIGINT to be lost because a child does not exit + due to SIGINT + + 2/7 + --- +configure.in + - changed release status to `release' + + 2/9 + --- +execute_cmd.c + - make sure some variables are declared as volatile if necessary. Bug + report and fix from Eric Blake + +[bash-4.2 frozen] + + 2/11 + ---- +print_cmd.c + - in indirection_level_string, change to simpler test of result of + MBLEN (< 0 instead of MB_INVALIDCH) + + 2/14 + ---- +[bash-4.2 released] + + 2/15 + ---- +lib/glob/gmisc.c + - fix wmatchlen and umatchlen to avoid going past the end of the + string on an incomplete bracket expression that ends with a + NUL. Partial fix for bug reported by Clark Wang + + 2/16 + ---- +subst.h + - new string extract flag value: SX_WORD. Used when calling + extract_dollar_brace_string to skip over the word in + ${param op word} from parameter_brace_expand + +subst.c + - change parameter_brace_expand to add SX_WORD to flags passed to + extract_dollar_brace_string + - change parameter_brace_expand to use SX_POSIXEXP for all non-posix + word expansion operators that treat single quotes as special, not + just % and # + - change extract_dollar_brace_string to initialize dolbrace_state to + DOLBRACE_WORD if SX_WORD flag supplied and we shouldn't use + DOLBRACE_QUOTE. Fixes bug reported by Juergen Daubert + +doc/{bash.1,bashref.texi} + - document the exact expansions here strings undergo + + 2/17 + ---- +lib/readline/vi_mode.c + - make sure that `dd', `cc', and `yy' call vidomove_dispatch from + rl_domove_read_callback. Fixes bug reported by Clark Wang + + +lib/readline/callback.c + - make sure _rl_internal_char_cleanup is called after the + vi-motion callbacks (rl_vi_domove_callback) in rl_callback_read_char. + Companion to above fix + +doc/{bash.1,bashref.texi} + - make sure that the text describing the rhs of the == and =~ + operators to [[ states that only the quoted portion of the pattern + is matched as a string + + 2/18 + ---- +lib/glob/gmisc.c + - better fix for umatchlen/wmatchlen: keep track of the number of + characters in a bracket expression as the value to increase + matchlen by if the bracket expression is not well-formed. Fixes + bug reported by Clark Wang + +subst.c + - change expand_string_for_rhs so that it sets the W_NOSPLIT2 flag + in the word flags. We will not perform word splitting or quote + removal on the result, so we do not want to add quoted nulls if + we see "" or ''. Fixes bug reported by Mike Frysinger + + + 2/19 + ---- +variables.c + - new function, int chkexport(name), checks whether variable NAME is + exported and remakes the export environment if necessary. Returns + 1 if NAME is exported and 0 if not + - call chkexport(name) to get tzset to look at the right variable in + the environment when modifying TZ in sv_tz. Don't call tzset if + chkexport doesn't indicate that the variable is exported + +variables.h + - new extern declaration for chkexport + + +{parse.y,builtins/printf.def} + - call sv_tz before calling localtime() when formatting time strings + in prompt strings or using printf. Fixes bug reported by + Dennis Williamson + +execute_cmd.c + - modify fix of 2/9 to add casts when those variables are passed to + functions; some compilers throw errors instead of warnings. Report + and fix from Joachim Schmitz + +support/shobj-conf + - add a stanza for nsk on the Tandem from Joachim Schmitz + + +{shell,lib/readline/shell}.c + - Tandem systems should use getpwnam (getlogin()); for some reason + they don't do well with using getuid(). Fix from Joachim Schmitz + + + 3/1 + --- +variables.c + - make sure that the return value from find_variable is non-null + before trying to use it in chkexport. Fixes bug reported by + Evangelos Foutras + + 3/3 + --- +parse.y + - when adding $$ to the current token buffer in read_token_word(), + don't xmalloc a buffer for two characters and then strcpy it, just + copy the characters directly into the token buffer. Fix from + Michael Whitten + +execute_cmd.c + - fix expand_word_unsplit to add the W_NOSPLIT2 flag to the word to + be expanded, so "" doesn't add CTLNUL. Similar to fix of 2/18 to + expand_string_for_rhs. Fixes bug reported by Nathanael D. Noblet + and Matthias Klose + +parse.y + - fix extended_glob case of read_token_word to allocate an extra + space in the buffer for the next character read after the extended + glob specification if it's a CTLESC or CTLNUL. Report and fix from + Michael Witten + - fix shell expansions case of read_token_word to allocate an extra + space in the buffer for the next character read after the shell + expansion if it's a CTLESC or CTLNUL. Report and fix from + Michael Witten + - TENTATIVE: fix read_token_word to reduce the amount of buffer space + required to hold the translated and double-quoted value of $"..." + strings. Report and fix from Michael Witten + - change code around got_character and got_escaped_character labels to + make sure that we call RESIZE_MALLOCED_BUFFER before adding the + CTLESC before a CTLESC or CTLNUL, and before adding the character if + we're not adding a CTLESC. Report and fix from + Michael Witten + +subst.c + - new param flags value, PF_ASSIGNRHS, mirrors W_ASSIGNRHS, noting that + parameter expansion is on rhs of assignment statement. That inhibits + word splitting + - change param_expand to call string_list_dollar_at with quoted == 1 + if PF_ASSIGNRHS is set, so it will quote IFS characters in the + positional parameter before separating them with the first char of + $IFS. This keeps the rhs from being split inappropriately. Fixes + bug reported by Andres Perera + + 3/4 + --- +lib/readline/bind.c + - add a missing free of `names' in rl_function_dumper. Bug report + and fix from Michael Snyder + + 3/5 + --- +lib/readline/rltty.c + - change rl_deprep_terminal so it uses fileno (stdin) for the tty fd + if rl_instream is not set, like rl_prep_terminal + + 3/6 + --- +lib/readline/display.c + - fix rl_message to use a dynamically-allocated buffer instead of a + fixed-size buffer of 128 chars for the `local message prompt'. Bug + report and fix from Micah Cowan + + 3/7 + --- +jobs.c + - add sentinel to wait_sigint_handler so it only sets wait_sigint_received + if waiting_for_child is non-zero; otherwise, it restores the old + SIGINT handler and sends itself the SIGINT + - set waiting_for_child around the calls to waitchld that use it to + synchronously wait for a process + - change logic that decides whether or not the child process blocked + or handled SIGINT based on whether or not waitpid returns -1/EINTR + and the shell receives a SIGINT and the child does not exit. If + the child later exits due to SIGINT, cancel the assumoption that it + was handled + - instead of testing whether or not the child exited due to SIGINT + when deciding whether the shell should act on a SIGINT it received + while waiting, test whether or not we think the child caught + SIGINT. If it did, we let it go (unless the shell has it trapped); + if it did not catch it, the shell acts on the SIGINT. Fix from + Linus Torvalds , bug report originally + from Oleg Nesterov + + 3/8 + --- +shell.c + - initialize no_line_editing to 1 if READLINE is not defined -- we + can't have line editing without readline + + 3/12 + ---- +lib/readline/signals.c + - add SIGHUP to the set of signals readline handles + +lib/readline/doc/rltech.texi + - document that SIGHUP is now part of the set of signals readline + handles + +lib/readline/input.c + - if _rl_caught_signal indicates that read() was interrupted by a + SIGHUP or SIGTERM, return READERR or EOF as appropriate + - call rl_event_hook, if it's set, if call to read in rl_getc + returns -1/EINTR. If rl_event_hook doesn't do anything, this + continues the loop as before. This handles the other fatal + signals + +execute_cmd.c + - add a couple of QUIT; calls to execute_disk_command and + execute_simple_command to improve responsiveness to interrupts + and fatal signals + +input.c + - rearrange getc_with_restart so that the return values from read() + are handled right + +parse.y + - don't need to set terminate_immediately in yy_stream_get, since + getc_with_restart checks for terminating signals itself + - since readline returns READERR on SIGHUP or SIGTERM, don't need + to set terminate_immediately. Still doesn't handle other + signals well -- will have to check that some more + +bashline.c + - new function, bash_event_hook, for rl_event_hook. Just checks for + terminating signals and acts on them using CHECK_TERMSIG. + - set rl_event_hook to bash_event_hook + +builtins/read.def + - take out setting terminate_immediately; add calls to CHECK_TERMSIG + after read calls + +doc/{bash.1,bashref.texi} + - move the text describing the effect of negative subscripts used to + reference indexed array elements to the paragraphs describing + ${parameter[subscript]}, since that's where they are implemented. + Pointed out by Christopher F. A. Johnson + +arrayfunc.[ch],subst.c + - array_expand_index now takes a new first argument: a SHELL_VAR * + of the array variable being subscripted. Can be used later to fully + implement negative subscripts + + 3/14 + ---- +lib/glob/glob.c + - fix mbskipname to not turn the directory entry name into a wide char + string if the conversion of the pattern to a wide char string fails + - fix mbskipname to call skipname if either the pattern or the filename + can't be converted into a wide-char string + +lib/glob/xmbsrtowcs.c + - fix xdupmbstowcs2 to handle return value of 0 from mbsnrtowcs and + short-circuit with failure in that case. Fixes bug reported by + Roman Rakus + + 3/15 + ---- +bashline.c + - new variable, bash_filename_quote_characters to store the value + assigned to rl_filename_quote_characters so it can be restored + if changed. + - change bashline_reset and attempt_shell_completion to restore + rl_filename_quote_characters if not set to default + + 3/22 + ---- +lib/glob/glob.c + - wdequote_pathname falls back to udequote_pathname if xdupmbstowcs + fails to convert the pathname to a wide-character string + +lib/glob/xmbsrtowcs.c + - xdupmbstowcs2: change to fix problem with leading '\\' (results in + nms == 0, which causes it to short-circuit with failure right + away). Fixes bug pointed out by Werner Fink + - xdupmbstowcs2: compensate for mbsnrtowcs returning 0 by taking the + next single-byte character and going on + - xdupmbstowcs2: change memory allocation to increase by WSBUF_INC + bytes; try to avoid calls to realloc (even if they don't actually + result in more memory being allocated) + + 3/24 + ---- +doc/{bash.1,bashref.texi} + - slightly modify BASH_SUBSHELL description based on complaint from + Sam Liddicott + + 3/25 + ---- +trap.c + - change free_trap_strings to not call free_trap_string for signals + that are being ignored, like reset_or_restore_signal_handlers. + Fixes bug reported by Satoshi Takahashi + + 3/26 + ---- +lib/readline/rltypedefs.h + - remove old Function/VFunction/CPFunction/CPPFunction typedefs as + suggested by Tom Tromey + +lib/readline/rlstdc.h + - move defines for USE_VARARGS/PREFER_STDARG/PREFER_VARARGS from + config.h.in to here because declaration of rl_message in + readline.h uses the defines. This makes it hard for another packages + to use after the header files are installed, since config.h is not + one of the installed files. Suggested by Tom Tromey + + + 3/27 + ---- +print_cmd.c + - change indirection_string from a static buffer to a dynamic one + managed by indirection_level_string(), so we don't end up truncating + PS4. Suggested by Dennis Williamson + +lib/readline/shell.c + - change sh_set_lines_and_columns to use static buffers instead of + allocating the buffers to pass to setenv/putenv + +lib/readline/terminal.c + - change _rl_get_screen_size to not call sh_set_lines_and_columns if + ignore_env == 0 + - _rl_sigwinch_resize_terminal: new function to just retrieve terminal + size, ignoring environment + +lib/readline/rlprivate.h + - new external declaration for _rl_sigwinch_resize_terminal() (currently + unused) + +lib/readline/signals.c + - rl_sigwinch_handler: set _rl_caught_signal to SIGWINCH + - rl_sigwinch_handler: don't immediately call rl_resize_terminal; just + leave _rl_caught_signal set for RL_CHECK_SIGNALS to handle + - _rl_signal_handler: call rl_resize_terminal if sig == SIGWINCH. + Should fix hang when sending multiple repeated SIGWINCH reported by + Henning Bekel + + 3/29 + ---- +lib/sh/snprintf.c + - include math.h for any defines for isinf/isnan + - use code from gnulib documentation to implement isinf/isnan if they + are not defined + +configure.in + - don't check for isinf or isnan; c99 says they're macros anyway + +config.h.in + - remove defines for ISINF_IN_LIBC and ISNAN_IN_LIBC, no longer used + by snprintf.c + + 4/2 + --- +braces.c + - brace_gobbler: fix to understand double-quoted command substitution, + since the shell understands unquoted comsubs. Fixes bug reported + by Michael Whitten + +lib/readline/display.c + - include on MDOS + - get and set screen size using DJGPP-specific calls on MSDOS + - move cursor up clear screen using DJGPP-specific calls + - don't call tputs on DJGPP; there is no good terminfo support + +lib/readline/terminal.c + - include on MDOS + - get and set screen size using DJGPP-specific calls on MSDOS + - use DJGPP-specific initialization on MSDOS, zeroing all the + _rl_term_* variables + - don't call tputs on DJGPP; there is no good terminfo support + DJGPP support from Eli Zaretskii + + 4/6 + --- + +config-top.h + - change DEFAULT_PATH_VALUE to something more useful and modern + + 4/8 + --- +tests/printf2.sub + - make sure LC_ALL and LC_CTYPE are set so LANG assignment takes effect. + Reported by Cedric Arbogast + + 4/11 + ---- +include/chartypes.h + - fix a couple of dicey defines (though ones that don't cause any + compiler warnings) in IN_CTYPE_DOMAIN + +doc/{bashref.texi,bash.1} + - add note referring to duplicating file descriptors in sections + describing redirecting stdout and stderr and appending to stdout + and stderr. Suggested by Matthew Dinger + +pcomplete.c + - it_init_helptopics: new function to support completing on help topics, + not just builtins + - it_helptopics: new programmable completion list of help topics + - build list of helptopic completions in gen_action_completions on + demand + +pcomplete.h + - new extern declaration for it_helptopics + +builtins/complete.def + - the `helptopic' action now maps to CA_HELPTOPIC intead of CA_BUILTIN, + since there are more help topics than just builtins. Suggested by + Clark Wang + + 4/12 + ---- +print_cmd.c + - fix print_arith_for_command to add a call to PRINT_DEFERRED_HEREDOCS + before ending the body of the command, so heredocs get attached to + the right command instead of to the loop. From gentoo bug 363371 + http://bugs.gentoo.org/show_bug.cgi?id=363371 + +execute_cmd.c + - change coproc_pidchk to unset the appropriate shell variables when + the (currently single) known coproc pid terminates + - cleanup and new functions to fully support multiple coprocesses when + and if I decide to go there + + 4/13 + ---- +print_cmd.c + - fix print_group_command to add a call to PRINT_DEFERRED_HEREDOCS + after call to make_command_string_internal before printing closing + `}' + - fix make_command_string_internal to add a call to + PRINT_DEFERRED_HEREDOCS after recursive call to + make_command_string_internal in case cm_subshell before printing + closing `)' + + 4/14 + ---- +print_cmd.c + - change overlapping strcpy in named_function_string to memmove + +sig.h + - UNBLOCK_SIGNAL: convenience define, same as UNBLOCK_CHILD, just + restores an old signal mask + +trap.c + - set_signal: instead of setting the signal handler to SIG_IGN while + installing the new trap handler, block the signal and unblock it + after the new handler is installed. Fixes bug reported by Roman + Rakus + + 4/15 + ---- +doc/{bash.1,bashref.texi} + - make it clear that enabling monitor mode means that all jobs run in + separate process groups + + 4/18 + ---- +builtins/fc.def + - update fix of 4/15/2010 to not take saved_command_line_count into + account when stepping down the history list to make sure that + last_hist indexes something that is valid. Fixes bug reported by + + + 4/19 + ---- +builtins/fc.def + - fc_gethnum: make sure the calculation to decide the last history + entry is exactly the same as fc_builtin. Fixes bug uncovered by + fix of 4/18 to stop seg fault + + 4/22 + ---- +lib/readline/terminal.c + - change _rl_enable_meta_key to set a flag indicating that it sent the + enable-meta sequence + - _rl_disable_meta_key: new function to turn off meta mode after we + turned it on with _rl_enable_meta_key + +lib/readline/rlprivate.h + - extern declaration for _rl_disable_meta_key + +configure.in + - if not cross-compiling, set CFLAGS_FOR_BUILD from any CFLAGS inherited + from the environment. Fixes HP/UX build problem reported by + "Daniel Richard G." + + 4/26 + ---- +config-top.h + - define MULTIPLE_COPROCS to 0 so the code is still disabled but easy + to enable via configure option or editing this file + + 4/29 + ---- +lib/sh/eaccess.c + - freebsd provides faccessat, with the same misfeature as their eaccess + and access implementations (X_OK returns true for uid==0 regardless + of the actual file permissions), so reorganize code to check the + file permissions as with eaccess. Report and fix from Johan Hattne + + + 5/2 + --- +doc/{bash.1,bashref.texi} + - add forward reference to `Pattern Matching' from `Pathname + Expansion', suggested by Greg Wooledge + + 5/5 + --- +pcomplib.c + - the bash_completion project now distributes over 200 completions + for various programs, with no end in sight, so increase the value + of COMPLETE_HASH_BUCKETS from 32 to 128 + +pathexp.c + - quote_string_for_globbing: make sure CTLESC quoting CTLESC is + translated into \ even if the flags include QGLOB_REGEXP. + We don't want to process the second CTLESC as a quote character. + Fixes bug reported by Shawn Bohrer + + 5/6 + --- +builtins/printf.def + - change PRETURN to not call fflush if ferror(stdout) is true + - if a call to one of the stdio functions or printstr leaves + ferror(stdout) true, and PRETURN is going to be called, let PRETURN + print the error message rather than doubling up the messages. Fixes + problem reported by Roman Rakus + + 5/9 + --- +doc/{bash.1,bashref.texi} + - add note to the effect that lists inside compound command can be + terminated by newlines as well as semicolons. Suggested by + Roman Byshko + + 5/10 + ---- +subst.c + - remove_quoted_nulls: fix problem that caused it to skip over the + character after a CTLNUL, which had the effect of skipping every + other of a series of CTLNULs. Fixes bug reported by + Marten Wikstrom + + 5/11 + ---- +subst.c + - extract_process_subst: add SX_COMMAND flag to call to + extract_delimited_string, since we're expanding the same sort of + command as command substitution. Fixes bug reported in Ubuntu + bug 779848 + + 5/12 + ---- +configure.in + - set the prefer_shared and prefer_static variables appropriately + depending on the value of $opt_static_link + +aclocal.m4 + - AC_LIB_LINKFLAGS_BODY: change to not prefer shared versions of the + libraries it's searching for if the prefer_shared variable is "no". + Fixes problem reported by Cedric Arbogast + + 5/13 + ---- +lib/readline/readline.c + - _rl_internal_teardown: add call to _rl_disable_meta_key to make the + meta key active only for the duration of the call to readline() + - _rl_internal_setup: move call to _rl_enable_meta_key here from + readline_initialize_everything so the meta key is active only for + the duration of the call to readline(). Suggestion from Miroslav + Lichvar + +builtins/help.def + - help_builtin: change strncmp to strcmp so that `help read' no longer + matches `readonly'. Suggested by Clark Wang + +config.h.in + - add define for GLIBC21, checked using jm_GLIBC21 as part of the tests + for libintl + +lib/malloc/malloc.c + - internal_free: don't use the cached value of memtop when deciding + whether or not to adjust the break and give memory back to the kernel + when using the GNU C library, since glibc uses sbrk for its own + internal purposes. From Debian bug 614815, reported by Samuel + Thibault + +aclocal.m4 + - BASH_STRUCT_WEXITSTATUS_OFFSET: change AC_RUN_IFELSE to AC_TRY_RUN + to avoid warning about not using AC_LANG_SOURCE + + 5/14 + ---- +bashline.[ch] + - two new functions, bashline_set_event_hook and bashline_reset_event_hook, + to set rl_event_hook to bash_event_hook and back to NULL, respectively + - don't set rl_event_hook unconditionally + +sig.c + - termsig_sighandler: if the shell is currently interactive and + readline is active, call bashline_set_event_hook to cause + termsig_handler to be called via bash_event_hook when the shell + returns from the signal handler + + 5/15 + ---- +lib/readline/display.c + - _rl_col_width: Mac OS X has a bug in wcwidth: it does not return 0 + for UTF-8 combining characters. Added workaround dependent on + MACOSX. Fixes problem pointed out by Thomas De Contes + + + 5/16 + ---- +lib/readline/rlmbutil.h + - WCWIDTH: wrapper for wcwidth that returns 0 for Unicode combining + characters on systems where wcwidth is broken (e.g., Mac OS X). + +lib/readline/{complete,display,mbutil}.c + - use WCWIDTH instead of wcwidth + + 5/17 + ---- +lib/readline/display.c + - update_line: after computing ofd and nfd, see whether the next + character in ofd is a zero-width combining character. If it is, + back ofd and nfd up one, so the base characters no longer compare + as equivalent. Fixes problem reported by Keith Winstein + + +lib/readline/nls.c + - _rl_utf8locale: new flag variable, set to non-zero if the current + locale is UTF-8 + - utf8locale(): new function, returns 1 if the passed lspec (or the + current locale) indicates that the locale is UTF-8. Called from + _rl_init_eightbit + +lib/readline/rlprivate.h + - extern declaration for _rl_utf8locale + +locale.c + - locale_utf8locale: new flag variable, set to non-zero if the current + locale is UTF-8 (currently unused) + - locale_isutf8(): new function, returns 1 if the passed lspec (or the + current locale) indicates that the locale is UTF-8. Should be called + whenever the locale or LC_CTYPE value is modified + +aclocal.m4 + - BASH_WCWIDTH_BROKEN: new test for whether or not wcwidth returns + zero-width characters like unicode combining characters as having + display length 1; define WCWIDTH_BROKEN in this case + +config.h.in + - WCWIDTH_BROKEN: new define + +lib/readline/rlmbutil.h + - change WCWIDTH macro to use _rl_utf8locale and the full range of + Unicode combining characters (U+0300-U+036F) + + 5/19 + ---- +lib/readline/rlprivate.h + - _rl_search_context: new member, prevc, will hold character read + prior to lastc + +lib/readline/isearch.c + - _rl_isearch_dispatch: if the character causes us to index into + another keymap, save that character in cxt->prevc + - _rl_isearch_dispatch: if we index into another keymap, but don't + find a function that's special to i-search, and the character that + caused us to index into that keymap would have terminated the + search, push back cxt->prevc and cxt->lastc to make it appear as + if `prevc' terminated the search, and execute lastc as a command. + We have to push prevc back so we index into the same keymap before + we read lastc. Fixes bug report from Davor Cubranic + + + 5/20 + ---- +expr.c + - expr_bind_variable: pay attention to the return value from + bind_variable and check whether or not we should error out due to + a readonly or noassign variable. Fixes bug reported by Eric + Blake + + 5/26 + ---- + +lib/readline/search.c + - include histlib.h for ANCHORED_SEARCH defines + - rl_history_search_flags: new variable, holds ANCHORED_SEARCH flag for + the duration of a history search + - rl_history_search_reinit: takes a new flags variable, defines whether + or not the search is anchored; assigned to rl_history_search_flags + - rl_history_serarch_reinit: if ANCHORED_SEARCH flag passed, add ^ to + beginning of search string; otherwise search string is unmodified + - rl_history_search_internal: set rl_point appropriately based on + whether or not rl_history_search_flags includes ANCHORED_SEARCH + - rl_history_substr_search_forward: new function, for non-anchored + substring search forward through history for string of characters + preceding rl_point + - rl_history_substr_search_backward: new function, for non-anchored + substring search backward through history for string of characters + preceding rl_point. Original code from Niraj Kulkarni + + +lib/readline/readline.h + - extern declarations for rl_history_substr_search_{for,back}ward + +lib/readline/funmap.c + - history-substring-search-forward: new bindable command, invokes + rl_history_substr_search_forward + - history-substring-search-backward: new bindable command, invokes + rl_history_substr_search_backward + +lib/readline/doc/{rluser.texi,readline.3} + - document history-substring-search-forward and + history-substring-search-backward + + 5/27 + ---- +{nojobs,jobs}.c + - add support for DONT_REPORT_SIGTERM so that the shell doesn't print + a message when a job exits due to SIGTERM since that's the default + signal sent by the kill builtin. Suggested by Marc Herbert + + +config-top.h + - DONT_REPORT_SIGTERM: new user-modifiable setting. Commented out + by default + + 5/28 + ---- +lib/readline/bind.c + - _rl_skip_to_delim: skip to a closing double quote or other delimiter, + allowing backslash to quote any character, including the delimiter + - rl_parse_and_bind: call _rl_skip_to_delim instead of using inline + code + - rl_parse_and_bind: allow quoted strings as the values of string + variables. Variable values without double quotes have trailing + whitespace removed (which still allows embedded whitespace, for + better or worse). Fixes problem with string variables not matching + in `set' command if values happen to have trailing spaces or tabs + (debian bash bug #602762), but introduces slight incompatibility. + + 5/29 + ---- +doc/{bash.1,bashref.texi} + - clarify unset description to specify that without options, a + variable, then a shell function if there is no variable by that + name, is unset. Fixes discrepancy reported by Mu Qiao + + + 6/4 + ---- +doc/{bash.1,bashref.texi} + - clarify description of LINES and COLUMNS (and checkwinsize shopt + option) to make it clear that only interactive shells set a + handler for SIGWINCH and update LINES and COLUMNS. Original + report submitted by Jonathan Nieder + +arrayfunc.c + - expand_compound_array_assignment: defer expansion of words between + parens when performing compound assignmnt to an associative array + variable + - assign_compound_array_list: perform the same expansions when doing + a compound array assignment to an associative array variable as + when doing a straight array index assignment. The idea is that + foo=( [ind1]=bar [ind2]=quux) + is the same as + foo[ind1]=bar ; foo[ind2]=quux + + This fixes problems with double-expansion and quote removal being + performed on the array indices + + 6/13 + ---- +doc/{bash.1,bashref.texi} + - Add a little text to make it clear that the locale determines how + range expressions in glob patterns are handled. + + + 6/21 + ---- +builtins/read.def + - display a message and return error status if -a is used with an + existing associative array. Fixes bug reported by Curtis Doty + + + 6/24 + ---- +{jobs,nojobs}.c + - non-interactive shells now react to the setting of checkwinsize + and set LINES and COLUMNS after a foreground job exits. From a + suggestion by Leslie Rhorer + +doc/{bash.1,bashref.texi} + - checkwinsize: remove language saying that only interactive shells + check the window size after each command + +lib/readline/histfile.c + - history_backupfile: new file, creates a backup history file name + given a filename (appending `-') + - history_do_write: when overwriting the history file, back it up + before writing. Restore backup file on a write error. Suggested + by chkno@chkno.net + +bashline.c + - find_cmd_name: two new arguments, return the start and end of the + actual text string used to find the command name, without taking + whitespace into account + - attempt_shell_completion: small changes to make sure that completion + attempted at the beginning of a non-empty line does not find a + programmable completion, even if the command name starts at point + - attempt_shell_completion: small change to make sure that completion + does not find a progcomp when in whitespace before the command + name + - attempt_shell_completion: small change to make sure that completion + does not find a progcomp when point is at the first character of a + command name, even when there is leading whitespace (similar to + above). Fixes problems noted by Ville Skytta + +subst.c + - brace_expand_word_list: since the individual strings in the strvec + returned by brace_expand are already allocated, don't copy them to + newly-allocated memory when building the WORD_LIST, just use them + intact + +locale.c + - locale_mb_cur_max: cache value of MB_CUR_MAX when we set or change + the locale to avoid a function call every time we need to read it + +shell.h + - new struct to save shell_input_line and associated variables: + shell_input_line_state_t + - add members of sh_parser_state_t to save and restore token and the + size of the token buffer + +parse.y + - {save,restore}_input_line_state: new functions to save and restore + shell_input_line and associated variables + - {save,restore}_parser_state: add code to save and restore the token + and token buffer size + - xparse_dolparen: call save_ and restore_input_line_state to avoid + problems with overwriting shell_input_line when we recursively + call the parser to parse a command substitution. Fixes bug + reported by Rui Santos + +include/shmbutil.h + - use locale_mb_cur_max instead of MB_CUR_MAX in ADVANCE_CHAR and + similar macros + +lib/glob/smatch.c + - rangecmp,rangecmp_wc: change to take an additional argument, which + forces the use of strcoll/wscoll when non-zero. If it's 0, a new + variable `glob_asciirange' controls whether or not we use strcoll/ + wscoll. If it's non-zero, we use straight C-locale-like ordering. + Suggested by Aharon Robbins + + 6/30 + ---- +execute_cmd.c + - execute_pipeline: make sure the lastpipe code is protected by + #ifdef JOB_CONTROL. Fixes problem reported by Thomas Cort + + + 7/2 + --- +lib/readline/complete.c + - EXPERIMENTAL: remove setting of _rl_interrupt_immediately around + completion functions that touch the file system. Idea from Jan + Kratochvil and the GDB development + team + +lib/readline/signals.c + - rl_signal_handler: if we're in callback mode, don't interrupt + immediately on a SIGWINCH + + 7/3 + --- +bashline.c + - set_directory_hook: and its siblings are a new set of functions to + set, save, and restore the appropriate directory completion hook + - change callers to use {set,save,restore}_directory_hook instead of + manipulating rl_directory_rewrite_hook directly + - dircomplete_expand: new variable, defaults to 0, if non-zero causes + directory names to be word-expanded during word and filename + completion + - change {set,save,restore}_directory_hook to look at dircomplete_expand + and change rl_directory_completion_hook or rl_directory_rewrite_hook + appropriately + +bashline.h + - extern declaration for set_directory_hook so shopt code can use it + + 7/6 + --- +builtins/shopt.def + - globasciiranges: new settable shopt option, makes glob ranges act + as if in the C locale (so b no longer comes between A and B). + Suggested by Aharon Robbins + + 7/7 + --- +doc/{bash.1,bashref.texi} + - document new `globasciiranges' shopt option + + 7/8 + --- +builtins/shopt.def + - direxpand: new settable option, makes filename completion expand + variables in directory names like bash-4.1 did. + - shopt_set_complete_direxpand: new function, does the work for the + above by calling set_directory_hook + +doc/{bash.1,bashref.texi} + - document new `direxpand' shopt option + + 7/15 + ---- +lib/readline/isearch.c + - _rl_isearch_dispatch: when adding character to search string, use + cxt->lastc (which we use in the switch statement) instead of c, + since lastc can be modified earlier in the function + + 7/18 + ---- +lib/readline/rlprivate.h + - _rl_search_context: add another member to save previous value of + (multibyte) lastc: pmb is to mb as prevc is to lastc + +lib/readline/isearch.c: + - _rl_isearch_dispatch: if a key sequence indexes into a new keymap, + but doesn't find any bound function (k[ind].function == 0) or is + bound to self-insert (k[ind].function == rl_insert), back up and + insert the previous character (the one that caused the index into a + new keymap) and arrange things so the current character is the next + one read, so both of them end up in the search string. Fixes bug + reported by Clark Wang + - _rl_isearch_dispatch: a couple of efficiency improvements when adding + characters to the isearch string + + 7/24 + ---- +lib/readline/isearch.c + - _rl_isearch_dispatch: save and restore cxt->mb and cxt->pmb + appropriately when in a multibyte locale + +doc/{bash.1,bashref.texi} + - correct description of {x}>file (and other redirection operators + that allocate a file descriptor) to note the the fd range is + greater than or equal to 10. Fixes problem reported by + Christian Ullrich + +lib/readline/signals.c + - rl_signal_handler: don't interrupt immediately if in callback mode + +lib/readline/callback.c + - rl_callback_read_char: install signal handlers only when readline + has control in callback mode, so readline's signal handlers aren't + called when the application is active (e.g., between the calls to + rl_callback_handler_install and rl_callback_read_char). If the + readline signal handlers only set a flag, which the application + doesn't know about, the signals will effectively be ignored until + the next time the application calls into the readline callback + interface. Fixes problem of calling unsafe functions from signal + handlers when in callback mode reported by Jan Kratochvil + + +execute_cmd.c + - fix_assignment_words: when in Posix mode, the `command' builtin + doesn't change whether or not the command name it protects is an + assignment builtin. One or more instances of `command' + preceding `export', for instance, doesn't make `export' treat its + assignment statement arguments differently. Posix interpretation + #351 + +doc/{bash.1,bashref.texi} + - document new Posix-mode behavior of `command' when preceding builtins + that take assignment statements as arguments + +builtins/printf.def + - printstr: if fieldwidth or precision are < 0 or > INT_MAX when + supplied explicitly (since we take care of the `-' separately), + clamp at INT_MAX like when using getint(). Fixes issue reported + by Ralph Coredroy + + 7/25 + ---- +lib/readline/chardefs.h + - isxdigit: don't define if compiling with c++; declared as a c++ + template function. Fixes bug reported by Miroslav Lichvar + + +builtins/printf.def + - getint: if garglist == 0, return whatever getintmax returns (0). + Fixes bug reported by Ralph Coredroy + + 7/28 + ---- +doc/{bash.1,bashref.texi} + - minor changes to the descriptions of the cd and pushd builtins + +lib/sh/zread.c + - zsyncfd: change variable holding return value from lseek to + off_t. Bug report and fix from Gregory Margo + + 8/1 + --- +expr.c + - don't check for division by 0 when in a context where no evaluation + is taking place. Fixes bug reported by dnade.ext@orange-ftgroup.com + + 8/6 + --- +execute_cmd.c + - execute_command_internal: the parent branch of the subshell code + (where the child calls execute_in_subshell) should not close all + open FIFOs with unlink_fifo_list if it's part of a shell function + that's still executing. Fixes bug reported by Maarten Billemont + + + 8/9 + --- +builtins/common.c + - get_exitstat: return EX_BADUSAGE (2) on a non-numeric argument + +builtins/return.def + - return_builtin: just call get_exitstat to get the return status, + let it handle proper parsing and handling of arguments. Fixes + issue most recently raised by Linda Walsh . + Reverses change from 9/11/2008 (see above) + + 8/16 + ---- +doc/{bash.1,bashref.texi} + - clean up `set -e' language to make it clearer that any failure of + a compound command will cause the shell to exit, not just subshells + and brace commands + + 8/17 + ---- +configure.in + - make the various XXX_FOR_BUILD variables `precious' to autoconf to + avoid stale data + - change how CC_FOR_BUILD is initialized when cross-compiling and not, + but do not change behavior + - initialize CFLAGS_FOR_BUILD to -g when cross-compiling + - initialize LIBS_FOR_BUILD to $(LIBS) when not cross-compiling, empty + when cross-compiling + - create AUTO_CFLAGS variable to hold basic CFLAGS defaults; used when + CFLAGS not inherited from environment (like effect of old + auto_cflags variable) + - substitute LIBS_FOR_BUILD into output Makefiles + [changes inspired by bug report from Nathan Phillip Brink + -- gentoo bug 378941] + +builtins/Makefile.in + - substitute LIBS_FOR_BUILD from configure, not strictly initialized + to $(LIBS) + + 8/27 + ---- +doc/{bash.1,bashref.texi} + - minor changes to the here string description to clarify the + expansions performed on the word + +support/shobj-conf + - handle compilation on Lion (Mac OS X 10.7/darwin11) with changes + to darwin stanzas. Fixes readline bug reported by Vincent + Sheffer + +lib/sh/strtrans.c + - ansic_wshouldquote: check a string with multi-byte characters for + characters that needs to be backslash-octal escaped for $'...' + - ansic_shouldquote: if is_basic fails for one character, let + ansic_wshouldquote examine the rest of the string and return what + it returns. From a patch sent by Roman Rakus + + 8/30 + ---- +lib/sh/strtrans.c + - ansic_quote: changes to quote (or not) multibyte characters. New + code converts them to wide characters and uses iswprint to check + valid wide chars. From a patch sent by Roman Rakus + + + 9/7 + --- +lib/sh/shquote.c + - sh_backslash_quote: change to be table-driven so we can use a + different table if we want to + - sh_backslash_quote: takes a second char table[256] argument; + +externs.h + - sh_backslash_quote: add second argument to function prototype + +bashline.c,braces.c,parse.y,builtins/printf.def + - change callers of sh_backslash_quote to add second argument + +bashline.c + - filename_bstab: table of characters to pass to sh_backslash_quote; + characters with value 1 will be backslash-quoted + - set_filename_bstab: turn on characters in filename backslash-quote + table according to passed string argument + - call set_filename_bstab every time rl_filename_quote_characters is + assigned a value + - bash_quote_filename: call sh_backslash_quote with filename_bstab + as second argument. This allows other characters in filenames to + be quoted without quoting, for instance, a dollar sign in a shell + variable reference + + 9/8 + --- +bashline.c + - complete_fullquote: new variable, controls table passed to + sh_backslash_quote. If non-zero (the default), the standard set + of shell metacharacters -- as in bash versions up to and including + bash-4.2 -- gets backslash-quoted by the completion code. If zero, + sh_backslash_quote gets the table with the characters in the + variable reference removed, which means they are removed from the + set of characters to be quoted in filenames + + 9/10 + ---- +bashline.c + - bash_filename_stat_hook: new function, designed to expand variable + references in filenames before readline passes them to stat(2) + to determine whether or not they are a directory + + 9/15 + ---- +builtins/declare.def + - if assign_array_element fails due to a bad (or empty) subscript, mark + it as an assignment error and don't attempt any further processing + of that declaration. Fixes segfault bug reported by Diego Augusto + Molina + + 9/19 + ---- +expr.c + - exppower: replace the simple exponentiation algorithm with an + implementation of exponentiation by squaring. Inspired by report + from Nicolas ARGYROU + +bashline.c + - bash_quote_filename: check for rtext being non-null before + dereferencing it + - set_saved_history: operate_and_get_next assumes that the previous + line was added to the history, even when the history is stifled and + at the max number of entries. If it wasn't, make sure the history + number is incremented properly. Partial fix for bug reported by + gregrwm + +doc/{bash.1,bashref.texi},lib/readline/doc/{hsuser,rluser}.texi + - minor editorial changes inspired by suggestions from + Roger Zauner + + 9/20 + ---- +lib/intl/localealias.c + - read_alias_file: close resource leak (fp) when returning on error + + 9/22 + ---- +execute_command.c + - execute_intern_function: implement Posix interpretation 383 by making + it an error to define a function with the same name as a special + builtin when in Posix mode. + http://austingroupbugs.net/view.php?id=383#c692 + + 9/25 + ---- +doc/{bash.1,bashref.texi} + - formatting and some content changes from Benno Schulenberg + + - document new posix-mode behavior from interp 383 change of 9/22 + + 9/30 + ---- +execute_cmd.c + - shell_execve: add strerror to error message about executable file + that shell can't execute as a shell script. From suggestion by + daysleeper + + 10/1 + ---- +bashhist.c + - maybe_add_history: act as if literal_history is set when parser_state + includes PST_HEREDOC, so we save the bodies of here-documents just + as they were entered. Fixes bug reported by Jonathan Wakely + + - bash_add_history: make sure that the second and subsequent lines of + a here document don't have extra newlines or other delimiting + chars added, since they have the trailing newline preserved, when + `lithist' is set and history_delimiting_chars isn't called + +execute_cmd.c + - execute_command_internal: avoid fd exhaustion caused by using + process substitution in loops inside shell functions by using + copy_fifo_list and close_new_fifos (). Fixes debian bash bug + 642504 + +lib/readline/complete.c + - new variable, rl_filename_stat_hook, used by append_to_match. If + filename completion is desired, and rl_filename_stat_hook points + to a function, call that function to expand the filename in an + application-specific way before calling stat. + +bashline.c + - bash_default_completion: if variable completion returns a single + match, use bash_filename_stat_hook and file_isdir to determine + whether or not the variable name expands to a directory. If it + does, set the filename_append_character to `/'. This is not + perfect, so we will see how it works out. Adds functionality + requested by Peter Toft and Patrick Pfeifer + + - rl_filename_stat_hook: assigned bash_filename_stat_hook, so things + like $HOME/Downloads (after completion) have a slash appended. + In general, this causes the stat hook to be called whenever + filename completion is appended. Adds functionality requested by + Patrick Pfeifer + +lib/readline/readline.h + - new extern declaration for rl_filename_stat_hook + +lib/readline/doc/rltech.texi + - rl_directory_rewrite_hook: now documented + - rl_filename_stat_hook: document + +pcomplete.c + - gen_action_completions: in the CA_DIRECTORY case, turn off + rl_filename_completion_desired if it was off before we called + rl_filename_completion_function and we didn't get any matches. + Having it on causes readline to quote the matches as if they + were filenames. Adds functionality requested by many, + including Clark Wang + +assoc.[ch] + - assoc_replace: new function, takes the same arguments as + assoc_insert, but returns the old data instead of freeing it + - assoc_insert: if the object returned by hash_insert doesn't have + the same value for its key as the key passed as an argument, we + are overwriting an existing value. In this case, we can free the + key. Fixes bug reported by David Parks + + 10/5 + ---- +print_cmd.c + - indirection_level_string: small change to only re-enable `x' + option after calling decode_prompt_string if it was on before. In + normal mode, it will be, but John Reiser + has a novel use for that code in conjunction with a pre-loaded + shared library that traces system call usage in shell scripts + + 10/10 + ----- +Makefile.in + - Fix from Mike Frysinger to avoid trying to + build y.tab.c and y.tab.h with two separate runs of yacc if + parse.y changes. Problem with parallel makes + - Fix from Mike Frysinger to avoid subdirectory + builds each trying to make version.h (and all its dependencies) + +lib/sh/Makefile.in + - remove some dependencies on version.h where it doesn't make sense + +variables.c + - initialize_shell_variables: while reading the environment, a shell + running in posix mode now checks for SHELLOPTS being readonly (it + gets set early on in main()) before trying to assign to it. It + saves an error message and the variable gets parsed as it should. + Fixes bug reported by Len Giambrone + + 10/14 + ----- +doc/{bash.1,bashref.texi} + - add to the "duplicating file descriptors" description that >&word + doesn't redirect stdout and stderr if word expands to `-' + - add to the "appending standard output and standard error" + description a note that >&word, where word is a number or `-', + causes other redirection operators to apply for sh and Posix + compatibility reasons. Suggested by Greg Wooledge + + + 10/15 + ----- +pcomplete.c + - change pcomp_filename_completion_function to only run the filename + dequoting function in the cases (as best as it can figure) where + readline won't do it via rl_filename_completion_function. Based + on reports from + + 10/19 + ----- +bashline.c + - attempt_shell_completion: add call to set_directory_hook() to make + sure the rewrite functions are correct. It's cheap and doesn't + hurt + - command_word_completion_function: if completing a command name that + starts with `.' or `..', temporarily suppress the effects of the + `direxpand' option and restore the correct value after calling + rl_filename_completion_function. If it's enabled, the directory + name will be rewritten and no longer match `./' or `../'. Fixes + problem reported by Michael Kalisz + + 10/22 + ----- +builtins/history.def + - push_history: make sure remember_on_history is enabled before we + try to delete the last history entry -- the `history -s' command + might not have been saved. Fixes bug reported by + lester@vmw-les.eng.vmware.com + +lib/readline/complete.c + - rl_callback_read_char: add calls to a macro CALLBACK_READ_RETURN + instead of straight return; add same call at end of function. + Placeholder for future work in deinstalling signal handlers when + readline is not active + + 10/25 + ----- +expr.c + - exp2: catch arithmetic overflow when val1 == INTMAX_MIN and val2 == -1 + for DIV and MOD and avoid SIGFPE. Bug report and pointer to fix + from Jaak Ristioja + - expassign: same changes for arithmetic overflow for DIV and MOD + + 10/28 + ----- +subst.c + - parameter_brace_expand: allow pattern substitution when there is an + expansion of the form ${var/} as a no-op: replacing nothing with + nothing + - parameter_brace_patsub: don't need to check for PATSUB being NULL; + it never is + +flags.c + - if STRICT_POSIX is defined, initialize history_expansion to 0, since + history expansion (and its treatment of ! within double quotes) is + not a conforming posix environment. From austin-group issue 500 + +lib/readline/histexpand.c + - history_expand: when processing a string within double quotes + (DQUOTE == 1), make the closing double quote inhibit history + expansion, as if the word were outside double quotes. In effect, + we assume that the double quote is followed by a character in + history_no_expand_chars. tcsh and csh seem to do this. This + answers a persistent complaint about history expansion + + 10/29 + ----- +make_cmd.c + - make_arith_for_command: use skip_to_delim to find the next `;' + when breaking the string between the double parens into three + separate components instead of a simple character loop. Fixes + bug reported by Dan Douglas + + 11/2 + ---- +Makefile.in + - make libbuiltins.a depend on builtext.h to serialize its creation + and avoid conflict between multiple invocations of mkbuiltins. + Fix from Mike Frysinger + + 11/5 + ---- +findcmd.c + - user_command_matches: if stat(".", ...) returns -1, set st_dev + and st_ino fields in dotinfo to 0 to avoid same_file matches + - find_user_command_in_path: check stat(2) return the same way + +lib/glob/glob.c + - glob_vector: don't call strlen(pat) without checking pat == 0 + - glob_dir_to_array: make sure to free `result' and all allocated + members before returning error due to malloc failure + - glob_vector: make sure to free `nextname' and `npat' on errors + (mostly when setting lose = 1) + - glob_vector: if flags & GX_MATCHDIRS but not GX_ALLDIRS, make + sure we free `subdir' + - glob_filename: when expanding ** (GX_ALLDIRS), make sure we + free temp_results (return value from glob_vector) + +lib/glob/xmbsrtowcs.c + - xdupmbstowcs: fix call to realloc to use sizeof (char *) instead + of sizeof (char **) when assigning idxtmp + +execute_cmd.c + - print_index_and_element: return 0 right away if L == 0 + - is_dirname: fix memory leak by freeing `temp' + - time_command: don't try to deref NULL `command' when assigning + to `posix_time' + - shell_execve: null-terminate `sample' after READ_SAMPLE_BUF so it's + terminated for functions that expect that + +builtins/read.def + - read_builtin: don't call bind_read_variable with a potentially-null + string + +pcomplete.c + - gen_command_matches: don't call dispose_word_desc with a NULL arg + - gen_compspec_completions: fix memory leak by freeing `ret' before + calling gen_action_completions (tcs, ...). happens when + performing directory completion as default and no completions + have been generated + - gen_progcomp_completions: make sure to set foundp to 0 whenever + returning NULL + - it_init_aliases: fix memory leak by freeing alias_list before + returning + +bashline.c + - command_word_completion_function: don't call restore_tilde with a + NULL directory_part argument + - bash_directory_expansion: bugfix: don't throw away results of + rl_directory_rewrite_hook if it's set and returns non-zero + - bind_keyseq_to_unix_command: free `kseq' before returning error + +arrayfunc.c + - assign_array_element_internal: make sure `akey' is freed if non-null + before returning error + - assign_compound_array_list: free `akey' before returning error + - array_value_internal: free `akey' before returning error + - unbind_array_element: free `akey' before returning error + +subst.c + - array_length_reference: free `akey' before returning error in case + of expand_assignment_string_to_string error + - array_length_reference: free `akey' after call to assoc_reference + - skip_to_delim: if skipping process and command substitution, free + return value from extract_process_subst + - parameter_brace_substring: free `val' (vtype == VT_VARIABLE) before + returning if verify_substring_values fails + - parameter_brace_expand: remove two duplicate lines that allocate + ret in parameter_brace_substring case + - parameter_brace_expand: convert `free (name); name = xmalloc (...)' + to use `xrealloc (name, ...)' + - parameter_brace_expand: free `name' before returning when handling + ${!PREFIX*} expansion + - split_at_delims: fix memory leak by freeing `d2' before returning + +redir.c + - redirection_error: free `filename' if the redirection operator is + REDIR_VARASSIGN by assigning allocname + +eval.c + - send_pwd_to_eterm: fix memory leak by freeing value returned by + get_working_directory() + +builtins/cd.def + - change_to_directory: fix memory leak by freeing return value from + resetpwd() + - cd_builtin: fix memory leak by freeing value returned by dirspell() + - cd_builtin: fix memory leak by freeing `directory' if appropriate + before overwriting with return value from resetpwd() + +builtins/type.def + - describe_command: free `full_path' before overwriting it with return + value from sh_makepath + +builtins/complete.def + - compgen_builtin: fix memory leak by calling strlist_dispose (sl) + before overwriting sl with return value from completions_to_stringlist + +builtins/hash.def + - list_hashed_filename_targets: fix memory leak by freeing `target' + +make_cmd.c + - make_arith_for_command: free `init', `test', and `step' before + returning error on parse error + +jobs.c + - initialize_job_control: don't call move_to_high_fd if shell_tty == -1 + +general.c + - check_dev_tty: don't call close with an fd < 0 + - legal_number: deal with NULL `string' argument, return invalid + +lib/sh/fmtulong.c + - fmtulong: if the `base' argument is invalid, make sure we index + buf by `len-1' at maximum + +print_cmd.c + - print_deferred_heredocs: don't try to dereference a NULL `cstring' + - cprintf: make sure to call va_end (args) + +variables.c + - push_dollar_vars: fix call to xrealloc to use sizeof (WORD_LIST *) + instead of sizeof (WORD_LIST **) + +lib/sh/zmapfd.c + - zmapfd: if read returns error, free result and return -1 immediately + instead of trying to reallocate it + + 11/6 + ---- +execute_cmd.c + - cpl_reap: rewrote to avoid using pointer after freeing it; now builds + new coproc list on the fly while traversing the old one and sets the + right values for coproc_list when done + + 11/12 + ----- +builtins/set.def + - if neither -f nor -v supplied, don't allow a readonly function to + be implicitly unset. Fixes bug reported by Jens Schmidt + + +lib/readline/callback.c + - change CALLBACK_READ_RETURN to clear signal handlers before returning + from rl_callback_read_char so readline's signal handlers aren't + installed when readline doesn't have control. Idea from Jan + Kratochvil and the GDB development + team + +pcomplete.h + - COPT_NOQUOTE: new complete/compgen option value + +builtins/complete.def + - noquote: new complete/compgen option; will be used to disable + filename completion quoting + +pcomplete.c + - pcomp_set_readline_variables: pay attention to COPT_NOQUOTE; turns + of rl_filename_quoting_desired if set; turns it on if unset (value + is inverted, since default is on) + +doc/bash.1,lib/readline/doc/rluser.texi + - document new -o noquote option to complete/compgen/compopt + +pathexp.c + - quote_string_for_globbing: if QGLOB_REGEXP, make sure characters + between brackets in an ERE bracket expression are not inappropriately + quoted with backslashes. This is a pretty substantial change, + should be stressed when opening bash up for alpha and beta tests. + Fixes bug pointed out by Stephane Chazleas + + +doc/{bash.1,bashref.texi} + - document that regexp matches can be inconsistent when quoting + characters in bracket expressions, since usual quoting characters + lose their meaning within brackets + - note that regular expression matching when the pattern is stored + in a shell variable which is quoted for expansion causes string + matching + +redir.h + - RX_SAVEFD: new flag value; notes that a redirection denotes an + fd used to save another even if it's not >= SHELL_FD_BASE + +redir.c + - do_redirection_internal: when deciding whether or not to reset the + close-on-exec flag on a restored file descriptor, trust the value + of redirect->flags & RX_SAVCLEXEC even if the fd is < SHELL_FD_BASE + if the RX_SAVEFD flag is set + - add_undo_redirect: set the RX_SAVEFD flag if the file descriptor + limit is such that the shell can't duplicate to a file descriptor + >= 10. Fixes a limitation that tripped a coreutils test reported + by Paul Eggert + + 11/19 + ----- +doc/{bash.1,bashref.texi},lib/readline/doc/hsuser.texi + - make it clear that bash runs HISTFILESIZE=$HISTSIZE after reading + the startup files + - make it clear that bash runs HISTSIZE=500 after reading the + startup files + - make it clear that setting HISTSIZE=0 causes commands to not be + saved in the history list + - make it clear that setting HISTFILESIZE=0 causes the history file + to be truncated to zero size + +variables.c + - sv_histsize: change so setting HISTSIZE to a value less than 0 + causes the history to be `unstifled' + - sv_histsize: change so setting HISTFILESIZE to a value less than 0 + results in no file truncation + - make it clear that numeric values less than 0 for HISTFILESIZE or + HISTSIZE inhibit the usual functions + + 11/23 + ----- +parse.y + - save_input_line_state: add missing `return ls' at the end, since the + function is supposed to return its argument. Pointed out by + Andreas Schwab + +builtins/read.def + - skip over NUL bytes in input, as most modern shells seem to. Bug + report by Matthew Story + +lib/readline/vi_mode.c + - rl_vi_replace: set _rl_vi_last_key_before_insert to invoking key + + 11/25 + ----- +builtins/read.def + - read_builtin: if xrealloc returns same pointer as first argument, + don't bother with the remove_unwind_protect/add_unwind_protect pair + - read_builtin: set a flag (`reading') around calls to zread/zreadc + and readline() + - sigalrm: change to set flag (`sigalrm_seen') and only longjmp if + currently in read(2) (reading != 0) + - CHECK_ALRM: new macro, checks sigalrm_seen and longjmps if non-zero, + behavior of old SIGALRM catching function + - read_builtin: call CHECK_ALRM in appropriate places while reading + line of input. Fixes bug reported by Pierre Gaston + + +lib/readline/vi_mode.c + - rl_vi_replace: initialize characters before printing characters in + vi_replace_keymap to their default values in vi_insertion_keymap, + since we're supposed to be in insert mode replacing characters + - rl_vi_replace: call rl_vi_start_inserting to set last command to + `R' for undo + - rl_vi_replace: set _rl_vi_last_key_before_insert to `R' for future + use by _rl_vi_done_inserting + - vi_save_insert_buffer: new function, broke out code that copies text + into vi_insert_buffer from _rl_vi_save_insert + - _rl_vi_save_replace: new function, saves text modified by + rl_vi_replace (using current point and vi_replace_count to figure + it out) to vi_replace_buffer + - _rl_vi_save_insert: call vi_save_insert_buffer + - _rl_vi_done_inserting: if _rl_vi_last_key_before_insert == 'R', call + _rl_vi_save_replace to save text modified in replace mode (uses + vi_save_insert_buffer) + - _rl_vi_replace_insert: new function, replaces the number of chars + in vi_insert_buffer after rl_point with contents ov vi_insert_buffer + - rl_vi_redo: call _rl_vi_replace_insert if last command == 'R' and + there's something in vi_insert_buffer. Fixes bug with `.' not + redoing the most recent `R' command, reported by Geoff Clare + in readline area on savannah + + 11/26 + ----- +lib/readline/rlprivate.h + - RL_SIG_RECEIVED(): evaluate to non-zero if there is a pending signal + to be handled + - RL_SIGINT_RECEIVED(): evaluate to non-zero if there is a pending + SIGINT to be handled + +lib/readline/complete.c + - remove all mention of _rl_interrupt_immediately + - rl_completion_matches: check RL_SIG_RECEIVED after each call to + the entry function, call RL_CHECK_SIGNALS if true to handle the + signal + - rl_completion_matches: if RL_SIG_RECEIVED evaluates to true, free + and zero out the match_list this function allocated + - rl_completion_matches: if the completion entry function is + rl_filename_completion_function, free the contents of match_list, + because that function does not keep state and will not free the + entries; avoids possible memory leak pointed out by + Garrett Cooper + - gen_completion_matches: if RL_SIG_RECEIVED evalutes to true after + calling rl_attempted_completion_function, free the returned match + list and handle the signal with RL_CHECK_SIGNALS; avoids + possible memory leak pointed out by Garrett Cooper + + - gen_completion_matches: if RL_SIG_RECEIVED evaluates to true after + calling rl_completion_matches, free the returned match list and + handle the signal with RL_CHECK_SIGNALS + +lib/readline/util.c + - rl_settracefp: new utility function to set the tracing FILE * + +lib/readline/signals.c + - _rl_sigcleanup: pointer to a function that will be called with the + signal and a void * argument from _rl_handle_signal + - _rl_sigcleanarg: void * that the rest of the code can set to have + passed to the signal cleanup function + - _rl_handle_signal: if _rl_sigcleanup set, call as + (*_rl_sigcleanup) (sig, _rl_sigcleanarg) + +lib/readline/rlprivate.h + - extern declarations for _rl_sigcleanup and _rl_sigcleanarg + +lib/readline/complete.c + - _rl_complete_sigcleanup: signal cleanup function for completion code; + calls _rl_free_match_list on _rl_sigcleanarg if signal == SIGINT + - rl_complete_internal: before calling display_matches if what_to_do + == `?', set _rl_sigcleanup to _rl_complete_sigcleanup so the match + list gets freed on SIGINT; avoids possible memory leak pointed out + by Garrett Cooper + - rl_complete_internal: in default switch case, call _rl_free_match_list + before returning to avoid memory leak + +doc/bashref.texi + - start at a set of examples for the =~ regular expression matching + operator, touching on keeping the pattern in a shell variable and + quoting portions of the pattern to remove their special meaning + + 12/1 + ---- +lib/glob/gmisc.c + - extglob_pattern: new function, returns 1 if pattern passed as an + argument looks like an extended globbing pattern + +lib/glob/glob.c + - skipname: return 0 immediately if extglob_pattern returns non-zero, + let the extended globbing code do the right thing with skipping + names beginning with a `.' + - mbskipname: return 0 immediately if extglob_pattern returns non-zero, + let the extended globbing code do the right thing with skipping + names beginning with a `.'. Fixes bug reported by Yongzhi Pan + + + 12/2 + ---- +lib/glob/smatch.c + - patscan, patscan_wc: no longer static so other parts of the glob + library can use them, renamed to glob_patscan, glob_patscan_wc + +lib/glob/glob.c + - extern declarations for glob_patscan, glob_patscan_wc + - wchkname: new function, does skipname on wchar_t pattern and dname, + old body of mbskipname after converting to wide chars + - extglob_skipname: new function, checks all subpatterns in an extglob + pattern to determine whether or not a filename should be skipped. + Calls skipname for each subpattern. Dname is only skipped if all + subpatterns indicate it should be. Better fix for bug reported by + Yongzhi Pan + - wextglob_skipname: wide-char version of extglob_skipname, calls + wchkname instead of calling back into mbskipname for each + subpattern to avoid problems with char/wchar_t mismatch + - skipname: call extglob_skipname if extglob_pattern returns non-zero + - mbskipname: call wextglob_skipname if extglob_pattern returns non-zero + - mbskipname: short-circuit immediately if no multibyte chars in + pattern or filename + +execute_cmd.c + - execute_cond_node: added parens to patmatch assignment statement to + make intent clearer + + 12/3 + ---- +configure.in,config.h.in + - check for imaxdiv, define HAVE_IMAXDIV if present + +expr.c + - expassign, exp2: use imaxdiv if available. Doesn't help with checks + for overflow from 10/25 + + 12/6 + ---- +lib/readline/complete.c + - compute_lcd_of_matches: if we're ignoring case in the matches, only + use what the user typed as the lcd if it matches the first match + (after sorting) up to the length of what was typed (if what the + user typed is longer than the shortest of the possible matches, use + the shortest common length of the matches instead). If it doesn't + match, use the first of the list of matches, as if case were not + being ignored. Fixes bug reported by Clark Wang + + + 12/7 + ---- +builtins/cd.def + - cd_builtin: add code to return error in case cd has more than one + non-option argument, conditional on CD_COMPLAINS define (which is + not defined anywhere) + +doc/{bash.1,bashref.texi} + - note that additional arguments to cd following the directory name + are ignored. Suggested by Vaclav Hanzl + + 12/10 + ----- +lib/readline/input.c + - rl_read_key: don't need to increment key sequence length here; doing + it leads to an off-by-one error + +lib/readline/macro.c + - rl_end_kbd_macro: after off-by-one error with rl_key_sequence_length + fixed, can decrement current_macro_index by rl_key_sequence_length + (length of key sequence that closes keyboard macro) + +lib/readline/readline.c + - _rl_dispatch_subseq: fix extra increment of rl_key_sequence_length + when ESC maps to a new keymap and we're converting meta characters + to ESC+key + - _rl_dispatch_subseq: better increment of rl_key_sequence_length + before we dispatch to a function in the ISFUNC case (where the + second increment above should have happened) + - rl_executing_keyseq: the full key sequence that ended up executing + a readline command. Available to the calling application, maintained + by _rl_dispatch_subseq, indexed by rl_key_sequence_length + - rl_executing_key: the key that was bound to the currently-executing + readline command. Same as the `key' argument to the function + +lib/readline/readline.h + - rl_executing_keyseq: extern declaration + - rl_executing_key: extern declaration + - rl_key_sequence_length: declaration moved here from rlprivate.h, + now part of public interface + +lib/readline/rlprivate.h + - new extern declaration for _rl_executing_keyseq_size, buffer size + for rl_executing_keyseq + +lib/readline/doc/rltech.texi + - documented new variables: rl_executing_key, rl_executing_keyseq, + rl_key_sequence_length + + 12/13 + ----- +bashline.c + - bash_execute_unix_command: replace ad-hoc code that searches + cmd_xmap for correct command with call to rl_function_of_keyseq + using rl_executing_keyseq; now supports key sequences longer + than two characters. Fixes bug reported by Michael Kazior + + + 12/15 + ----- +make_cmd.c + - make_function_def: don't null out source_file before calling + make_command so it can be used later on when the function definition + is executed + +execute_cmd.c + - execute_intern_function: second argument is now FUNCTION_DEF * + instead of COMMAND * + - execute_command_internal: call execute_intern_function with the + new second argument (the entire FUNCTION_DEF instead of just the + command member) + - execute_intern_function: if DEBUGGER is defined, call + bind_function_def before calling bind_function, just like + make_function_def does (might be able to take out the call in + make_function_def depending on what the debugger does with it). + Fixes bug reported by + +expr.c + - more minor changes to cases of INTMAX_MIN % -1 and INTMAX_MIN / 1; + fix typos and logic errors + + 12/16 + ----- +bashline.c + - find_cmd_start: change flags to remove SD_NOSKIPCMD so it skips over + command substitutions and doesn't treat them as command separators + - attempt_shell_completion: instead of taking first return from + find_cmd_name as command name to use for programmable completion, + use loop to skip over assignment statements. Fixes problem reported + by Raphael Droz + - attempt_shell_completion: if we don't find a command name but the + command line is non-empty, assume the other words are all assignment + statements and flag that point is in a command position so we can + do command name completion + - attempt_shell_completion: if the word being completed is the first + word following a series of assignment statements, and the + command line is non-empty, flag that point is in a command position + so we can do command name completion + +lib/readline/history.c + - history_get_time: atol -> strtol + + 12/18 + ----- +parse.y + - parser_in_command_position: external interface to the + command_token_position macro for use by other parts of the shell, + like the completion mechanism + +externs.h + - extern declaration for parser_in_command_position + + 12/19 + ----- + +builtins/read.def + - read_builtin: make sure all calls to bind_read_variable are passed + a non-null string. Fixes bug reported by Dan Douglas + + +bashline.c + - attempt_shell_completion: mark that we're in a command position if + we're at the start of the line and the parser is ready to accept + a reserved word or command name. Feature most recently suggested + by Peng Yu + + 12/21 + ----- +lib/readline/bind.c + - _rl_escchar: return the character that would be backslash-escaped + to denote the control character passed as an argument ('\n' -> 'n') + - _rl_isescape: return 1 if character passed is one that has a + backslash escape + - _rl_untranslate_macro_value: new second argument: use_escapes, if + non-zero translate to backslash escapes where possible instead of + using straight \C-x for control character `x'. Change callers + - _rl_untranslate_macro_value: now global + +lib/readline/rlprivate.h + - _rl_untranslate_macro_value: extern declaration + +lib/readline/{macro.c,readline.h} + - rl_print_last_kbd_macro: new bindable function, inspired by patch + from Mitchel Humpherys + +lib/readline/funmap.c + - print-last-kbd-macro: new bindable command, bound to + rl_print_last_kbd_macro + +lib/readline/doc/{rluser.texi,readline.3},doc/bash.1 + - print-last-kbd-macro: document. + +lib/readline/text.c + - _rl_insert_next: if we're defining a macro, make sure the key gets + added to the macro text (should really audit calls to rl_read_key() + and make sure the right thing is happening for all of them) + +bashline.[ch] + - print_unix_command_map: new function, prints all bound commands in + cmd_xmap using rl_macro_dumper in a reusable format + +builtins/bind.def + - new -X option: print all keysequences bound to Unix commands using + print_unix_command_map. Feature suggested by Dennis Williamson + (2/2011) + +doc/{bash.1,bashref.texi} + - document new `bind -X' option + + 12/24 + ----- + +doc/{bash.1,bashref.texi} + - add a couple of sentences to the description of the case modification + operators making it clearer that each character of parameter is + tested against the pattern, and that the pattern should only attempt + to match a single character. Suggested by Bill Gradwohl + + + 12/28 + ----- +shell.c + - init_noninteractive: instead of calling set_job_control(0) to + unconditionally turn off job control, turn on job control if + forced_interactive or jobs_m_flag is set + - shell_initialize: call initialize_job_control with jobs_m_flag as + argument so `bash -m script' enables job control while running the + script + +jobs.c + - initialize_job_control: if the `force' argument is non-zero, turn on + job control even if the shell is not currently interactive + (interactive == 0) + + 12/29 + ----- + +flags.h + - new extern declaration for jobs_m_flag + +builtins/{cd,set}.def,doc/{bash.1,bashref.texi} + - added text clarifying the descriptions of cd -L and -P, suggested by + Padraig Brady + - slight change to the description of `set -P' about resolving symbolic + links + +lib/readline/doc/rluser.texi + - Added an example to the programmable completion section: _comp_cd, + a completion function for cd, with additional verbiage. Text + includes a reference to the bash_completion project + + 1/1/2012 + -------- +jobs.c + - set_job_status_and_cleanup: note that a job is stopped due to + SIGTSTP (any_tstped) if job_control is set; there's no need to + test interactive + + 1/5 + --- +quit.h + - LASTSIG(): new macro, expands to signal number of last terminating + signal received (terminating_signal or SIGINT) + +trap.c + - first_pending_trap: returns lowest signal number with a trap pending + - trapped_signal_received: set to the last trapped signal the shell + received in trap_handler(); reset to 0 in run_pending_traps + +builtins/read.def + - read_builtin: changes to posix-mode (posixly_correct != 0) to make + `read' interruptible by a trapped signal. After the trap runs, + read returns 128+sig and does not assign the partially-read line + to the named variable(s). From an austin-group discussion started + by David Korn + + 1/11 + ---- +doc/{bash.1,bashref.texi} + - slight changes to the descriptions of the compat32 and compat40 shell + options to clarify their meaning + + 1/12 + ---- +lib/readline/{colors.[ch],parse-colors.[ch]} + - new files, part of color infrastructure support + +Makefile.in,lib/readline/Makefile.in + - arrange to have colors.o and parse-colors.o added to readline + library + +{configure,config.h}.in + - check for stdbool.h, define HAVE_STDBOOL_H if found + + 1/14 + ---- +lib/readline/bind.c + - colored_stats: new bindable variable, enables using colors to + indicate file type when listing completions + +lib/readline/complete.c + - _rl_colored_stats: new variable, controlled by colored-stats bindable + variable + - colored_stat_start, colored_stat_end: new functions to set and reset + the terminal color appropriately depending on the type of the + filename to be printed + - print_filename: changes to print colors if `colored-stats' variable + set. Changes contributed by Raphael Droz + + +lib/readline/readline.c + - rl_initialize_everything: add call to _rl_parse_colors to parse + color values out of $LS_COLORS. May have to add to rl_initialize + to make more dynamic if LS_COLORS changes (which doesn't happen + very often, if at all) + +lib/readline/rlprivate.h + - _rl_colored_stats: new extern declaration + +lib/readline/doc/{readline.3,rluser.texi},doc/bash.1 + - colored-stats: document new bindable readline variable + +lib/readline/colors.c + - _rl_print_color_indicator: call rl_filename_stat_hook before calling + lstat/stat so we can get color indicators for stuff like + $HOME/Applications + +lib/readline/complete.c + - stat_char: call rl_filename_stat_hook before calling lstat/stat + +findcmd.[ch],execute_cmd.c + - search_for_command: now takes a second `flags' argument; changed + header function prototype and callers + - search_for_command: if (flags & 1), put the command found in $PATH + into the command hash table (previous default behavior) + +execute_cmd.c + - is_dirname: call search_for_command with flags argument of 0 so it + doesn't try to put something in the command hash table + +bashline.c + - bash_command_name_stat_hook: a hook function for readline's + filename_stat_hook that does $PATH searching the same way that + execute_cmd.c:execute_disk_command() does it, and rewrites the + passed filename if found. Does not put names into command hash + table. This allows command name completion to take advantage + of `visible-stats' and `colored-stats' settings. + - executable_completion: new function, calls the directory completion + hook to expand the filename before calling executable_file or + executable_or_directory; change command_word_completion_function to + call executable_completion. This allows $HOME/bin/[TAB] to do + command completion and display alternatives + + 1/17 + ---- +pcomplete.c + - gen_command_matches: now takes a new second argument: the command + name as deciphered by the programmable completion code and used + to look up the compspec; changed callers (gen_compspec_completions) + - gen_shell_function_matches: now takes a new second argument: the + command that originally caused the completion function to be + invoked; changed callers (gen_compspec_completions)) + - build_arg_list: now takes a new second argument: the command name + corresponding to the current compspec; changed callers + (gen_command_matches, gen_shell_function_matches) + - build_arg_list: now uses `cmd' argument to create $1 passed to + invoked command or shell function + - gen_compspec_completions: if we skipped a null command at the + beginning of the line (e.g., for completing `>'), add a new word for + it at the beginning of the word list and increment nw and cw + appropriately. This is all a partial fix for the shortcoming + pointed out by Sung Pae + + 1/18 + ---- + +{configure,config.h}.in + - new check: check for AUDIT_USER_TTY defined in , + define HAVE_DECL_AUDIT_USER_TTY if both are found + +lib/readline/rlconf.h + - ENABLE_TTY_AUDIT_SUPPORT: new define, allows use of the Linux kernel + tty auditing system if it's available and enabled + +lib/readline/util.c + - _rl_audit_tty: new function, send a string to the kernel tty audit + system + +lib/readline/rlprivate.h + - _rl_audit_tty: new extern declaration + +lib/readline/readline.c + - readline: call _rl_audit_tty with line to be returned before returning + it if the Linux tty audit system is available and it's been enabled + in rlconf.h Original patch from Miroslav Trmac; recent request + from Miroslav Lichvar + + 1/21 + ---- + +lib/readline/readline.c: + - _rl_dispatch_subseq: add an inter-character timeout for multi-char + key sequences. Suggested by . Still needs + work to make a user-settable variable + +parse.y + - shell_getc: make code that uses the pop_alias dependent on ALIAS + define + +variables.h + - sv_tz: extern define should only depend on HAVE_TZSET + +expr.c + - expr_streval: if ARRAY_VARS is not defined, set lvalue->ind to -1; + move assignment to `ind' inside define + - expr_bind_array_element: declaration and uses need to be #ifdef + ARRAY_VARS + +arrayfunc.h + - AV_ALLOWALL, AV_QUOTED, AV_USEIND: define to 0 if ARRAY_VARS not + defined; used in subst.c unconditionally + +sig.h + - make the signal blocking functions not dependent on JOB_CONTROL + +sig.c + - sigprocmask: make the replacement definition not dependent on + JOB_CONTROL + +trap.c + - use BLOCK_SIGNAL/UNBLOCK_SIGNAL instead of code dependent on + HAVE_POSIX_SIGNALS and BSD signals + + 1/24 + ---- + +print_cmd.c + - print_redirection_list: change the conditions under which + r_duplicating_output_word is mapped to r_err_and_out to more or + less match those used in redir.c. Fixes bug pointed out by + Dan Douglas + + + 1/29 + ---- +lib/readline/signals.c + - _rl_block_sigwinch,_rl_release_sigwinch: don't compile in bodies + unless SIGWINCH is defined. Fixes bug reported by Pierre Muller + + +doc/{bash.1,bashref.texi} + - small modifications to the introduction to the REDIRECTION section + to describe how redirections can modify file handles + - small modification to the section describing base#n to make it + clearer that n can be denoted using non-numerics. From a posting + by Linda Walsh + + 2/2 + --- +builtins/printf.def + - printf_builtin: make sure vbuf is intialized and non-null when -v + is supplied, since other parts of the code assume that it's not + null (e.g., bind_printf_variable()). Fixes bug reported by Jim + Avera + + 2/4 + --- +lib/readline/undo.c + - _rl_free_undo_list: new function, old body of rl_free_undo_list, + frees undo entries in UNDO_LIST * passed as argument + - rl_free_undo_list: call _rl_free_undo_list + +lib/readline/rlprivate.h + - _rl_free_undo_list: new extern declaration + - _rl_keyseq_timeout: new extern declaration (see below) + +lib/readline/misc.c + - rl_clear_history: new function. Clears the history list and frees + all associated data similar to history.c:clear_history(), but + takes rl_undo_list into account and frees and UNDO_LISTs saved as + `data' members of a history list entry + +lib/readline/doc/rltech.texi + - rl_clear_history: documented + +lib/readline/readline.c + - _rl_keyseq_timeout: new variable to hold intra-key timeout value + from 1/21 fix; specified in milliseconds. Default value is 500 + - _rl_dispatch_subseq: change to use _rl_keyseq_timeout as intra-key + timeout if it's greater than 0; no timeout if <= 0 + - _rl_dispatch_subseq: don't check for queued keyboard input if we have + pushed or pending input, or if we're reading input from a macro + +lib/readline/bind.c + - keyseq-timeout: new bindable variable, shadows _rl_keyseq_timeout + - string_varlist: add keyseq-timeout + - sv_seqtimeout: new function to modify value of _rl_keyseq_timeout; + clamps negative values at 0 for now + - _rl_get_string_variable_value: return value for keyseq-timeout + +doc/bash.1,lib/readline/doc/{rluser.texi,readline.3} + - keyseq-timeout: documented + +lib/readline/isearch.c + - _rl_isearch_dispatch: modification to fix from 7/18 to not use + cxt->keymap and cxt->okeymap, since by the time this code is + executed, they are equal. Use `f' to check for rl_insert or + unbound func + - _rl_isearch_dispatch: if we're switching keymaps, not in + callback mode, and don't have pending or pushed input, use + _rl_input_queued to resolve a potentially ambiguous key sequence. + Suggested by Roger Zauner + - _rl_isearch_dispatch: if we have changed keymaps and resolved to + an editing function (not self-insert), make sure we stuff the + right characters back onto the input after changing the keymap + back so the right editing function is executed after the search + is terminated. Rest of fix for bug reported by Roger Zauner + + + 2/5 + --- +builtins/gen-helpfiles.c + - new file: reads struct builtin and writes the long docs to files + in the `helpdirs' subdirectory. The filename is given in the + previously-unused `handle' member of the struct builtin. Links + with `tmpbuiltins.o', which is created by Makefile to have the + right long documentation. When not cross-compiling, gets the + right #defines based on configuration options from config.h instead + of trying to parse conditional parts of def files. Fixes + shortcoming pointed out by Andreas Schwab + +builtins/Makefile.in + - tmpbuiltins.c: new generated file, created to enable creation of + separate helpfiles based on correct #defines instead of trying to + parse conditional parts of def files + - gen-helpfiles: new program to generate helpfiles, links with + tmpbuiltins.o + - HELPFILES_TARGET: new target, substituted by configure to `helpdoc' + if separate helpfiles requested + - targets: new target, libbuiltins.a and $(HELPFILES_TARGET) + - CREATED_OBJECTS: new variable, holds created object files for + make clean; changed make clean to remove created objects + - helpdoc: changed to call gen-helpfiles instead of mkbuiltins + +Makefile.in + - when building libbuiltins.a, recursively call make with `targets' + argument to make sure separate helpfiles get built + +configure.in + - substitute `helpdoc' as value of HELPFILES_TARGET if + --enable-separate-helpfiles supplied as configure argument + +builtins/mkbuiltins.c + - `-nofunctions': new argument, causes mkbuiltins to not write value + for function implementing a particular builtin to struct builtin + and to write document file name to `handle' member of struct builtin + - no longer writes separate helpfiles; that is left to gen-helpfiles + + 2/8 + --- +subst.c + - make sure last_command_exit_value is set to a non-zero value before + any calls to report_error, since `-e' set will short-circuit + report_error. Fixes bug reported by Ewan Mellor + + +variables.c + - make_local_array_variable: added second argument; if non-zero, + function will return an existing local associative array variable + instead of insisting on an indexed array + +variable.h,subst.c + - make_local_array_variable: changed prototype and caller + +builtins/declare.def + - declare_internal: add second arg to call to make_local_array_variable; + making_array_special, which indicates we're processing an + assignment like declare a[b]=c. Fixes seg fault resulting from + a being an already-declared local associative array variable in a + function. Ubuntu bash bug 928900. + + 2/14 + ---- + +execute_cmd.c + - execute_command_internal: if redirections into or out of a loop fail, + don't try to free ofifo_list unless saved_fifo is non-zero. It's + only valid if saved_fifo is set + + 2/15 + ---- +{arrayfunc,braces,variables}.c + - last_command_exit_value: make sure it's set before any calls to + report_error, since -e will cause that to exit the shell + +builtins/common.c + - get_job_by_name: call internal_error instead of report_error so this + doesn't exit the shell + + 2/18 + ---- +builtins/evalstring.c + - parse_and_execute: make sure the file descriptor to be redirected to + is 1 before calling cat_file. One fix for bug reported by Dan Douglas + + +parse.y + - read_token_word: don't return NUMBER if a string of all digits + resolves to a number that overflows the bounds of an intmax_t. + Other fix for bug reported by Dan Douglas + + 2/19 + ---- +lib/sh/strtrans.c + - ansicstr: use 0x7f as the boundary for characters that translate + directly from ASCII to unicode (\u and \U escapes) instead of + UCHAR_MAX, since everything >= 0x80 requires more than one byte. + Bug and fix from John Kearney + +builtins/printf.def + - tescape: ditto for printf \u and \U escape sequences + + 2/20 + ---- +lib/sh/unicode.c + - u32toutf8: fix to handle encodings up to six bytes long correctly + (though technically UTF-8 only has characters up to 4 bytes long). + Report and fix from John Kearney + - u32toutf8: first argument is now an unsigned 32-bit quantity, + changed callers (u32cconv) to pass c instead of wc + - u32reset: new function, resets local static state to uninitialized + (locale information, currently) + +locale.c + - call u32reset whenever LC_CTYPE/LC_ALL/LANG is changed to reset the + cached locale information used by u32cconv. From a report from + John Kearney + + 2/21 + ---- +doc/{bash,builtins}.1 + - minor changes from Bjarni Ingi Gislason + +lib/sh/unicode.c + - u32cconv: only assume you can directly call wctomb on the passed + value if __STDC_ISO_10646__ is defined and the value is <= + 0x7fffffff + - stub_charset: return locale as default instead of "ASCII", let + rest of code decide what to do with it + +lib/readline/parens.c + - _rl_enable_paren_matching: make paren matching work in vi insert + mode. Bug report from + + 2/22 + ---- +lib/sh/shquote.c + - sh_backslash_quote: quote tilde in places where it would be + expanded. From a report from John Kearney + + 2/23 + ---- +execute_cmd.c + - execute_pipeline: wrap the discard_unwind_frame call in #ifdef + JOB_CONTROL, since the frame is only created if JOB_CONTROL is + defined. Bug and fix from Doug Kehn + + 2/25 + ---- +error.c + - report_error: make sure last_command_exit_value is non-zero before + we call exit_shell, since the exit trap may reference it. Call + exit_shell with last_command_exit_value to allow exit statuses + other than 1 + +unicode.c + - stub_charset: use local static buffer to hold charset, don't change + value returned by get_locale_var. Based on idea and code from + John Kearney + - u32toutf16: function to convert unsigned 32-bit value (unicode) to + UTF-16. From John Kearney + - u32cconv: call u32toutf16 if __STDC_ISO_10646__ defined and wchar_t + is two bytes, send result to wcstombs, return if not encoding error. + From John Kearney + - u32cconv: return UTF-8 conversion if iconv conversion to local + charset is unsupported + + 3/2 + --- +lib/readline/complete.c + - print_filename: if there is no directory hook, but there is a stat + hook, and we want to append a slash to directories, call the stat + hook before calling path_isdir on the expanded directory name. + Report and pointer to fix from Steve Rago + + 3/3 + --- +builtins/evalstring.c + - parse_and_execute: fix to change of 2/18: make sure the file + descriptor being redirected to is 0 before calling cat_file when + we see something like $(< file). Real fix for bug reported by + Dan Douglas + +subst.c + - parameter_brace_patsub: run the replacement string through quote + removal even if the expansion is within double quotes, because + the parser and string extract functions treat the quotes and + backslashes as special. If they're treated as special, quote + removal should remove them (this is the Posix position and + compatible with ksh93). THIS IS NOT BACKWARDS COMPATIBLE. + + 3/4 + --- +lib/readline/complete.c + - rl_menu_complete: fix to make show-all-if-ambiguous and + menu-complete-display-prefix work together if both are set. Fix + from Sami Pietila + + 3/5 + --- +bashline.c + - dircomplete_expand_relpath: new variable, if non-zero, means that + `shopt -s direxpand' should expand relative pathnames. Zero by + default, not user-settable yet + - bash_directory_completion_hook: if we have a relative pathname that + isn't changed by canonicalization or spell checking after being + appended to $PWD, then don't change what the user typed. Controlled + by dircomplete_expand_relpath + + 3/7 + --- +m4/timespec.m4 + - new macros, cribbed from gnulib and coreutils: find out whether we + have `struct timespec' and what file includes it + +m4/stat-time.m4 + - new macros, cribbed from gnulib and coreutils: find out whether the + mtime/atime/ctime/etctime fields of struct stat are of type + struct timespec, and what the name is + +include/stat-time.h + - new file, cribbed from gnulib, with additions from coreutils: include + the right file to get the struct timespec define, or provide our own + replacement. Provides a bunch of inline functions to turn the + appropriate members of struct stat into `struct timespec' values, + zeroing out the tv_nsec field if necessary + +test.c + - include "stat-time.h" for the nanosecond timestamp resolution stuff + - stat_mtime: new function, returns struct stat and the mod time + normalized into a `struct timespec' for the filename passed as the + first argument + - filecomp: call stat_mtime instead of sh_stat for each filename + argument to get the mtime as a struct timespec + - filecomp: call timespec_cmp instead of using a straight arithmetic + comparison for the -nt and -ot operators, using timespec returned by + stat_mtime. Added functionality requested by by Werner Fink + for systems that can support it + + 3/10 + ---- +include/posixdir.h + - REAL_DIR_ENTRY: remove dependency on _POSIX_SOURCE, only use feature + test macros to decide whether dirent.d_ino is present and usable; + define D_INO_AVAILABLE. Report and fix from Fabrizion Gennari + + - D_FILENO_AVAILABLE: define if we can use dirent.d_fileno + +lib/sh/getcwd.c + - use D_FILENO_AVAILABLE to decide whether or not to compile in + _path_checkino and whether or not to call it. Report and initial + fix from Fabrizion Gennari + +lib/readline/signals.c + - make sure all occurrences of SIGWINCH are protected by #ifdef + +sig.c + - make sure all occurrences of SIGCHLD are protected by #ifdef + +nojobs.c + - make sure SA_RESTART is defined to 0 if the OS doesn't define it + +version.c + - show_shell_version: don't use string literals in printf, use %s. + Has added benefit of removing newline from string to be translated + +trap.c + - queue_sigchld_trap: new function, increments the number of pending + SIGCHLD signals by the argument, which is by convention the number + of children reaped in a call to waitchld() + +trap.h + - queue_sigchld_trap: new extern declaration + +jobs.c + - waitchld: if called from the SIGCHLD signal handler (sigchld > 0), + then call queue_sigchld_trap to avoid running the trap in a signal + handler context. Report and original fix from Siddhesh Poyarekar + + +lib/sh/unicode.c + - u32tocesc: take an unsigned 32-bit quantity and encode it using + ISO C99 string notation (\u/\U) + - u32cconv: call u32tocesc as a fallback instead of u32cchar + - u32cconv: call u32tocesc if iconv cannot convert the character. + Maybe do the same thing if iconv_open fails + - u32reset: call iconv_close on localconv if u32init == 1 + + 3/11 + ---- +config-top.h + - CHECKWINSIZE_DEFAULT: new define, set to initial value of + check_window_size (shopt checkwinsize): 0 for off, 1 for on. + Default is 0 + +{jobs,nojobs}.c + - check_window_size: default initial value to CHECKWINSIZE_DEFAULT + + 3/13 + ---- +doc/bashref.texi + - change text referring to the copying restrictions to that + recommended by the FSF (no Front-Cover Texts and no Back-Cover + Texts) + +lib/readline/doc/{history,rlman,rluserman}.texi + - change text referring to the copying restrictions to that + recommended by the FSF (no Front-Cover Texts and no Back-Cover + Texts) + + 3/15 + ---- +array.c + - LASTREF_START: new macro to set the starting position for an array + traversal to `lastref' if that's valid, and to the start of the array + if not. Used in array_reference, array_insert, array_remove + - array_remove: try to be a little smarter with lastref instead of + unconditionally invalidating it + + 3/16 + ---- +array.c + - array_insert: fix memory leak by deleting element to be added in the + case of an error + + 3/18 + ---- +lib/sh/mbschr.c + - mbschr: don't call mbrlen unless is_basic is false; devolves to a + straight character-by-character run through the string + + 3/19 + ---- +stringlib.c + - substring: use memcpy instead of strncpy, since we know the length + and are going to add our own NUL terminator + + 3/20 + ---- +subst.c + - parameter_brace_expand_rhs: if expand_string_for_rhs returns a quoted + null string (a list with one element for which + QUOTED_NULL(list->word->word) returns true), return the quoted null + and set the flags in the returned word to indicate it. Fixes bug + reported by Mark Edgar + +lib/sh/tmpfile.c + - use random(3) instead of get_random_number to avoid perturbing the + random sequence you get using $RANDOM. Bug report and fix from + Jurij Mihelic + + 3/21 + ---- +config-top.h + - OPTIMIZE_SEQUENTIAL_ARRAY_ASSIGNMENT: define to 1 to optimize + sequential indexed array assignment patterns. Defined to 1 by + default + +array.c + - array_insert: if OPTIMIZE_SEQUENTIAL_ARRAY_ASSIGNMENT is defined, + start the search at lastref (see change from 3/15) + + 3/27 + ---- +print_cmd.c + - debug_print_word_list: new debugging function, prints a word list + preceded by an optional string and using a caller-specified + separator + + 4/1 + --- +command.h + - W_ASSNGLOBAL: new flag, set to indicate declare -g + +execute_cmd.c + - fix_assignment_words: note that we have a -g argument to an assignment + builtin and set the W_ASSNGLOBAL flag in the variable word + +subst.c + - dump_word_flags: print out W_ASSNGLOBAL if present + - do_assignment_internal: only set ASS_MKLOCAL if W_ASSIGNARG is set + and W_ASSNGLOBAL is not. Don't want to create a local variable even + if variable_context is non-zero if ASSNGLOBAL is set. Fixes bug + reported by Bill Gradwohl + + 4/7 + --- +lib/readline/readline.c + - _rl_dispatch_subseq: make the `keyseq-timeout' variable apply to + ESC processing when in vi mode. After hitting ESC, readline will + wait up to _rl_keyseq_timeout*1000 microseconds (if set) for + additional input before dispatching on the ESC and switching to + command/movement mode. Completes timeout work suggested by + ; this prompted by report from Barry Downes + + +lib/sh/shmbchar.c + - sh_mbsnlen: new function, returns the number of (possibly multibyte) + characters in a passed string with a passed length, examining at most + maxlen (third argument) bytes + +externs.h + - sh_mbsnlen: extern declaration for new function + +shell.c + - exit_shell: call maybe_save_shell_history if remember_on_history is + set, not just in interactive shells. That means the history is + saved if history is enabled, regardless of whether or not the shell + is interactive + +doc/{bash.1,bashref.texi} + - TMOUT: fix description to make it explicit that TMOUT is the timeout + period for a complete line of input, not just any input. Fixes + problem reported in Ubuntu bug 957303: + https://bugs.launchpad.net/ubuntu/+source/bash/+bug/957303 + - HISTFILE: document change to write history list to history file in + any shell with history enabled, not just interactive shells. This + seems to be more logical behavior. Suggested by Greg Wooledge + + + 4/12 + ---- +lib/readline/colors.h + - only include stdbool.h if HAVE_STDBOOL_H is defined + - if HAVE_STDBOOL_H is not defined, provide enough definition for the + library to use `bool', `true', and `false' + +lib/readline/parse-colors.[ch] + - don't try to include at all; rely on colors.h to do it + +lib/sh/snprintf.c + - vsnprintf_internal: only treat '0' as a flag to indicate zero padding + if `.' hasn't been encountered ((flags&PF_DOT) == 0); otherwise treat + it as the first digit of a precision specifier. Fixes bug reported + by Petr Sumbera + + 4/15 + ---- +lib/sh/snprintf.c + - vsnprintf_internal: if the '0' and '-' flags both occur, the '0' + flag is ignored -- Posix. Start of a series of fixes based on + tests and patches from Petr Sumbera + - PUT_PLUS: make sure PF_PLUS flag is specified before putting the `+' + - vsnprintf_internal: when '+' is read as a flag, don't set right- + justify flag if the LADJUST (`-') flag has already been supplied + - floating: make sure to output space padding before the `+', zero + padding after + - exponent: make sure to output space padding before the `+', zero + padding after + - exponent: only subtract one from the width for the decimal point + if we're really going to print one + - floating: use presence of PF_PLUS flag to decide whether to account + for the `+' in the padded field width. Ditto for exponent() + + 4/16 + ---- +lib/sh/snprintf.c + - vsnprint_internal: only reduce precision by 1 when processing the `g' + format if it's > 0. A precision of 0 should stay 0; otherwise it + gets set to -1 (NOT_FOUND) and converted to the default + - number, lnumber: if an explicit precision is supplied, turn off the + zero-padding flag and set the pad character back to space + - number, lnumber: only account for a `+' when performing the field + width calculation if the coversion is base 10; we don't add a `+' + for other bases + + 4/18 + ---- +tests/printf3.sub + - try using "perl -e 'print time'" to get the current time in seconds + since the epoch if "date +%s" is not available (solaris 8-10) + + 4/19 + ---- +tests/run-printf + - use cat -v instead of relying on diff -a being available to convert + control characters to ascii and avoid the dreaded "Binary files + /tmp/xx and printf.right differ" + + 4/20 + ---- +lib/sh/strftime.c + - incoporated new version from Aharon Robbins + + 4/22 + ---- +doc/{bash.1,bashref.texi} + - slight change to the description of /dev/tcp and /dev/udp + +subst.c + - match_wpattern: logic fix to the calculation of `simple' (was |=, + needs to be &=). Bug report from Mike Frysinger , + fix from Andreas Schwab + +bashline.c + - bash_filename_stat_hook: add code from bash_directory_completion_hook + that performs pathname canonicalization in the same way that cd and + other builtins will do + + 4/25 + ---- +execute_cmd.c + - execute_pipeline: change the call to move_to_high_fd to make it use + getdtablesize() and to not stomp on existing open file descriptors, + like the fd the shell is using to read a script. Bug report from + Greg Wooledge + + 5/6 + --- +subst.c + - expand_word_internal: case '$': after calling param_expand and + setting had_quoted_null, set TEMP to null. The code that builds the + returned string at the end of the function will take care of making + and returning a quoted null string if there's nothing else in + ISTRING. If there is, the quoted null should just go away. Part of + fix for bug reported by Ruediger Kuhlmann diff --git a/CWRU/POSIX.NOTES.old b/CWRU/POSIX.NOTES.old new file mode 100644 index 000000000..1707ab10c --- /dev/null +++ b/CWRU/POSIX.NOTES.old @@ -0,0 +1,82 @@ +Starting bash with the `--posix' command-line option or executing +`set -o posix' while bash is running will cause bash to conform more +closely to the Posix.2 standard by changing the behavior to match that +specified by Posix.2 in areas where the bash default differs. + +The following list is what's changed when `posix mode' is in effect: + +1. When a command in the hash table no longer exists, bash will re-search + $PATH to find the new location. This is also available with + `shopt -s checkhash'. + +2. The >& redirection does not redirect stdout and stderr. + +3. The message printed by the job control code and builtins when a job + exits with a non-zero status is `Done(status)'. + +4. Reserved words may not be aliased. + +5. The Posix.2 PS1 and PS2 expansions of `!' -> history number and + `!!' -> `!' are enabled, and parameter expansion is performed on + the value regardless of the setting of the `promptvars' option. + +6. Interactive comments are enabled by default. (Note that bash has + them on by default anyway.) + +7. The Posix.2 startup files are executed ($ENV) rather than the normal + bash files. + +8. Tilde expansion is only performed on assignments preceding a command + name, rather than on all assignment statements on the line. + +9. The default history file is ~/.sh_history (default value of $HISTFILE). + +10. The output of `kill -l' prints all the signal names on a single line, + separated by spaces. + +11. Non-interactive shells exit if `file' in `. file' is not found. + +12. Redirection operators do not perform pathname expansion on the word + in the redirection unless the shell is interactive + +13. Function names must be valid shell identifiers. That is, they may not + contain characters other than letters, digits, and underscores, and + may not start with a digit. Declaring a function with an illegal name + causes a fatal syntax error in non-interactive shells. + +14. Posix.2 `special' builtins are found before shell functions during command + lookup. + +15. If a Posix.2 special builtin returns an error status, a non-interactive + shell exits. The fatal errors are those listed in the POSIX.2 standard, + and include things like passing incorrect options, redirection errors, + variable assignment errors for assignments preceding the command name, + and so on. + +16. The environment passed to executed commands is not sorted. Neither is + the output of `set'. This is not strictly Posix.2 behavior, but sh + does it this way. Ksh does not. It's not necessary to sort the + environment; no program should rely on it being sorted. + +17. If the `cd' builtin finds a directory to change to using $CDPATH, the + value it assigns to $PWD does not contain any symbolic links, as if + `cd -P' had been executed. + +18. A non-interactive shell exits with an error status if a variable + assignment error occurs when no command name follows the assignment + statements. A variable assignment error occurs, for example, when + trying to assign a value to a read-only variable. + +19. A non-interactive shell exits with an error status if the iteration + variable in a for statement or the selection variable in a select + statement is a read-only variable. + +20. Process substitution is not available. + +21. Assignment statements preceding POSIX.2 `special' builtins persist in + the shell environment after the builtin completes. + +There is other Posix.2 behavior that bash does not implement. Specifically: + +1. Assignment statements affect the execution environment of all builtins, + not just special ones. diff --git a/CWRU/old/set.def.save b/CWRU/old/set.def.save new file mode 100644 index 000000000..87b78d7cc --- /dev/null +++ b/CWRU/old/set.def.save @@ -0,0 +1,544 @@ +This file is set.def, from which is created set.c. +It implements the "set" and "unset" builtins in Bash. + +Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc. + +This file is part of GNU Bash, the Bourne Again SHell. + +Bash is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 1, or (at your option) any later +version. + +Bash is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with Bash; see the file COPYING. If not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +$PRODUCES set.c + +#include +#include "../shell.h" +#include "../flags.h" + +#include "bashgetopt.h" + +extern int interactive; +extern int noclobber, posixly_correct; +#if defined (READLINE) +extern int rl_editing_mode, no_line_editing; +#endif /* READLINE */ + +$BUILTIN set +$FUNCTION set_builtin +$SHORT_DOC set [--abefhkmnptuvxldBCHP] [-o option] [arg ...] + -a Mark variables which are modified or created for export. + -b Notify of job termination immediately. + -e Exit immediately if a command exits with a non-zero status. + -f Disable file name generation (globbing). + -h Locate and remember function commands as functions are + defined. Function commands are normally looked up when + the function is executed. + -i Force the shell to be an "interactive" one. Interactive shells + always read `~/.bashrc' on startup. + -k All keyword arguments are placed in the environment for a + command, not just those that precede the command name. + -m Job control is enabled. + -n Read commands but do not execute them. + -o option-name + Set the variable corresponding to option-name: + allexport same as -a + braceexpand same as -B +#if defined (READLINE) + emacs use an emacs-style line editing interface +#endif /* READLINE */ + errexit same as -e + histexpand same as -H + ignoreeof the shell will not exit upon reading EOF + interactive-comments + allow comments to appear in interactive commands + monitor same as -m + noclobber disallow redirection to existing files + noexec same as -n + noglob same as -f + nohash same as -d + notify save as -b + nounset same as -u + physical same as -P + posix change the behavior of bash where the default + operation differs from the 1003.2 standard to + match the standard + privileged same as -p + verbose same as -v +#if defined (READLINE) + vi use a vi-style line editing interface +#endif /* READLINE */ + xtrace same as -x + -p Turned on whenever the real and effective user ids do not match. + Disables processing of the $ENV file and importing of shell + functions. Turning this option off causes the effective uid and + gid to be set to the real uid and gid. + -t Exit after reading and executing one command. + -u Treat unset variables as an error when substituting. + -v Print shell input lines as they are read. + -x Print commands and their arguments as they are executed. + -l Save and restore the binding of the NAME in a FOR command. + -d Disable the hashing of commands that are looked up for execution. + Normally, commands are remembered in a hash table, and once + found, do not have to be looked up again. +#if defined (BRACE_EXPANSION) + -B the shell will perform brace expansion +#endif /* BRACE_EXPANSION */ +#if defined (BANG_HISTORY) + -H Enable ! style history substitution. This flag is on + by default. +#endif /* BANG_HISTORY */ + -C If set, disallow existing regular files to be overwritten + by redirection of output. + -P If set, do not follow symbolic links when executing commands + such as cd which change the current directory. + +Using + rather than - causes these flags to be turned off. The +flags can also be used upon invocation of the shell. The current +set of flags may be found in $-. The remaining n ARGs are positional +parameters and are assigned, in order, to $1, $2, .. $n. If no +ARGs are given, all shell variables are printed. +$END + +/* An a-list used to match long options for set -o to the corresponding + option letter. */ +struct { + char *name; + int letter; +} o_options[] = { + { "allexport", 'a' }, +#if defined (BRACE_EXPANSION) + { "braceexpand",'B' }, +#endif + { "errexit", 'e' }, + { "histexpand", 'H' }, + { "monitor", 'm' }, + { "noexec", 'n' }, + { "noglob", 'f' }, + { "nohash", 'd' }, +#if defined (JOB_CONTROL) + { "notify", 'b' }, +#endif /* JOB_CONTROL */ + {"nounset", 'u' }, + {"physical", 'P' }, + {"privileged", 'p' }, + {"verbose", 'v' }, + {"xtrace", 'x' }, + {(char *)NULL, 0}, +}; + +#define MINUS_O_FORMAT "%-15s\t%s\n" + +void +list_minus_o_opts () +{ + register int i; + char *on = "on", *off = "off"; + + printf (MINUS_O_FORMAT, "noclobber", (noclobber == 1) ? on : off); + + if (find_variable ("ignoreeof") || find_variable ("IGNOREEOF")) + printf (MINUS_O_FORMAT, "ignoreeof", on); + else + printf (MINUS_O_FORMAT, "ignoreeof", off); + + printf (MINUS_O_FORMAT, "interactive-comments", + interactive_comments ? on : off); + + printf (MINUS_O_FORMAT, "posix", posixly_correct ? on : off); + +#if defined (READLINE) + if (no_line_editing) + { + printf (MINUS_O_FORMAT, "emacs", off); + printf (MINUS_O_FORMAT, "vi", off); + } + else + { + /* Magic. This code `knows' how readline handles rl_editing_mode. */ + printf (MINUS_O_FORMAT, "emacs", (rl_editing_mode == 1) ? on : off); + printf (MINUS_O_FORMAT, "vi", (rl_editing_mode == 0) ? on : off); + } +#endif /* READLINE */ + + for (i = 0; o_options[i].name; i++) + { + int *on_or_off, zero = 0; + + on_or_off = find_flag (o_options[i].letter); + if (on_or_off == FLAG_UNKNOWN) + on_or_off = &zero; + printf (MINUS_O_FORMAT, o_options[i].name, (*on_or_off == 1) ? on : off); + } +} + +set_minus_o_option (on_or_off, option_name) + int on_or_off; + char *option_name; +{ + int option_char = -1; + + if (STREQ (option_name, "noclobber")) + { + if (on_or_off == FLAG_ON) + bind_variable ("noclobber", ""); + else + unbind_variable ("noclobber"); + stupidly_hack_special_variables ("noclobber"); + } + else if (STREQ (option_name, "ignoreeof")) + { + unbind_variable ("ignoreeof"); + unbind_variable ("IGNOREEOF"); + if (on_or_off == FLAG_ON) + bind_variable ("IGNOREEOF", "10"); + stupidly_hack_special_variables ("IGNOREEOF"); + } + +#if defined (READLINE) + else if ((STREQ (option_name, "emacs")) || (STREQ (option_name, "vi"))) + { + if (on_or_off == FLAG_ON) + { + rl_variable_bind ("editing-mode", option_name); + + if (interactive) + with_input_from_stdin (); + no_line_editing = 0; + } + else + { + int isemacs = (rl_editing_mode == 1); + if ((isemacs && STREQ (option_name, "emacs")) || + (!isemacs && STREQ (option_name, "vi"))) + { + if (interactive) + with_input_from_stream (stdin, "stdin"); + no_line_editing = 1; + } + else + builtin_error ("not in %s editing mode", option_name); + } + } +#endif /* READLINE */ + else if (STREQ (option_name, "interactive-comments")) + interactive_comments = (on_or_off == FLAG_ON); + else if (STREQ (option_name, "posix")) + { + posixly_correct = (on_or_off == FLAG_ON); + unbind_variable ("POSIXLY_CORRECT"); + unbind_variable ("POSIX_PEDANTIC"); + if (on_or_off == FLAG_ON) + { + bind_variable ("POSIXLY_CORRECT", ""); + stupidly_hack_special_variables ("POSIXLY_CORRECT"); + } + } + else + { + register int i; + for (i = 0; o_options[i].name; i++) + { + if (STREQ (option_name, o_options[i].name)) + { + option_char = o_options[i].letter; + break; + } + } + if (option_char == -1) + { + builtin_error ("%s: unknown option name", option_name); + return (EXECUTION_FAILURE); + } + if (change_flag (option_char, on_or_off) == FLAG_ERROR) + { + bad_option (option_name); + return (EXECUTION_FAILURE); + } + } + return (EXECUTION_SUCCESS); +} + +/* Set some flags from the word values in the input list. If LIST is empty, + then print out the values of the variables instead. If LIST contains + non-flags, then set $1 - $9 to the successive words of LIST. */ +set_builtin (list) + WORD_LIST *list; +{ + int on_or_off, flag_name, force_assignment = 0; + + if (!list) + { + SHELL_VAR **vars; + + vars = all_shell_variables (); + if (vars) + { + print_var_list (vars); + free (vars); + } + + vars = all_shell_functions (); + if (vars) + { + print_var_list (vars); + free (vars); + } + + return (EXECUTION_SUCCESS); + } + + /* Check validity of flag arguments. */ + if (*list->word->word == '-' || *list->word->word == '+') + { + register char *arg; + WORD_LIST *save_list = list; + + while (list && (arg = list->word->word)) + { + char c; + + if (arg[0] != '-' && arg[0] != '+') + break; + + /* `-' or `--' signifies end of flag arguments. */ + if (arg[0] == '-' && + (!arg[1] || (arg[1] == '-' && !arg[2]))) + break; + + while (c = *++arg) + { + if (find_flag (c) == FLAG_UNKNOWN && c != 'o') + { + char s[2]; + s[0] = c; s[1] = '\0'; + bad_option (s); + if (c == '?') + builtin_usage (); + return (c == '?' ? EXECUTION_SUCCESS : EXECUTION_FAILURE); + } + } + list = list->next; + } + list = save_list; + } + + /* Do the set command. While the list consists of words starting with + '-' or '+' treat them as flags, otherwise, start assigning them to + $1 ... $n. */ + while (list) + { + char *string = list->word->word; + + /* If the argument is `--' or `-' then signal the end of the list + and remember the remaining arguments. */ + if (string[0] == '-' && (!string[1] || (string[1] == '-' && !string[2]))) + { + list = list->next; + + /* `set --' unsets the positional parameters. */ + if (string[1] == '-') + force_assignment = 1; + + /* Until told differently, the old shell behaviour of + `set - [arg ...]' being equivalent to `set +xv [arg ...]' + stands. Posix.2 says the behaviour is marked as obsolescent. */ + else + { + change_flag ('x', '+'); + change_flag ('v', '+'); + } + + break; + } + + if ((on_or_off = *string) && + (on_or_off == '-' || on_or_off == '+')) + { + int i = 1; + while (flag_name = string[i++]) + { + if (flag_name == '?') + { + builtin_usage (); + return (EXECUTION_SUCCESS); + } + else if (flag_name == 'o') /* -+o option-name */ + { + char *option_name; + WORD_LIST *opt; + + opt = list->next; + + if (!opt) + { + list_minus_o_opts (); + continue; + } + + option_name = opt->word->word; + + if (!option_name || !*option_name || (*option_name == '-')) + { + list_minus_o_opts (); + continue; + } + list = list->next; /* Skip over option name. */ + + if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS) + return (EXECUTION_FAILURE); + } + else + { + if (change_flag (flag_name, on_or_off) == FLAG_ERROR) + { + char opt[3]; + opt[0] = on_or_off; + opt[1] = flag_name; + opt[2] = '\0'; + bad_option (opt); + builtin_usage (); + return (EXECUTION_FAILURE); + } + } + } + } + else + { + break; + } + list = list->next; + } + + /* Assigning $1 ... $n */ + if (list || force_assignment) + remember_args (list, 1); + return (EXECUTION_SUCCESS); +} + +$BUILTIN unset +$FUNCTION unset_builtin +$SHORT_DOC unset [-f] [-v] [name ...] +For each NAME, remove the corresponding variable or function. Given +the `-v', unset will only act on variables. Given the `-f' flag, +unset will only act on functions. With neither flag, unset first +tries to unset a variable, and if that fails, then tries to unset a +function. Some variables (such as PATH and IFS) cannot be unset; also +see readonly. +$END + +#define NEXT_VARIABLE() any_failed++; list = list->next; continue; + +unset_builtin (list) + WORD_LIST *list; +{ + int unset_function, unset_variable, unset_array, opt, any_failed; + char *name; + + unset_function = unset_variable = unset_array = any_failed = 0; + + reset_internal_getopt (); + while ((opt = internal_getopt (list, "fv")) != -1) + { + switch (opt) + { + case 'f': + unset_function = 1; + break; + case 'v': + unset_variable = 1; + break; + default: + builtin_usage (); + return (EXECUTION_FAILURE); + } + } + + list = loptend; + + if (unset_function && unset_variable) + { + builtin_error ("cannot simultaneously unset a function and a variable"); + return (EXECUTION_FAILURE); + } + + while (list) + { + SHELL_VAR *var; + int tem; +#if defined (ARRAY_VARS) + char *t; +#endif + + name = list->word->word; + +#if defined (ARRAY_VARS) + if (!unset_function && valid_array_reference (name)) + { + t = strchr (name, '['); + *t++ = '\0'; + unset_array++; + } +#endif + + var = unset_function ? find_function (name) : find_variable (name); + + if (var && !unset_function && non_unsettable_p (var)) + { + builtin_error ("%s: cannot unset", name); + NEXT_VARIABLE (); + } + + /* Posix.2 says that unsetting readonly variables is an error. */ + if (var && readonly_p (var)) + { + builtin_error ("%s: cannot unset: readonly %s", + name, unset_function ? "function" : "variable"); + NEXT_VARIABLE (); + } + + /* Unless the -f option is supplied, the name refers to a variable. */ +#if defined (ARRAY_VARS) + if (var && unset_array) + { + if (array_p (var) == 0) + { + builtin_error ("%s: not an array variable", name); + NEXT_VARIABLE (); + } + else + tem = unbind_array_element (var, t); + } + else +#endif /* ARRAY_VARS */ + tem = makunbound (name, unset_function ? shell_functions : shell_variables); + + /* This is what Posix.2 draft 11+ says. ``If neither -f nor -v + is specified, the name refers to a variable; if a variable by + that name does not exist, a function by that name, if any, + shall be unset.'' */ + if ((tem == -1) && !unset_function && !unset_variable) + tem = makunbound (name, shell_functions); + + if (tem == -1) + any_failed++; + else if (!unset_function) + stupidly_hack_special_variables (name); + + list = list->next; + } + + if (any_failed) + return (EXECUTION_FAILURE); + else + return (EXECUTION_SUCCESS); +} diff --git a/CWRU/save/unwind_prot.h.save b/CWRU/save/unwind_prot.h.save new file mode 100644 index 000000000..998fd72b6 --- /dev/null +++ b/CWRU/save/unwind_prot.h.save @@ -0,0 +1,50 @@ +/* unwind_prot.h - Macros and functions for hacking unwind protection. */ + +/* Copyright (C) 1993 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + Bash is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with Bash; see the file COPYING. If not, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#if !defined (_UNWIND_PROT_H) +#define _UNWIND_PROT_H + +/* Run a function without interrupts. */ +extern void begin_unwind_frame (); +extern void discard_unwind_frame (); +extern void run_unwind_frame (); +extern void add_unwind_protect (); +extern void remove_unwind_protect (); +extern void run_unwind_protects (); +extern void unwind_protect_var (); + +/* Define for people who like their code to look a certain way. */ +#define end_unwind_frame() + +/* How to protect an integer. */ +#define unwind_protect_int(X) unwind_protect_var (&(X), (char *)(X), sizeof (int)) + +/* How to protect a pointer to a string. */ +#define unwind_protect_string(X) \ + unwind_protect_var ((int *)&(X), (X), sizeof (char *)) + +/* How to protect any old pointer. */ +#define unwind_protect_pointer(X) unwind_protect_string (X) + +/* How to protect the contents of a jmp_buf. */ +#define unwind_protect_jmp_buf(X) \ + unwind_protect_var ((int *)(X), (char *)(X), sizeof (procenv_t)) + +#endif /* _UNWIND_PROT_H */ diff --git a/MANIFEST b/MANIFEST index 49b906fef..770102d45 100644 --- a/MANIFEST +++ b/MANIFEST @@ -942,6 +942,7 @@ tests/intl2.sub f tests/intl.right f tests/iquote.tests f tests/iquote.right f +tests/iquote1.sub f tests/invert.tests f tests/invert.right f tests/jobs.tests f diff --git a/MANIFEST~ b/MANIFEST~ new file mode 100644 index 000000000..49b906fef --- /dev/null +++ b/MANIFEST~ @@ -0,0 +1,1211 @@ +# +# Master distribution manifest for bash +# +# +# Filename type +# +CWRU d +CWRU/misc d +builtins d +cross-build d +doc d +examples d +examples/obashdb d +examples/complete d +examples/functions d +examples/scripts d +examples/scripts.v2 d +examples/scripts.noah d +examples/startup-files d +examples/startup-files/apple d +examples/misc d +examples/loadables d +examples/loadables/perl d +include d +lib d +lib/glob d +lib/glob/doc d +lib/intl d +lib/malloc d +lib/readline d +lib/readline/doc d +lib/readline/examples d +lib/sh d +lib/termcap d +lib/tilde d +m4 d +po d +support d +tests d +tests/misc d +ABOUT-NLS f +ChangeLog s CWRU/changelog +CHANGES f +COMPAT f +COPYING f +INSTALL f +MANIFEST f +NEWS f +NOTES f +POSIX f +README f +RBASH f +AUTHORS f +Y2K f +configure.in f +configure f 755 +Makefile.in f +config-top.h f +config-bot.h f +config.h.in f +aclocal.m4 f +array.c f +arrayfunc.c f +assoc.c f +eval.c f +print_cmd.c f +general.c f +list.c f +locale.c f +stringlib.c f +variables.c f +make_cmd.c f +copy_cmd.c f +unwind_prot.c f +dispose_cmd.c f +bashhist.c f +hashcmd.c f +hashlib.c f +parse.y f +pathexp.c f +subst.c f +shell.c f +trap.c f +sig.c f +siglist.c f +version.c f +flags.c f +jobs.c f +input.c f +mailcheck.c f +test.c f +expr.c f +alias.c f +execute_cmd.c f +findcmd.c f +redir.c f +bashline.c f +braces.c f +bracecomp.c f +nojobs.c f +error.c f +xmalloc.c f +pcomplete.c f +pcomplib.c f +mksyntax.c f +alias.h f +builtins.h f +bashhist.h f +bashline.h f +conftypes.h f +patchlevel.h f +variables.h f +array.h f +arrayfunc.h f +assoc.h f +jobs.h f +findcmd.h f +hashlib.h f +quit.h f +flags.h f +shell.h f +syntax.h f +pathexp.h f +parser.h f +pcomplete.h f +sig.h f +test.h f +trap.h f +general.h f +unwind_prot.h f +input.h f +error.h f +command.h f +externs.h f +siglist.h f +subst.h f +dispose_cmd.h f +hashcmd.h f +bashansi.h f +bashjmp.h f +bashintl.h f +make_cmd.h f +execute_cmd.h f +redir.h f +bashtypes.h f +mailcheck.h f +xmalloc.h f +y.tab.c f +y.tab.h f +parser-built f +pathnames.h.in f +builtins/Makefile.in f +builtins/alias.def f +builtins/bind.def f +builtins/break.def f +builtins/builtin.def f +builtins/caller.def f +builtins/cd.def f +builtins/colon.def f +builtins/command.def f +builtins/complete.def f +builtins/common.c f +builtins/declare.def f +builtins/echo.def f +builtins/enable.def f +builtins/eval.def f +builtins/evalfile.c f +builtins/evalstring.c f +builtins/exec.def f +builtins/exit.def f +builtins/fc.def f +builtins/fg_bg.def f +builtins/gen-helpfiles.c f +builtins/getopt.c f +builtins/getopt.h f +builtins/getopts.def f +builtins/hash.def f +builtins/help.def f +builtins/let.def f +builtins/history.def f +builtins/jobs.def f +builtins/kill.def f +builtins/mapfile.def f +builtins/mkbuiltins.c f +builtins/printf.def f +builtins/pushd.def f +builtins/read.def f +builtins/reserved.def f +builtins/return.def f +builtins/set.def f +builtins/setattr.def f +builtins/shift.def f +builtins/shopt.def f +builtins/source.def f +builtins/suspend.def f +builtins/test.def f +builtins/times.def f +builtins/trap.def f +builtins/type.def f +builtins/ulimit.def f +builtins/umask.def f +builtins/wait.def f +builtins/psize.c f +builtins/psize.sh f +builtins/inlib.def f +builtins/bashgetopt.c f +builtins/common.h f +builtins/bashgetopt.h f +cross-build/cygwin32.cache f +cross-build/x86-beos.cache f +cross-build/opennt.cache f +include/ansi_stdlib.h f +include/chartypes.h f +include/filecntl.h f +include/gettext.h f +include/maxpath.h f +include/memalloc.h f +include/ocache.h f +include/posixdir.h f +include/posixjmp.h f +include/posixselect.h f +include/posixstat.h f +include/posixtime.h f +include/posixwait.h f +include/shmbchar.h f +include/shmbutil.h f +include/shtty.h f +include/stat-time.h f +include/stdc.h f +include/systimes.h f +include/typemax.h f +include/unionwait.h f +lib/glob/Makefile.in f +lib/glob/sm_loop.c f +lib/glob/smatch.c f +lib/glob/strmatch.c f +lib/glob/strmatch.h f +lib/glob/glob.c f +lib/glob/glob.h f +lib/glob/glob_loop.c f +lib/glob/gmisc.c f +lib/glob/xmbsrtowcs.c f +lib/glob/collsyms.h f +lib/glob/doc/Makefile f +lib/glob/doc/glob.texi f +lib/glob/ndir.h f +lib/intl/ChangeLog f +lib/intl/Makefile.in f +lib/intl/VERSION f +lib/intl/bindtextdom.c f +lib/intl/config.charset f +lib/intl/dcgettext.c f +lib/intl/dcigettext.c f +lib/intl/dcngettext.c f +lib/intl/dgettext.c f +lib/intl/dngettext.c f +lib/intl/eval-plural.h f +lib/intl/explodename.c f +lib/intl/finddomain.c f +lib/intl/gettext.c f +lib/intl/gettextP.h f +lib/intl/gmo.h f +lib/intl/hash-string.h f +lib/intl/intl-compat.c f +lib/intl/l10nflist.c f +lib/intl/libgnuintl.h.in f +lib/intl/loadinfo.h f +lib/intl/loadmsgcat.c f +lib/intl/localcharset.c f +lib/intl/localcharset.h f +lib/intl/locale.alias f +lib/intl/localealias.c f +lib/intl/localename.c f +lib/intl/log.c f +lib/intl/ngettext.c f +lib/intl/os2compat.c f +lib/intl/os2compat.h f +lib/intl/osdep.c f +lib/intl/plural-exp.c f +lib/intl/plural-exp.h f +lib/intl/plural.c f +lib/intl/plural.y f +lib/intl/ref-add.sin f +lib/intl/ref-del.sin f +lib/intl/relocatable.c f +lib/intl/relocatable.h f +lib/intl/textdomain.c f +lib/malloc/Makefile.in f +lib/malloc/getpagesize.h f +lib/malloc/imalloc.h f +lib/malloc/mstats.h f +lib/malloc/shmalloc.h f +lib/malloc/table.h f +lib/malloc/watch.h f +lib/malloc/alloca.c f +lib/malloc/malloc.c f +lib/malloc/stats.c f +lib/malloc/table.c f +lib/malloc/trace.c f +lib/malloc/watch.c f +lib/malloc/xmalloc.c f +lib/malloc/xleaktrace f 755 +lib/malloc/stub.c f +lib/malloc/i386-alloca.s f +lib/malloc/x386-alloca.s f +lib/readline/COPYING f +lib/readline/Makefile.in f +lib/readline/ChangeLog f +lib/readline/README f +lib/readline/STANDALONE f +lib/readline/readline.c f +lib/readline/vi_mode.c f +lib/readline/emacs_keymap.c f +lib/readline/vi_keymap.c f +lib/readline/history.c f +lib/readline/histexpand.c f +lib/readline/histsearch.c f +lib/readline/histfile.c f +lib/readline/funmap.c f +lib/readline/keymaps.c f +lib/readline/util.c f +lib/readline/terminal.c f +lib/readline/xfree.c f +lib/readline/xmalloc.c f +lib/readline/search.c f +lib/readline/isearch.c f +lib/readline/parens.c f +lib/readline/rltty.c f +lib/readline/compat.c f +lib/readline/complete.c f +lib/readline/bind.c f +lib/readline/display.c f +lib/readline/signals.c f +lib/readline/kill.c f +lib/readline/text.c f +lib/readline/undo.c f +lib/readline/macro.c f +lib/readline/input.c f +lib/readline/callback.c f +lib/readline/mbutil.c f +lib/readline/misc.c f +lib/readline/nls.c f +lib/readline/shell.c f +lib/readline/colors.c f +lib/readline/parse-colors.c f +lib/readline/savestring.c f +lib/readline/tilde.c f +lib/readline/tilde.h f +lib/readline/rldefs.h f +lib/readline/rlconf.h f +lib/readline/rlmbutil.h f +lib/readline/rlshell.h f +lib/readline/rltty.h f +lib/readline/rltypedefs.h f +lib/readline/rlwinsize.h f +lib/readline/readline.h f +lib/readline/tcap.h f +lib/readline/keymaps.h f +lib/readline/history.h f +lib/readline/histlib.h f +lib/readline/chardefs.h f +lib/readline/posixdir.h f +lib/readline/posixjmp.h f +lib/readline/posixselect.h f +lib/readline/posixstat.h f +lib/readline/ansi_stdlib.h f +lib/readline/rlstdc.h f +lib/readline/rlprivate.h f +lib/readline/colors.h f +lib/readline/parse-colors.h f +lib/readline/xmalloc.h f +lib/readline/doc/Makefile f +lib/readline/doc/version.texi f +lib/readline/doc/rlman.texi f +lib/readline/doc/rltech.texi f +lib/readline/doc/rluser.texi f +lib/readline/doc/rluserman.texi f +lib/readline/doc/history.texi f +lib/readline/doc/hstech.texi f +lib/readline/doc/hsuser.texi f +lib/readline/doc/fdl.texi f +lib/readline/examples/Makefile f +lib/readline/examples/excallback.c f +lib/readline/examples/fileman.c f +lib/readline/examples/manexamp.c f +lib/readline/examples/histexamp.c f +lib/readline/examples/rltest.c f +lib/readline/examples/rl.c f +lib/readline/examples/rlcat.c f +lib/readline/examples/Inputrc f +lib/sh/Makefile.in f +lib/sh/casemod.c f +lib/sh/clktck.c f +lib/sh/clock.c f +lib/sh/dprintf.c f +lib/sh/eaccess.c f +lib/sh/fmtullong.c f +lib/sh/fmtulong.c f +lib/sh/fmtumax.c f +lib/sh/fnxform.c f +lib/sh/fpurge.c f +lib/sh/getcwd.c f +lib/sh/getenv.c f +lib/sh/inet_aton.c f +lib/sh/input_avail.c f +lib/sh/itos.c f +lib/sh/mailstat.c f +lib/sh/makepath.c f +lib/sh/mbscasecmp.c f +lib/sh/mbschr.c f +lib/sh/mbscmp.c f +lib/sh/memset.c f +lib/sh/mktime.c f +lib/sh/netconn.c f +lib/sh/netopen.c f +lib/sh/oslib.c f +lib/sh/pathcanon.c f +lib/sh/pathphys.c f +lib/sh/rename.c f +lib/sh/setlinebuf.c f +lib/sh/shmatch.c f +lib/sh/shmbchar.c f +lib/sh/shquote.c f +lib/sh/shtty.c f +lib/sh/snprintf.c f +lib/sh/spell.c f +lib/sh/strcasecmp.c f +lib/sh/strcasestr.c f +lib/sh/strchrnul.c f +lib/sh/strerror.c f +lib/sh/strftime.c f +lib/sh/stringlist.c f +lib/sh/stringvec.c f +lib/sh/strnlen.c f +lib/sh/strpbrk.c f +lib/sh/strstr.c f +lib/sh/strtod.c f +lib/sh/strtoimax.c f +lib/sh/strtol.c f +lib/sh/strtoll.c f +lib/sh/strtoul.c f +lib/sh/strtoull.c f +lib/sh/strtoumax.c f +lib/sh/strtrans.c f +lib/sh/times.c f +lib/sh/timeval.c f +lib/sh/tmpfile.c f +lib/sh/uconvert.c f +lib/sh/ufuncs.c f +lib/sh/unicode.c f +lib/sh/vprint.c f +lib/sh/wcsdup.c f +lib/sh/wcswidth.c f +lib/sh/winsize.c f +lib/sh/zcatfd.c f +lib/sh/zgetline.c f +lib/sh/zmapfd.c f +lib/sh/zread.c f +lib/sh/zwrite.c f +lib/termcap/Makefile.in f +lib/termcap/ltcap.h f +lib/termcap/termcap.c f +lib/termcap/termcap.h f +lib/termcap/tparam.c f +lib/termcap/version.c f +lib/tilde/README f +lib/tilde/Makefile.in f +lib/tilde/tilde.c f +lib/tilde/tilde.h f +lib/tilde/shell.c f +m4/stat-time.m4 f +m4/timespec.m4 f +po/LINGUAS f +po/Makefile.in.in f +po/Makevars f +po/POTFILES.in f +po/README f +po/Rules-builtins f +po/Rules-quot f +po/bash.pot f +po/boldquot.sed f +po/en@boldquot.gmo f +po/en@boldquot.header f +po/en@boldquot.po f +po/en@quot.gmo f +po/en@quot.header f +po/en@quot.po f +po/af.gmo f +po/af.po f +po/bg.gmo f +po/bg.po f +po/ca.gmo f +po/ca.po f +po/cs.gmo f +po/cs.po f +po/da.gmo f +po/da.po f +po/de.gmo f +po/de.po f +po/eo.gmo f +po/eo.po f +po/es.gmo f +po/es.po f +po/et.gmo f +po/et.po f +po/fi.gmo f +po/fi.po f +po/fr.gmo f +po/fr.po f +po/ga.gmo f +po/ga.po f +po/gl.gmo f +po/gl.po f +po/hu.gmo f +po/hu.po f +po/id.gmo f +po/id.po f +po/it.gmo f +po/it.po f +po/ja.gmo f +po/ja.po f +po/lt.gmo f +po/lt.po f +po/nl.gmo f +po/nl.po f +po/pl.gmo f +po/pl.po f +po/pt_BR.gmo f +po/pt_BR.po f +po/ro.gmo f +po/ro.po f +po/ru.gmo f +po/ru.po f +po/sk.gmo f +po/sk.po f +po/sl.gmo f +po/sl.po f +po/sv.gmo f +po/sv.po f +po/tr.gmo f +po/tr.po f +po/uk.gmo f +po/uk.po f +po/vi.gmo f +po/vi.po f +po/zh_CN.gmo f +po/zh_CN.po f +po/zh_TW.gmo f +po/zh_TW.po f +po/insert-header.sin f +po/quot.sed f +po/remove-potcdate.sin f +CWRU/misc/open-files.c f +CWRU/misc/sigs.c f +CWRU/misc/sigstat.c f +CWRU/misc/bison f +CWRU/misc/errlist.c f +CWRU/misc/hpux10-dlfcn.h f +CWRU/PLATFORMS f +CWRU/README f +CWRU/changelog f +CWRU/sh-redir-hack f +CWRU/mh-folder-comp f +doc/FAQ f +doc/Makefile.in f +doc/bash.1 f +doc/bashbug.1 f +doc/builtins.1 f +doc/rbash.1 f +doc/README f +doc/INTRO f +doc/texinfo.tex f +doc/bashref.texi f +doc/version.texi f +doc/bashref.info f +doc/article.ms f +doc/htmlpost.sh f 755 +doc/infopost.sh f 755 +doc/fdl.texi f +doc/fdl.txt f +support/Makefile.in f +support/bashversion.c f +support/checkbashisms f 755 +support/config.guess f +support/config.rpath f 755 +support/config.sub f +support/printenv.sh f 755 +support/printenv.c f +support/bash.xbm f +support/missing f 755 +support/mkclone f 755 +support/mkconffiles f 755 +support/mkdirs f 755 +support/mkinstalldirs f 755 +support/mkversion.sh f 755 +support/mksignames.c f +support/signames.c f +support/bashbug.sh f +support/man2html.c f +support/recho.c f +support/zecho.c f +support/xcase.c f +support/SYMLINKS f +support/fixlinks f 755 +support/install.sh f 755 +support/texi2dvi f 755 +support/texi2html f 755 +support/xenix-link.sh f 755 +support/shobj-conf f 755 +support/rlvers.sh f 755 +examples/INDEX.txt f +examples/INDEX.html f +examples/obashdb/PERMISSION f +examples/obashdb/README f +examples/obashdb/bashdb f +examples/obashdb/bashdb.el f +examples/complete/bash_completion f +examples/complete/cdfunc f +examples/complete/complete-examples f +examples/complete/complete.ianmac f +examples/complete/complete2.ianmac f +examples/complete/complete.freebsd f +examples/complete/complete.gnu-longopt f +examples/complete/bashcc-1.0.1.tar.gz f +examples/loadables/README f +examples/loadables/template.c f +examples/loadables/Makefile.in f +examples/loadables/necho.c f +examples/loadables/hello.c f +examples/loadables/print.c f +examples/loadables/realpath.c f +examples/loadables/sleep.c f +examples/loadables/strftime.c f +examples/loadables/truefalse.c f +examples/loadables/getconf.h f +examples/loadables/getconf.c f +examples/loadables/finfo.c f +examples/loadables/cat.c f +examples/loadables/cut.c f +examples/loadables/logname.c f +examples/loadables/basename.c f +examples/loadables/dirname.c f +examples/loadables/tty.c f +examples/loadables/pathchk.c f +examples/loadables/tee.c f +examples/loadables/rmdir.c f +examples/loadables/head.c f +examples/loadables/printenv.c f +examples/loadables/push.c f +examples/loadables/id.c f +examples/loadables/whoami.c f +examples/loadables/uname.c f +examples/loadables/sync.c f +examples/loadables/mkdir.c f +examples/loadables/ln.c f +examples/loadables/mypid.c f +examples/loadables/unlink.c f +examples/loadables/perl/Makefile.in f +examples/loadables/perl/README f +examples/loadables/perl/bperl.c f +examples/loadables/perl/iperl.c f +examples/functions/array-stuff f +examples/functions/array-to-string f +examples/functions/autoload f +examples/functions/autoload.v2 f +examples/functions/autoload.v3 f +examples/functions/basename f +examples/functions/basename2 f +examples/functions/coproc.bash f +examples/functions/coshell.README f +examples/functions/coshell.bash f +examples/functions/csh-compat f +examples/functions/dirfuncs f +examples/functions/dirname f +examples/functions/emptydir f +examples/functions/exitstat f +examples/functions/external f +examples/functions/fact f +examples/functions/fstty f +examples/functions/func f +examples/functions/gethtml f +examples/functions/getoptx.bash f +examples/functions/inetaddr f +examples/functions/inpath f +examples/functions/isnum.bash f +examples/functions/isnum2 f +examples/functions/isvalidip f +examples/functions/jdate.bash f +examples/functions/jj.bash f +examples/functions/keep f +examples/functions/ksh-cd f +examples/functions/ksh-compat-test f +examples/functions/kshenv f +examples/functions/login f +examples/functions/lowercase f +examples/functions/manpage f +examples/functions/mhfold f +examples/functions/newdirstack.bsh f +examples/functions/notify.bash f +examples/functions/pathfuncs f +examples/functions/recurse f +examples/functions/repeat2 f +examples/functions/repeat3 f +examples/functions/seq f +examples/functions/seq2 f +examples/functions/shcat f +examples/functions/shcat2 f +examples/functions/sort-pos-params f +examples/functions/substr f +examples/functions/substr2 f +examples/functions/term f +examples/functions/whatis f +examples/functions/whence f +examples/functions/which f +examples/functions/xalias.bash f +examples/functions/xfind.bash f +examples/scripts/adventure.sh f +examples/scripts/bash-hexdump.sh f +examples/scripts/bcsh.sh f +examples/scripts/cat.sh f +examples/scripts/center f +examples/scripts/dd-ex.sh f +examples/scripts/fixfiles.bash f +examples/scripts/hanoi.bash f +examples/scripts/inpath f +examples/scripts/krand.bash f +examples/scripts/line-input.bash f +examples/scripts/nohup.bash f +examples/scripts/precedence f +examples/scripts/randomcard.bash f +examples/scripts/scrollbar f +examples/scripts/scrollbar2 f +examples/scripts/self-repro f +examples/scripts/showperm.bash f +examples/scripts/shprompt f +examples/scripts/spin.bash f +examples/scripts/timeout f +examples/scripts/timeout2 f +examples/scripts/timeout3 f +examples/scripts/vtree2 f +examples/scripts/vtree3 f +examples/scripts/vtree3a f +examples/scripts/websrv.sh f +examples/scripts/xterm_title f +examples/scripts/zprintf f +examples/startup-files/README f +examples/startup-files/Bashrc.bfox f +examples/startup-files/Bash_aliases f +examples/startup-files/Bash_profile f +examples/startup-files/bash-profile f +examples/startup-files/bashrc f +examples/startup-files/apple/README f +examples/startup-files/apple/aliases f +examples/startup-files/apple/bash.defaults f +examples/startup-files/apple/environment f +examples/startup-files/apple/login f +examples/startup-files/apple/logout f +examples/startup-files/apple/rc f +examples/misc/suncmd.termcap f +examples/misc/aliasconv.sh f +examples/misc/aliasconv.bash f +examples/misc/cshtobash f +tests/README f +tests/COPYRIGHT f +tests/alias.tests f +tests/alias1.sub f +tests/alias.right f +tests/appendop.tests f +tests/appendop.right f +tests/arith-for.tests f +tests/arith-for.right f +tests/arith.tests f +tests/arith.right f +tests/arith1.sub f +tests/arith2.sub f +tests/arith3.sub f +tests/arith4.sub f +tests/arith5.sub f +tests/array.tests f +tests/array.right f +tests/array1.sub f +tests/array2.sub f +tests/array3.sub f +tests/array4.sub f +tests/array5.sub f +tests/array6.sub f +tests/array7.sub f +tests/array8.sub f +tests/array9.sub f +tests/array10.sub f +tests/array11.sub f +tests/array12.sub f +tests/array13.sub f +tests/array-at-star f +tests/array2.right f +tests/assoc.tests f +tests/assoc.right f +tests/assoc1.sub f +tests/assoc2.sub f +tests/assoc3.sub f +tests/assoc4.sub f +tests/assoc5.sub f +tests/assoc6.sub f +tests/assoc7.sub f +tests/braces.tests f +tests/braces.right f +tests/builtins.tests f +tests/builtins.right f +tests/builtins1.sub f +tests/builtins2.sub f +tests/builtins3.sub f +tests/source1.sub f +tests/source2.sub f +tests/source3.sub f +tests/source4.sub f +tests/source5.sub f +tests/source6.sub f +tests/case.tests f +tests/case.right f +tests/casemod.tests f +tests/casemod.right f +tests/comsub.tests f +tests/comsub.right f +tests/comsub1.sub f +tests/comsub-eof.tests f +tests/comsub-eof0.sub f +tests/comsub-eof1.sub f +tests/comsub-eof2.sub f +tests/comsub-eof3.sub f +tests/comsub-eof4.sub f +tests/comsub-eof5.sub f +tests/comsub-eof.right f +tests/comsub-posix.tests f +tests/comsub-posix.right f +tests/comsub-posix1.sub f +tests/comsub-posix2.sub f +tests/comsub-posix3.sub f +tests/cond.tests f +tests/cond.right f +tests/cond-regexp1.sub f +tests/cond-regexp2.sub f +tests/coproc.tests f +tests/coproc.right f +tests/cprint.tests f +tests/cprint.right f +tests/dbg-support.right f +tests/dbg-support.sub f +tests/dbg-support.tests f +tests/dbg-support2.right f +tests/dbg-support2.tests f +tests/dbg-support3.sub f +tests/dollar-at-star f +tests/dollar-at1.sub f +tests/dollar-at2.sub f +tests/dollar-at3.sub f +tests/dollar-at4.sub f +tests/dollar-star1.sub f +tests/dollar-star2.sub f +tests/dollar-star3.sub f +tests/dollar-star4.sub f +tests/dollar-star5.sub f +tests/dollar.right f +tests/dstack.tests f +tests/dstack.right f +tests/dstack2.tests f +tests/dstack2.right f +tests/errors.tests f +tests/errors.right f +tests/errors1.sub f +tests/errors2.sub f +tests/execscript f +tests/exec.right f +tests/exec1.sub f 755 +tests/exec2.sub f +tests/exec3.sub f +tests/exec4.sub f +tests/exec5.sub f +tests/exec6.sub f +tests/exec7.sub f +tests/exec8.sub f +tests/exec9.sub f +tests/exp.tests f +tests/exp.right f +tests/exp1.sub f +tests/exp2.sub f +tests/exp3.sub f +tests/exp4.sub f +tests/exp5.sub f +tests/exp6.sub f +tests/extglob.tests f +tests/extglob.right f +tests/extglob1.sub f +tests/extglob2.tests f +tests/extglob2.right f +tests/extglob3.tests f +tests/extglob3.right f +tests/func.tests f +tests/func.right f +tests/func1.sub f +tests/func2.sub f +tests/func3.sub f +tests/func4.sub f +tests/getopts.tests f +tests/getopts.right f +tests/getopts1.sub f +tests/getopts2.sub f +tests/getopts3.sub f +tests/getopts4.sub f +tests/getopts5.sub f +tests/getopts6.sub f +tests/getopts7.sub f +tests/glob.tests f +tests/glob1.sub f +tests/glob.right f +tests/globstar.tests f +tests/globstar.right f +tests/globstar1.sub f +tests/heredoc.tests f +tests/heredoc.right f +tests/heredoc1.sub f +tests/heredoc2.sub f +tests/heredoc3.sub f +tests/herestr.tests f +tests/herestr.right f +tests/histexp.tests f +tests/histexp.right f +tests/history.tests f +tests/history.right f +tests/history.list f 444 +tests/history1.sub f +tests/history2.sub f +tests/ifs.tests f +tests/ifs.right f +tests/ifs-posix.tests f +tests/ifs-posix.right f +tests/input-line.sh f +tests/input-line.sub f +tests/input.right f +tests/intl.tests f +tests/intl1.sub f +tests/intl2.sub f +tests/intl.right f +tests/iquote.tests f +tests/iquote.right f +tests/invert.tests f +tests/invert.right f +tests/jobs.tests f +tests/jobs1.sub f +tests/jobs2.sub f +tests/jobs3.sub f +tests/jobs4.sub f +tests/jobs.right f +tests/lastpipe.right f +tests/lastpipe.tests f +tests/lastpipe1.sub f +tests/mapfile.data f +tests/mapfile.right f +tests/mapfile.tests f +tests/mapfile1.sub f +tests/more-exp.tests f +tests/more-exp.right f +tests/new-exp.tests f +tests/new-exp1.sub f +tests/new-exp2.sub f +tests/new-exp3.sub f +tests/new-exp4.sub f +tests/new-exp5.sub f +tests/new-exp6.sub f +tests/new-exp7.sub f +tests/new-exp8.sub f +tests/new-exp.right f +tests/nquote.tests f +tests/nquote.right f +tests/nquote1.sub f +tests/nquote1.tests f +tests/nquote1.right f +tests/nquote2.tests f +tests/nquote2.right f +tests/nquote3.tests f +tests/nquote3.right f +tests/nquote4.tests f +tests/nquote4.right f +tests/nquote5.tests f +tests/nquote5.right f +tests/posix2.tests f +tests/posix2.right f +tests/posixexp.tests f +tests/posixexp.right f +tests/posixexp1.sub f +tests/posixexp2.sub f +tests/posixexp2.tests f +tests/posixexp2.right f +tests/posixpat.tests f +tests/posixpat.right f +tests/posixpipe.tests f +tests/posixpipe.right f +tests/prec.right f +tests/precedence f +tests/printf.tests f +tests/printf.right f +tests/printf1.sub f +tests/printf2.sub f +tests/printf3.sub f +tests/printf4.sub f +tests/quote.tests f +tests/quote.right f +tests/read.tests f +tests/read.right f +tests/read1.sub f +tests/read2.sub f +tests/read3.sub f +tests/read4.sub f +tests/read5.sub f +tests/read6.sub f +tests/redir.tests f +tests/redir.right f +tests/redir1.sub f +tests/redir2.sub f +tests/redir3.sub f +tests/redir3.in1 f +tests/redir3.in2 f +tests/redir4.sub f +tests/redir4.in1 f +tests/redir5.sub f +tests/redir6.sub f +tests/redir7.sub f +tests/redir8.sub f +tests/redir9.sub f +tests/redir10.sub f +tests/rhs-exp.tests f +tests/rhs-exp.right f +tests/rhs-exp1.sub f +tests/rsh.tests f +tests/rsh.right f +tests/run-all f +tests/run-minimal f +tests/run-alias f +tests/run-appendop f +tests/run-arith-for f +tests/run-arith f +tests/run-array f +tests/run-array2 f +tests/run-assoc f +tests/run-braces f +tests/run-builtins f +tests/run-case f +tests/run-casemod f +tests/run-comsub f +tests/run-comsub-eof f +tests/run-comsub-posix f +tests/run-cond f +tests/run-coproc f +tests/run-cprint f +tests/run-dbg-support f +tests/run-dbg-support2 f +tests/run-dirstack f +tests/run-dollars f +tests/run-errors f +tests/run-execscript f +tests/run-exp-tests f +tests/run-extglob f +tests/run-extglob2 f +tests/run-extglob3 f +tests/run-func f +tests/run-getopts f +tests/run-glob-test f +tests/run-globstar f +tests/run-heredoc f +tests/run-herestr f +tests/run-histexpand f +tests/run-history f +tests/run-ifs f +tests/run-ifs-posix f +tests/run-input-test f +tests/run-intl f +tests/run-iquote f +tests/run-invert f +tests/run-jobs f +tests/run-lastpipe f +tests/run-mapfile f +tests/run-more-exp f +tests/run-new-exp f +tests/run-nquote f +tests/run-nquote1 f +tests/run-nquote2 f +tests/run-nquote3 f +tests/run-nquote4 f +tests/run-nquote5 f +tests/run-posix2 f +tests/run-posixexp f +tests/run-posixexp2 f +tests/run-posixpat f +tests/run-posixpipe f +tests/run-precedence f +tests/run-printf f +tests/run-quote f +tests/run-read f +tests/run-redir f +tests/run-rhs-exp f +tests/run-rsh f +tests/run-set-e f +tests/run-set-x f +tests/run-shopt f +tests/run-strip f +tests/run-test f +tests/run-tilde f +tests/run-tilde2 f +tests/run-trap f +tests/run-type f +tests/run-varenv f +tests/run-vredir f +tests/set-e.tests f +tests/set-e1.sub f +tests/set-e2.sub f +tests/set-e.right f +tests/set-x.tests f +tests/set-x1.sub f +tests/set-x.right f +tests/shopt.tests f +tests/shopt.right f +tests/strip.tests f +tests/strip.right f +tests/test.tests f +tests/test.right f +tests/tilde.tests f +tests/tilde.right f +tests/tilde2.tests f +tests/tilde2.right f +tests/trap.tests f +tests/trap.right f +tests/trap1.sub f 755 +tests/trap2.sub f 755 +tests/trap2a.sub f 755 +tests/trap3.sub f +tests/type.tests f +tests/type.right f +tests/type1.sub f +tests/type2.sub f +tests/type3.sub f +tests/type4.sub f +tests/unicode1.sub f +tests/unicode2.sub f +tests/varenv.right f +tests/varenv.sh f +tests/varenv1.sub f +tests/varenv2.sub f +tests/version f +tests/version.mini f +tests/vredir.tests f +tests/vredir.right f +tests/vredir1.sub f +tests/vredir2.sub f +tests/vredir3.sub f +tests/vredir4.sub f +tests/vredir5.sub f +tests/vredir6.sub f +tests/misc/dev-tcp.tests f +tests/misc/perf-script f +tests/misc/perftest f +tests/misc/read-nchars.tests f +tests/misc/redir-t2.sh f +tests/misc/run-r2.sh f +tests/misc/sigint-1.sh f +tests/misc/sigint-2.sh f +tests/misc/sigint-3.sh f +tests/misc/sigint-4.sh f +tests/misc/test-minus-e.1 f +tests/misc/test-minus-e.2 f +tests/misc/wait-bg.tests f +examples/scripts.v2/PERMISSION f +examples/scripts.v2/README f +examples/scripts.v2/arc2tarz f +examples/scripts.v2/bashrand f +examples/scripts.v2/cal2day.bash f +examples/scripts.v2/cdhist.bash f +examples/scripts.v2/corename f +examples/scripts.v2/fman f +examples/scripts.v2/frcp f +examples/scripts.v2/lowercase f +examples/scripts.v2/ncp f +examples/scripts.v2/newext f +examples/scripts.v2/nmv f +examples/scripts.v2/pages f +examples/scripts.v2/pf f +examples/scripts.v2/ren f +examples/scripts.v2/rename f +examples/scripts.v2/repeat f +examples/scripts.v2/untar f +examples/scripts.v2/uudec f +examples/scripts.v2/uuenc f +examples/scripts.v2/vtree f +examples/scripts.v2/where f +examples/scripts.v2/pmtop f +examples/scripts.v2/shprof f +examples/scripts.noah/PERMISSION f +examples/scripts.noah/README f +examples/scripts.noah/aref.bash f +examples/scripts.noah/bash.sub.bash f +examples/scripts.noah/bash_version.bash f +examples/scripts.noah/meta.bash f +examples/scripts.noah/mktmp.bash f +examples/scripts.noah/number.bash f +examples/scripts.noah/prompt.bash f +examples/scripts.noah/remap_keys.bash f +examples/scripts.noah/require.bash f +examples/scripts.noah/send_mail.bash f +examples/scripts.noah/shcat.bash f +examples/scripts.noah/source.bash f +examples/scripts.noah/string.bash f +examples/scripts.noah/stty.bash f +examples/scripts.noah/y_or_n_p.bash f diff --git a/builtins/wait.def b/builtins/wait.def index 846b7bf7a..401cba6db 100644 --- a/builtins/wait.def +++ b/builtins/wait.def @@ -1,7 +1,7 @@ This file is wait.def, from which is created wait.c. It implements the builtin "wait" in Bash. -Copyright (C) 1987-2009 Free Software Foundation, Inc. +Copyright (C) 1987-2012 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -39,16 +39,16 @@ $END $BUILTIN wait $FUNCTION wait_builtin $DEPENDS_ON !JOB_CONTROL -$SHORT_DOC wait [pid] +$SHORT_DOC wait [pid ...] Wait for process completion and return exit status. -Waits for the specified process and reports its termination status. If -PID is not given, all currently active child processes are waited for, -and the return code is zero. PID must be a process ID. +Waits for each process specified by a PID and reports its termination status. +If PID is not given, waits for all currently active child processes, +and the return status is zero. PID must be a process ID. Exit Status: -Returns the status of ID; fails if ID is invalid or an invalid option is -given. +Returns the status of the last PID; fails if PID is invalid or an invalid +option is given. $END #include diff --git a/cross-build/cygwin32.cache.old b/cross-build/cygwin32.cache.old new file mode 100644 index 000000000..640390fbf --- /dev/null +++ b/cross-build/cygwin32.cache.old @@ -0,0 +1,42 @@ +# This file is a shell script that caches the results of configure +# tests for CYGWIN32 so they don't need to be done when cross-compiling. + +# AC_FUNC_GETPGRP should also define GETPGRP_VOID +ac_cv_func_getpgrp_void=${ac_cv_func_getpgrp_void='yes'} +# AC_FUNC_SETVBUF_REVERSED should not define anything else +ac_cv_func_setvbuf_reversed=${ac_cv_func_setvbuf_reversed='no'} +# on CYGWIN32, system calls do not restart +ac_cv_sys_restartable_syscalls=${ac_cv_sys_restartable_syscalls='no'} +bash_cv_sys_restartable_syscalls=${bash_cv_sys_restartable_syscalls='no'} + +# these may be necessary, but they are currently commented out +#ac_cv_c_bigendian=${ac_cv_c_bigendian='no'} +ac_cv_sizeof_char_p=${ac_cv_sizeof_char_p='4'} +ac_cv_sizeof_int=${ac_cv_sizeof_int='4'} +ac_cv_sizeof_long=${ac_cv_sizeof_long='4'} +ac_cv_sizeof_double=${ac_cv_sizeof_double='8'} + +bash_cv_dup2_broken=${bash_cv_dup2_broken='no'} +bash_cv_pgrp_pipe=${bash_cv_pgrp_pipe='no'} +bash_cv_type_rlimit=${bash_cv_type_rlimit='long'} +bash_cv_decl_under_sys_siglist=${bash_cv_decl_under_sys_siglist='no'} +bash_cv_under_sys_siglist=${bash_cv_under_sys_siglist='no'} +bash_cv_sys_siglist=${bash_cv_sys_siglist='no'} +bash_cv_opendir_not_robust=${bash_cv_opendir_not_robust='no'} +bash_cv_getenv_redef=${bash_cv_getenv_redef='yes'} +bash_cv_printf_declared=${bash_cv_printf_declared='yes'} +bash_cv_ulimit_maxfds=${bash_cv_ulimit_maxfds='no'} +bash_cv_getcwd_calls_popen=${bash_cv_getcwd_calls_popen='no'} +bash_cv_must_reinstall_sighandlers=${bash_cv_must_reinstall_sighandlers='no'} +bash_cv_job_control_missing=${bash_cv_job_control_missing='present'} +bash_cv_sys_named_pipes=${bash_cv_sys_named_pipes='missing'} +bash_cv_func_sigsetjmp=${bash_cv_func_sigsetjmp='missing'} +bash_cv_mail_dir=${bash_cv_mail_dir='unknown'} +bash_cv_func_strcoll_broken=${bash_cv_func_strcoll_broken='no'} + +bash_cv_type_int32_t=${bash_cv_type_int32_t='int'} +bash_cv_type_u_int32_t=${bash_cv_type_u_int32_t='int'} + +ac_cv_type_bits64_t=${ac_cv_type_bits64_t='no'} + +# end of cross-build/cygwin32.cache diff --git a/doc/FAQ-20090219 b/doc/FAQ-20090219 new file mode 100644 index 000000000..29d453a5f --- /dev/null +++ b/doc/FAQ-20090219 @@ -0,0 +1,2060 @@ +This is the Bash FAQ, version 4.01, for Bash version 4.0. + +This document contains a set of frequently-asked questions concerning +Bash, the GNU Bourne-Again Shell. Bash is a freely-available command +interpreter with advanced features for both interactive use and shell +programming. + +Another good source of basic information about shells is the collection +of FAQ articles periodically posted to comp.unix.shell. + +Questions and comments concerning this document should be sent to +chet.ramey@case.edu. + +This document is available for anonymous FTP with the URL + +ftp://ftp.cwru.edu/pub/bash/FAQ + +The Bash home page is http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html + +---------- +Contents: + +Section A: The Basics + +A1) What is it? +A2) What's the latest version? +A3) Where can I get it? +A4) On what machines will bash run? +A5) Will bash run on operating systems other than Unix? +A6) How can I build bash with gcc? +A7) How can I make bash my login shell? +A8) I just changed my login shell to bash, and now I can't FTP into my + machine. Why not? +A9) What's the `POSIX Shell and Utilities standard'? +A10) What is the bash `posix mode'? + +Section B: The latest version + +B1) What's new in version 4.0? +B2) Are there any user-visible incompatibilities between bash-4.0, + bash-3.2, and bash-2.05b? + +Section C: Differences from other Unix shells + +C1) How does bash differ from sh, the Bourne shell? +C2) How does bash differ from the Korn shell, version ksh88? +C3) Which new features in ksh-93 are not in bash, and which are? + +Section D: Why does bash do some things differently than other Unix shells? + +D1) Why does bash run a different version of `command' than + `which command' says it will? +D2) Why doesn't bash treat brace expansions exactly like csh? +D3) Why doesn't bash have csh variable modifiers? +D4) How can I make my csh aliases work when I convert to bash? +D5) How can I pipe standard output and standard error from one command to + another, like csh does with `|&'? +D6) Now that I've converted from ksh to bash, are there equivalents to + ksh features like autoloaded functions and the `whence' command? + +Section E: Why does bash do certain things the way it does? + +E1) Why is the bash builtin `test' slightly different from /bin/test? +E2) Why does bash sometimes say `Broken pipe'? +E3) When I have terminal escape sequences in my prompt, why does bash + wrap lines at the wrong column? +E4) If I pipe the output of a command into `read variable', why doesn't + the output show up in $variable when the read command finishes? +E5) I have a bunch of shell scripts that use backslash-escaped characters + in arguments to `echo'. Bash doesn't interpret these characters. Why + not, and how can I make it understand them? +E6) Why doesn't a while or for loop get suspended when I type ^Z? +E7) What about empty for loops in Makefiles? +E8) Why does the arithmetic evaluation code complain about `08'? +E9) Why does the pattern matching expression [A-Z]* match files beginning + with every letter except `z'? +E10) Why does `cd //' leave $PWD as `//'? +E11) If I resize my xterm while another program is running, why doesn't bash + notice the change? +E12) Why don't negative offsets in substring expansion work like I expect? +E13) Why does filename completion misbehave if a colon appears in the filename? +E14) Why does quoting the pattern argument to the regular expression matching + conditional operator (=~) cause matching to stop working? + +Section F: Things to watch out for on certain Unix versions + +F1) Why can't I use command line editing in my `cmdtool'? +F2) I built bash on Solaris 2. Why do globbing expansions and filename + completion chop off the first few characters of each filename? +F3) Why does bash dump core after I interrupt username completion or + `~user' tilde expansion on a machine running NIS? +F4) I'm running SVR4.2. Why is the line erased every time I type `@'? +F5) Why does bash report syntax errors when my C News scripts use a + redirection before a subshell command? +F6) Why can't I use vi-mode editing on Red Hat Linux 6.1? +F7) Why do bash-2.05a and bash-2.05b fail to compile `printf.def' on + HP/UX 11.x? + +Section G: How can I get bash to do certain common things? + +G1) How can I get bash to read and display eight-bit characters? +G2) How do I write a function `x' to replace builtin command `x', but + still invoke the command from within the function? +G3) How can I find the value of a shell variable whose name is the value + of another shell variable? +G4) How can I make the bash `time' reserved word print timing output that + looks like the output from my system's /usr/bin/time? +G5) How do I get the current directory into my prompt? +G6) How can I rename "*.foo" to "*.bar"? +G7) How can I translate a filename from uppercase to lowercase? +G8) How can I write a filename expansion (globbing) pattern that will match + all files in the current directory except "." and ".."? + +Section H: Where do I go from here? + +H1) How do I report bugs in bash, and where should I look for fixes and + advice? +H2) What kind of bash documentation is there? +H3) What's coming in future versions? +H4) What's on the bash `wish list'? +H5) When will the next release appear? + +---------- +Section A: The Basics + +A1) What is it? + +Bash is a Unix command interpreter (shell). It is an implementation of +the Posix 1003.2 shell standard, and resembles the Korn and System V +shells. + +Bash contains a number of enhancements over those shells, both +for interactive use and shell programming. Features geared +toward interactive use include command line editing, command +history, job control, aliases, and prompt expansion. Programming +features include additional variable expansions, shell +arithmetic, and a number of variables and options to control +shell behavior. + +Bash was originally written by Brian Fox of the Free Software +Foundation. The current developer and maintainer is Chet Ramey +of Case Western Reserve University. + +A2) What's the latest version? + +The latest version is 4.0, first made available on 20 February, 2009. + +A3) Where can I get it? + +Bash is the GNU project's shell, and so is available from the +master GNU archive site, ftp.gnu.org, and its mirrors. The +latest version is also available for FTP from ftp.cwru.edu. +The following URLs tell how to get version 4.0: + +ftp://ftp.gnu.org/pub/gnu/bash/bash-4.0.tar.gz +ftp://ftp.cwru.edu/pub/bash/bash-4.0.tar.gz + +Formatted versions of the documentation are available with the URLs: + +ftp://ftp.gnu.org/pub/gnu/bash/bash-doc-4.0.tar.gz +ftp://ftp.cwru.edu/pub/bash/bash-doc-4.0.tar.gz + +Any patches for the current version are available with the URL: + +ftp://ftp.cwru.edu/pub/bash/bash-4.0-patches/ + +A4) On what machines will bash run? + +Bash has been ported to nearly every version of Unix. All you +should have to do to build it on a machine for which a port +exists is to type `configure' and then `make'. The build process +will attempt to discover the version of Unix you have and tailor +itself accordingly, using a script created by GNU autoconf. + +More information appears in the file `INSTALL' in the distribution. + +The Bash web page (http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html) +explains how to obtain binary versions of bash for most of the major +commercial Unix systems. + +A5) Will bash run on operating systems other than Unix? + +Configuration specifics for Unix-like systems such as QNX and +LynxOS are included in the distribution. Bash-2.05 and later +versions should compile and run on Minix 2.0 (patches were +contributed), but I don't believe anyone has built bash-2.x on +earlier Minix versions yet. + +Bash has been ported to versions of Windows implementing the Win32 +programming interface. This includes Windows 95 and Windows NT. +The port was done by Cygnus Solutions (now part of Red Hat) as part +of their CYGWIN project. For more information about the project, see +http://www.cygwin.com/. + +Cygnus originally ported bash-1.14.7, and that port was part of their +early GNU-Win32 (the original name) releases. Cygnus has also done +ports of bash-2.05b and bash-3.2 to the CYGWIN environment, and both +are available as part of their current release. + +Bash-2.05b and later versions should require no local Cygnus changes to +build and run under CYGWIN. + +DJ Delorie has a port of bash-2.x which runs under MS-DOS, as part +of the DJGPP project. For more information on the project, see + +http://www.delorie.com/djgpp/ + +I have been told that the original DJGPP port was done by Daisuke Aoyama. + +Mark Elbrecht has sent me notice that bash-2.04 +is available for DJGPP V2. The files are available as: + +ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh204b.zip binary +ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh204d.zip documentation +ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh204s.zip source + +Mark began to work with bash-2.05, but I don't know the current status. + +Bash-3.0 compiles and runs with no modifications under Microsoft's Services +for Unix (SFU), once known as Interix. I do not anticipate any problems +with building bash-4.0, but will gladly accept any patches that are needed. + +A6) How can I build bash with gcc? + +Bash configures to use gcc by default if it is available. Read the +file INSTALL in the distribution for more information. + +A7) How can I make bash my login shell? + +Some machines let you use `chsh' to change your login shell. Other +systems use `passwd -s' or `passwd -e'. If one of these works for +you, that's all you need. Note that many systems require the full +pathname to a shell to appear in /etc/shells before you can make it +your login shell. For this, you may need the assistance of your +friendly local system administrator. + +If you cannot do this, you can still use bash as your login shell, but +you need to perform some tricks. The basic idea is to add a command +to your login shell's startup file to replace your login shell with +bash. + +For example, if your login shell is csh or tcsh, and you have installed +bash in /usr/gnu/bin/bash, add the following line to ~/.login: + + if ( -f /usr/gnu/bin/bash ) exec /usr/gnu/bin/bash --login + +(the `--login' tells bash that it is a login shell). + +It's not a good idea to put this command into ~/.cshrc, because every +csh you run without the `-f' option, even ones started to run csh scripts, +reads that file. If you must put the command in ~/.cshrc, use something +like + + if ( $?prompt ) exec /usr/gnu/bin/bash --login + +to ensure that bash is exec'd only when the csh is interactive. + +If your login shell is sh or ksh, you have to do two things. + +First, create an empty file in your home directory named `.bash_profile'. +The existence of this file will prevent the exec'd bash from trying to +read ~/.profile, and re-execing itself over and over again. ~/.bash_profile +is the first file bash tries to read initialization commands from when +it is invoked as a login shell. + +Next, add a line similar to the above to ~/.profile: + + [ -f /usr/gnu/bin/bash ] && [ -x /usr/gnu/bin/bash ] && \ + exec /usr/gnu/bin/bash --login + +This will cause login shells to replace themselves with bash running as +a login shell. Once you have this working, you can copy your initialization +code from ~/.profile to ~/.bash_profile. + +I have received word that the recipe supplied above is insufficient for +machines running CDE. CDE has a maze of twisty little startup files, all +slightly different. + +If you cannot change your login shell in the password file to bash, you +will have to (apparently) live with CDE using the shell in the password +file to run its startup scripts. If you have changed your shell to bash, +there is code in the CDE startup files (on Solaris, at least) that attempts +to do the right thing. It is, however, often broken, and may require that +you use the $BASH_ENV trick described below. + +`dtterm' claims to use $SHELL as the default program to start, so if you +can change $SHELL in the CDE startup files, you should be able to use bash +in your terminal windows. + +Setting DTSOURCEPROFILE in ~/.dtprofile will cause the `Xsession' program +to read your login shell's startup files. You may be able to use bash for +the rest of the CDE programs by setting SHELL to bash in ~/.dtprofile as +well, but I have not tried this. + +You can use the above `exec' recipe to start bash when not logging in with +CDE by testing the value of the DT variable: + + if [ -n "$DT" ]; then + [ -f /usr/gnu/bin/bash ] && exec /usr/gnu/bin/bash --login + fi + +If CDE starts its shells non-interactively during login, the login shell +startup files (~/.profile, ~/.bash_profile) will not be sourced at login. +To get around this problem, append a line similar to the following to your +~/.dtprofile: + + BASH_ENV=${HOME}/.bash_profile ; export BASH_ENV + +and add the following line to the beginning of ~/.bash_profile: + + unset BASH_ENV + +A8) I just changed my login shell to bash, and now I can't FTP into my + machine. Why not? + +You must add the full pathname to bash to the file /etc/shells. As +noted in the answer to the previous question, many systems require +this before you can make bash your login shell. + +Most versions of ftpd use this file to prohibit `special' users +such as `uucp' and `news' from using FTP. + +A9) What's the `POSIX Shell and Utilities standard'? + +POSIX is a name originally coined by Richard Stallman for a +family of open system standards based on UNIX. There are a +number of aspects of UNIX under consideration for +standardization, from the basic system services at the system +call and C library level to applications and tools to system +administration and management. Each area of standardization is +assigned to a working group in the 1003 series. + +The POSIX Shell and Utilities standard was originally developed by +IEEE Working Group 1003.2 (POSIX.2). Today it has been merged with +the original 1003.1 Working Group and is maintained by the Austin +Group (a joint working group of the IEEE, The Open Group and +ISO/IEC SC22/WG15). Today the Shell and Utilities are a volume +within the set of documents that make up IEEE Std 1003.1-2001, and +thus now the former POSIX.2 (from 1992) is now part of the current +POSIX.1 standard (POSIX 1003.1-2001). + +The Shell and Utilities volume concentrates on the command +interpreter interface and utility programs commonly executed from +the command line or by other programs. The standard is freely +available on the web at http://www.UNIX-systems.org/version3/ . +Work continues at the Austin Group on maintenance issues; see +http://www.opengroup.org/austin/ to join the discussions. + +Bash is concerned with the aspects of the shell's behavior defined +by the POSIX Shell and Utilities volume. The shell command +language has of course been standardized, including the basic flow +control and program execution constructs, I/O redirection and +pipelining, argument handling, variable expansion, and quoting. + +The `special' builtins, which must be implemented as part of the +shell to provide the desired functionality, are specified as +being part of the shell; examples of these are `eval' and +`export'. Other utilities appear in the sections of POSIX not +devoted to the shell which are commonly (and in some cases must +be) implemented as builtin commands, such as `read' and `test'. +POSIX also specifies aspects of the shell's interactive +behavior as part of the UPE, including job control and command +line editing. Only vi-style line editing commands have been +standardized; emacs editing commands were left out due to +objections. + +The latest version of the POSIX Shell and Utilities standard is +available (now updated to the 2004 Edition) as part of the Single +UNIX Specification Version 3 at + +http://www.UNIX-systems.org/version3/ + +A10) What is the bash `posix mode'? + +Although bash is an implementation of the POSIX shell +specification, there are areas where the bash default behavior +differs from that spec. The bash `posix mode' changes the bash +behavior in these areas so that it obeys the spec more closely. + +Posix mode is entered by starting bash with the --posix or +'-o posix' option or executing `set -o posix' after bash is running. + +The specific aspects of bash which change when posix mode is +active are listed in the file POSIX in the bash distribution. +They are also listed in a section in the Bash Reference Manual +(from which that file is generated). + +Section B: The latest version + +B1) What's new in version 4.0? + +Bash-4.0 is the fourth major release of bash. There are numerous new features, +some experimental. Depending on community reception, the experimental +features will evolve. + +Bash-4.0 contains the following new features (see the manual page for +complete descriptions and the CHANGES and NEWS files in the bash-4.0 +distribution): + +o When using substring expansion on the positional parameters, a starting + index of 0 now causes $0 to be prefixed to the list. + +o There is a new variable, $BASHPID, which always returns the process id of + the current shell. + +o There is a new `autocd' option that, when enabled, causes bash to attempt + to `cd' to a directory name that is supplied as the first word of a + simple command. + +o There is a new `checkjobs' option that causes the shell to check for and + report any running or stopped jobs at exit. + +o The programmable completion code exports a new COMP_TYPE variable, set to + a character describing the type of completion being attempted. + +o The programmable completion code exports a new COMP_KEY variable, set to + the character that caused the completion to be invoked (e.g., TAB). + +o The programmable completion code now uses the same set of characters as + readline when breaking the command line into a list of words. + +o The block multiplier for the ulimit -c and -f options is now 512 when in + Posix mode, as Posix specifies. + +o Changed the behavior of the read builtin to save any partial input received + in the specified variable when the read builtin times out. This also + results in variables specified as arguments to read to be set to the empty + string when there is no input available. When the read builtin times out, + it returns an exit status greater than 128. + +o The shell now has the notion of a `compatibility level', controlled by + new variables settable by `shopt'. Setting this variable currently + restores the bash-3.1 behavior when processing quoted strings on the rhs + of the `=~' operator to the `[[' command. + +o The `ulimit' builtin now has new -b (socket buffer size) and -T (number + of threads) options. + +o There is a new `compopt' builtin that allows completion functions to modify + completion options for existing completions or the completion currently + being executed. + +o The `read' builtin has a new -i option which inserts text into the reply + buffer when using readline. + +o A new `-E' option to the complete builtin allows control of the default + behavior for completion on an empty line. + +o There is now limited support for completing command name words containing + globbing characters. + +o The `help' builtin now has a new -d option, to display a short description, + and a -m option, to print help information in a man page-like format. + +o There is a new `mapfile' builtin to populate an array with lines from a + given file. + +o If a command is not found, the shell attempts to execute a shell function + named `command_not_found_handle', supplying the command words as the + function arguments. + +o There is a new shell option: `globstar'. When enabled, the globbing code + treats `**' specially -- it matches all directories (and files within + them, when appropriate) recursively. + +o There is a new shell option: `dirspell'. When enabled, the filename + completion code performs spelling correction on directory names during + completion. + +o The `-t' option to the `read' builtin now supports fractional timeout + values. + +o Brace expansion now allows zero-padding of expanded numeric values and + will add the proper number of zeroes to make sure all values contain the + same number of digits. + +o There is a new bash-specific bindable readline function: `dabbrev-expand'. + It uses menu completion on a set of words taken from the history list. + +o The command assigned to a key sequence with `bind -x' now sets two new + variables in the environment of the executed command: READLINE_LINE_BUFFER + and READLINE_POINT. The command can change the current readline line + and cursor position by modifying READLINE_LINE_BUFFER and READLINE_POINT, + respectively. + +o There is a new >>& redirection operator, which appends the standard output + and standard error to the named file. + +o The parser now understands `|&' as a synonym for `2>&1 |', which redirects + the standard error for a command through a pipe. + +o The new `;&' case statement action list terminator causes execution to + continue with the action associated with the next pattern in the + statement rather than terminating the command. + +o The new `;;&' case statement action list terminator causes the shell to + test the next set of patterns after completing execution of the current + action, rather than terminating the command. + +o The shell understands a new variable: PROMPT_DIRTRIM. When set to an + integer value greater than zero, prompt expansion of \w and \W will + retain only that number of trailing pathname components and replace + the intervening characters with `...'. + +o There are new case-modifying word expansions: uppercase (^[^]) and + lowercase (,[,]). They can work on either the first character or + array element, or globally. They accept an optional shell pattern + that determines which characters to modify. There is an optionally- + configured feature to include capitalization operators. + +o The shell provides associative array variables, with the appropriate + support to create, delete, assign values to, and expand them. + +o The `declare' builtin now has new -l (convert value to lowercase upon + assignment) and -u (convert value to uppercase upon assignment) options. + There is an optionally-configurable -c option to capitalize a value at + assignment. + +o There is a new `coproc' reserved word that specifies a coprocess: an + asynchronous command run with two pipes connected to the creating shell. + Coprocs can be named. The input and output file descriptors and the + PID of the coprocess are available to the calling shell in variables + with coproc-specific names. + +o A value of 0 for the -t option to `read' now returns success if there is + input available to be read from the specified file descriptor. + +o CDPATH and GLOBIGNORE are ignored when the shell is running in privileged + mode. + +o New bindable readline functions shell-forward-word and shell-backward-word, + which move forward and backward words delimited by shell metacharacters + and honor shell quoting. + +o New bindable readline functions shell-backward-kill-word and shell-kill-word + which kill words backward and forward, but use the same word boundaries + as shell-forward-word and shell-backward-word. + +A short feature history dating from Bash-2.0: + +Bash-3.2 contained the following new features: + +o Bash-3.2 now checks shell scripts for NUL characters rather than non-printing + characters when deciding whether or not a script is a binary file. + +o Quoting the string argument to the [[ command's =~ (regexp) operator now + forces string matching, as with the other pattern-matching operators. + +Bash-3.1 contained the following new features: + +o Bash-3.1 may now be configured and built in a mode that enforces strict + POSIX compliance. + +o The `+=' assignment operator, which appends to the value of a string or + array variable, has been implemented. + +o It is now possible to ignore case when matching in contexts other than + filename generation using the new `nocasematch' shell option. + +Bash-3.0 contained the following new features: + +o Features to support the bash debugger have been implemented, and there + is a new `extdebug' option to turn the non-default options on + +o HISTCONTROL is now a colon-separated list of options and has been + extended with a new `erasedups' option that will result in only one + copy of a command being kept in the history list + +o Brace expansion has been extended with a new {x..y} form, producing + sequences of digits or characters + +o Timestamps are now kept with history entries, with an option to save + and restore them from the history file; there is a new HISTTIMEFORMAT + variable describing how to display the timestamps when listing history + entries + +o The `[[' command can now perform extended regular expression (egrep-like) + matching, with matched subexpressions placed in the BASH_REMATCH array + variable + +o A new `pipefail' option causes a pipeline to return a failure status if + any command in it fails + +o The `jobs', `kill', and `wait' builtins now accept job control notation + in their arguments even if job control is not enabled + +o The `gettext' package and libintl have been integrated, and the shell + messages may be translated into other languages + +Bash-2.05b introduced the following new features: + +o support for multibyte characters has been added to both bash and readline + +o the DEBUG trap is now run *before* simple commands, ((...)) commands, + [[...]] conditional commands, and for ((...)) loops + +o the shell now performs arithmetic in the largest integer size the machine + supports (intmax_t) + +o there is a new \D{...} prompt expansion; passes the `...' to strftime(3) + and inserts the result into the expanded prompt + +o there is a new `here-string' redirection operator: <<< word + +o when displaying variables, function attributes and definitions are shown + separately, allowing them to be re-used as input (attempting to re-use + the old output would result in syntax errors). + +o `read' has a new `-u fd' option to read from a specified file descriptor + +o the bash debugger in examples/bashdb has been modified to work with the + new DEBUG trap semantics, the command set has been made more gdb-like, + and the changes to $LINENO make debugging functions work better + +o the expansion of $LINENO inside a shell function is only relative to the + function start if the shell is interactive -- if the shell is running a + script, $LINENO expands to the line number in the script. This is as + POSIX-2001 requires + +Bash-2.05a introduced the following new features: + +o The `printf' builtin has undergone major work + +o There is a new read-only `shopt' option: login_shell, which is set by + login shells and unset otherwise + +o New `\A' prompt string escape sequence; expanding to time in 24-hour + HH:MM format + +o New `-A group/-g' option to complete and compgen; goes group name + completion + +o New [+-]O invocation option to set and unset `shopt' options at startup + +o ksh-like `ERR' trap + +o `for' loops now allow empty word lists after the `in' reserved word + +o new `hard' and `soft' arguments for the `ulimit' builtin + +o Readline can be configured to place the user at the same point on the line + when retrieving commands from the history list + +o Readline can be configured to skip `hidden' files (filenames with a leading + `.' on Unix) when performing completion + +Bash-2.05 introduced the following new features: + +o This version has once again reverted to using locales and strcoll(3) when + processing pattern matching bracket expressions, as POSIX requires. +o Added a new `--init-file' invocation argument as a synonym for `--rcfile', + per the new GNU coding standards. +o The /dev/tcp and /dev/udp redirections now accept service names as well as + port numbers. +o `complete' and `compgen' now take a `-o value' option, which controls some + of the aspects of that compspec. Valid values are: + + default - perform bash default completion if programmable + completion produces no matches + dirnames - perform directory name completion if programmable + completion produces no matches + filenames - tell readline that the compspec produces filenames, + so it can do things like append slashes to + directory names and suppress trailing spaces +o A new loadable builtin, realpath, which canonicalizes and expands symlinks + in pathname arguments. +o When `set' is called without options, it prints function defintions in a + way that allows them to be reused as input. This affects `declare' and + `declare -p' as well. This only happens when the shell is not in POSIX + mode, since POSIX.2 forbids this behavior. + +Bash-2.04 introduced the following new features: + +o Programmable word completion with the new `complete' and `compgen' builtins; + examples are provided in examples/complete/complete-examples +o `history' has a new `-d' option to delete a history entry +o `bind' has a new `-x' option to bind key sequences to shell commands +o The prompt expansion code has new `\j' and `\l' escape sequences +o The `no_empty_cmd_completion' shell option, if enabled, inhibits + command completion when TAB is typed on an empty line +o `help' has a new `-s' option to print a usage synopsis +o New arithmetic operators: var++, var--, ++var, --var, expr1,expr2 (comma) +o New ksh93-style arithmetic for command: + for ((expr1 ; expr2; expr3 )); do list; done +o `read' has new options: `-t', `-n', `-d', `-s' +o The redirection code handles several filenames specially: /dev/fd/N, + /dev/stdin, /dev/stdout, /dev/stderr +o The redirection code now recognizes /dev/tcp/HOST/PORT and + /dev/udp/HOST/PORT and tries to open a TCP or UDP socket, respectively, + to the specified port on the specified host +o The ${!prefix*} expansion has been implemented +o A new FUNCNAME variable, which expands to the name of a currently-executing + function +o The GROUPS variable is no longer readonly +o A new shopt `xpg_echo' variable, to control the behavior of echo with + respect to backslash-escape sequences at runtime +o The NON_INTERACTIVE_LOGIN_SHELLS #define has returned + +The version of Readline released with Bash-2.04, Readline-4.1, had several +new features as well: + +o Parentheses matching is always compiled into readline, and controllable + with the new `blink-matching-paren' variable +o The history-search-forward and history-search-backward functions now leave + point at the end of the line when the search string is empty, like + reverse-search-history, and forward-search-history +o A new function for applications: rl_on_new_line_with_prompt() +o New variables for applications: rl_already_prompted, and rl_gnu_readline_p + + +Bash-2.03 had very few new features, in keeping with the convention +that odd-numbered releases provide mainly bug fixes. A number of new +features were added to Readline, mostly at the request of the Cygnus +folks. + +A new shopt option, `restricted_shell', so that startup files can test + whether or not the shell was started in restricted mode +Filename generation is now performed on the words between ( and ) in + compound array assignments (this is really a bug fix) +OLDPWD is now auto-exported, as POSIX.2 requires +ENV and BASH_ENV are read-only variables in a restricted shell +Bash may now be linked against an already-installed Readline library, + as long as the Readline library is version 4 or newer +All shells begun with the `--login' option will source the login shell + startup files, even if the shell is not interactive + +There were lots of changes to the version of the Readline library released +along with Bash-2.03. For a complete list of the changes, read the file +CHANGES in the Bash-2.03 distribution. + +Bash-2.02 contained the following new features: + +a new version of malloc (based on the old GNU malloc code in previous + bash versions) that is more page-oriented, more conservative + with memory usage, does not `orphan' large blocks when they + are freed, is usable on 64-bit machines, and has allocation + checking turned on unconditionally +POSIX.2-style globbing character classes ([:alpha:], [:alnum:], etc.) +POSIX.2-style globbing equivalence classes +POSIX.2-style globbing collating symbols +the ksh [[...]] extended conditional command +the ksh egrep-style extended pattern matching operators +a new `printf' builtin +the ksh-like $(, &>, >|, <<<, [n]<&word-, [n]>&word-, >>& + prompt string special char translation and variable expansion + auto-export of variables in initial environment + command search finds functions before builtins + bash return builtin will exit a file sourced with `.' + builtins: cd -/-L/-P, exec -l/-c/-a, echo -e/-E, hash -d/-l/-p/-t. + export -n/-f/-p/name=value, pwd -L/-P, + read -e/-p/-a/-t/-n/-d/-s/-u/-i, + readonly -a/-f/name=value, trap -l, set +o, + set -b/-m/-o option/-h/-p/-B/-C/-H/-P, + unset -f/-v, ulimit -i/-m/-p/-q/-u/-x, + type -a/-p/-t/-f/-P, suspend -f, kill -n, + test -o optname/s1 == s2/s1 < s2/s1 > s2/-nt/-ot/-ef/-O/-G/-S + bash reads ~/.bashrc for interactive shells, $ENV for non-interactive + bash restricted shell mode is more extensive + bash allows functions and variables with the same name + brace expansion + tilde expansion + arithmetic expansion with $((...)) and `let' builtin + the `[[...]]' extended conditional command + process substitution + aliases and alias/unalias builtins + local variables in functions and `local' builtin + readline and command-line editing with programmable completion + command history and history/fc builtins + csh-like history expansion + other new bash builtins: bind, command, compgen, complete, builtin, + declare/typeset, dirs, enable, fc, help, + history, logout, popd, pushd, disown, shopt, + printf, compopt, mapfile + exported functions + filename generation when using output redirection (command >a*) + POSIX.2-style globbing character classes + POSIX.2-style globbing equivalence classes + POSIX.2-style globbing collating symbols + egrep-like extended pattern matching operators + case-insensitive pattern matching and globbing + variable assignments preceding commands affect only that command, + even for builtins and functions + posix mode and strict posix conformance + redirection to /dev/fd/N, /dev/stdin, /dev/stdout, /dev/stderr, + /dev/tcp/host/port, /dev/udp/host/port + debugger support, including `caller' builtin and new variables + RETURN trap + the `+=' assignment operator + autocd shell option and behavior + command-not-found hook with command_not_found_handle shell function + globstar shell option and `**' globbing behavior + |& synonym for `2>&1 |' + ;& and ;;& case action list terminators + case-modifying word expansions and variable attributes + associative arrays + coprocesses using the `coproc' reserved word and variables + +Things sh has that bash does not: + uses variable SHACCT to do shell accounting + includes `stop' builtin (bash can use alias stop='kill -s STOP') + `newgrp' builtin + turns on job control if called as `jsh' + $TIMEOUT (like bash $TMOUT) + `^' is a synonym for `|' + new SVR4.2 sh builtins: mldmode, priv + +Implementation differences: + redirection to/from compound commands causes sh to create a subshell + bash does not allow unbalanced quotes; sh silently inserts them at EOF + bash does not mess with signal 11 + sh sets (euid, egid) to (uid, gid) if -p not supplied and uid < 100 + bash splits only the results of expansions on IFS, using POSIX.2 + field splitting rules; sh splits all words on IFS + sh does not allow MAILCHECK to be unset (?) + sh does not allow traps on SIGALRM or SIGCHLD + bash allows multiple option arguments when invoked (e.g. -x -v); + sh allows only a single option argument (`sh -x -v' attempts + to open a file named `-v', and, on SunOS 4.1.4, dumps core. + On Solaris 2.4 and earlier versions, sh goes into an infinite + loop.) + sh exits a script if any builtin fails; bash exits only if one of + the POSIX.2 `special' builtins fails + +C2) How does bash differ from the Korn shell, version ksh88? + +Things bash has or uses that ksh88 does not: + long invocation options + [-+]O invocation option + -l invocation option + `!' reserved word + arithmetic for command: for ((expr1 ; expr2; expr3 )); do list; done + arithmetic in largest machine-supported size (intmax_t) + posix mode and posix conformance + command hashing + tilde expansion for assignment statements that look like $PATH + process substitution with named pipes if /dev/fd is not available + the ${!param} indirect parameter expansion operator + the ${!param*} prefix expansion operator + the ${param:offset[:length]} parameter substring operator + the ${param/pat[/string]} parameter pattern substitution operator + variables: BASH, BASH_VERSION, BASH_VERSINFO, BASHPID, UID, EUID, SHLVL, + TIMEFORMAT, HISTCMD, HOSTTYPE, OSTYPE, MACHTYPE, + HISTFILESIZE, HISTIGNORE, HISTCONTROL, PROMPT_COMMAND, + IGNOREEOF, FIGNORE, INPUTRC, HOSTFILE, DIRSTACK, + PIPESTATUS, HOSTNAME, OPTERR, SHELLOPTS, GLOBIGNORE, + GROUPS, FUNCNAME, histchars, auto_resume, PROMPT_DIRTRIM + prompt expansion with backslash escapes and command substitution + redirection: &> (stdout and stderr), <<<, [n]<&word-, [n]>&word-, >>& + more extensive and extensible editing and programmable completion + builtins: bind, builtin, command, declare, dirs, echo -e/-E, enable, + exec -l/-c/-a, fc -s, export -n/-f/-p, hash, help, history, + jobs -x/-r/-s, kill -s/-n/-l, local, logout, popd, pushd, + read -e/-p/-a/-t/-n/-d/-s, readonly -a/-n/-f/-p, + set -o braceexpand/-o histexpand/-o interactive-comments/ + -o notify/-o physical/-o posix/-o hashall/-o onecmd/ + -h/-B/-C/-b/-H/-P, set +o, suspend, trap -l, type, + typeset -a/-F/-p, ulimit -i/-q/-u/-x, umask -S, alias -p, + shopt, disown, printf, complete, compgen, compopt, mapfile + `!' csh-style history expansion + POSIX.2-style globbing character classes + POSIX.2-style globbing equivalence classes + POSIX.2-style globbing collating symbols + egrep-like extended pattern matching operators + case-insensitive pattern matching and globbing + `**' arithmetic operator to do exponentiation + redirection to /dev/fd/N, /dev/stdin, /dev/stdout, /dev/stderr + arrays of unlimited size + TMOUT is default timeout for `read' and `select' + debugger support, including the `caller' builtin + RETURN trap + Timestamps in history entries + {x..y} brace expansion + The `+=' assignment operator + autocd shell option and behavior + command-not-found hook with command_not_found_handle shell function + globstar shell option and `**' globbing behavior + |& synonym for `2>&1 |' + ;& and ;;& case action list terminators + case-modifying word expansions and variable attributes + associative arrays + coprocesses using the `coproc' reserved word and variables + +Things ksh88 has or uses that bash does not: + tracked aliases (alias -t) + variables: ERRNO, FPATH, EDITOR, VISUAL + co-processes (bash uses different syntax) + weirdly-scoped functions + typeset +f to list all function names without definitions + text of command history kept in a file, not memory + builtins: alias -x, cd old new, newgrp, print, + read -p/-s/var?prompt, set -A/-o gmacs/ + -o bgnice/-o markdirs/-o trackall/-o viraw/-s, + typeset -H/-L/-R/-Z/-A/-ft/-fu/-fx/-t, whence + using environment to pass attributes of exported variables + arithmetic evaluation done on arguments to some builtins + reads .profile from $PWD when invoked as login shell + +Implementation differences: + ksh runs last command of a pipeline in parent shell context + bash has brace expansion by default (ksh88 compile-time option) + bash has fixed startup file for all interactive shells; ksh reads $ENV + bash has exported functions + bash command search finds functions before builtins + bash waits for all commands in pipeline to exit before returning status + emacs-mode editing has some slightly different key bindings + +C3) Which new features in ksh-93 are not in bash, and which are? + +This list is current through ksh93t (11/04/2008) + +New things in ksh-93 not in bash-4.0: + floating point arithmetic and variables + math library functions + ${!name[sub]} name of subscript for associative array + `.' is allowed in variable names to create a hierarchical namespace + more extensive compound assignment syntax + discipline functions + KEYBD trap + variables: .sh.edchar, .sh.edmode, .sh.edcol, .sh.edtext, .sh.version, + .sh.name, .sh.subscript, .sh.value, .sh.match, HISTEDIT + backreferences in pattern matching (\N) + `&' operator in pattern lists for matching (match all instead of any) + exit statuses between 0 and 255 + FPATH and PATH mixing + lexical scoping for local variables in `ksh' functions + no scoping for local variables in `POSIX' functions + $'' \C[.collating-element.] escape sequence + -C/-I invocation options + print -f (bash uses printf) + `fc' has been renamed to `hist' + `.' can execute shell functions + getopts -a + printf %B, %H, %P, %R, %T, %Z modifiers, output base for %d, `=' flag + read -N (read -n differs, too)/-v + set -o showme/-o multiline (bash default) + `sleep' and `getconf' builtins (bash has loadable versions) + typeset -n and `nameref' variables + typeset -C/-S/-T/-X/-h/-s + experimental `type' definitions (a la typedef) using typeset + negative subscripts for indexed array variables + array expansions ${array[sub1..sub2]} and ${!array[sub1..sub2]} + associative array assignments using `;' as element separator + command substitution $(n<#) expands to current byte offset for fd N + new '${ ' form of command substitution, executed in current shell + new >;/<#pat/<##pat/<#/># redirections + redirection operators preceded with {varname} to store fd number in varname + brace expansion printf-like formats + +New things in ksh-93 present in bash-4.0: + associative arrays + [n]<&word- and [n]>&word- redirections (combination dup and close) + for (( expr1; expr2; expr3 )) ; do list; done - arithmetic for command + ?:, ++, --, `expr1 , expr2' arithmetic operators + expansions: ${!param}, ${param:offset[:len]}, ${param/pat[/str]}, + ${!param*} + compound array assignment + the `!' reserved word + loadable builtins -- but ksh uses `builtin' while bash uses `enable' + new $'...' and $"..." quoting + FIGNORE (but bash uses GLOBIGNORE), HISTCMD + brace expansion and set -B + changes to kill builtin + `command', `builtin', `disown' builtins + echo -e + exec -c/-a + read -A (bash uses read -a) + read -t/-d + trap -p + `.' restores the positional parameters when it completes + set -o notify/-C + set -o pipefail + set -G (-o globstar) and ** + POSIX.2 `test' + umask -S + unalias -a + command and arithmetic substitution performed on PS1, PS4, and ENV + command name completion, TAB displaying possible completions + ENV processed only for interactive shells + The `+=' assignment operator + the `;&' case statement "fallthrough" pattern list terminator + csh-style history expansion and set -H + negative offsets in ${param:offset:length} + +Section D: Why does bash do some things differently than other Unix shells? + +D1) Why does bash run a different version of `command' than + `which command' says it will? + +On many systems, `which' is actually a csh script that assumes +you're running csh. In tcsh, `which' and its cousin `where' +are builtins. On other Unix systems, `which' is a perl script +that uses the PATH environment variable. Many Linux distributions +use GNU `which', which is a C program that can understand shell +aliases. + +The csh script version reads the csh startup files from your +home directory and uses those to determine which `command' will +be invoked. Since bash doesn't use any of those startup files, +there's a good chance that your bash environment differs from +your csh environment. The bash `type' builtin does everything +`which' does, and will report correct results for the running +shell. If you're really wedded to the name `which', try adding +the following function definition to your .bashrc: + + which() + { + builtin type "$@" + } + +If you're moving from tcsh and would like to bring `where' along +as well, use this function: + + where() + { + builtin type -a "$@" + } + +D2) Why doesn't bash treat brace expansions exactly like csh? + +The only difference between bash and csh brace expansion is that +bash requires a brace expression to contain at least one unquoted +comma if it is to be expanded. Any brace-surrounded word not +containing an unquoted comma is left unchanged by the brace +expansion code. This affords the greatest degree of sh +compatibility. + +Bash, ksh, zsh, and pd-ksh all implement brace expansion this way. + +D3) Why doesn't bash have csh variable modifiers? + +Posix has specified a more powerful, albeit somewhat more cryptic, +mechanism cribbed from ksh, and bash implements it. + +${parameter%word} + Remove smallest suffix pattern. The WORD is expanded to produce + a pattern. It then expands to the value of PARAMETER, with the + smallest portion of the suffix matched by the pattern deleted. + + x=file.c + echo ${x%.c}.o + -->file.o + +${parameter%%word} + + Remove largest suffix pattern. The WORD is expanded to produce + a pattern. It then expands to the value of PARAMETER, with the + largest portion of the suffix matched by the pattern deleted. + + x=posix/src/std + echo ${x%%/*} + -->posix + +${parameter#word} + Remove smallest prefix pattern. The WORD is expanded to produce + a pattern. It then expands to the value of PARAMETER, with the + smallest portion of the prefix matched by the pattern deleted. + + x=$HOME/src/cmd + echo ${x#$HOME} + -->/src/cmd + +${parameter##word} + Remove largest prefix pattern. The WORD is expanded to produce + a pattern. It then expands to the value of PARAMETER, with the + largest portion of the prefix matched by the pattern deleted. + + x=/one/two/three + echo ${x##*/} + -->three + + +Given + a=/a/b/c/d + b=b.xxx + + csh bash result + --- ---- ------ + $a:h ${a%/*} /a/b/c + $a:t ${a##*/} d + $b:r ${b%.*} b + $b:e ${b##*.} xxx + + +D4) How can I make my csh aliases work when I convert to bash? + +Bash uses a different syntax to support aliases than csh does. +The details can be found in the documentation. We have provided +a shell script which does most of the work of conversion for you; +this script can be found in ./examples/misc/aliasconv.sh. Here is +how you use it: + +Start csh in the normal way for you. (e.g., `csh') + +Pipe the output of `alias' through `aliasconv.sh', saving the +results into `bash_aliases': + + alias | bash aliasconv.sh >bash_aliases + +Edit `bash_aliases', carefully reading through any created +functions. You will need to change the names of some csh specific +variables to the bash equivalents. The script converts $cwd to +$PWD, $term to $TERM, $home to $HOME, $user to $USER, and $prompt +to $PS1. You may also have to add quotes to avoid unwanted +expansion. + +For example, the csh alias: + + alias cd 'cd \!*; echo $cwd' + +is converted to the bash function: + + cd () { command cd "$@"; echo $PWD ; } + +The only thing that needs to be done is to quote $PWD: + + cd () { command cd "$@"; echo "$PWD" ; } + +Merge the edited file into your ~/.bashrc. + +There is an additional, more ambitious, script in +examples/misc/cshtobash that attempts to convert your entire csh +environment to its bash equivalent. This script can be run as +simply `cshtobash' to convert your normal interactive +environment, or as `cshtobash ~/.login' to convert your login +environment. + +D5) How can I pipe standard output and standard error from one command to + another, like csh does with `|&'? + +Use + command 2>&1 | command2 + +The key is to remember that piping is performed before redirection, so +file descriptor 1 points to the pipe when it is duplicated onto file +descriptor 2. + +D6) Now that I've converted from ksh to bash, are there equivalents to + ksh features like autoloaded functions and the `whence' command? + +There are features in ksh-88 and ksh-93 that do not have direct bash +equivalents. Most, however, can be emulated with very little trouble. + +ksh-88 feature Bash equivalent +-------------- --------------- +compiled-in aliases set up aliases in .bashrc; some ksh aliases are + bash builtins (hash, history, type) +coprocesses named pipe pairs (one for read, one for write) +typeset +f declare -F +cd, print, whence function substitutes in examples/functions/kshenv +autoloaded functions examples/functions/autoload is the same as typeset -fu +read var?prompt read -p prompt var + +ksh-93 feature Bash equivalent +-------------- --------------- +sleep, getconf Bash has loadable versions in examples/loadables +${.sh.version} $BASH_VERSION +print -f printf +hist alias hist=fc +$HISTEDIT $FCEDIT + +Section E: How can I get bash to do certain things, and why does bash do + things the way it does? + +E1) Why is the bash builtin `test' slightly different from /bin/test? + +The specific example used here is [ ! x -o x ], which is false. + +Bash's builtin `test' implements the Posix.2 spec, which can be +summarized as follows (the wording is due to David Korn): + +Here is the set of rules for processing test arguments. + + 0 Args: False + 1 Arg: True iff argument is not null. + 2 Args: If first arg is !, True iff second argument is null. + If first argument is unary, then true if unary test is true + Otherwise error. + 3 Args: If second argument is a binary operator, do binary test of $1 $3 + If first argument is !, negate two argument test of $2 $3 + If first argument is `(' and third argument is `)', do the + one-argument test of the second argument. + Otherwise error. + 4 Args: If first argument is !, negate three argument test of $2 $3 $4. + Otherwise unspecified + 5 or more Args: unspecified. (Historical shells would use their + current algorithm). + +The operators -a and -o are considered binary operators for the purpose +of the 3 Arg case. + +As you can see, the test becomes (not (x or x)), which is false. + +E2) Why does bash sometimes say `Broken pipe'? + +If a sequence of commands appears in a pipeline, and one of the +reading commands finishes before the writer has finished, the +writer receives a SIGPIPE signal. Many other shells special-case +SIGPIPE as an exit status in the pipeline and do not report it. +For example, in: + + ps -aux | head + +`head' can finish before `ps' writes all of its output, and ps +will try to write on a pipe without a reader. In that case, bash +will print `Broken pipe' to stderr when ps is killed by a +SIGPIPE. + +As of bash-3.1, bash does not report SIGPIPE errors by default. You +can build a version of bash that will report such errors. + +E3) When I have terminal escape sequences in my prompt, why does bash + wrap lines at the wrong column? + +Readline, the line editing library that bash uses, does not know +that the terminal escape sequences do not take up space on the +screen. The redisplay code assumes, unless told otherwise, that +each character in the prompt is a `printable' character that +takes up one character position on the screen. + +You can use the bash prompt expansion facility (see the PROMPTING +section in the manual page) to tell readline that sequences of +characters in the prompt strings take up no screen space. + +Use the \[ escape to begin a sequence of non-printing characters, +and the \] escape to signal the end of such a sequence. + +E4) If I pipe the output of a command into `read variable', why doesn't + the output show up in $variable when the read command finishes? + +This has to do with the parent-child relationship between Unix +processes. It affects all commands run in pipelines, not just +simple calls to `read'. For example, piping a command's output +into a `while' loop that repeatedly calls `read' will result in +the same behavior. + +Each element of a pipeline, even a builtin or shell function, +runs in a separate process, a child of the shell running the +pipeline. A subprocess cannot affect its parent's environment. +When the `read' command sets the variable to the input, that +variable is set only in the subshell, not the parent shell. When +the subshell exits, the value of the variable is lost. + +Many pipelines that end with `read variable' can be converted +into command substitutions, which will capture the output of +a specified command. The output can then be assigned to a +variable: + + grep ^gnu /usr/lib/news/active | wc -l | read ngroup + +can be converted into + + ngroup=$(grep ^gnu /usr/lib/news/active | wc -l) + +This does not, unfortunately, work to split the text among +multiple variables, as read does when given multiple variable +arguments. If you need to do this, you can either use the +command substitution above to read the output into a variable +and chop up the variable using the bash pattern removal +expansion operators or use some variant of the following +approach. + +Say /usr/local/bin/ipaddr is the following shell script: + +#! /bin/sh +host `hostname` | awk '/address/ {print $NF}' + +Instead of using + + /usr/local/bin/ipaddr | read A B C D + +to break the local machine's IP address into separate octets, use + + OIFS="$IFS" + IFS=. + set -- $(/usr/local/bin/ipaddr) + IFS="$OIFS" + A="$1" B="$2" C="$3" D="$4" + +Beware, however, that this will change the shell's positional +parameters. If you need them, you should save them before doing +this. + +This is the general approach -- in most cases you will not need to +set $IFS to a different value. + +Some other user-supplied alternatives include: + +read A B C D << HERE + $(IFS=.; echo $(/usr/local/bin/ipaddr)) +HERE + +and, where process substitution is available, + +read A B C D < <(IFS=.; echo $(/usr/local/bin/ipaddr)) + +E5) I have a bunch of shell scripts that use backslash-escaped characters + in arguments to `echo'. Bash doesn't interpret these characters. Why + not, and how can I make it understand them? + +This is the behavior of echo on most Unix System V machines. + +The bash builtin `echo' is modeled after the 9th Edition +Research Unix version of `echo'. It does not interpret +backslash-escaped characters in its argument strings by default; +it requires the use of the -e option to enable the +interpretation. The System V echo provides no way to disable the +special characters; the bash echo has a -E option to disable +them. + +There is a configuration option that will make bash behave like +the System V echo and interpret things like `\t' by default. Run +configure with the --enable-xpg-echo-default option to turn this +on. Be aware that this will cause some of the tests run when you +type `make tests' to fail. + +There is a shell option, `xpg_echo', settable with `shopt', that will +change the behavior of echo at runtime. Enabling this option turns +on expansion of backslash-escape sequences. + +E6) Why doesn't a while or for loop get suspended when I type ^Z? + +This is a consequence of how job control works on Unix. The only +thing that can be suspended is the process group. This is a single +command or pipeline of commands that the shell forks and executes. + +When you run a while or for loop, the only thing that the shell forks +and executes are any commands in the while loop test and commands in +the loop bodies. These, therefore, are the only things that can be +suspended when you type ^Z. + +If you want to be able to stop the entire loop, you need to put it +within parentheses, which will force the loop into a subshell that +may be stopped (and subsequently restarted) as a single unit. + +E7) What about empty for loops in Makefiles? + +It's fairly common to see constructs like this in automatically-generated +Makefiles: + +SUBDIRS = @SUBDIRS@ + + ... + +subdirs-clean: + for d in ${SUBDIRS}; do \ + ( cd $$d && ${MAKE} ${MFLAGS} clean ) \ + done + +When SUBDIRS is empty, this results in a command like this being passed to +bash: + + for d in ; do + ( cd $d && ${MAKE} ${MFLAGS} clean ) + done + +In versions of bash before bash-2.05a, this was a syntax error. If the +reserved word `in' was present, a word must follow it before the semicolon +or newline. The language in the manual page referring to the list of words +being empty referred to the list after it is expanded. These versions of +bash required that there be at least one word following the `in' when the +construct was parsed. + +The idiomatic Makefile solution is something like: + +SUBDIRS = @SUBDIRS@ + +subdirs-clean: + subdirs=$SUBDIRS ; for d in $$subdirs; do \ + ( cd $$d && ${MAKE} ${MFLAGS} clean ) \ + done + +The latest updated POSIX standard has changed this: the word list +is no longer required. Bash versions 2.05a and later accept the +new syntax. + +E8) Why does the arithmetic evaluation code complain about `08'? + +The bash arithmetic evaluation code (used for `let', $(()), (()), and in +other places), interprets a leading `0' in numeric constants as denoting +an octal number, and a leading `0x' as denoting hexadecimal. This is +in accordance with the POSIX.2 spec, section 2.9.2.1, which states that +arithmetic constants should be handled as signed long integers as defined +by the ANSI/ISO C standard. + +The POSIX.2 interpretation committee has confirmed this: + +http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-173.html + +E9) Why does the pattern matching expression [A-Z]* match files beginning + with every letter except `z'? + +Bash-2.03, Bash-2.05 and later versions honor the current locale setting +when processing ranges within pattern matching bracket expressions ([A-Z]). +This is what POSIX.2 and SUSv3/XPG6 specify. + +The behavior of the matcher in bash-2.05 and later versions depends on the +current LC_COLLATE setting. Setting this variable to `C' or `POSIX' will +result in the traditional behavior ([A-Z] matches all uppercase ASCII +characters). Many other locales, including the en_US locale (the default +on many US versions of Linux) collate the upper and lower case letters like +this: + + AaBb...Zz + +which means that [A-Z] matches every letter except `z'. Others collate like + + aAbBcC...zZ + +which means that [A-Z] matches every letter except `a'. + +The portable way to specify upper case letters is [:upper:] instead of +A-Z; lower case may be specified as [:lower:] instead of a-z. + +Look at the manual pages for setlocale(3), strcoll(3), and, if it is +present, locale(1). If you have locale(1), you can use it to find +your current locale information even if you do not have any of the +LC_ variables set. + +My advice is to put + + export LC_COLLATE=C + +into /etc/profile and inspect any shell scripts run from cron for +constructs like [A-Z]. This will prevent things like + + rm [A-Z]* + +from removing every file in the current directory except those beginning +with `z' and still allow individual users to change the collation order. +Users may put the above command into their own profiles as well, of course. + +E10) Why does `cd //' leave $PWD as `//'? + +POSIX.2, in its description of `cd', says that *three* or more leading +slashes may be replaced with a single slash when canonicalizing the +current working directory. + +This is, I presume, for historical compatibility. Certain versions of +Unix, and early network file systems, used paths of the form +//hostname/path to access `path' on server `hostname'. + +E11) If I resize my xterm while another program is running, why doesn't bash + notice the change? + +This is another issue that deals with job control. + +The kernel maintains a notion of a current terminal process group. Members +of this process group (processes whose process group ID is equal to the +current terminal process group ID) receive terminal-generated signals like +SIGWINCH. (For more details, see the JOB CONTROL section of the bash +man page.) + +If a terminal is resized, the kernel sends SIGWINCH to each member of +the terminal's current process group (the `foreground' process group). + +When bash is running with job control enabled, each pipeline (which may be +a single command) is run in its own process group, different from bash's +process group. This foreground process group receives the SIGWINCH; bash +does not. Bash has no way of knowing that the terminal has been resized. + +There is a `checkwinsize' option, settable with the `shopt' builtin, that +will cause bash to check the window size and adjust its idea of the +terminal's dimensions each time a process stops or exits and returns control +of the terminal to bash. Enable it with `shopt -s checkwinsize'. + +E12) Why don't negative offsets in substring expansion work like I expect? + +When substring expansion of the form ${param:offset[:length} is used, +an `offset' that evaluates to a number less than zero counts back from +the end of the expanded value of $param. + +When a negative `offset' begins with a minus sign, however, unexpected things +can happen. Consider + + a=12345678 + echo ${a:-4} + +intending to print the last four characters of $a. The problem is that +${param:-word} already has a well-defined meaning: expand to word if the +expanded value of param is unset or null, and $param otherwise. + +To use negative offsets that begin with a minus sign, separate the +minus sign and the colon with a space. + +E13) Why does filename completion misbehave if a colon appears in the filename? + +Filename completion (and word completion in general) may appear to behave +improperly if there is a colon in the word to be completed. + +The colon is special to readline's word completion code: it is one of the +characters that breaks words for the completer. Readline uses these characters +in sort of the same way that bash uses $IFS: they break or separate the words +the completion code hands to the application-specific or default word +completion functions. The original intent was to make it easy to edit +colon-separated lists (such as $PATH in bash) in various applications using +readline for input. + +This is complicated by the fact that some versions of the popular +`bash-completion' programmable completion package have problems with the +default completion behavior in the presence of colons. + +The current set of completion word break characters is available in bash as +the value of the COMP_WORDBREAKS variable. Removing `:' from that value is +enough to make the colon not special to completion: + +COMP_WORDBREAKS=${COMP_WORDBREAKS//:} + +You can also quote the colon with a backslash to achieve the same result +temporarily. + +E14) Why does quoting the pattern argument to the regular expression matching + conditional operator (=~) cause regexp matching to stop working? + +In versions of bash prior to bash-3.2, the effect of quoting the regular +expression argument to the [[ command's =~ operator was not specified. +The practical effect was that double-quoting the pattern argument required +backslashes to quote special pattern characters, which interfered with the +backslash processing performed by double-quoted word expansion and was +inconsistent with how the == shell pattern matching operator treated +quoted characters. + +In bash-3.2, the shell was changed to internally quote characters in single- +and double-quoted string arguments to the =~ operator, which suppresses the +special meaning of the characters special to regular expression processing +(`.', `[', `\', `(', `), `*', `+', `?', `{', `|', `^', and `$') and forces +them to be matched literally. This is consistent with how the `==' pattern +matching operator treats quoted portions of its pattern argument. + +Since the treatment of quoted string arguments was changed, several issues +have arisen, chief among them the problem of white space in pattern arguments +and the differing treatment of quoted strings between bash-3.1 and bash-3.2. +Both problems may be solved by using a shell variable to hold the pattern. +Since word splitting is not performed when expanding shell variables in all +operands of the [[ command, this allows users to quote patterns as they wish +when assigning the variable, then expand the values to a single string that +may contain whitespace. The first problem may be solved by using backslashes +or any other quoting mechanism to escape the white space in the patterns. + +Bash-4.0 introduces the concept of a `compatibility level', controlled by +several options to the `shopt' builtin. If the `compat31' option is enabled, +bash reverts to the bash-3.1 behavior with respect to quoting the rhs of +the =~ operator. + +Section F: Things to watch out for on certain Unix versions + +F1) Why can't I use command line editing in my `cmdtool'? + +The problem is `cmdtool' and bash fighting over the input. When +scrolling is enabled in a cmdtool window, cmdtool puts the tty in +`raw mode' to permit command-line editing using the mouse for +applications that cannot do it themselves. As a result, bash and +cmdtool each try to read keyboard input immediately, with neither +getting enough of it to be useful. + +This mode also causes cmdtool to not implement many of the +terminal functions and control sequences appearing in the +`sun-cmd' termcap entry. For a more complete explanation, see +that file examples/suncmd.termcap in the bash distribution. + +`xterm' is a better choice, and gets along with bash much more +smoothly. + +If you must use cmdtool, you can use the termcap description in +examples/suncmd.termcap. Set the TERMCAP variable to the terminal +description contained in that file, i.e. + +TERMCAP='Mu|sun-cmd:am:bs:km:pt:li#34:co#80:cl=^L:ce=\E[K:cd=\E[J:rs=\E[s:' + +Then export TERMCAP and start a new cmdtool window from that shell. +The bash command-line editing should behave better in the new +cmdtool. If this works, you can put the assignment to TERMCAP +in your bashrc file. + +F2) I built bash on Solaris 2. Why do globbing expansions and filename + completion chop off the first few characters of each filename? + +This is the consequence of building bash on SunOS 5 and linking +with the libraries in /usr/ucblib, but using the definitions +and structures from files in /usr/include. + +The actual conflict is between the dirent structure in +/usr/include/dirent.h and the struct returned by the version of +`readdir' in libucb.a (a 4.3-BSD style `struct direct'). + +Make sure you've got /usr/ccs/bin ahead of /usr/ucb in your $PATH +when configuring and building bash. This will ensure that you +use /usr/ccs/bin/cc or acc instead of /usr/ucb/cc and that you +link with libc before libucb. + +If you have installed the Sun C compiler, you may also need to +put /usr/ccs/bin and /opt/SUNWspro/bin into your $PATH before +/usr/ucb. + +F3) Why does bash dump core after I interrupt username completion or + `~user' tilde expansion on a machine running NIS? + +This is a famous and long-standing bug in the SunOS YP (sorry, NIS) +client library, which is part of libc. + +The YP library code keeps static state -- a pointer into the data +returned from the server. When YP initializes itself (setpwent), +it looks at this pointer and calls free on it if it's non-null. +So far, so good. + +If one of the YP functions is interrupted during getpwent (the +exact function is interpretwithsave()), and returns NULL, the +pointer is freed without being reset to NULL, and the function +returns. The next time getpwent is called, it sees that this +pointer is non-null, calls free, and the bash free() blows up +because it's being asked to free freed memory. + +The traditional Unix mallocs allow memory to be freed multiple +times; that's probably why this has never been fixed. You can +run configure with the `--without-gnu-malloc' option to use +the C library malloc and avoid the problem. + +F4) I'm running SVR4.2. Why is the line erased every time I type `@'? + +The `@' character is the default `line kill' character in most +versions of System V, including SVR4.2. You can change this +character to whatever you want using `stty'. For example, to +change the line kill character to control-u, type + + stty kill ^U + +where the `^' and `U' can be two separate characters. + +F5) Why does bash report syntax errors when my C News scripts use a + redirection before a subshell command? + +The actual command in question is something like + + < file ( command ) + +According to the grammar given in the POSIX.2 standard, this construct +is, in fact, a syntax error. Redirections may only precede `simple +commands'. A subshell construct such as the above is one of the shell's +`compound commands'. A redirection may only follow a compound command. + +This affects the mechanical transformation of commands that use `cat' +to pipe a file into a command (a favorite Useless-Use-Of-Cat topic on +comp.unix.shell). While most commands of the form + + cat file | command + +can be converted to `< file command', shell control structures such as +loops and subshells require `command < file'. + +The file CWRU/sh-redir-hack in the bash distribution is an +(unofficial) patch to parse.y that will modify the grammar to +support this construct. It will not apply with `patch'; you must +modify parse.y by hand. Note that if you apply this, you must +recompile with -DREDIRECTION_HACK. This introduces a large +number of reduce/reduce conflicts into the shell grammar. + +F6) Why can't I use vi-mode editing on Red Hat Linux 6.1? + +The short answer is that Red Hat screwed up. + +The long answer is that they shipped an /etc/inputrc that only works +for emacs mode editing, and then screwed all the vi users by setting +INPUTRC to /etc/inputrc in /etc/profile. + +The short fix is to do one of the following: remove or rename +/etc/inputrc, set INPUTRC=~/.inputrc in ~/.bashrc (or .bash_profile, +but make sure you export it if you do), remove the assignment to +INPUTRC from /etc/profile, add + + set keymap emacs + +to the beginning of /etc/inputrc, or bracket the key bindings in +/etc/inputrc with these lines + + $if mode=emacs + [...] + $endif + +F7) Why do bash-2.05a and bash-2.05b fail to compile `printf.def' on + HP/UX 11.x? + +HP/UX's support for long double is imperfect at best. + +GCC will support it without problems, but the HP C library functions +like strtold(3) and printf(3) don't actually work with long doubles. +HP implemented a `long_double' type as a 4-element array of 32-bit +ints, and that is what the library functions use. The ANSI C +`long double' type is a 128-bit floating point scalar. + +The easiest fix, until HP fixes things up, is to edit the generated +config.h and #undef the HAVE_LONG_DOUBLE line. After doing that, +the compilation should complete successfully. + +Section G: How can I get bash to do certain common things? + +G1) How can I get bash to read and display eight-bit characters? + +This is a process requiring several steps. + +First, you must ensure that the `physical' data path is a full eight +bits. For xterms, for example, the `vt100' resources `eightBitInput' +and `eightBitOutput' should be set to `true'. + +Once you have set up an eight-bit path, you must tell the kernel and +tty driver to leave the eighth bit of characters alone when processing +keyboard input. Use `stty' to do this: + + stty cs8 -istrip -parenb + +For old BSD-style systems, you can use + + stty pass8 + +You may also need + + stty even odd + +Finally, you need to tell readline that you will be inputting and +displaying eight-bit characters. You use readline variables to do +this. These variables can be set in your .inputrc or using the bash +`bind' builtin. Here's an example using `bind': + + bash$ bind 'set convert-meta off' + bash$ bind 'set meta-flag on' + bash$ bind 'set output-meta on' + +The `set' commands between the single quotes may also be placed +in ~/.inputrc. + +The script examples/scripts.noah/meta.bash encapsulates the bind +commands in a shell function. + +G2) How do I write a function `x' to replace builtin command `x', but + still invoke the command from within the function? + +This is why the `command' and `builtin' builtins exist. The +`command' builtin executes the command supplied as its first +argument, skipping over any function defined with that name. The +`builtin' builtin executes the builtin command given as its first +argument directly. + +For example, to write a function to replace `cd' that writes the +hostname and current directory to an xterm title bar, use +something like the following: + + cd() + { + builtin cd "$@" && xtitle "$HOST: $PWD" + } + +This could also be written using `command' instead of `builtin'; +the version above is marginally more efficient. + +G3) How can I find the value of a shell variable whose name is the value + of another shell variable? + +Versions of Bash newer than Bash-2.0 support this directly. You can use + + ${!var} + +For example, the following sequence of commands will echo `z': + + var1=var2 + var2=z + echo ${!var1} + +For sh compatibility, use the `eval' builtin. The important +thing to remember is that `eval' expands the arguments you give +it again, so you need to quote the parts of the arguments that +you want `eval' to act on. + +For example, this expression prints the value of the last positional +parameter: + + eval echo \"\$\{$#\}\" + +The expansion of the quoted portions of this expression will be +deferred until `eval' runs, while the `$#' will be expanded +before `eval' is executed. In versions of bash later than bash-2.0, + + echo ${!#} + +does the same thing. + +This is not the same thing as ksh93 `nameref' variables, though the syntax +is similar. I may add namerefs in a future bash version. + +G4) How can I make the bash `time' reserved word print timing output that + looks like the output from my system's /usr/bin/time? + +The bash command timing code looks for a variable `TIMEFORMAT' and +uses its value as a format string to decide how to display the +timing statistics. + +The value of TIMEFORMAT is a string with `%' escapes expanded in a +fashion similar in spirit to printf(3). The manual page explains +the meanings of the escape sequences in the format string. + +If TIMEFORMAT is not set, bash acts as if the following assignment had +been performed: + + TIMEFORMAT=$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS' + +The POSIX.2 default time format (used by `time -p command') is + + TIMEFORMAT=$'real %2R\nuser %2U\nsys %2S' + +The BSD /usr/bin/time format can be emulated with: + + TIMEFORMAT=$'\t%1R real\t%1U user\t%1S sys' + +The System V /usr/bin/time format can be emulated with: + + TIMEFORMAT=$'\nreal\t%1R\nuser\t%1U\nsys\t%1S' + +The ksh format can be emulated with: + + TIMEFORMAT=$'\nreal\t%2lR\nuser\t%2lU\nsys\t%2lS' + +G5) How do I get the current directory into my prompt? + +Bash provides a number of backslash-escape sequences which are expanded +when the prompt string (PS1 or PS2) is displayed. The full list is in +the manual page. + +The \w expansion gives the full pathname of the current directory, with +a tilde (`~') substituted for the current value of $HOME. The \W +expansion gives the basename of the current directory. To put the full +pathname of the current directory into the path without any tilde +subsitution, use $PWD. Here are some examples: + + PS1='\w$ ' # current directory with tilde + PS1='\W$ ' # basename of current directory + PS1='$PWD$ ' # full pathname of current directory + +The single quotes are important in the final example to prevent $PWD from +being expanded when the assignment to PS1 is performed. + +G6) How can I rename "*.foo" to "*.bar"? + +Use the pattern removal functionality described in D3. The following `for' +loop will do the trick: + + for f in *.foo; do + mv $f ${f%foo}bar + done + +G7) How can I translate a filename from uppercase to lowercase? + +The script examples/functions/lowercase, originally written by John DuBois, +will do the trick. The converse is left as an exercise. + +G8) How can I write a filename expansion (globbing) pattern that will match + all files in the current directory except "." and ".."? + +You must have set the `extglob' shell option using `shopt -s extglob' to use +this: + + echo .!(.|) * + +A solution that works without extended globbing is given in the Unix Shell +FAQ, posted periodically to comp.unix.shell. It's a variant of + + echo .[!.]* ..?* * + +(The ..?* catches files with names of three or more characters beginning +with `..') + +Section H: Where do I go from here? + +H1) How do I report bugs in bash, and where should I look for fixes and + advice? + +Use the `bashbug' script to report bugs. It is built and +installed at the same time as bash. It provides a standard +template for reporting a problem and automatically includes +information about your configuration and build environment. + +`bashbug' sends its reports to bug-bash@gnu.org, which +is a large mailing list gatewayed to the usenet newsgroup gnu.bash.bug. + +Bug fixes, answers to questions, and announcements of new releases +are all posted to gnu.bash.bug. Discussions concerning bash features +and problems also take place there. + +To reach the bash maintainers directly, send mail to +bash-maintainers@gnu.org. + +H2) What kind of bash documentation is there? + +First, look in the doc directory in the bash distribution. It should +contain at least the following files: + +bash.1 an extensive, thorough Unix-style manual page +builtins.1 a manual page covering just bash builtin commands +bashref.texi a reference manual in GNU tex`info format +bashref.info an info version of the reference manual +FAQ this file +article.ms text of an article written for The Linux Journal +readline.3 a man page describing readline + +Postscript, HTML, and ASCII files created from the above source are +available in the documentation distribution. + +There is additional documentation available for anonymous FTP from host +ftp.cwru.edu in the `pub/bash' directory. + +Cameron Newham and Bill Rosenblatt have written a book on bash, published +by O'Reilly and Associates. The book is based on Bill Rosenblatt's Korn +Shell book. The title is ``Learning the Bash Shell'', and the ISBN number +of the third edition, published in March, 2005, is 0-596-00965-8. Look for +it in fine bookstores near you. This edition of the book has been updated +to cover bash-3.0. + +The GNU Bash Reference Manual has been published as a printed book by +Network Theory Ltd (Paperback, ISBN: 0-9541617-7-7, Nov. 2006). It covers +bash-3.2 and is available from most online bookstores (see +http://www.network-theory.co.uk/bash/manual/ for details). The publisher +will donate $1 to the Free Software Foundation for each copy sold. + +Arnold Robbins and Nelson Beebe have written ``Classic Shell Scripting'', +published by O'Reilly. The first edition, with ISBN number 0-596-00595-4, +was published in May, 2005. + +Chris F. A. Johnson, a frequent contributor to comp.unix.shell and +gnu.bash.bug, has written ``Shell Scripting Recipes: A Problem-Solution +Approach,'' a new book on shell scripting, concentrating on features of +the POSIX standard helpful to shell script writers. The first edition from +Apress, with ISBN number 1-59059-471-1, was published in May, 2005. + +H3) What's coming in future versions? + +These are features I hope to include in a future version of bash. + +Rocky Bernstein's bash debugger (support is included with bash-4.0) + +H4) What's on the bash `wish list' for future versions? + +These are features that may or may not appear in a future version of bash. + +breaking some of the shell functionality into embeddable libraries +a module system like zsh's, using dynamic loading like builtins +a bash programmer's guide with a chapter on creating loadable builtins +a better loadable interface to perl with access to the shell builtins and + variables (contributions gratefully accepted) +ksh93-like `nameref' variables +ksh93-like `xx.yy' variables (including some of the .sh.* variables) and + associated disipline functions +Some of the new ksh93 pattern matching operators, like backreferencing + +H5) When will the next release appear? + +The next version will appear sometime in 2009. Never make predictions. + +This document is Copyright 1995-2009 by Chester Ramey. + +Permission is hereby granted, without written agreement and +without license or royalty fees, to use, copy, and distribute +this document for any purpose, provided that the above copyright +notice appears in all copies of this document and that the +contents of this document remain unaltered. diff --git a/doc/FAQ.orig b/doc/FAQ.orig new file mode 100644 index 000000000..1cff3c8ef --- /dev/null +++ b/doc/FAQ.orig @@ -0,0 +1,1745 @@ +This is the Bash FAQ, version 3.24, for Bash version 2.05b. + +This document contains a set of frequently-asked questions concerning +Bash, the GNU Bourne-Again Shell. Bash is a freely-available command +interpreter with advanced features for both interactive use and shell +programming. + +Another good source of basic information about shells is the collection +of FAQ articles periodically posted to comp.unix.shell. + +Questions and comments concerning this document should be sent to +chet@po.cwru.edu. + +This document is available for anonymous FTP with the URL + +ftp://ftp.cwru.edu/pub/bash/FAQ + +The Bash home page is http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html + +---------- +Contents: + +Section A: The Basics + +A1) What is it? +A2) What's the latest version? +A3) Where can I get it? +A4) On what machines will bash run? +A5) Will bash run on operating systems other than Unix? +A6) How can I build bash with gcc? +A7) How can I make bash my login shell? +A8) I just changed my login shell to bash, and now I can't FTP into my + machine. Why not? +A9) What's the `POSIX 1003.2 standard'? +A10) What is the bash `posix mode'? + +Section B: The latest version + +B1) What's new in version 2.05b? +B2) Are there any user-visible incompatibilities between bash-2.05b and + bash-1.14.7? + +Section C: Differences from other Unix shells + +C1) How does bash differ from sh, the Bourne shell? +C2) How does bash differ from the Korn shell, version ksh88? +C3) Which new features in ksh-93 are not in bash, and which are? + +Section D: Why does bash do some things differently than other Unix shells? + +D1) Why does bash run a different version of `command' than + `which command' says it will? +D2) Why doesn't bash treat brace expansions exactly like csh? +D3) Why doesn't bash have csh variable modifiers? +D4) How can I make my csh aliases work when I convert to bash? +D5) How can I pipe standard output and standard error from one command to + another, like csh does with `|&'? +D6) Now that I've converted from ksh to bash, are there equivalents to + ksh features like autoloaded functions and the `whence' command? + +Section E: Why does bash do certain things the way it does? + +E1) Why is the bash builtin `test' slightly different from /bin/test? +E2) Why does bash sometimes say `Broken pipe'? +E3) When I have terminal escape sequences in my prompt, why does bash + wrap lines at the wrong column? +E4) If I pipe the output of a command into `read variable', why doesn't + the output show up in $variable when the read command finishes? +E5) I have a bunch of shell scripts that use backslash-escaped characters + in arguments to `echo'. Bash doesn't interpret these characters. Why + not, and how can I make it understand them? +E6) Why doesn't a while or for loop get suspended when I type ^Z? +E7) What about empty for loops in Makefiles? +E8) Why does the arithmetic evaluation code complain about `08'? +E9) Why does the pattern matching expression [A-Z]* match files beginning + with every letter except `z'? +E10) Why does `cd //' leave $PWD as `//'? +E11) If I resize my xterm while another program is running, why doesn't bash + notice the change? + +Section F: Things to watch out for on certain Unix versions + +F1) Why can't I use command line editing in my `cmdtool'? +F2) I built bash on Solaris 2. Why do globbing expansions and filename + completion chop off the first few characters of each filename? +F3) Why does bash dump core after I interrupt username completion or + `~user' tilde expansion on a machine running NIS? +F4) I'm running SVR4.2. Why is the line erased every time I type `@'? +F5) Why does bash report syntax errors when my C News scripts use a + redirection before a subshell command? +F6) Why can't I use vi-mode editing on Red Hat Linux 6.1? +F7) Why do bash-2.05a and bash-2.05b fail to compile `printf.def' on + HP/UX 11.x? + +Section G: How can I get bash to do certain common things? + +G1) How can I get bash to read and display eight-bit characters? +G2) How do I write a function `x' to replace builtin command `x', but + still invoke the command from within the function? +G3) How can I find the value of a shell variable whose name is the value + of another shell variable? +G4) How can I make the bash `time' reserved word print timing output that + looks like the output from my system's /usr/bin/time? +G5) How do I get the current directory into my prompt? +G6) How can I rename "*.foo" to "*.bar"? +G7) How can I translate a filename from uppercase to lowercase? +G8) How can I write a filename expansion (globbing) pattern that will match + all files in the current directory except "." and ".."? + +Section H: Where do I go from here? + +H1) How do I report bugs in bash, and where should I look for fixes and + advice? +H2) What kind of bash documentation is there? +H3) What's coming in future versions? +H4) What's on the bash `wish list'? +H5) When will the next release appear? + +---------- +Section A: The Basics + +A1) What is it? + +Bash is a Unix command interpreter (shell). It is an implementation of +the Posix 1003.2 shell standard, and resembles the Korn and System V +shells. + +Bash contains a number of enhancements over those shells, both +for interactive use and shell programming. Features geared +toward interactive use include command line editing, command +history, job control, aliases, and prompt expansion. Programming +features include additional variable expansions, shell +arithmetic, and a number of variables and options to control +shell behavior. + +Bash was originally written by Brian Fox of the Free Software +Foundation. The current developer and maintainer is Chet Ramey +of Case Western Reserve University. + +A2) What's the latest version? + +The latest version is 2.05b, first made available on Wednesday, 17 +July, 2002. + +A3) Where can I get it? + +Bash is the GNU project's shell, and so is available from the +master GNU archive site, ftp.gnu.org, and its mirrors. The +latest version is also available for FTP from ftp.cwru.edu. +The following URLs tell how to get version 2.05b: + +ftp://ftp.gnu.org/pub/gnu/bash/bash-2.05b.tar.gz +ftp://ftp.cwru.edu/pub/bash/bash-2.05b.tar.gz + +Formatted versions of the documentation are available with the URLs: + +ftp://ftp.gnu.org/pub/gnu/bash/bash-doc-2.05b.tar.gz +ftp://ftp.cwru.edu/pub/bash/bash-doc-2.05b.tar.gz + +A4) On what machines will bash run? + +Bash has been ported to nearly every version of UNIX. All you +should have to do to build it on a machine for which a port +exists is to type `configure' and then `make'. The build process +will attempt to discover the version of UNIX you have and tailor +itself accordingly, using a script created by GNU autoconf. + +More information appears in the file `INSTALL' in the distribution. + +The Bash web page (http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html) +explains how to obtain binary versions of bash for most of the major +commercial Unix systems. + +A5) Will bash run on operating systems other than Unix? + +Configuration specifics for Unix-like systems such as QNX and +LynxOS are included in the distribution. Bash-2.05 and later +versions should compile and run on Minix 2.0 (patches were +contributed), but I don't believe anyone has built bash-2.x on +earlier Minix versions yet. + +Bash has been ported to versions of Windows implementing the Win32 +programming interface. This includes Windows 95 and Windows NT. +The port was done by Cygnus Solutions as part of their CYGWIN +project. For more information about the project, look at the URLs + +http://www.cygwin.com/ +http://sourceware.cygnus.com/cygwin + +Cygnus originally ported bash-1.14.7, and that port was part of their +early GNU-Win32 (the original name) releases. Cygnus has also done a +port of bash-2.05 to the CYGWIN environment, and it is available as +part of their current release. + +Bash-2.05b should require no local Cygnus changes to build and run under +CYGWIN. + +The Cygnus port works only on Intel machines. There is a port of bash +(I don't know which version) to the alpha/NT environment available from + +ftp://ftp.gnustep.org//pub/win32/bash-alpha-nt-1.01.tar.gz + +DJ Delorie has a port of bash-2.x which runs under MS-DOS, as part +of the DJGPP project. For more information on the project, see + +http://www.delorie.com/djgpp/ + +I have been told that the original DJGPP port was done by Daisuke Aoyama. + +Mark Elbrecht has sent me notice that bash-2.04 +is available for DJGPP V2. The files are available as: + +ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh204b.zip binary +ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh204d.zip documentation +ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh204s.zip source + +Mark has begun to work with bash-2.05, but I don't know the status. + +Ports of bash-1.12 and bash-2.0 are available for OS/2 from + +ftp://hobbes.nmsu.edu/pub/os2/util/shell/bash_112.zip +ftp://hobbes.nmsu.edu/pub/os2/util/shell/bash-2.0(253).zip + +I haven't looked at either, but the second appears to be a binary-only +distribution. Beware. + +I have received word that Bash (I'm not sure which version, but I +believe that it's at least bash-2.02.1) is the standard shell on +BeOS. + +A6) How can I build bash with gcc? + +Bash configures to use gcc by default if it is available. Read the +file INSTALL in the distribution for more information. + +A7) How can I make bash my login shell? + +Some machines let you use `chsh' to change your login shell. Other +systems use `passwd -s' or `passwd -e'. If one of these works for +you, that's all you need. Note that many systems require the full +pathname to a shell to appear in /etc/shells before you can make it +your login shell. For this, you may need the assistance of your +friendly local system administrator. + +If you cannot do this, you can still use bash as your login shell, but +you need to perform some tricks. The basic idea is to add a command +to your login shell's startup file to replace your login shell with +bash. + +For example, if your login shell is csh or tcsh, and you have installed +bash in /usr/gnu/bin/bash, add the following line to ~/.login: + + if ( -f /usr/gnu/bin/bash ) exec /usr/gnu/bin/bash --login + +(the `--login' tells bash that it is a login shell). + +It's not a good idea to put this command into ~/.cshrc, because every +csh you run without the `-f' option, even ones started to run csh scripts, +reads that file. If you must put the command in ~/.cshrc, use something +like + + if ( $?prompt ) exec /usr/gnu/bin/bash --login + +to ensure that bash is exec'd only when the csh is interactive. + +If your login shell is sh or ksh, you have to do two things. + +First, create an empty file in your home directory named `.bash_profile'. +The existence of this file will prevent the exec'd bash from trying to +read ~/.profile, and re-execing itself over and over again. ~/.bash_profile +is the first file bash tries to read initialization commands from when +it is invoked as a login shell. + +Next, add a line similar to the above to ~/.profile: + + [ -f /usr/gnu/bin/bash ] && [ -x /usr/gnu/bin/bash ] && \ + exec /usr/gnu/bin/bash --login + +This will cause login shells to replace themselves with bash running as +a login shell. Once you have this working, you can copy your initialization +code from ~/.profile to ~/.bash_profile. + +I have received word that the recipe supplied above is insufficient for +machines running CDE. CDE has a maze of twisty little startup files, all +slightly different. + +If you cannot change your login shell in the password file to bash, you +will have to (apparently) live with CDE using the shell in the password +file to run its startup scripts. If you have changed your shell to bash, +there is code in the CDE startup files (on Solaris, at least) that attempts +to do the right thing. It is, however, often broken, and may require that +you use the $BASH_ENV trick described below. + +`dtterm' claims to use $SHELL as the default program to start, so if you +can change $SHELL in the CDE startup files, you should be able to use bash +in your terminal windows. + +Setting DTSOURCEPROFILE in ~/.dtprofile will cause the `Xsession' program +to read your login shell's startup files. You may be able to use bash for +the rest of the CDE programs by setting SHELL to bash in ~/.dtprofile as +well, but I have not tried this. + +You can use the above `exec' recipe to start bash when not logging in with +CDE by testing the value of the DT variable: + + if [ -n "$DT" ]; then + [ -f /usr/gnu/bin/bash ] && exec /usr/gnu/bin/bash --login + fi + +If CDE starts its shells non-interactively during login, the login shell +startup files (~/.profile, ~/.bash_profile) will not be sourced at login. +To get around this problem, append a line similar to the following to your +~/.dtprofile: + + BASH_ENV=${HOME}/.bash_profile ; export BASH_ENV + +and add the following line to the beginning of ~/.bash_profile: + + unset BASH_ENV + +A8) I just changed my login shell to bash, and now I can't FTP into my + machine. Why not? + +You must add the full pathname to bash to the file /etc/shells. As +noted in the answer to the previous question, many systems require +this before you can make bash your login shell. + +Most versions of ftpd use this file to prohibit `special' users +such as `uucp' and `news' from using FTP. + +A9) What's the `POSIX 1003.2 standard'? + +POSIX is a name originally coined by Richard Stallman for a +family of open system standards based on UNIX. There are a +number of aspects of UNIX under consideration for +standardization, from the basic system services at the system +call and C library level to applications and tools to system +administration and management. Each area of standardization is +assigned to a working group in the 1003 series. + +The POSIX Shell and Utilities standard has been developed by IEEE +Working Group 1003.2 (POSIX.2). It concentrates on the command +interpreter interface and utility programs commonly executed from +the command line or by other programs. An initial version of the +standard has been approved and published by the IEEE, and work is +currently underway to update it. + +Bash is concerned with the aspects of the shell's behavior +defined by POSIX.2. The shell command language has of course +been standardized, including the basic flow control and program +execution constructs, I/O redirection and pipelining, argument +handling, variable expansion, and quoting. + +The `special' builtins, which must be implemented as part of the +shell to provide the desired functionality, are specified as +being part of the shell; examples of these are `eval' and +`export'. Other utilities appear in the sections of POSIX.2 not +devoted to the shell which are commonly (and in some cases must +be) implemented as builtin commands, such as `read' and `test'. +POSIX.2 also specifies aspects of the shell's interactive +behavior as part of the UPE, including job control and command +line editing. Only vi-style line editing commands have been +standardized; emacs editing commands were left out due to +objections. + +The Open Group has made an older version of its Single Unix +Specification (version 2), which is very similar to POSIX.2, +available on the web at + +http://www.opengroup.org/onlinepubs/007908799/ + +The Single Unix Specification, version 3, is available on the web at + +http://www.opengroup.org/onlinepubs/007904975/ + +A10) What is the bash `posix mode'? + +Although bash is an implementation of the POSIX.2 shell +specification, there are areas where the bash default behavior +differs from that spec. The bash `posix mode' changes the bash +behavior in these areas so that it obeys the spec more closely. + +Posix mode is entered by starting bash with the --posix or +'-o posix' option or executing `set -o posix' after bash is running. + +The specific aspects of bash which change when posix mode is +active are listed in the file POSIX in the bash distribution. +They are also listed in a section in the Bash Reference Manual +(from which that file is generated). + +Section B: The latest version + +B1) What's new in version 2.05b? + +The raison d'etre for bash-2.05b is to make a second intermediate +release containing the first of the new features to be available +in bash-3.0 and get feedback on those features before proceeding. +The major new feature is multibyte character support in both Bash +and Readline. + +Bash-2.05b contains the following new features (see the manual page for +complete descriptions and the CHANGES and NEWS files in the bash-2.05b +distribution): + +o support for multibyte characters has been added to both bash and readline + +o the DEBUG trap is now run *before* simple commands, ((...)) commands, + [[...]] conditional commands, and for ((...)) loops + +o the shell now performs arithmetic in the largest integer size the machine + supports (intmax_t) + +o there is a new \D{...} prompt expansion; passes the `...' to strftime(3) + and inserts the result into the expanded prompt + +o there is a new `here-string' redirection operator: <<< word + +o when displaying variables, function attributes and definitions are shown + separately, allowing them to be re-used as input (attempting to re-use + the old output would result in syntax errors). + +o `read' has a new `-u fd' option to read from a specified file descriptor + +o the bash debugger in examples/bashdb has been modified to work with the + new DEBUG trap semantics, the command set has been made more gdb-like, + and the changes to $LINENO make debugging functions work better + +o the expansion of $LINENO inside a shell function is only relative to the + function start if the shell is interactive -- if the shell is running a + script, $LINENO expands to the line number in the script. This is as + POSIX-2001 requires + + +A short feature history dating from Bash-2.0: + +Bash-2.05a introduced the following new features: + +o The `printf' builtin has undergone major work + +o There is a new read-only `shopt' option: login_shell, which is set by + login shells and unset otherwise + +o New `\A' prompt string escape sequence; expanding to time in 24-hour + HH:MM format + +o New `-A group/-g' option to complete and compgen; goes group name + completion + +o New [+-]O invocation option to set and unset `shopt' options at startup + +o ksh-like `ERR' trap + +o `for' loops now allow empty word lists after the `in' reserved word + +o new `hard' and `soft' arguments for the `ulimit' builtin + +o Readline can be configured to place the user at the same point on the line + when retrieving commands from the history list + +o Readline can be configured to skip `hidden' files (filenames with a leading + `.' on Unix) when performing completion + +Bash-2.05 introduced the following new features: + +o This version has once again reverted to using locales and strcoll(3) when + processing pattern matching bracket expressions, as POSIX requires. +o Added a new `--init-file' invocation argument as a synonym for `--rcfile', + per the new GNU coding standards. +o The /dev/tcp and /dev/udp redirections now accept service names as well as + port numbers. +o `complete' and `compgen' now take a `-o value' option, which controls some + of the aspects of that compspec. Valid values are: + + default - perform bash default completion if programmable + completion produces no matches + dirnames - perform directory name completion if programmable + completion produces no matches + filenames - tell readline that the compspec produces filenames, + so it can do things like append slashes to + directory names and suppress trailing spaces +o A new loadable builtin, realpath, which canonicalizes and expands symlinks + in pathname arguments. +o When `set' is called without options, it prints function defintions in a + way that allows them to be reused as input. This affects `declare' and + `declare -p' as well. This only happens when the shell is not in POSIX + mode, since POSIX.2 forbids this behavior. + +Bash-2.04 introduced the following new features: + +o Programmable word completion with the new `complete' and `compgen' builtins; + examples are provided in examples/complete/complete-examples +o `history' has a new `-d' option to delete a history entry +o `bind' has a new `-x' option to bind key sequences to shell commands +o The prompt expansion code has new `\j' and `\l' escape sequences +o The `no_empty_cmd_completion' shell option, if enabled, inhibits + command completion when TAB is typed on an empty line +o `help' has a new `-s' option to print a usage synopsis +o New arithmetic operators: var++, var--, ++var, --var, expr1,expr2 (comma) +o New ksh93-style arithmetic for command: + for ((expr1 ; expr2; expr3 )); do list; done +o `read' has new options: `-t', `-n', `-d', `-s' +o The redirection code handles several filenames specially: /dev/fd/N, + /dev/stdin, /dev/stdout, /dev/stderr +o The redirection code now recognizes /dev/tcp/HOST/PORT and + /dev/udp/HOST/PORT and tries to open a TCP or UDP socket, respectively, + to the specified port on the specified host +o The ${!prefix*} expansion has been implemented +o A new FUNCNAME variable, which expands to the name of a currently-executing + function +o The GROUPS variable is no longer readonly +o A new shopt `xpg_echo' variable, to control the behavior of echo with + respect to backslash-escape sequences at runtime +o The NON_INTERACTIVE_LOGIN_SHELLS #define has returned + +The version of Readline released with Bash-2.04, Readline-4.1, had several +new features as well: + +o Parentheses matching is always compiled into readline, and controllable + with the new `blink-matching-paren' variable +o The history-search-forward and history-search-backward functions now leave + point at the end of the line when the search string is empty, like + reverse-search-history, and forward-search-history +o A new function for applications: rl_on_new_line_with_prompt() +o New variables for applications: rl_already_prompted, and rl_gnu_readline_p + + +Bash-2.03 had very few new features, in keeping with the convention +that odd-numbered releases provide mainly bug fixes. A number of new +features were added to Readline, mostly at the request of the Cygnus +folks. + +A new shopt option, `restricted_shell', so that startup files can test + whether or not the shell was started in restricted mode +Filename generation is now performed on the words between ( and ) in + compound array assignments (this is really a bug fix) +OLDPWD is now auto-exported, as POSIX.2 requires +ENV and BASH_ENV are read-only variables in a restricted shell +Bash may now be linked against an already-installed Readline library, + as long as the Readline library is version 4 or newer +All shells begun with the `--login' option will source the login shell + startup files, even if the shell is not interactive + +There were lots of changes to the version of the Readline library released +along with Bash-2.03. For a complete list of the changes, read the file +CHANGES in the Bash-2.03 distribution. + +Bash-2.02 contained the following new features: + +a new version of malloc (based on the old GNU malloc code in previous + bash versions) that is more page-oriented, more conservative + with memory usage, does not `orphan' large blocks when they + are freed, is usable on 64-bit machines, and has allocation + checking turned on unconditionally +POSIX.2-style globbing character classes ([:alpha:], [:alnum:], etc.) +POSIX.2-style globbing equivalence classes +POSIX.2-style globbing collating symbols +the ksh [[...]] extended conditional command +the ksh egrep-style extended pattern matching operators +a new `printf' builtin +the ksh-like $(, &>, >|, <<<, [n]<&word-, [n]>&word- + prompt string special char translation and variable expansion + auto-export of variables in initial environment + command search finds functions before builtins + bash return builtin will exit a file sourced with `.' + builtins: cd -/-L/-P, exec -l/-c/-a, echo -e/-E, hash -d/-l/-p/-t. + export -n/-f/-p/name=value, pwd -L/-P, + read -e/-p/-a/-t/-n/-d/-s/-u, + readonly -a/-f/name=value, trap -l, set +o, + set -b/-m/-o option/-h/-p/-B/-C/-H/-P, + unset -f/-v, ulimit -m/-p/-u, + type -a/-p/-t/-f/-P, suspend -f, kill -n, + test -o optname/s1 == s2/s1 < s2/s1 > s2/-nt/-ot/-ef/-O/-G/-S + bash reads ~/.bashrc for interactive shells, $ENV for non-interactive + bash restricted shell mode is more extensive + bash allows functions and variables with the same name + brace expansion + tilde expansion + arithmetic expansion with $((...)) and `let' builtin + the `[[...]]' extended conditional command + process substitution + aliases and alias/unalias builtins + local variables in functions and `local' builtin + readline and command-line editing with programmable completion + command history and history/fc builtins + csh-like history expansion + other new bash builtins: bind, command, compgen, complete, builtin, + declare/typeset, dirs, enable, fc, help, + history, logout, popd, pushd, disown, shopt, + printf + exported functions + filename generation when using output redirection (command >a*) + POSIX.2-style globbing character classes + POSIX.2-style globbing equivalence classes + POSIX.2-style globbing collating symbols + egrep-like extended pattern matching operators + case-insensitive pattern matching and globbing + variable assignments preceding commands affect only that command, + even for builtins and functions + posix mode + redirection to /dev/fd/N, /dev/stdin, /dev/stdout, /dev/stderr, + /dev/tcp/host/port, /dev/udp/host/port + +Things sh has that bash does not: + uses variable SHACCT to do shell accounting + includes `stop' builtin (bash can use alias stop='kill -s STOP') + `newgrp' builtin + turns on job control if called as `jsh' + $TIMEOUT (like bash $TMOUT) + `^' is a synonym for `|' + new SVR4.2 sh builtins: mldmode, priv + +Implementation differences: + redirection to/from compound commands causes sh to create a subshell + bash does not allow unbalanced quotes; sh silently inserts them at EOF + bash does not mess with signal 11 + sh sets (euid, egid) to (uid, gid) if -p not supplied and uid < 100 + bash splits only the results of expansions on IFS, using POSIX.2 + field splitting rules; sh splits all words on IFS + sh does not allow MAILCHECK to be unset (?) + sh does not allow traps on SIGALRM or SIGCHLD + bash allows multiple option arguments when invoked (e.g. -x -v); + sh allows only a single option argument (`sh -x -v' attempts + to open a file named `-v', and, on SunOS 4.1.4, dumps core. + On Solaris 2.4 and earlier versions, sh goes into an infinite + loop.) + sh exits a script if any builtin fails; bash exits only if one of + the POSIX.2 `special' builtins fails + +C2) How does bash differ from the Korn shell, version ksh88? + +Things bash has or uses that ksh88 does not: + long invocation options + [-+]O invocation option + -l invocation option + `!' reserved word + arithmetic for command: for ((expr1 ; expr2; expr3 )); do list; done + arithmetic in largest machine-supported size (intmax_t) + posix mode and posix conformance + command hashing + tilde expansion for assignment statements that look like $PATH + process substitution with named pipes if /dev/fd is not available + the ${!param} indirect parameter expansion operator + the ${!param*} prefix expansion operator + the ${param:offset[:length]} parameter substring operator + the ${param/pat[/string]} parameter pattern substitution operator + variables: BASH, BASH_VERSION, BASH_VERSINFO, UID, EUID, SHLVL, + TIMEFORMAT, HISTCMD, HOSTTYPE, OSTYPE, MACHTYPE, + HISTFILESIZE, HISTIGNORE, HISTCONTROL, PROMPT_COMMAND, + IGNOREEOF, FIGNORE, INPUTRC, HOSTFILE, DIRSTACK, + PIPESTATUS, HOSTNAME, OPTERR, SHELLOPTS, GLOBIGNORE, + GROUPS, FUNCNAME, histchars, auto_resume + prompt expansion with backslash escapes and command substitution + redirection: &> (stdout and stderr), <<<, [n]<&word-, [n]>&word- + more extensive and extensible editing and programmable completion + builtins: bind, builtin, command, declare, dirs, echo -e/-E, enable, + exec -l/-c/-a, fc -s, export -n/-f/-p, hash, help, history, + jobs -x/-r/-s, kill -s/-n/-l, local, logout, popd, pushd, + read -e/-p/-a/-t/-n/-d/-s, readonly -a/-n/-f/-p, + set -o braceexpand/-o histexpand/-o interactive-comments/ + -o notify/-o physical/-o posix/-o hashall/-o onecmd/ + -h/-B/-C/-b/-H/-P, set +o, suspend, trap -l, type, + typeset -a/-F/-p, ulimit -u, umask -S, alias -p, shopt, + disown, printf, complete, compgen + `!' csh-style history expansion + POSIX.2-style globbing character classes + POSIX.2-style globbing equivalence classes + POSIX.2-style globbing collating symbols + egrep-like extended pattern matching operators + case-insensitive pattern matching and globbing + `**' arithmetic operator to do exponentiation + redirection to /dev/fd/N, /dev/stdin, /dev/stdout, /dev/stderr + arrays of unlimited size + TMOUT is default timeout for `read' and `select' + +Things ksh88 has or uses that bash does not: + tracked aliases (alias -t) + variables: ERRNO, FPATH, EDITOR, VISUAL + co-processes (|&, >&p, <&p) + weirdly-scoped functions + typeset +f to list all function names without definitions + text of command history kept in a file, not memory + builtins: alias -x, cd old new, fc -e -, newgrp, print, + read -p/-s/var?prompt, set -A/-o gmacs/ + -o bgnice/-o markdirs/-o nolog/-o trackall/-o viraw/-s, + typeset -H/-L/-R/-Z/-A/-ft/-fu/-fx/-l/-u/-t, whence + using environment to pass attributes of exported variables + arithmetic evaluation done on arguments to some builtins + reads .profile from $PWD when invoked as login shell + +Implementation differences: + ksh runs last command of a pipeline in parent shell context + bash has brace expansion by default (ksh88 compile-time option) + bash has fixed startup file for all interactive shells; ksh reads $ENV + bash has exported functions + bash command search finds functions before builtins + bash waits for all commands in pipeline to exit before returning status + emacs-mode editing has some slightly different key bindings + +C3) Which new features in ksh-93 are not in bash, and which are? + +New things in ksh-93 not in bash-2.05b: + associative arrays + floating point arithmetic and variables + math library functions + ${!name[sub]} name of subscript for associative array + `.' is allowed in variable names to create a hierarchical namespace + more extensive compound assignment syntax + discipline functions + `sleep' and `getconf' builtins (bash has loadable versions) + typeset -n and `nameref' variables + KEYBD trap + variables: .sh.edchar, .sh.edmode, .sh.edcol, .sh.edtext, .sh.version, + .sh.name, .sh.subscript, .sh.value, .sh.match, HISTEDIT + backreferences in pattern matching (\N) + `&' operator in pattern lists for matching + print -f (bash uses printf) + `fc' has been renamed to `hist' + `.' can execute shell functions + exit statuses between 0 and 255 + set -o pipefail + `+=' variable assignment operator + FPATH and PATH mixing + getopts -a + -I invocation option + DEBUG trap now executed before each simple command, instead of after + printf %H, %P, %T, %Z modifiers, output base for %d + lexical scoping for local variables in `ksh' functions + no scoping for local variables in `POSIX' functions + +New things in ksh-93 present in bash-2.05b: + [n]<&word- and [n]>&word- redirections (combination dup and close) + for (( expr1; expr2; expr3 )) ; do list; done - arithmetic for command + ?:, ++, --, `expr1 , expr2' arithmetic operators + expansions: ${!param}, ${param:offset[:len]}, ${param/pat[/str]}, + ${!param*} + compound array assignment + the `!' reserved word + loadable builtins -- but ksh uses `builtin' while bash uses `enable' + `command', `builtin', `disown' builtins + new $'...' and $"..." quoting + FIGNORE (but bash uses GLOBIGNORE), HISTCMD + set -o notify/-C + changes to kill builtin + read -A (bash uses read -a) + read -t/-d + trap -p + exec -c/-a + `.' restores the positional parameters when it completes + POSIX.2 `test' + umask -S + unalias -a + command and arithmetic substitution performed on PS1, PS4, and ENV + command name completion + ENV processed only for interactive shells + +Section D: Why does bash do some things differently than other Unix shells? + +D1) Why does bash run a different version of `command' than + `which command' says it will? + +On many systems, `which' is actually a csh script that assumes +you're running csh. In tcsh, `which' and its cousin `where' +are builtins. On other Unix systems, `which' is a perl script +that uses the PATH environment variable. + +The csh script version reads the csh startup files from your +home directory and uses those to determine which `command' will +be invoked. Since bash doesn't use any of those startup files, +there's a good chance that your bash environment differs from +your csh environment. The bash `type' builtin does everything +`which' does, and will report correct results for the running +shell. If you're really wedded to the name `which', try adding +the following function definition to your .bashrc: + + which() + { + builtin type "$@" + } + +If you're moving from tcsh and would like to bring `where' along +as well, use this function: + + where() + { + builtin type -a "$@" + } + +D2) Why doesn't bash treat brace expansions exactly like csh? + +The only difference between bash and csh brace expansion is that +bash requires a brace expression to contain at least one unquoted +comma if it is to be expanded. Any brace-surrounded word not +containing an unquoted comma is left unchanged by the brace +expansion code. This affords the greatest degree of sh +compatibility. + +Bash, ksh, zsh, and pd-ksh all implement brace expansion this way. + +D3) Why doesn't bash have csh variable modifiers? + +Posix has specified a more powerful, albeit somewhat more cryptic, +mechanism cribbed from ksh, and bash implements it. + +${parameter%word} + Remove smallest suffix pattern. The WORD is expanded to produce + a pattern. It then expands to the value of PARAMETER, with the + smallest portion of the suffix matched by the pattern deleted. + + x=file.c + echo ${x%.c}.o + -->file.o + +${parameter%%word} + + Remove largest suffix pattern. The WORD is expanded to produce + a pattern. It then expands to the value of PARAMETER, with the + largest portion of the suffix matched by the pattern deleted. + + x=posix/src/std + echo ${x%%/*} + -->posix + +${parameter#word} + Remove smallest prefix pattern. The WORD is expanded to produce + a pattern. It then expands to the value of PARAMETER, with the + smallest portion of the prefix matched by the pattern deleted. + + x=$HOME/src/cmd + echo ${x#$HOME} + -->/src/cmd + +${parameter##word} + Remove largest prefix pattern. The WORD is expanded to produce + a pattern. It then expands to the value of PARAMETER, with the + largest portion of the prefix matched by the pattern deleted. + + x=/one/two/three + echo ${x##*/} + -->three + + +Given + a=/a/b/c/d + b=b.xxx + + csh bash result + --- ---- ------ + $a:h ${a%/*} /a/b/c + $a:t ${a##*/} d + $b:r ${b%.*} b + $b:e ${b##*.} xxx + + +D4) How can I make my csh aliases work when I convert to bash? + +Bash uses a different syntax to support aliases than csh does. +The details can be found in the documentation. We have provided +a shell script which does most of the work of conversion for you; +this script can be found in ./examples/misc/aliasconv.sh. Here is +how you use it: + +Start csh in the normal way for you. (e.g., `csh') + +Pipe the output of `alias' through `aliasconv.sh', saving the +results into `bash_aliases': + + alias | bash aliasconv.sh >bash_aliases + +Edit `bash_aliases', carefully reading through any created +functions. You will need to change the names of some csh specific +variables to the bash equivalents. The script converts $cwd to +$PWD, $term to $TERM, $home to $HOME, $user to $USER, and $prompt +to $PS1. You may also have to add quotes to avoid unwanted +expansion. + +For example, the csh alias: + + alias cd 'cd \!*; echo $cwd' + +is converted to the bash function: + + cd () { command cd "$@"; echo $PWD ; } + +The only thing that needs to be done is to quote $PWD: + + cd () { command cd "$@"; echo "$PWD" ; } + +Merge the edited file into your ~/.bashrc. + +There is an additional, more ambitious, script in +examples/misc/cshtobash that attempts to convert your entire csh +environment to its bash equivalent. This script can be run as +simply `cshtobash' to convert your normal interactive +environment, or as `cshtobash ~/.login' to convert your login +environment. + +D5) How can I pipe standard output and standard error from one command to + another, like csh does with `|&'? + +Use + command 2>&1 | command2 + +The key is to remember that piping is performed before redirection, so +file descriptor 1 points to the pipe when it is duplicated onto file +descriptor 2. + +D6) Now that I've converted from ksh to bash, are there equivalents to + ksh features like autoloaded functions and the `whence' command? + +There are features in ksh-88 and ksh-93 that do not have direct bash +equivalents. Most, however, can be emulated with very little trouble. + +ksh-88 feature Bash equivalent +-------------- --------------- +compiled-in aliases set up aliases in .bashrc; some ksh aliases are + bash builtins (hash, history, type) +coprocesses named pipe pairs (one for read, one for write) +typeset +f declare -F +cd, print, whence function substitutes in examples/functions/kshenv +autoloaded functions examples/functions/autoload is the same as typeset -fu +read var?prompt read -p prompt var + +ksh-93 feature Bash equivalent +-------------- --------------- +sleep, getconf Bash has loadable versions in examples/loadables +${.sh.version} $BASH_VERSION +print -f printf +hist alias hist=fc +$HISTEDIT $FCEDIT + +Section E: How can I get bash to do certain things, and why does bash do + things the way it does? + +E1) Why is the bash builtin `test' slightly different from /bin/test? + +The specific example used here is [ ! x -o x ], which is false. + +Bash's builtin `test' implements the Posix.2 spec, which can be +summarized as follows (the wording is due to David Korn): + +Here is the set of rules for processing test arguments. + + 0 Args: False + 1 Arg: True iff argument is not null. + 2 Args: If first arg is !, True iff second argument is null. + If first argument is unary, then true if unary test is true + Otherwise error. + 3 Args: If second argument is a binary operator, do binary test of $1 $3 + If first argument is !, negate two argument test of $2 $3 + If first argument is `(' and third argument is `)', do the + one-argument test of the second argument. + Otherwise error. + 4 Args: If first argument is !, negate three argument test of $2 $3 $4. + Otherwise unspecified + 5 or more Args: unspecified. (Historical shells would use their + current algorithm). + +The operators -a and -o are considered binary operators for the purpose +of the 3 Arg case. + +As you can see, the test becomes (not (x or x)), which is false. + +E2) Why does bash sometimes say `Broken pipe'? + +If a sequence of commands appears in a pipeline, and one of the +reading commands finishes before the writer has finished, the +writer receives a SIGPIPE signal. Many other shells special-case +SIGPIPE as an exit status in the pipeline and do not report it. +For example, in: + + ps -aux | head + +`head' can finish before `ps' writes all of its output, and ps +will try to write on a pipe without a reader. In that case, bash +will print `Broken pipe' to stderr when ps is killed by a +SIGPIPE. + +You can build a version of bash that will not report SIGPIPE errors +by uncommenting the definition of DONT_REPORT_SIGPIPE in the file +config-top.h. + +E3) When I have terminal escape sequences in my prompt, why does bash + wrap lines at the wrong column? + +Readline, the line editing library that bash uses, does not know +that the terminal escape sequences do not take up space on the +screen. The redisplay code assumes, unless told otherwise, that +each character in the prompt is a `printable' character that +takes up one character position on the screen. + +You can use the bash prompt expansion facility (see the PROMPTING +section in the manual page) to tell readline that sequences of +characters in the prompt strings take up no screen space. + +Use the \[ escape to begin a sequence of non-printing characters, +and the \] escape to signal the end of such a sequence. + +E4) If I pipe the output of a command into `read variable', why doesn't + the output show up in $variable when the read command finishes? + +This has to do with the parent-child relationship between Unix +processes. It affects all commands run in pipelines, not just +simple calls to `read'. For example, piping a command's output +into a `while' loop that repeatedly calls `read' will result in +the same behavior. + +Each element of a pipeline runs in a separate process, a child of +the shell running the pipeline. A subprocess cannot affect its +parent's environment. When the `read' command sets the variable +to the input, that variable is set only in the subshell, not the +parent shell. When the subshell exits, the value of the variable +is lost. + +Many pipelines that end with `read variable' can be converted +into command substitutions, which will capture the output of +a specified command. The output can then be assigned to a +variable: + + grep ^gnu /usr/lib/news/active | wc -l | read ngroup + +can be converted into + + ngroup=$(grep ^gnu /usr/lib/news/active | wc -l) + +This does not, unfortunately, work to split the text among +multiple variables, as read does when given multiple variable +arguments. If you need to do this, you can either use the +command substitution above to read the output into a variable +and chop up the variable using the bash pattern removal +expansion operators or use some variant of the following +approach. + +Say /usr/local/bin/ipaddr is the following shell script: + +#! /bin/sh +host `hostname` | awk '/address/ {print $NF}' + +Instead of using + + /usr/local/bin/ipaddr | read A B C D + +to break the local machine's IP address into separate octets, use + + OIFS="$IFS" + IFS=. + set -- $(/usr/local/bin/ipaddr) + IFS="$OIFS" + A="$1" B="$2" C="$3" D="$4" + +Beware, however, that this will change the shell's positional +parameters. If you need them, you should save them before doing +this. + +This is the general approach -- in most cases you will not need to +set $IFS to a different value. + +Some other user-supplied alternatives include: + +read A B C D << HERE + $(IFS=.; echo $(/usr/local/bin/ipaddr)) +HERE + +and, where process substitution is available, + +read A B C D < <(IFS=.; echo $(/usr/local/bin/ipaddr)) + +E5) I have a bunch of shell scripts that use backslash-escaped characters + in arguments to `echo'. Bash doesn't interpret these characters. Why + not, and how can I make it understand them? + +This is the behavior of echo on most Unix System V machines. + +The bash builtin `echo' is modeled after the 9th Edition +Research Unix version of `echo'. It does not interpret +backslash-escaped characters in its argument strings by default; +it requires the use of the -e option to enable the +interpretation. The System V echo provides no way to disable the +special characters; the bash echo has a -E option to disable +them. + +There is a configuration option that will make bash behave like +the System V echo and interpret things like `\t' by default. Run +configure with the --enable-xpg-echo-default option to turn this +on. Be aware that this will cause some of the tests run when you +type `make tests' to fail. + +There is a shell option, `xpg_echo', settable with `shopt', that will +change the behavior of echo at runtime. Enabling this option turns +on expansion of backslash-escape sequences. + +E6) Why doesn't a while or for loop get suspended when I type ^Z? + +This is a consequence of how job control works on Unix. The only +thing that can be suspended is the process group. This is a single +command or pipeline of commands that the shell forks and executes. + +When you run a while or for loop, the only thing that the shell forks +and executes are any commands in the while loop test and commands in +the loop bodies. These, therefore, are the only things that can be +suspended when you type ^Z. + +If you want to be able to stop the entire loop, you need to put it +within parentheses, which will force the loop into a subshell that +may be stopped (and subsequently restarted) as a single unit. + +E7) What about empty for loops in Makefiles? + +It's fairly common to see constructs like this in automatically-generated +Makefiles: + +SUBDIRS = @SUBDIRS@ + + ... + +subdirs-clean: + for d in ${SUBDIRS}; do \ + ( cd $$d && ${MAKE} ${MFLAGS} clean ) \ + done + +When SUBDIRS is empty, this results in a command like this being passed to +bash: + + for d in ; do + ( cd $d && ${MAKE} ${MFLAGS} clean ) + done + +In versions of bash before bash-2.05a, this was a syntax error. If the +reserved word `in' was present, a word must follow it before the semicolon +or newline. The language in the manual page referring to the list of words +being empty referred to the list after it is expanded. These versions of +bash required that there be at least one word following the `in' when the +construct was parsed. + +The idiomatic Makefile solution is something like: + +SUBDIRS = @SUBDIRS@ + +subdirs-clean: + subdirs=$SUBDIRS ; for d in $$subdirs; do \ + ( cd $$d && ${MAKE} ${MFLAGS} clean ) \ + done + +The latest drafts of the updated POSIX standard have changed this: the +word list is no longer required. Bash versions 2.05a and later accept +the new syntax. + +E8) Why does the arithmetic evaluation code complain about `08'? + +The bash arithmetic evaluation code (used for `let', $(()), (()), and in +other places), interprets a leading `0' in numeric constants as denoting +an octal number, and a leading `0x' as denoting hexadecimal. This is +in accordance with the POSIX.2 spec, section 2.9.2.1, which states that +arithmetic constants should be handled as signed long integers as defined +by the ANSI/ISO C standard. + +The POSIX.2 interpretation committee has confirmed this: + +http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-173.html + +E9) Why does the pattern matching expression [A-Z]* match files beginning + with every letter except `z'? + +Bash-2.03, Bash-2.05 and later versions honor the current locale setting +when processing ranges within pattern matching bracket expressions ([A-Z]). +This is what POSIX.2 and SUSv3/XPG6 specify. + +The behavior of the matcher in bash-2.05 and later versions depends on the +current LC_COLLATE setting. Setting this variable to `C' or `POSIX' will +result in the traditional behavior ([A-Z] matches all uppercase ASCII +characters). Many other locales, including the en_US locale (the default +on many US versions of Linux) collate the upper and lower case letters like +this: + + AaBb...Zz + +which means that [A-Z] matches every letter except `z'. Others collate like + + aAbBcC...zZ + +which means that [A-Z] matches every letter except `a'. + +The portable way to specify upper case letters is [:upper:] instead of +A-Z; lower case may be specified as [:lower:] instead of a-z. + +Look at the manual pages for setlocale(3), strcoll(3), and, if it is +present, locale(1). If you have locale(1), you can use it to find +your current locale information even if you do not have any of the +LC_ variables set. + +My advice is to put + + export LC_COLLATE=C + +into /etc/profile and inspect any shell scripts run from cron for +constructs like [A-Z]. This will prevent things like + + rm [A-Z]* + +from removing every file in the current directory except those beginning +with `z' and still allow individual users to change the collation order. +Users may put the above command into their own profiles as well, of course. + +E10) Why does `cd //' leave $PWD as `//'? + +POSIX.2, in its description of `cd', says that *three* or more leading +slashes may be replaced with a single slash when canonicalizing the +current working directory. + +This is, I presume, for historical compatibility. Certain versions of +Unix, and early network file systems, used paths of the form +//hostname/path to access `path' on server `hostname'. + +E11) If I resize my xterm while another program is running, why doesn't bash + notice the change? + +This is another issue that deals with job control. + +The kernel maintains a notion of a current terminal process group. Members +of this process group (processes whose process group ID is equal to the +current terminal process group ID) receive terminal-generated signals like +SIGWINCH. (For more details, see the JOB CONTROL section of the bash +man page.) + +If a terminal is resized, the kernel sends SIGWINCH to each member of +the terminal's current process group (the `foreground' process group). + +When bash is running with job control enabled, each pipeline (which may be +a single command) is run in its own process group, different from bash's +process group. This foreground process group receives the SIGWINCH; bash +does not. Bash has no way of knowing that the terminal has been resized. + +There is a `checkwinsize' option, settable with the `shopt' builtin, that +will cause bash to check the window size and adjust its idea of the +terminal's dimensions each time a process stops or exits and returns control +of the terminal to bash. Enable it with `shopt -s checkwinsize'. + +Section F: Things to watch out for on certain Unix versions + +F1) Why can't I use command line editing in my `cmdtool'? + +The problem is `cmdtool' and bash fighting over the input. When +scrolling is enabled in a cmdtool window, cmdtool puts the tty in +`raw mode' to permit command-line editing using the mouse for +applications that cannot do it themselves. As a result, bash and +cmdtool each try to read keyboard input immediately, with neither +getting enough of it to be useful. + +This mode also causes cmdtool to not implement many of the +terminal functions and control sequences appearing in the +`sun-cmd' termcap entry. For a more complete explanation, see +that file examples/suncmd.termcap in the bash distribution. + +`xterm' is a better choice, and gets along with bash much more +smoothly. + +If you must use cmdtool, you can use the termcap description in +examples/suncmd.termcap. Set the TERMCAP variable to the terminal +description contained in that file, i.e. + +TERMCAP='Mu|sun-cmd:am:bs:km:pt:li#34:co#80:cl=^L:ce=\E[K:cd=\E[J:rs=\E[s:' + +Then export TERMCAP and start a new cmdtool window from that shell. +The bash command-line editing should behave better in the new +cmdtool. If this works, you can put the assignment to TERMCAP +in your bashrc file. + +F2) I built bash on Solaris 2. Why do globbing expansions and filename + completion chop off the first few characters of each filename? + +This is the consequence of building bash on SunOS 5 and linking +with the libraries in /usr/ucblib, but using the definitions +and structures from files in /usr/include. + +The actual conflict is between the dirent structure in +/usr/include/dirent.h and the struct returned by the version of +`readdir' in libucb.a (a 4.3-BSD style `struct direct'). + +Make sure you've got /usr/ccs/bin ahead of /usr/ucb in your $PATH +when configuring and building bash. This will ensure that you +use /usr/ccs/bin/cc or acc instead of /usr/ucb/cc and that you +link with libc before libucb. + +If you have installed the Sun C compiler, you may also need to +put /usr/ccs/bin and /opt/SUNWspro/bin into your $PATH before +/usr/ucb. + +F3) Why does bash dump core after I interrupt username completion or + `~user' tilde expansion on a machine running NIS? + +This is a famous and long-standing bug in the SunOS YP (sorry, NIS) +client library, which is part of libc. + +The YP library code keeps static state -- a pointer into the data +returned from the server. When YP initializes itself (setpwent), +it looks at this pointer and calls free on it if it's non-null. +So far, so good. + +If one of the YP functions is interrupted during getpwent (the +exact function is interpretwithsave()), and returns NULL, the +pointer is freed without being reset to NULL, and the function +returns. The next time getpwent is called, it sees that this +pointer is non-null, calls free, and the bash free() blows up +because it's being asked to free freed memory. + +The traditional Unix mallocs allow memory to be freed multiple +times; that's probably why this has never been fixed. You can +run configure with the `--without-gnu-malloc' option to use +the C library malloc and avoid the problem. + +F4) I'm running SVR4.2. Why is the line erased every time I type `@'? + +The `@' character is the default `line kill' character in most +versions of System V, including SVR4.2. You can change this +character to whatever you want using `stty'. For example, to +change the line kill character to control-u, type + + stty kill ^U + +where the `^' and `U' can be two separate characters. + +F5) Why does bash report syntax errors when my C News scripts use a + redirection before a subshell command? + +The actual command in question is something like + + < file ( command ) + +According to the grammar given in the POSIX.2 standard, this construct +is, in fact, a syntax error. Redirections may only precede `simple +commands'. A subshell construct such as the above is one of the shell's +`compound commands'. A redirection may only follow a compound command. + +This affects the mechanical transformation of commands that use `cat' +to pipe a file into a command (a favorite Useless-Use-Of-Cat topic on +comp.unix.shell). While most commands of the form + + cat file | command + +can be converted to `< file command', shell control structures such as +loops and subshells require `command < file'. + +The file CWRU/sh-redir-hack in the bash-2.05a distribution is an +(unofficial) patch to parse.y that will modify the grammar to +support this construct. It will not apply with `patch'; you must +modify parse.y by hand. Note that if you apply this, you must +recompile with -DREDIRECTION_HACK. This introduces a large +number of reduce/reduce conflicts into the shell grammar. + +F6) Why can't I use vi-mode editing on Red Hat Linux 6.1? + +The short answer is that Red Hat screwed up. + +The long answer is that they shipped an /etc/inputrc that only works +for emacs mode editing, and then screwed all the vi users by setting +INPUTRC to /etc/inputrc in /etc/profile. + +The short fix is to do one of the following: remove or rename +/etc/inputrc, set INPUTRC=~/.inputrc in ~/.bashrc (or .bash_profile, +but make sure you export it if you do), remove the assignment to +INPUTRC from /etc/profile, add + + set keymap emacs + +to the beginning of /etc/inputrc, or bracket the key bindings in +/etc/inputrc with these lines + + $if mode=emacs + [...] + $endif + +F7) Why do bash-2.05a and bash-2.05b fail to compile `printf.def' on + HP/UX 11.x? + +HP/UX's support for long double is imperfect at best. + +GCC will support it without problems, but the HP C library functions +like strtold(3) and printf(3) don't actually work with long doubles. +HP implemented a `long_double' type as a 4-element array of 32-bit +ints, and that is what the library functions use. The ANSI C +`long double' type is a 128-bit floating point scalar. + +The easiest fix, until HP fixes things up, is to edit the generated +config.h and #undef the HAVE_LONG_DOUBLE line. After doing that, +the compilation should complete successfully. + +Section G: How can I get bash to do certain common things? + +G1) How can I get bash to read and display eight-bit characters? + +This is a process requiring several steps. + +First, you must ensure that the `physical' data path is a full eight +bits. For xterms, for example, the `vt100' resources `eightBitInput' +and `eightBitOutput' should be set to `true'. + +Once you have set up an eight-bit path, you must tell the kernel and +tty driver to leave the eighth bit of characters alone when processing +keyboard input. Use `stty' to do this: + + stty cs8 -istrip -parenb + +For old BSD-style systems, you can use + + stty pass8 + +You may also need + + stty even odd + +Finally, you need to tell readline that you will be inputting and +displaying eight-bit characters. You use readline variables to do +this. These variables can be set in your .inputrc or using the bash +`bind' builtin. Here's an example using `bind': + + bash$ bind 'set convert-meta off' + bash$ bind 'set meta-flag on' + bash$ bind 'set output-meta on' + +The `set' commands between the single quotes may also be placed +in ~/.inputrc. + +G2) How do I write a function `x' to replace builtin command `x', but + still invoke the command from within the function? + +This is why the `command' and `builtin' builtins exist. The +`command' builtin executes the command supplied as its first +argument, skipping over any function defined with that name. The +`builtin' builtin executes the builtin command given as its first +argument directly. + +For example, to write a function to replace `cd' that writes the +hostname and current directory to an xterm title bar, use +something like the following: + + cd() + { + builtin cd "$@" && xtitle "$HOST: $PWD" + } + +This could also be written using `command' instead of `builtin'; +the version above is marginally more efficient. + +G3) How can I find the value of a shell variable whose name is the value + of another shell variable? + +Versions of Bash newer than Bash-2.0 support this directly. You can use + + ${!var} + +For example, the following sequence of commands will echo `z': + + var1=var2 + var2=z + echo ${!var1} + +For sh compatibility, use the `eval' builtin. The important +thing to remember is that `eval' expands the arguments you give +it again, so you need to quote the parts of the arguments that +you want `eval' to act on. + +For example, this expression prints the value of the last positional +parameter: + + eval echo \"\$\{$#\}\" + +The expansion of the quoted portions of this expression will be +deferred until `eval' runs, while the `$#' will be expanded +before `eval' is executed. In versions of bash later than bash-2.0, + + echo ${!#} + +does the same thing. + +This is not the same thing as ksh93 `nameref' variables, though the syntax +is similar. I may add namerefs in a future bash version. + +G4) How can I make the bash `time' reserved word print timing output that + looks like the output from my system's /usr/bin/time? + +The bash command timing code looks for a variable `TIMEFORMAT' and +uses its value as a format string to decide how to display the +timing statistics. + +The value of TIMEFORMAT is a string with `%' escapes expanded in a +fashion similar in spirit to printf(3). The manual page explains +the meanings of the escape sequences in the format string. + +If TIMEFORMAT is not set, bash acts as if the following assignment had +been performed: + + TIMEFORMAT=$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS' + +The POSIX.2 default time format (used by `time -p command') is + + TIMEFORMAT=$'real %2R\nuser %2U\nsys %2S' + +The BSD /usr/bin/time format can be emulated with: + + TIMEFORMAT=$'\t%1R real\t%1U user\t%1S sys' + +The System V /usr/bin/time format can be emulated with: + + TIMEFORMAT=$'\nreal\t%1R\nuser\t%1U\nsys\t%1S' + +The ksh format can be emulated with: + + TIMEFORMAT=$'\nreal\t%2lR\nuser\t%2lU\nsys\t%2lS' + +G5) How do I get the current directory into my prompt? + +Bash provides a number of backslash-escape sequences which are expanded +when the prompt string (PS1 or PS2) is displayed. The full list is in +the manual page. + +The \w expansion gives the full pathname of the current directory, with +a tilde (`~') substituted for the current value of $HOME. The \W +expansion gives the basename of the current directory. To put the full +pathname of the current directory into the path without any tilde +subsitution, use $PWD. Here are some examples: + + PS1='\w$ ' # current directory with tilde + PS1='\W$ ' # basename of current directory + PS1='$PWD$ ' # full pathname of current directory + +The single quotes are important in the final example to prevent $PWD from +being expanded when the assignment to PS1 is performed. + +G6) How can I rename "*.foo" to "*.bar"? + +Use the pattern removal functionality described in D3. The following `for' +loop will do the trick: + + for f in *.foo; do + mv $f ${f%foo}bar + done + +G7) How can I translate a filename from uppercase to lowercase? + +The script examples/functions/lowercase, originally written by John DuBois, +will do the trick. The converse is left as an exercise. + +G8) How can I write a filename expansion (globbing) pattern that will match + all files in the current directory except "." and ".."? + +You must have set the `extglob' shell option using `shopt -s extglob' to use +this: + + echo .!(.|) * + +A solution that works without extended globbing is given in the Unix Shell +FAQ, posted periodically to comp.unix.shell. + +Section H: Where do I go from here? + +H1) How do I report bugs in bash, and where should I look for fixes and + advice? + +Use the `bashbug' script to report bugs. It is built and +installed at the same time as bash. It provides a standard +template for reporting a problem and automatically includes +information about your configuration and build environment. + +`bashbug' sends its reports to bug-bash@gnu.org, which +is a large mailing list gatewayed to the usenet newsgroup gnu.bash.bug. + +Bug fixes, answers to questions, and announcements of new releases +are all posted to gnu.bash.bug. Discussions concerning bash features +and problems also take place there. + +To reach the bash maintainers directly, send mail to +bash-maintainers@gnu.org. + +H2) What kind of bash documentation is there? + +First, look in the doc directory in the bash distribution. It should +contain at least the following files: + +bash.1 an extensive, thorough Unix-style manual page +builtins.1 a manual page covering just bash builtin commands +bashref.texi a reference manual in GNU tex`info format +bashref.info an info version of the reference manual +FAQ this file +article.ms text of an article written for The Linux Journal +readline.3 a man page describing readline + +Postscript, HTML, and ASCII files created from the above source are +available in the documentation distribution. + +There is additional documentation available for anonymous FTP from host +ftp.cwru.edu in the `pub/bash' directory. + +Cameron Newham and Bill Rosenblatt have written a book on bash, published +by O'Reilly and Associates. The book is based on Bill Rosenblatt's Korn +Shell book. The title is ``Learning the Bash Shell'', and the ISBN number +is 1-56592-147-X. Look for it in fine bookstores near you. This book +covers bash-1.14, but has an appendix describing some of the new features +in bash-2.0. + +A second edition of this book is available, published in January, 1998. +The ISBN number is 1-56592-347-2. Look for it in the same fine bookstores +or on the web. + +The GNU Bash Reference Manual has been published as a printed book by +Network Theory Ltd (Paperback, ISBN: 0-9541617-7-7, Feb 2003). It covers +bash-2.0 and is available from most online bookstores (see +http://www.network-theory.co.uk/bash/manual/ for details). The publisher +will donate $1 to the Free Software Foundation for each copy sold. + +H3) What's coming in future versions? + +These are features I hope to include in a future version of bash. + +a better bash debugger (a minimally-tested version is included with bash-2.05b) +associative arrays +co-processes, but with a new-style syntax that looks like function declaration + +H4) What's on the bash `wish list' for future versions? + +These are features that may or may not appear in a future version of bash. + +breaking some of the shell functionality into embeddable libraries +a module system like zsh's, using dynamic loading like builtins +better internationalization using GNU `gettext' +date-stamped command history +a bash programmer's guide with a chapter on creating loadable builtins +a better loadable interface to perl with access to the shell builtins and + variables (contributions gratefully accepted) +ksh93-like `nameref' variables +ksh93-like `+=' variable assignment operator +ksh93-like `xx.yy' variables (including some of the .sh.* variables) and + associated disipline functions +Some of the new ksh93 pattern matching operators, like backreferencing + +H5) When will the next release appear? + +The next version will appear sometime in 2002. Never make predictions. + + +This document is Copyright 1995-2003 by Chester Ramey. + +Permission is hereby granted, without written agreement and +without license or royalty fees, to use, copy, and distribute +this document for any purpose, provided that the above copyright +notice appears in all copies of this document and that the +contents of this document remain unaltered. diff --git a/examples/functions/getoptx.bash b/examples/functions/getoptx.bash index d402c7d78..86b51a31d 100644 --- a/examples/functions/getoptx.bash +++ b/examples/functions/getoptx.bash @@ -135,7 +135,7 @@ function getoptex() [ $OPTIND -lt $# ] || return 1 shift $OPTIND if [ "$1" != "-" ] && [ "$1" != "${1#-}" ] - then OPTIND=$[OPTIND+1]; if [ "$1" != "--" ] + then OPTIND=$(( OPTIND+1 )); if [ "$1" != "--" ] then local o o="-${1#-$OPTOFS}" @@ -158,7 +158,7 @@ function getoptex() OPTOPT="?" return 1; fi - OPTIND=$[OPTIND+1] # skip option's argument + OPTIND=$(( OPTIND+1 )) # skip option's argument return 0 ;; "--$OPTOPT="*) @@ -186,14 +186,14 @@ function getoptex() OPTOPT="?" return 1 fi - OPTIND=$[OPTIND+1] # skip option's argument + OPTIND=$(( OPTIND+1 )) # skip option's argument return 0 ;; "-$OPTOPT"*) if [ $opttype = ";" ] then # an option with no argument is in a chain of options OPTOFS="$OPTOFS?" # move to the next option in the chain - OPTIND=$[OPTIND-1] # the chain still has other options + OPTIND=$(( OPTIND-1 )) # the chain still has other options return 0 else unset OPTOFS @@ -215,7 +215,7 @@ function optlistex local l="$1" local m # mask local r # to store result - while [ ${#m} -lt $[${#l}-1] ]; do m="$m?"; done # create a "???..." mask + while [ ${#m} -lt $(( ${#l}-1 )) ]; do m="$m?"; done # create a "???..." mask while [ -n "$l" ] do r="${r:+"$r "}${l%$m}" # append the first character of $l to $r @@ -260,7 +260,7 @@ function getopt() #do # echo "Option <$OPTOPT> ${OPTARG:+has an arg <$OPTARG>}" #done -#shift $[OPTIND-1] +#shift $(( OPTIND-1 )) #for arg in "$@" #do # echo "Non option argument <$arg>" @@ -288,7 +288,7 @@ function getopt() #do # echo "Option <$OPTOPT> ${OPTARG:+has an arg <$OPTARG>}" #done -#shift $[OPTIND-1] +#shift $(( OPTIND-1 )) #for arg in "$@" #do # echo "Non option argument <$arg>" diff --git a/examples/functions/substr2 b/examples/functions/substr2 index 2bb8d3630..de08287a8 100644 --- a/examples/functions/substr2 +++ b/examples/functions/substr2 @@ -29,7 +29,7 @@ substr() done if [ "$OPTIND" -gt 1 ] ; then - shift $[ $OPTIND -1 ] + shift $(( $OPTIND -1 )) fi if [ "$#" -eq 0 ] || [ "$#" -gt 2 ] ; then diff --git a/examples/loadables/Makefile.in.save b/examples/loadables/Makefile.in.save new file mode 100644 index 000000000..f6208f5cc --- /dev/null +++ b/examples/loadables/Makefile.in.save @@ -0,0 +1,238 @@ +# +# Simple makefile for the sample loadable builtins +# +# Copyright (C) 1996 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +# Include some boilerplate Gnu makefile definitions. +prefix = @prefix@ + +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +infodir = @infodir@ +includedir = @includedir@ + +topdir = @top_srcdir@ +BUILD_DIR = @BUILD_DIR@ +srcdir = @srcdir@ +VPATH = .:@srcdir@ + +@SET_MAKE@ +CC = @CC@ +RM = rm -f + +SHELL = @MAKE_SHELL@ + +host_os = @host_os@ +host_cpu = @host_cpu@ +host_vendor = @host_vendor@ + +CFLAGS = @CFLAGS@ +LOCAL_CFLAGS = @LOCAL_CFLAGS@ +DEFS = @DEFS@ +LOCAL_DEFS = @LOCAL_DEFS@ + +CPPFLAGS = @CPPFLAGS@ + +BASHINCDIR = ${topdir}/include + +LIBBUILD = ${BUILD_DIR}/lib + +INTL_LIBSRC = ${topdir}/lib/intl +INTL_BUILDDIR = ${LIBBUILD}/intl +INTL_INC = @INTL_INC@ +LIBINTL_H = @LIBINTL_H@ + +CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS) + +# +# These values are generated for configure by ${topdir}/support/shobj-conf. +# If your system is not supported by that script, but includes facilities for +# dynamic loading of shared objects, please update the script and send the +# changes to bash-maintainers@gnu.org. +# +SHOBJ_CC = @SHOBJ_CC@ +SHOBJ_CFLAGS = @SHOBJ_CFLAGS@ +SHOBJ_LD = @SHOBJ_LD@ +SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@ +SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@ +SHOBJ_LIBS = @SHOBJ_LIBS@ +SHOBJ_STATUS = @SHOBJ_STATUS@ + +INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \ + -I$(BASHINCDIR) -I$(BUILD_DIR) -I$(LIBBUILD) \ + -I$(BUILD_DIR)/builtins $(INTL_INC) + +.c.o: + $(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) $(INC) -c -o $@ $< + + +ALLPROG = print truefalse sleep pushd finfo logname basename dirname \ + tty pathchk tee head mkdir rmdir printenv id whoami \ + uname sync push ln unlink cut realpath getconf strftime +OTHERPROG = necho hello cat + +all: $(SHOBJ_STATUS) + +supported: $(ALLPROG) +others: $(OTHERPROG) + +unsupported: + @echo "Your system (${host_os}) is not supported by the" + @echo "${topdir}/support/shobj-conf script." + @echo "If your operating system provides facilities for dynamic" + @echo "loading of shared objects using the dlopen(3) interface," + @echo "please update the script and re-run configure. + @echo "Please send the changes you made to bash-maintainers@gnu.org" + @echo "for inclusion in future bash releases." + +everything: supported others + +print: print.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ print.o $(SHOBJ_LIBS) + +necho: necho.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ necho.o $(SHOBJ_LIBS) + +getconf: getconf.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ getconf.o $(SHOBJ_LIBS) + +hello: hello.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ hello.o $(SHOBJ_LIBS) + +truefalse: truefalse.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ truefalse.o $(SHOBJ_LIBS) + +sleep: sleep.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sleep.o $(SHOBJ_LIBS) + +finfo: finfo.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ finfo.o $(SHOBJ_LIBS) + +cat: cat.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cat.o $(SHOBJ_LIBS) + +logname: logname.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ logname.o $(SHOBJ_LIBS) + +basename: basename.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ basename.o $(SHOBJ_LIBS) + +dirname: dirname.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ dirname.o $(SHOBJ_LIBS) + +tty: tty.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tty.o $(SHOBJ_LIBS) + +pathchk: pathchk.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pathchk.o $(SHOBJ_LIBS) + +tee: tee.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tee.o $(SHOBJ_LIBS) + +mkdir: mkdir.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mkdir.o $(SHOBJ_LIBS) + +rmdir: rmdir.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ rmdir.o $(SHOBJ_LIBS) + +head: head.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ head.o $(SHOBJ_LIBS) + +printenv: printenv.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ printenv.o $(SHOBJ_LIBS) + +id: id.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ id.o $(SHOBJ_LIBS) + +whoami: whoami.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ whoami.o $(SHOBJ_LIBS) + +uname: uname.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ uname.o $(SHOBJ_LIBS) + +sync: sync.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sync.o $(SHOBJ_LIBS) + +push: push.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ push.o $(SHOBJ_LIBS) + +ln: ln.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ ln.o $(SHOBJ_LIBS) + +unlink: unlink.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ unlink.o $(SHOBJ_LIBS) + +cut: cut.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cut.o $(SHOBJ_LIBS) + +realpath: realpath.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ realpath.o $(SHOBJ_LIBS) + +strftime: strftime.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ strftime.o $(SHOBJ_LIBS) + +# pushd is a special case. We use the same source that the builtin version +# uses, with special compilation options. +# +pushd.c: ${topdir}/builtins/pushd.def + $(RM) $@ + ${BUILD_DIR}/builtins/mkbuiltins -D ${topdir}/builtins ${topdir}/builtins/pushd.def + +pushd.o: pushd.c + $(RM) $@ + $(SHOBJ_CC) -DHAVE_CONFIG_H -DPUSHD_AND_POPD -DLOADABLE_BUILTIN $(SHOBJ_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(INC) -c -o $@ $< + +pushd: pushd.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pushd.o $(SHOBJ_LIBS) + +clean: + $(RM) $(ALLPROG) $(OTHERPROG) *.o + -( cd perl && ${MAKE} ${MFLAGS} $@ ) + +mostlyclean: clean + -( cd perl && ${MAKE} ${MFLAGS} $@ ) + +distclean maintainer-clean: clean + $(RM) Makefile pushd.c + -( cd perl && ${MAKE} ${MFLAGS} $@ ) + +print.o: print.c +truefalse.o: truefalse.c +sleep.o: sleep.c +finfo.o: finfo.c +logname.o: logname.c +basename.o: basename.c +dirname.o: dirname.c +tty.o: tty.c +pathchk.o: pathchk.c +tee.o: tee.c +head.o: head.c +rmdir.o: rmdir.c +necho.o: necho.c +getconf.o: getconf.c +hello.o: hello.c +cat.o: cat.c +printenv.o: printenv.c +id.o: id.c +whoami.o: whoami.c +uname.o: uname.c +sync.o: sync.c +push.o: push.c +mkdir.o: mkdir.c +realpath.o: realpath.c +strftime.o: strftime.c diff --git a/examples/scripts/adventure.sh b/examples/scripts/adventure.sh index 169445014..346af9df2 100755 --- a/examples/scripts/adventure.sh +++ b/examples/scripts/adventure.sh @@ -88,7 +88,7 @@ trap 'echo Ouch!' 2 3 #ash_lk(){ echo " $1 " | fgrep " $2 " >&- 2>&-; } ash_lk(){ echo " $1 " | fgrep -q " $2 " >/dev/null 2>&1 ; } -ash_pr(){ echo $* | tr ' ' '\012' | pr -5 -t -w75 -l$[ ( $# + 4 ) / 5 ]; } +ash_pr(){ echo $* | tr ' ' '\012' | pr -5 -t -w75 -l$(( ( $# + 4 ) / 5 )); } ash_rm(){ echo " $1 " | sed -e "s/ $2 / /" -e 's/^ //' -e 's/ $//'; } # enable history, bang history expansion, and emacs editing diff --git a/examples/scripts/adventure.sh.save1 b/examples/scripts/adventure.sh.save1 new file mode 100755 index 000000000..4e2239396 --- /dev/null +++ b/examples/scripts/adventure.sh.save1 @@ -0,0 +1,549 @@ +#!/bin/bash +# ash -- "Adventure shell" +# last edit: 86/04/21 D A Gwyn +# SCCS ID: @(#)ash.sh 1.4 + +OPATH=$PATH + +ask() +{ + echo -n "$@" '[y/n] ' + read ans + + case "$ans" in + y*|Y*) + return 0 + ;; + *) + return 1 + ;; + esac +} + +CAT=${PAGER:-more} + +ash_inst() +{ + cat <<- EOF + + Instructions for the Adventure shell + + Welcome to the Adventure shell! In this exploration of the UNIX file + system, I will act as your eyes and hands. As you move around, I will + describe whatever is visible and will carry out your commands. The + general form of a command is + Verb Object Extra_stuff. + Most commands pay no attention to the "Extra_stuff", and many do not + need an "Object". A typical command is + get all + which picks up all files in the current "room" (directory). You can + find out what you are carrying by typing the command + inventory + The command "help" results in a full description of all commands that I + understand. To quit the Adventure shell, type + quit + + There are UNIX monsters lurking in the background. These are also + known as "commands with arguments". + + Good luck! + EOF +} + +ash_help() +{ +echo "I understand the following commands (synonyms in parentheses):" +echo "" + +echo "change OBJECT to NEW_NAME changes the name of the object" +echo "clone OBJECT as NEW_NAME duplicates the object" +echo "drop OBJECTS leaves the objects in the room" +echo "enter (go) PASSAGE takes the labeled passage" +echo "examine OBJECTS describes the objects in detail" +echo "feed OBJECT to MONSTER stuffs the object into a UNIX monster" +echo "get (take) OBJECTS picks up the specified objects" +echo "gripe (bug) report a problem with the Adventure shell" +echo "help prints this summary" +echo "inventory (i) tells what you are carrying" +echo "kill (destroy) OBJECTS destroys the objects" +echo "look (l) describes the room, including hidden objects" +echo "open (read) OBJECT shows the contents of an object" +echo "quit (exit) leaves the Adventure shell" +echo "resurrect OBJECTS attempts to restore dead objects" +echo "steal OBJECT from MONSTER obtains the object from a UNIX monster" +echo "throw OBJECT at daemon feeds the object to the printer daemon" +echo "up takes the overhead passage" +echo "wake MONSTER awakens a UNIX monster" +echo "where (w) tells you where you are" +echo "xyzzy moves you to your home" +} + +MAINT=chet@ins.cwru.edu + +PATH=/usr/ucb:/bin:/usr/bin:/usr/local/bin:. +export PATH + +trap 'echo Ouch!' 2 3 +#trap '' 18 # disable Berkeley job control + +ash_lk(){ echo " $1 " | fgrep " $2 " >&- 2>&-; } +ash_pr(){ echo $* | tr ' ' '\012' | pr -5 -t -w75 -l$[ ( $# + 4 ) / 5 ]; } +ash_rm(){ echo " $1 " | sed -e "s/ $2 / /" -e 's/^ //' -e 's/ $//'; } + +# enable history, bang history expansion, and emacs editing +set -o history +set -o histexpand +set -o emacs + +cd +LIM=.limbo # $HOME/$LIM contains "destroyed" objects +mkdir $LIM >&- 2>&- +KNAP=.knapsack # $HOME/$KNAP contains objects being "carried" +if [ ! -d $KNAP ] +then mkdir $KNAP >&- 2>&- + if [ $? = 0 ] + then echo 'You found a discarded empty knapsack.' + else echo 'You have no knapsack to carry things in.' + exit 1 + fi +else echo 'One moment while I peek in your old knapsack...' +fi + +kn=`echo \`ls -a $KNAP | sed -e '/^\.$/d' -e '/^\.\.$/d'\`` + +if ask 'Welcome to the Adventure shell! Do you need instructions?' +then + ash_inst + echo -n 'Type a newline to continue: ' + read +fi + +wiz=false +cha=false +prev=$LIM +while : +do room=`pwd` + if [ $room != $prev ] + then if [ $room = $HOME ] + then echo 'You are in your own home.' + else echo "You have entered $room." + fi + exs= + obs= + hexs= + hobs= + f=false + for i in `ls -a` + do case $i in + .|..) ;; + .*) if [ -f $i ] + then hobs="$hobs $i" + elif [ -d $i ] + then hexs="$hexs $i" + else f=true + fi + ;; + *) if [ -f $i ] + then obs="$obs $i" + elif [ -d $i ] + then exs="$exs $i" + else f=true + fi + ;; + esac + done + if [ "$obs" ] + then echo 'This room contains:' + ash_pr $obs + else echo 'The room looks empty.' + fi + if [ "$exs" ] + then echo 'There are exits labeled:' + ash_pr $exs + echo 'as well as a passage overhead.' + else echo 'There is a passage overhead.' + fi + if sh -c $f + then echo 'There are shadowy figures in the corner.' + fi + prev=$room + fi + + read -e -p '-advsh> ' verb obj x # prompt is '-advsh> ' + if [ $? != 0 ] + then verb=quit # EOF + fi + + case $verb in + change) if [ "$obj" ] + then if ash_lk "$obs $hobs" "$obj" + then set -- $x + case "$1" in + to) if [ "$2" ] + then if [ -f $2 ] + then echo "You must destroy $2 first." + set -- + fi + if [ "$2" ] + then if mv $obj $2 >&- 2>&- + then echo "The $obj shimmers and turns into $2." + obs=`ash_rm "$2 $obs" "$obj"` + else echo "There is a cloud of smoke but the $obj is unchanged." + fi + fi + else echo 'To what?' + fi + ;; + *) echo "Change $obj to what?" + ;; + esac + else if ash_lk "$kn" "$obj" + then echo 'You must drop it first.' + else echo "I see no $obj here." + fi + fi + else echo 'Change what?' + fi + ;; + clone) if [ "$obj" ] + then if ash_lk "$obs $hobs" "$obj" + then if [ ! -r $obj ] + then echo "The $obj does not wish to be cloned." + else set -- $x + case "$1" in + as) if [ "$2" ] + then if [ -f $2 ] + then echo "You must destroy $2 first." + else if cp $obj $2 >&- 2>&- + then echo "Poof! When the smoke clears, you see the new $2." + obs="$obs $2" + else echo 'You hear a dull thud but no clone appears.' + fi + fi + else echo 'As what?' + fi + ;; + *) echo "Clone $obj as what?" + ;; + esac + fi + else if ash_lk "$kn" "$obj" + then echo 'You must drop it first.' + else echo "I see no $obj here." + fi + fi + else echo 'Clone what?' + fi + ;; + drop) if [ "$obj" ] + then for it in $obj $x + do if ash_lk "$kn" "$it" + then if [ -w $it ] + then echo "You must destroy $it first." + else if mv $HOME/$KNAP/$it $it >&- 2>&- + then echo "$it: dropped." + kn=`ash_rm "$kn" "$it"` + obs=`echo $it $obs` + else echo "The $it is caught in your knapsack." + fi + fi + else echo "You're not carrying the $it!" + fi + done + else echo 'Drop what?' + fi + ;; + enter|go) if [ "$obj" ] + then if [ $obj != up ] + then if ash_lk "$exs $hexs" "$obj" + then if [ -x $obj ] + then if cd $obj + then echo 'You squeeze through the passage.' + else echo "You can't go that direction." + fi + else echo 'An invisible force blocks your way.' + fi + else echo 'I see no such passage.' + fi + else if cd .. + then echo 'You struggle upwards.' + else echo "You can't reach that high." + fi + fi + else echo 'Which passage?' + fi + ;; + examine) if [ "$obj" ] + then if [ $obj = all ] + then $obj=`echo $obs $exs` + x= + fi + for it in $obj $x + do if ash_lk "$obs $hobs $exs $hexs" "$it" + then echo "Upon close inspection of the $it, you see:" + ls -ld $it 2>&- + if [ $? != 0 ] + then echo "-- when you look directly at the $it, it vanishes." + fi + else if ash_lk "$kn" "$it" + then echo 'You must drop it first.' + else echo "I see no $it here." + fi + fi + done + else echo 'Examine what?' + fi + ;; + feed) if [ "$obj" ] + then if ash_lk "$obs $hobs" "$obj" + then set -- $x + case "$1" in + to) if [ "$2" ] + then shift + if PATH=$OPATH $* <$obj 2>&- + then echo "The $1 monster devours your $obj." + if rm -f $obj >&- 2>&- + then obs=`ash_rm "$obs" "$obj"` + else echo 'But he spits it back up.' + fi + else echo "The $1 monster holds his nose in disdain." + fi + else echo 'To what?' + fi + ;; + *) echo "Feed $obj to what?" + ;; + esac + else if ash_lk "$kn" "$obj" + then echo 'You must drop it first.' + else echo "I see no $obj here." + fi + fi + else echo 'Feed what?' + fi + ;; + get|take) if [ "$obj" ] + then if [ $obj = all ] + then obj="$obs" + x= + fi + for it in $obj $x + do if ash_lk "$obs $hobs" "$it" + then if ash_lk "$kn" "$it" + then echo 'You already have one.' + else if mv $it $HOME/$KNAP/$it >&- 2>&- + then echo "$it: taken." + kn="$it $kn" + obs=`ash_rm "$obs" "$it"` + else echo "The $it is too heavy." + fi + fi + else echo "I see no $it here." + fi + done + else echo 'Get what?' + fi + ;; + gripe|bug) echo 'Please describe the problem and your situation at the time it failed.\nEnd the bug report with a line containing just a Ctrl-D.' + cat | mail $MAINT -s 'ash bug' + echo 'Thank you!' + ;; + help) ash_help + ;; + inventory|i) if [ "$kn" ] + then echo 'Your knapsack contains:' + ash_pr $kn + else echo 'You are poverty-stricken.' + fi + ;; + kill|destroy) if [ "$obj" ] + then if [ $obj = all ] + then x= + if ask "Do you really want to attempt to $verb them all?" + then obj=`echo $obs` + else echo 'Chicken!' + obj= + fi + fi + for it in $obj $x + do if ash_lk "$obs $hobs" "$it" + then if mv $it $HOME/$LIM <&- >&- 2>&- + then if [ $verb = kill ] + then echo "The $it cannot defend himself; he dies." + else echo "You have destroyed the $it; it vanishes." + fi + obs=`ash_rm "$obs" "$it"` + else if [ $verb = kill ] + then echo "Your feeble blows are no match for the $it." + else echo "The $it is indestructible." + fi + fi + else if ash_lk "$kn" "$it" + then echo "You must drop the $it first." + found=false + else echo "I see no $it here." + fi + fi + done + else echo 'Kill what?' + fi + ;; + look|l) obs=`echo $obs $hobs` + hobs= + if [ "$obs" ] + then echo 'The room contains:' + ash_pr $obs + else echo 'The room is empty.' + fi + exs=`echo $exs $hexs` + hexs= + if [ "$exs" ] + then echo 'There are exits plainly labeled:' + ash_pr $exs + echo 'and a passage directly overhead.' + else echo 'The only exit is directly overhead.' + fi + ;; + magic) if [ "$obj" = mode ] + then if sh -c $cha + then echo 'You had your chance and you blew it.' + else if ask 'Are you a wizard?' + then echo -n 'Prove it! Say the magic word: ' + read obj + if [ "$obj" = armadillo ] + then echo 'Yes, master!!' + wiz=true + else echo "Homie says: I don't think so" + cha=true + fi + else echo "I didn't think so." + fi + fi + else echo 'Nice try.' + fi + ;; + open|read) if [ "$obj" ] + then if ash_lk "$obs $hobs" "$obj" + then if [ -r $obj ] + then if [ -s $obj ] + then echo "Opening the $obj reveals:" + $CAT < $obj + if [ $? != 0 ] + then echo '-- oops, you lost the contents!' + fi + else echo "There is nothing inside the $obj." + fi + else echo "You do not have the proper tools to open the $obj." + fi + else if ash_lk "$kn" "$obj" + then echo 'You must drop it first.' + found=false + else echo "I see no $obj here." + fi + fi + else echo 'Open what?' + fi + ;; + quit|exit) if ask 'Do you really want to quit now?' + then if [ "$kn" ] + then echo 'The contents of your knapsack will still be there next time.' + fi + rm -rf $HOME/$LIM + echo 'See you later!' + exit 0 + fi + ;; + resurrect) if [ "$obj" ] + then for it in $obj $x + do if ash_lk "$obs $hobs" "$it" + then echo "The $it is already alive and well." + else if mv $HOME/$LIM/$it $it <&- >&- 2>&- + then echo "The $it staggers to his feet." + obs=`echo $it $obs` + else echo "There are sparks but no $it appears." + fi + fi + done + else echo 'Resurrect what?' + fi + ;; + steal) if [ "$obj" ] + then if ash_lk "$obs $hobs" "$obj" + then echo 'There is already one here.' + else set -- $x + case "$1" in + from) if [ "$2" ] + then shift + if PATH=$OPATH $* >$obj 2>&- + then echo "The $1 monster drops the $obj." + obs=`echo $obj $obs` + else echo "The $1 monster runs away as you approach." + rm -f $obj >&- 2>&- + fi + else echo 'From what?' + fi + ;; + *) echo "Steal $obj from what?" + ;; + esac + fi + else echo 'Steal what?' + fi + ;; + throw) if [ "$obj" ] + then if ash_lk "$obs $hobs" "$obj" + then set -- $x + case "$1" in + at) case "$2" in + daemon) if sh -c "lpr -r $obj" + then echo "The daemon catches the $obj, turns it into paper,\nand leaves it in the basket." + obs=`ash_rm "$obs" "$obj"` + else echo "The daemon is nowhere to be found." + fi + ;; + *) echo 'At what?' + ;; + esac + ;; + *) echo "Throw $obj at what?" + ;; + esac + else if ash_lk "$kn" "$obj" + then echo 'It is in your knapsack.' + found=false + else echo "I see no $obj here." + fi + fi + else echo 'Throw what?' + fi + ;; + u|up) if cd .. + then echo 'You pull yourself up a level.' + else echo "You can't reach that high." + fi + ;; + wake) if [ "$obj" ] + then echo "You awaken the $obj monster:" + PATH=$OPATH $obj $x + echo 'The monster slithers back into the darkness.' + else echo 'Wake what?' + fi + ;; + w|where) echo "You are in $room." + ;; + xyzzy) if cd + then echo 'A strange feeling comes over you.' + else echo 'Your spell fizzles out.' + fi + ;; + *) if [ "$verb" ] + then if sh -c $wiz + then PATH=$OPATH $verb $obj $x + else echo "I don't know how to \"$verb\"." + echo 'Type "help" for assistance.' + fi + else echo 'Say something!' + fi + ;; + esac +done diff --git a/examples/scripts/bcsh.sh b/examples/scripts/bcsh.sh index b810cab8f..83f69cdd7 100755 --- a/examples/scripts/bcsh.sh +++ b/examples/scripts/bcsh.sh @@ -747,7 +747,7 @@ esac/ ;; *) counter="`expr \"$counter\" + 1`" - # counter=$[ $counter + 1 ] + # counter=$(( $counter + 1 )) ;; esac done @@ -1226,7 +1226,7 @@ $cmd case "$inc_cmdno" in yes) cmdno="`expr \"$cmdno\" + 1`" - # cmdno=$[$cmdno + 1] + # cmdno=$(( $cmdno + 1 )) ;; esac ;; diff --git a/examples/scripts/shprompt b/examples/scripts/shprompt index ec8b997ad..f21e92fe6 100755 --- a/examples/scripts/shprompt +++ b/examples/scripts/shprompt @@ -44,7 +44,7 @@ do done if [ "$OPTIND" -gt 1 ] ; then - shift $[$OPTIND - 1] + shift $(( $OPTIND - 1 )) fi while : diff --git a/lib/readline/complete.c.save1 b/lib/readline/complete.c.save1 new file mode 100644 index 000000000..7ebb104e9 --- /dev/null +++ b/lib/readline/complete.c.save1 @@ -0,0 +1,2705 @@ +/* complete.c -- filename completion for readline. */ + +/* Copyright (C) 1987-2011 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library (Readline), a library + for reading lines of text with interactive input and history editing. + + Readline is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Readline is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Readline. If not, see . +*/ + +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include +#if defined (HAVE_SYS_FILE_H) +# include +#endif + +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include + +#include +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +#if defined (HAVE_PWD_H) +#include +#endif + +#include "posixdir.h" +#include "posixstat.h" + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" +#include "rlmbutil.h" + +/* Some standard library routines. */ +#include "readline.h" +#include "xmalloc.h" +#include "rlprivate.h" + +#ifdef __STDC__ +typedef int QSFUNC (const void *, const void *); +#else +typedef int QSFUNC (); +#endif + +#ifdef HAVE_LSTAT +# define LSTAT lstat +#else +# define LSTAT stat +#endif + +/* Unix version of a hidden file. Could be different on other systems. */ +#define HIDDEN_FILE(fname) ((fname)[0] == '.') + +/* Most systems don't declare getpwent in if _POSIX_SOURCE is + defined. */ +#if defined (HAVE_GETPWENT) && (!defined (HAVE_GETPW_DECLS) || defined (_POSIX_SOURCE)) +extern struct passwd *getpwent PARAMS((void)); +#endif /* HAVE_GETPWENT && (!HAVE_GETPW_DECLS || _POSIX_SOURCE) */ + +/* If non-zero, then this is the address of a function to call when + completing a word would normally display the list of possible matches. + This function is called instead of actually doing the display. + It takes three arguments: (char **matches, int num_matches, int max_length) + where MATCHES is the array of strings that matched, NUM_MATCHES is the + number of strings in that array, and MAX_LENGTH is the length of the + longest string in that array. */ +rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL; + +#if defined (VISIBLE_STATS) +# if !defined (X_OK) +# define X_OK 1 +# endif +static int stat_char PARAMS((char *)); +#endif + +static int path_isdir PARAMS((const char *)); + +static char *rl_quote_filename PARAMS((char *, int, char *)); + +static void _rl_complete_sigcleanup PARAMS((int, void *)); + +static void set_completion_defaults PARAMS((int)); +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 print_filename PARAMS((char *, char *, int)); + +static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int)); + +static char **remove_duplicate_matches PARAMS((char **)); +static void insert_match PARAMS((char *, int, int, char *)); +static int append_to_match PARAMS((char *, int, int, int)); +static void insert_all_matches PARAMS((char **, int, char *)); +static int complete_fncmp PARAMS((const char *, int, const char *, int)); +static void display_matches PARAMS((char **)); +static int compute_lcd_of_matches PARAMS((char **, int, const char *)); +static int postprocess_matches PARAMS((char ***, int)); +static int complete_get_screenwidth PARAMS((void)); + +static char *make_quoted_replacement PARAMS((char *, int, char *)); + +/* **************************************************************** */ +/* */ +/* Completion matching, from readline's point of view. */ +/* */ +/* **************************************************************** */ + +/* Variables known only to the readline library. */ + +/* If non-zero, non-unique completions always show the list of matches. */ +int _rl_complete_show_all = 0; + +/* If non-zero, non-unique completions show the list of matches, unless it + is not possible to do partial completion and modify the line. */ +int _rl_complete_show_unmodified = 0; + +/* If non-zero, completed directory names have a slash appended. */ +int _rl_complete_mark_directories = 1; + +/* If non-zero, the symlinked directory completion behavior introduced in + readline-4.2a is disabled, and symlinks that point to directories have + a slash appended (subject to the value of _rl_complete_mark_directories). + This is user-settable via the mark-symlinked-directories variable. */ +int _rl_complete_mark_symlink_dirs = 0; + +/* If non-zero, completions are printed horizontally in alphabetical order, + like `ls -x'. */ +int _rl_print_completions_horizontally; + +/* Non-zero means that case is not significant in filename completion. */ +#if defined (__MSDOS__) && !defined (__DJGPP__) +int _rl_completion_case_fold = 1; +#else +int _rl_completion_case_fold = 0; +#endif + +/* Non-zero means that `-' and `_' are equivalent when comparing filenames + for completion. */ +int _rl_completion_case_map = 0; + +/* If zero, don't match hidden files (filenames beginning with a `.' on + Unix) when doing filename completion. */ +int _rl_match_hidden_files = 1; + +/* Length in characters of a common prefix replaced with an ellipsis (`...') + when displaying completion matches. Matches whose printable portion has + more than this number of displaying characters in common will have the common + display prefix replaced with an ellipsis. */ +int _rl_completion_prefix_display_length = 0; + +/* The readline-private number of screen columns to use when displaying + matches. If < 0 or > _rl_screenwidth, it is ignored. */ +int _rl_completion_columns = -1; + +/* Global variables available to applications using readline. */ + +#if defined (VISIBLE_STATS) +/* Non-zero means add an additional character to each filename displayed + during listing completion iff rl_filename_completion_desired which helps + to indicate the type of file being listed. */ +int rl_visible_stats = 0; +#endif /* VISIBLE_STATS */ + +/* If non-zero, when completing in the middle of a word, don't insert + characters from the match that match characters following point in + the word. This means, for instance, completing when the cursor is + after the `e' in `Makefile' won't result in `Makefilefile'. */ +int _rl_skip_completed_text = 0; + +/* If non-zero, menu completion displays the common prefix first in the + cycle of possible completions instead of the last. */ +int _rl_menu_complete_prefix_first = 0; + +/* If non-zero, then this is the address of a function to call when + completing on a directory name. The function is called with + the address of a string (the current directory name) as an arg. */ +rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL; + +rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL; + +rl_icppfunc_t *rl_filename_stat_hook = (rl_icppfunc_t *)NULL; + +/* If non-zero, this is the address of a function to call when reading + directory entries from the filesystem for completion and comparing + them to the partial word to be completed. The function should + either return its first argument (if no conversion takes place) or + newly-allocated memory. This can, for instance, convert filenames + between character sets for comparison against what's typed at the + keyboard. The returned value is what is added to the list of + matches. The second argument is the length of the filename to be + converted. */ +rl_dequote_func_t *rl_filename_rewrite_hook = (rl_dequote_func_t *)NULL; + +/* Non-zero means readline completion functions perform tilde expansion. */ +int rl_complete_with_tilde_expansion = 0; + +/* Pointer to the generator function for completion_matches (). + NULL means to use rl_filename_completion_function (), the default filename + completer. */ +rl_compentry_func_t *rl_completion_entry_function = (rl_compentry_func_t *)NULL; + +/* Pointer to generator function for rl_menu_complete (). NULL means to use + *rl_completion_entry_function (see above). */ +rl_compentry_func_t *rl_menu_completion_entry_function = (rl_compentry_func_t *)NULL; + +/* Pointer to alternative function to create matches. + Function is called with TEXT, START, and END. + START and END are indices in RL_LINE_BUFFER saying what the boundaries + of TEXT are. + If this function exists and returns NULL then call the value of + rl_completion_entry_function to try to match, otherwise use the + array of strings returned. */ +rl_completion_func_t *rl_attempted_completion_function = (rl_completion_func_t *)NULL; + +/* Non-zero means to suppress normal filename completion after the + user-specified completion function has been called. */ +int rl_attempted_completion_over = 0; + +/* Set to a character indicating the type of completion being performed + by rl_complete_internal, available for use by application completion + functions. */ +int rl_completion_type = 0; + +/* Up to this many items will be displayed in response to a + possible-completions call. After that, we ask the user if + she is sure she wants to see them all. A negative value means + don't ask. */ +int rl_completion_query_items = 100; + +int _rl_page_completions = 1; + +/* The basic list of characters that signal a break between words for the + completer routine. The contents of this variable is what breaks words + in the shell, i.e. " \t\n\"\\'`@$><=" */ +const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; /* }) */ + +/* List of basic quoting characters. */ +const char *rl_basic_quote_characters = "\"'"; + +/* The list of characters that signal a break between words for + rl_complete_internal. The default list is the contents of + rl_basic_word_break_characters. */ +/*const*/ char *rl_completer_word_break_characters = (/*const*/ char *)NULL; + +/* Hook function to allow an application to set the completion word + break characters before readline breaks up the line. Allows + position-dependent word break characters. */ +rl_cpvfunc_t *rl_completion_word_break_hook = (rl_cpvfunc_t *)NULL; + +/* List of characters which can be used to quote a substring of the line. + Completion occurs on the entire substring, and within the substring + rl_completer_word_break_characters are treated as any other character, + unless they also appear within this list. */ +const char *rl_completer_quote_characters = (const char *)NULL; + +/* List of characters that should be quoted in filenames by the completer. */ +const char *rl_filename_quote_characters = (const char *)NULL; + +/* List of characters that are word break characters, but should be left + in TEXT when it is passed to the completion function. The shell uses + this to help determine what kind of completing to do. */ +const char *rl_special_prefixes = (const char *)NULL; + +/* If non-zero, then disallow duplicates in the matches. */ +int rl_ignore_completion_duplicates = 1; + +/* Non-zero means that the results of the matches are to be treated + as filenames. This is ALWAYS zero on entry, and can only be changed + within a completion entry finder function. */ +int rl_filename_completion_desired = 0; + +/* Non-zero means that the results of the matches are to be quoted using + double quotes (or an application-specific quoting mechanism) if the + filename contains any characters in rl_filename_quote_chars. This is + ALWAYS non-zero on entry, and can only be changed within a completion + entry finder function. */ +int rl_filename_quoting_desired = 1; + +/* This function, if defined, is called by the completer when real + filename completion is done, after all the matching names have been + generated. It is passed a (char**) known as matches in the code below. + It consists of a NULL-terminated array of pointers to potential + matching strings. The 1st element (matches[0]) is the maximal + substring that is common to all matches. This function can re-arrange + the list of matches as required, but all elements of the array must be + free()'d if they are deleted. The main intent of this function is + to implement FIGNORE a la SunOS csh. */ +rl_compignore_func_t *rl_ignore_some_completions_function = (rl_compignore_func_t *)NULL; + +/* Set to a function to quote a filename in an application-specific fashion. + Called with the text to quote, the type of match found (single or multiple) + and a pointer to the quoting character to be used, which the function can + reset if desired. */ +rl_quote_func_t *rl_filename_quoting_function = rl_quote_filename; + +/* Function to call to remove quoting characters from a filename. Called + before completion is attempted, so the embedded quotes do not interfere + with matching names in the file system. Readline doesn't do anything + with this; it's set only by applications. */ +rl_dequote_func_t *rl_filename_dequoting_function = (rl_dequote_func_t *)NULL; + +/* Function to call to decide whether or not a word break character is + quoted. If a character is quoted, it does not break words for the + completer. */ +rl_linebuf_func_t *rl_char_is_quoted_p = (rl_linebuf_func_t *)NULL; + +/* If non-zero, the completion functions don't append anything except a + possible closing quote. This is set to 0 by rl_complete_internal and + may be changed by an application-specific completion function. */ +int rl_completion_suppress_append = 0; + +/* Character appended to completed words when at the end of the line. The + default is a space. */ +int rl_completion_append_character = ' '; + +/* If non-zero, the completion functions don't append any closing quote. + This is set to 0 by rl_complete_internal and may be changed by an + application-specific completion function. */ +int rl_completion_suppress_quote = 0; + +/* Set to any quote character readline thinks it finds before any application + completion function is called. */ +int rl_completion_quote_character; + +/* Set to a non-zero value if readline found quoting anywhere in the word to + be completed; set before any application completion function is called. */ +int rl_completion_found_quote; + +/* If non-zero, a slash will be appended to completed filenames that are + symbolic links to directory names, subject to the value of the + mark-directories variable (which is user-settable). This exists so + that application completion functions can override the user's preference + (set via the mark-symlinked-directories variable) if appropriate. + It's set to the value of _rl_complete_mark_symlink_dirs in + rl_complete_internal before any application-specific completion + function is called, so without that function doing anything, the user's + preferences are honored. */ +int rl_completion_mark_symlink_dirs; + +/* If non-zero, inhibit completion (temporarily). */ +int rl_inhibit_completion; + +/* Set to the last key used to invoke one of the completion functions */ +int rl_completion_invoking_key; + +/* If non-zero, sort the completion matches. On by default. */ +int rl_sort_completion_matches = 1; + +/* Variables local to this file. */ + +/* Local variable states what happened during the last completion attempt. */ +static int completion_changed_buffer; + +/* The result of the query to the user about displaying completion matches */ +static int completion_y_or_n; + +/*************************************/ +/* */ +/* Bindable completion functions */ +/* */ +/*************************************/ + +/* Complete the word at or before point. You have supplied the function + that does the initial simple matching selection algorithm (see + rl_completion_matches ()). The default is to do filename completion. */ +int +rl_complete (ignore, invoking_key) + int ignore, invoking_key; +{ + rl_completion_invoking_key = invoking_key; + + if (rl_inhibit_completion) + return (_rl_insert_char (ignore, invoking_key)); + else if (rl_last_func == rl_complete && !completion_changed_buffer) + return (rl_complete_internal ('?')); + else if (_rl_complete_show_all) + return (rl_complete_internal ('!')); + else if (_rl_complete_show_unmodified) + return (rl_complete_internal ('@')); + else + return (rl_complete_internal (TAB)); +} + +/* List the possible completions. See description of rl_complete (). */ +int +rl_possible_completions (ignore, invoking_key) + int ignore, invoking_key; +{ + rl_completion_invoking_key = invoking_key; + return (rl_complete_internal ('?')); +} + +int +rl_insert_completions (ignore, invoking_key) + int ignore, invoking_key; +{ + rl_completion_invoking_key = invoking_key; + return (rl_complete_internal ('*')); +} + +/* Return the correct value to pass to rl_complete_internal performing + the same tests as rl_complete. This allows consecutive calls to an + application's completion function to list possible completions and for + an application-specific completion function to honor the + show-all-if-ambiguous readline variable. */ +int +rl_completion_mode (cfunc) + rl_command_func_t *cfunc; +{ + if (rl_last_func == cfunc && !completion_changed_buffer) + return '?'; + else if (_rl_complete_show_all) + return '!'; + else if (_rl_complete_show_unmodified) + return '@'; + else + return TAB; +} + +/************************************/ +/* */ +/* Completion utility functions */ +/* */ +/************************************/ + +/* Reset readline state on a signal or other event. */ +void +_rl_reset_completion_state () +{ + rl_completion_found_quote = 0; + rl_completion_quote_character = 0; +} + +static void +_rl_complete_sigcleanup (sig, ptr) + int sig; + void *ptr; +{ + if (sig == SIGINT) /* XXX - for now */ + _rl_free_match_list ((char **)ptr); +} + +/* Set default values for readline word completion. These are the variables + that application completion functions can change or inspect. */ +static void +set_completion_defaults (what_to_do) + int what_to_do; +{ + /* Only the completion entry function can change these. */ + rl_filename_completion_desired = 0; + rl_filename_quoting_desired = 1; + rl_completion_type = what_to_do; + rl_completion_suppress_append = rl_completion_suppress_quote = 0; + rl_completion_append_character = ' '; + + /* The completion entry function may optionally change this. */ + rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs; +} + +/* The user must press "y" or "n". Non-zero return means "y" pressed. */ +static int +get_y_or_n (for_pager) + int for_pager; +{ + int c; + + /* For now, disable pager in callback mode, until we later convert to state + driven functions. Have to wait until next major version to add new + state definition, since it will change value of RL_STATE_DONE. */ +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + return 1; +#endif + + for (;;) + { + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (c == 'y' || c == 'Y' || c == ' ') + return (1); + if (c == 'n' || c == 'N' || c == RUBOUT) + return (0); + if (c == ABORT_CHAR || c < 0) + _rl_abort_internal (); + if (for_pager && (c == NEWLINE || c == RETURN)) + return (2); + if (for_pager && (c == 'q' || c == 'Q')) + return (0); + rl_ding (); + } +} + +static int +_rl_internal_pager (lines) + int lines; +{ + int i; + + fprintf (rl_outstream, "--More--"); + fflush (rl_outstream); + i = get_y_or_n (1); + _rl_erase_entire_line (); + if (i == 0) + return -1; + else if (i == 2) + return (lines - 1); + else + return 0; +} + +static int +path_isdir (filename) + const char *filename; +{ + struct stat finfo; + + return (stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode)); +} + +#if defined (VISIBLE_STATS) +/* Return the character which best describes FILENAME. + `@' for symbolic links + `/' for directories + `*' for executables + `=' for sockets + `|' for FIFOs + `%' for character special devices + `#' for block special devices */ +static int +stat_char (filename) + char *filename; +{ + struct stat finfo; + int character, r; + + /* Short-circuit a //server on cygwin, since that will always behave as + a directory. */ +#if __CYGWIN__ + if (filename[0] == '/' && filename[1] == '/' && strchr (filename+2, '/') == 0) + return '/'; +#endif + +#if defined (HAVE_LSTAT) && defined (S_ISLNK) + r = lstat (filename, &finfo); +#else + r = stat (filename, &finfo); +#endif + + if (r == -1) + return (0); + + character = 0; + if (S_ISDIR (finfo.st_mode)) + character = '/'; +#if defined (S_ISCHR) + else if (S_ISCHR (finfo.st_mode)) + character = '%'; +#endif /* S_ISCHR */ +#if defined (S_ISBLK) + else if (S_ISBLK (finfo.st_mode)) + character = '#'; +#endif /* S_ISBLK */ +#if defined (S_ISLNK) + else if (S_ISLNK (finfo.st_mode)) + character = '@'; +#endif /* S_ISLNK */ +#if defined (S_ISSOCK) + else if (S_ISSOCK (finfo.st_mode)) + character = '='; +#endif /* S_ISSOCK */ +#if defined (S_ISFIFO) + else if (S_ISFIFO (finfo.st_mode)) + character = '|'; +#endif + else if (S_ISREG (finfo.st_mode)) + { + if (access (filename, X_OK) == 0) + character = '*'; + } + return (character); +} +#endif /* VISIBLE_STATS */ + +/* Return the portion of PATHNAME that should be output when listing + possible completions. If we are hacking filename completion, we + are only interested in the basename, the portion following the + final slash. Otherwise, we return what we were passed. Since + printing empty strings is not very informative, if we're doing + filename completion, and the basename is the empty string, we look + for the previous slash and return the portion following that. If + there's no previous slash, we just return what we were passed. */ +static char * +printable_part (pathname) + char *pathname; +{ + char *temp, *x; + + if (rl_filename_completion_desired == 0) /* don't need to do anything */ + return (pathname); + + temp = strrchr (pathname, '/'); +#if defined (__MSDOS__) + if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':') + temp = pathname + 1; +#endif + + if (temp == 0 || *temp == '\0') + return (pathname); + /* If the basename is NULL, we might have a pathname like '/usr/src/'. + Look for a previous slash and, if one is found, return the portion + following that slash. If there's no previous slash, just return the + pathname we were passed. */ + else if (temp[1] == '\0') + { + for (x = temp - 1; x > pathname; x--) + if (*x == '/') + break; + return ((*x == '/') ? x + 1 : pathname); + } + else + return ++temp; +} + +/* Compute width of STRING when displayed on screen by print_filename */ +static int +fnwidth (string) + const char *string; +{ + int width, pos; +#if defined (HANDLE_MULTIBYTE) + mbstate_t ps; + int left, w; + size_t clen; + wchar_t wc; + + left = strlen (string) + 1; + memset (&ps, 0, sizeof (mbstate_t)); +#endif + + width = pos = 0; + while (string[pos]) + { + if (CTRL_CHAR (string[pos]) || string[pos] == RUBOUT) + { + width += 2; + pos++; + } + else + { +#if defined (HANDLE_MULTIBYTE) + clen = mbrtowc (&wc, string + pos, left - pos, &ps); + if (MB_INVALIDCH (clen)) + { + width++; + pos++; + memset (&ps, 0, sizeof (mbstate_t)); + } + else if (MB_NULLWCH (clen)) + break; + else + { + pos += clen; + w = WCWIDTH (wc); + width += (w >= 0) ? w : 1; + } +#else + width++; + pos++; +#endif + } + } + + return width; +} + +#define ELLIPSIS_LEN 3 + +static int +fnprint (to_print, prefix_bytes) + const char *to_print; + int prefix_bytes; +{ + int printed_len, w; + const char *s; +#if defined (HANDLE_MULTIBYTE) + mbstate_t ps; + const char *end; + size_t tlen; + int width; + wchar_t wc; + + end = to_print + strlen (to_print) + 1; + memset (&ps, 0, sizeof (mbstate_t)); +#endif + + printed_len = 0; + + /* Don't print only the ellipsis if the common prefix is one of the + possible completions */ + if (to_print[prefix_bytes] == '\0') + prefix_bytes = 0; + + if (prefix_bytes) + { + char ellipsis; + + ellipsis = (to_print[prefix_bytes] == '.') ? '_' : '.'; + for (w = 0; w < ELLIPSIS_LEN; w++) + putc (ellipsis, rl_outstream); + printed_len = ELLIPSIS_LEN; + } + + s = to_print + prefix_bytes; + while (*s) + { + if (CTRL_CHAR (*s)) + { + putc ('^', rl_outstream); + putc (UNCTRL (*s), rl_outstream); + printed_len += 2; + s++; +#if defined (HANDLE_MULTIBYTE) + memset (&ps, 0, sizeof (mbstate_t)); +#endif + } + else if (*s == RUBOUT) + { + putc ('^', rl_outstream); + putc ('?', rl_outstream); + printed_len += 2; + s++; +#if defined (HANDLE_MULTIBYTE) + memset (&ps, 0, sizeof (mbstate_t)); +#endif + } + else + { +#if defined (HANDLE_MULTIBYTE) + tlen = mbrtowc (&wc, s, end - s, &ps); + if (MB_INVALIDCH (tlen)) + { + tlen = 1; + width = 1; + memset (&ps, 0, sizeof (mbstate_t)); + } + else if (MB_NULLWCH (tlen)) + break; + else + { + w = WCWIDTH (wc); + width = (w >= 0) ? w : 1; + } + fwrite (s, 1, tlen, rl_outstream); + s += tlen; + printed_len += width; +#else + putc (*s, rl_outstream); + s++; + printed_len++; +#endif + } + } + + return printed_len; +} + +/* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we + are using it, check for and output a single character for `special' + filenames. Return the number of characters we output. */ + +static int +print_filename (to_print, full_pathname, prefix_bytes) + char *to_print, *full_pathname; + int prefix_bytes; +{ + int printed_len, extension_char, slen, tlen; + char *s, c, *new_full_pathname, *dn; + + extension_char = 0; + printed_len = fnprint (to_print, prefix_bytes); + +#if defined (VISIBLE_STATS) + if (rl_filename_completion_desired && (rl_visible_stats || _rl_complete_mark_directories)) +#else + if (rl_filename_completion_desired && _rl_complete_mark_directories) +#endif + { + /* If to_print != full_pathname, to_print is the basename of the + path passed. In this case, we try to expand the directory + name before checking for the stat character. */ + if (to_print != full_pathname) + { + /* Terminate the directory name. */ + c = to_print[-1]; + to_print[-1] = '\0'; + + /* If setting the last slash in full_pathname to a NUL results in + full_pathname being the empty string, we are trying to complete + files in the root directory. If we pass a null string to the + bash directory completion hook, for example, it will expand it + to the current directory. We just want the `/'. */ + if (full_pathname == 0 || *full_pathname == 0) + dn = "/"; + else if (full_pathname[0] != '/') + dn = full_pathname; + else if (full_pathname[1] == 0) + dn = "//"; /* restore trailing slash to `//' */ + else if (full_pathname[1] == '/' && full_pathname[2] == 0) + dn = "/"; /* don't turn /// into // */ + else + dn = full_pathname; + s = tilde_expand (dn); + if (rl_directory_completion_hook) + (*rl_directory_completion_hook) (&s); + + slen = strlen (s); + tlen = strlen (to_print); + new_full_pathname = (char *)xmalloc (slen + tlen + 2); + strcpy (new_full_pathname, s); + if (s[slen - 1] == '/') + slen--; + else + new_full_pathname[slen] = '/'; + new_full_pathname[slen] = '/'; + strcpy (new_full_pathname + slen + 1, to_print); + +#if defined (VISIBLE_STATS) + if (rl_visible_stats) + extension_char = stat_char (new_full_pathname); + else +#endif + if (path_isdir (new_full_pathname)) + extension_char = '/'; + + xfree (new_full_pathname); + to_print[-1] = c; + } + else + { + s = tilde_expand (full_pathname); +#if defined (VISIBLE_STATS) + if (rl_visible_stats) + extension_char = stat_char (s); + else +#endif + if (path_isdir (s)) + extension_char = '/'; + } + + xfree (s); + if (extension_char) + { + putc (extension_char, rl_outstream); + printed_len++; + } + } + + return printed_len; +} + +static char * +rl_quote_filename (s, rtype, qcp) + char *s; + int rtype; + char *qcp; +{ + char *r; + + r = (char *)xmalloc (strlen (s) + 2); + *r = *rl_completer_quote_characters; + strcpy (r + 1, s); + if (qcp) + *qcp = *rl_completer_quote_characters; + return r; +} + +/* Find the bounds of the current word for completion purposes, and leave + rl_point set to the end of the word. This function skips quoted + substrings (characters between matched pairs of characters in + rl_completer_quote_characters). First we try to find an unclosed + quoted substring on which to do matching. If one is not found, we use + the word break characters to find the boundaries of the current word. + We call an application-specific function to decide whether or not a + particular word break character is quoted; if that function returns a + non-zero result, the character does not break a word. This function + returns the opening quote character if we found an unclosed quoted + substring, '\0' otherwise. FP, if non-null, is set to a value saying + which (shell-like) quote characters we found (single quote, double + quote, or backslash) anywhere in the string. DP, if non-null, is set to + the value of the delimiter character that caused a word break. */ + +char +_rl_find_completion_word (fp, dp) + int *fp, *dp; +{ + int scan, end, found_quote, delimiter, pass_next, isbrk; + char quote_char, *brkchars; + + end = rl_point; + found_quote = delimiter = 0; + quote_char = '\0'; + + brkchars = 0; + if (rl_completion_word_break_hook) + brkchars = (*rl_completion_word_break_hook) (); + if (brkchars == 0) + brkchars = rl_completer_word_break_characters; + + if (rl_completer_quote_characters) + { + /* We have a list of characters which can be used in pairs to + quote substrings for the completer. Try to find the start + of an unclosed quoted substring. */ + /* FOUND_QUOTE is set so we know what kind of quotes we found. */ + for (scan = pass_next = 0; scan < end; scan = MB_NEXTCHAR (rl_line_buffer, scan, 1, MB_FIND_ANY)) + { + if (pass_next) + { + pass_next = 0; + continue; + } + + /* Shell-like semantics for single quotes -- don't allow backslash + to quote anything in single quotes, especially not the closing + quote. If you don't like this, take out the check on the value + of quote_char. */ + if (quote_char != '\'' && rl_line_buffer[scan] == '\\') + { + pass_next = 1; + found_quote |= RL_QF_BACKSLASH; + continue; + } + + if (quote_char != '\0') + { + /* Ignore everything until the matching close quote char. */ + if (rl_line_buffer[scan] == quote_char) + { + /* Found matching close. Abandon this substring. */ + quote_char = '\0'; + rl_point = end; + } + } + else if (strchr (rl_completer_quote_characters, rl_line_buffer[scan])) + { + /* Found start of a quoted substring. */ + quote_char = rl_line_buffer[scan]; + rl_point = scan + 1; + /* Shell-like quoting conventions. */ + if (quote_char == '\'') + found_quote |= RL_QF_SINGLE_QUOTE; + else if (quote_char == '"') + found_quote |= RL_QF_DOUBLE_QUOTE; + else + found_quote |= RL_QF_OTHER_QUOTE; + } + } + } + + if (rl_point == end && quote_char == '\0') + { + /* We didn't find an unclosed quoted substring upon which to do + completion, so use the word break characters to find the + substring on which to complete. */ + while (rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_ANY)) + { + scan = rl_line_buffer[rl_point]; + + if (strchr (brkchars, scan) == 0) + continue; + + /* Call the application-specific function to tell us whether + this word break character is quoted and should be skipped. */ + if (rl_char_is_quoted_p && found_quote && + (*rl_char_is_quoted_p) (rl_line_buffer, rl_point)) + continue; + + /* Convoluted code, but it avoids an n^2 algorithm with calls + to char_is_quoted. */ + break; + } + } + + /* If we are at an unquoted word break, then advance past it. */ + scan = rl_line_buffer[rl_point]; + + /* If there is an application-specific function to say whether or not + a character is quoted and we found a quote character, let that + function decide whether or not a character is a word break, even + if it is found in rl_completer_word_break_characters. Don't bother + if we're at the end of the line, though. */ + if (scan) + { + if (rl_char_is_quoted_p) + isbrk = (found_quote == 0 || + (*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) && + strchr (brkchars, scan) != 0; + else + isbrk = strchr (brkchars, scan) != 0; + + if (isbrk) + { + /* If the character that caused the word break was a quoting + character, then remember it as the delimiter. */ + if (rl_basic_quote_characters && + strchr (rl_basic_quote_characters, scan) && + (end - rl_point) > 1) + delimiter = scan; + + /* If the character isn't needed to determine something special + about what kind of completion to perform, then advance past it. */ + if (rl_special_prefixes == 0 || strchr (rl_special_prefixes, scan) == 0) + rl_point++; + } + } + + if (fp) + *fp = found_quote; + if (dp) + *dp = delimiter; + + return (quote_char); +} + +static char ** +gen_completion_matches (text, start, end, our_func, found_quote, quote_char) + char *text; + int start, end; + rl_compentry_func_t *our_func; + int found_quote, quote_char; +{ + char **matches; + + rl_completion_found_quote = found_quote; + rl_completion_quote_character = quote_char; + + /* If the user wants to TRY to complete, but then wants to give + up and use the default completion function, they set the + variable rl_attempted_completion_function. */ + if (rl_attempted_completion_function) + { + matches = (*rl_attempted_completion_function) (text, start, end); + if (RL_SIG_RECEIVED()) + { + _rl_free_match_list (matches); + matches = 0; + RL_CHECK_SIGNALS (); + } + + if (matches || rl_attempted_completion_over) + { + rl_attempted_completion_over = 0; + return (matches); + } + } + + /* XXX -- filename dequoting moved into rl_filename_completion_function */ + + /* rl_completion_matches will check for signals as well to avoid a long + delay while reading a directory. */ + matches = rl_completion_matches (text, our_func); + if (RL_SIG_RECEIVED()) + { + _rl_free_match_list (matches); + matches = 0; + RL_CHECK_SIGNALS (); + } + return matches; +} + +/* Filter out duplicates in MATCHES. This frees up the strings in + MATCHES. */ +static char ** +remove_duplicate_matches (matches) + char **matches; +{ + char *lowest_common; + int i, j, newlen; + char dead_slot; + char **temp_array; + + /* Sort the items. */ + for (i = 0; matches[i]; i++) + ; + + /* Sort the array without matches[0], since we need it to + stay in place no matter what. */ + if (i && rl_sort_completion_matches) + qsort (matches+1, i-1, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); + + /* Remember the lowest common denominator for it may be unique. */ + lowest_common = savestring (matches[0]); + + for (i = newlen = 0; matches[i + 1]; i++) + { + if (strcmp (matches[i], matches[i + 1]) == 0) + { + xfree (matches[i]); + matches[i] = (char *)&dead_slot; + } + else + newlen++; + } + + /* We have marked all the dead slots with (char *)&dead_slot. + Copy all the non-dead entries into a new array. */ + temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *)); + for (i = j = 1; matches[i]; i++) + { + if (matches[i] != (char *)&dead_slot) + temp_array[j++] = matches[i]; + } + temp_array[j] = (char *)NULL; + + if (matches[0] != (char *)&dead_slot) + xfree (matches[0]); + + /* Place the lowest common denominator back in [0]. */ + temp_array[0] = lowest_common; + + /* If there is one string left, and it is identical to the + lowest common denominator, then the LCD is the string to + insert. */ + if (j == 2 && strcmp (temp_array[0], temp_array[1]) == 0) + { + xfree (temp_array[1]); + temp_array[1] = (char *)NULL; + } + return (temp_array); +} + +/* Find the common prefix of the list of matches, and put it into + matches[0]. */ +static int +compute_lcd_of_matches (match_list, matches, text) + char **match_list; + int matches; + const char *text; +{ + register int i, c1, c2, si; + int low; /* Count of max-matched characters. */ + char *dtext; /* dequoted TEXT, if needed */ +#if defined (HANDLE_MULTIBYTE) + int v; + mbstate_t ps1, ps2; + wchar_t wc1, wc2; +#endif + + /* If only one match, just use that. Otherwise, compare each + member of the list with the next, finding out where they + stop matching. */ + if (matches == 1) + { + match_list[0] = match_list[1]; + match_list[1] = (char *)NULL; + return 1; + } + + for (i = 1, low = 100000; i < matches; i++) + { +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + memset (&ps1, 0, sizeof (mbstate_t)); + memset (&ps2, 0, sizeof (mbstate_t)); + } +#endif + if (_rl_completion_case_fold) + { + for (si = 0; + (c1 = _rl_to_lower(match_list[i][si])) && + (c2 = _rl_to_lower(match_list[i + 1][si])); + si++) +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1); + mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2); + wc1 = towlower (wc1); + wc2 = towlower (wc2); + if (wc1 != wc2) + break; + else if (v > 1) + si += v - 1; + } + else +#endif + if (c1 != c2) + break; + } + else + { + for (si = 0; + (c1 = match_list[i][si]) && + (c2 = match_list[i + 1][si]); + si++) +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + mbstate_t ps_back; + ps_back = ps1; + if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2)) + break; + else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1) + si += v - 1; + } + else +#endif + if (c1 != c2) + break; + } + + if (low > si) + low = si; + } + + /* If there were multiple matches, but none matched up to even the + first character, and the user typed something, use that as the + value of matches[0]. */ + if (low == 0 && text && *text) + { + match_list[0] = (char *)xmalloc (strlen (text) + 1); + strcpy (match_list[0], text); + } + else + { + match_list[0] = (char *)xmalloc (low + 1); + + /* XXX - this might need changes in the presence of multibyte chars */ + + /* If we are ignoring case, try to preserve the case of the string + the user typed in the face of multiple matches differing in case. */ + if (_rl_completion_case_fold) + { + /* We're making an assumption here: + IF we're completing filenames AND + the application has defined a filename dequoting function AND + we found a quote character AND + the application has requested filename quoting + THEN + we assume that TEXT was dequoted before checking against + the file system and needs to be dequoted here before we + check against the list of matches + FI */ + dtext = (char *)NULL; + if (rl_filename_completion_desired && + rl_filename_dequoting_function && + rl_completion_found_quote && + rl_filename_quoting_desired) + { + dtext = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character); + text = dtext; + } + + /* sort the list to get consistent answers. */ + qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare); + + si = strlen (text); + if (si <= low) + { + for (i = 1; i <= matches; i++) + if (strncmp (match_list[i], text, si) == 0) + { + strncpy (match_list[0], match_list[i], low); + break; + } + /* no casematch, use first entry */ + if (i > matches) + strncpy (match_list[0], match_list[1], low); + } + else + /* otherwise, just use the text the user typed. */ + strncpy (match_list[0], text, low); + + FREE (dtext); + } + else + strncpy (match_list[0], match_list[1], low); + + match_list[0][low] = '\0'; + } + + return matches; +} + +static int +postprocess_matches (matchesp, matching_filenames) + char ***matchesp; + int matching_filenames; +{ + char *t, **matches, **temp_matches; + int nmatch, i; + + matches = *matchesp; + + if (matches == 0) + return 0; + + /* It seems to me that in all the cases we handle we would like + to ignore duplicate possiblilities. Scan for the text to + insert being identical to the other completions. */ + if (rl_ignore_completion_duplicates) + { + temp_matches = remove_duplicate_matches (matches); + xfree (matches); + matches = temp_matches; + } + + /* If we are matching filenames, then here is our chance to + do clever processing by re-examining the list. Call the + ignore function with the array as a parameter. It can + munge the array, deleting matches as it desires. */ + if (rl_ignore_some_completions_function && matching_filenames) + { + for (nmatch = 1; matches[nmatch]; nmatch++) + ; + (void)(*rl_ignore_some_completions_function) (matches); + if (matches == 0 || matches[0] == 0) + { + FREE (matches); + *matchesp = (char **)0; + return 0; + } + else + { + /* If we removed some matches, recompute the common prefix. */ + for (i = 1; matches[i]; i++) + ; + if (i > 1 && i < nmatch) + { + t = matches[0]; + compute_lcd_of_matches (matches, i - 1, t); + FREE (t); + } + } + } + + *matchesp = matches; + return (1); +} + +static int +complete_get_screenwidth () +{ + int cols; + char *envcols; + + cols = _rl_completion_columns; + if (cols >= 0 && cols <= _rl_screenwidth) + return cols; + envcols = getenv ("COLUMNS"); + if (envcols && *envcols) + cols = atoi (envcols); + if (cols >= 0 && cols <= _rl_screenwidth) + return cols; + return _rl_screenwidth; +} + +/* A convenience function for displaying a list of strings in + columnar format on readline's output stream. MATCHES is the list + of strings, in argv format, LEN is the number of strings in MATCHES, + and MAX is the length of the longest string in MATCHES. */ +void +rl_display_match_list (matches, len, max) + char **matches; + int len, max; +{ + int count, limit, printed_len, lines, cols; + int i, j, k, l, common_length, sind; + char *temp, *t; + + /* Find the length of the prefix common to all items: length as displayed + characters (common_length) and as a byte index into the matches (sind) */ + common_length = sind = 0; + if (_rl_completion_prefix_display_length > 0) + { + t = printable_part (matches[0]); + temp = strrchr (t, '/'); + common_length = temp ? fnwidth (temp) : fnwidth (t); + sind = temp ? strlen (temp) : strlen (t); + + if (common_length > _rl_completion_prefix_display_length && common_length > ELLIPSIS_LEN) + max -= common_length - ELLIPSIS_LEN; + else + common_length = sind = 0; + } + + /* How many items of MAX length can we fit in the screen window? */ + cols = complete_get_screenwidth (); + max += 2; + limit = cols / max; + if (limit != 1 && (limit * max == cols)) + limit--; + + /* If cols == 0, limit will end up -1 */ + if (cols < _rl_screenwidth && limit < 0) + limit = 1; + + /* Avoid a possible floating exception. If max > cols, + limit will be 0 and a divide-by-zero fault will result. */ + if (limit == 0) + limit = 1; + + /* How many iterations of the printing loop? */ + count = (len + (limit - 1)) / limit; + + /* Watch out for special case. If LEN is less than LIMIT, then + just do the inner printing loop. + 0 < len <= limit implies count = 1. */ + + /* Sort the items if they are not already sorted. */ + if (rl_ignore_completion_duplicates == 0 && rl_sort_completion_matches) + qsort (matches + 1, len, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); + + rl_crlf (); + + lines = 0; + if (_rl_print_completions_horizontally == 0) + { + /* Print the sorted items, up-and-down alphabetically, like ls. */ + for (i = 1; i <= count; i++) + { + for (j = 0, l = i; j < limit; j++) + { + if (l > len || matches[l] == 0) + break; + else + { + temp = printable_part (matches[l]); + printed_len = print_filename (temp, matches[l], sind); + + if (j + 1 < limit) + for (k = 0; k < max - printed_len; k++) + putc (' ', rl_outstream); + } + l += count; + } + rl_crlf (); + lines++; + if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count) + { + lines = _rl_internal_pager (lines); + if (lines < 0) + return; + } + } + } + else + { + /* Print the sorted items, across alphabetically, like ls -x. */ + for (i = 1; matches[i]; i++) + { + temp = printable_part (matches[i]); + printed_len = print_filename (temp, matches[i], sind); + /* Have we reached the end of this line? */ + if (matches[i+1]) + { + if (i && (limit > 1) && (i % limit) == 0) + { + rl_crlf (); + lines++; + if (_rl_page_completions && lines >= _rl_screenheight - 1) + { + lines = _rl_internal_pager (lines); + if (lines < 0) + return; + } + } + else + for (k = 0; k < max - printed_len; k++) + putc (' ', rl_outstream); + } + } + rl_crlf (); + } +} + +/* Display MATCHES, a list of matching filenames in argv format. This + handles the simple case -- a single match -- first. If there is more + than one match, we compute the number of strings in the list and the + length of the longest string, which will be needed by the display + function. If the application wants to handle displaying the list of + matches itself, it sets RL_COMPLETION_DISPLAY_MATCHES_HOOK to the + address of a function, and we just call it. If we're handling the + display ourselves, we just call rl_display_match_list. We also check + that the list of matches doesn't exceed the user-settable threshold, + and ask the user if he wants to see the list if there are more matches + than RL_COMPLETION_QUERY_ITEMS. */ +static void +display_matches (matches) + char **matches; +{ + int len, max, i; + char *temp; + + /* Move to the last visible line of a possibly-multiple-line command. */ + _rl_move_vert (_rl_vis_botlin); + + /* Handle simple case first. What if there is only one answer? */ + if (matches[1] == 0) + { + temp = printable_part (matches[0]); + rl_crlf (); + print_filename (temp, matches[0], 0); + rl_crlf (); + + rl_forced_update_display (); + rl_display_fixed = 1; + + return; + } + + /* There is more than one answer. Find out how many there are, + and find the maximum printed length of a single entry. */ + for (max = 0, i = 1; matches[i]; i++) + { + temp = printable_part (matches[i]); + len = fnwidth (temp); + + if (len > max) + max = len; + } + + len = i - 1; + + /* If the caller has defined a display hook, then call that now. */ + if (rl_completion_display_matches_hook) + { + (*rl_completion_display_matches_hook) (matches, len, max); + return; + } + + /* If there are many items, then ask the user if she really wants to + see them all. */ + if (rl_completion_query_items > 0 && len >= rl_completion_query_items) + { + rl_crlf (); + fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len); + fflush (rl_outstream); + if ((completion_y_or_n = get_y_or_n (0)) == 0) + { + rl_crlf (); + + rl_forced_update_display (); + rl_display_fixed = 1; + + return; + } + } + + rl_display_match_list (matches, len, max); + + rl_forced_update_display (); + rl_display_fixed = 1; +} + +static char * +make_quoted_replacement (match, mtype, qc) + char *match; + int mtype; + char *qc; /* Pointer to quoting character, if any */ +{ + int should_quote, do_replace; + char *replacement; + + /* If we are doing completion on quoted substrings, and any matches + contain any of the completer_word_break_characters, then auto- + matically prepend the substring with a quote character (just pick + the first one from the list of such) if it does not already begin + with a quote string. FIXME: Need to remove any such automatically + inserted quote character when it no longer is necessary, such as + if we change the string we are completing on and the new set of + matches don't require a quoted substring. */ + replacement = match; + + should_quote = match && rl_completer_quote_characters && + rl_filename_completion_desired && + rl_filename_quoting_desired; + + if (should_quote) + should_quote = should_quote && (!qc || !*qc || + (rl_completer_quote_characters && strchr (rl_completer_quote_characters, *qc))); + + if (should_quote) + { + /* If there is a single match, see if we need to quote it. + This also checks whether the common prefix of several + matches needs to be quoted. */ + should_quote = rl_filename_quote_characters + ? (_rl_strpbrk (match, rl_filename_quote_characters) != 0) + : 0; + + do_replace = should_quote ? mtype : NO_MATCH; + /* Quote the replacement, since we found an embedded + word break character in a potential match. */ + if (do_replace != NO_MATCH && rl_filename_quoting_function) + replacement = (*rl_filename_quoting_function) (match, do_replace, qc); + } + return (replacement); +} + +static void +insert_match (match, start, mtype, qc) + char *match; + int start, mtype; + char *qc; +{ + char *replacement, *r; + char oqc; + int end, rlen; + + oqc = qc ? *qc : '\0'; + replacement = make_quoted_replacement (match, mtype, qc); + + /* Now insert the match. */ + if (replacement) + { + rlen = strlen (replacement); + /* Don't double an opening quote character. */ + if (qc && *qc && start && rl_line_buffer[start - 1] == *qc && + replacement[0] == *qc) + start--; + /* If make_quoted_replacement changed the quoting character, remove + the opening quote and insert the (fully-quoted) replacement. */ + else if (qc && (*qc != oqc) && start && rl_line_buffer[start - 1] == oqc && + replacement[0] != oqc) + start--; + end = rl_point - 1; + /* Don't double a closing quote character */ + if (qc && *qc && end && rl_line_buffer[rl_point] == *qc && replacement[rlen - 1] == *qc) + end++; + if (_rl_skip_completed_text) + { + r = replacement; + while (start < rl_end && *r && rl_line_buffer[start] == *r) + { + start++; + r++; + } + if (start <= end || *r) + _rl_replace_text (r, start, end); + rl_point = start + strlen (r); + } + else + _rl_replace_text (replacement, start, end); + if (replacement != match) + xfree (replacement); + } +} + +/* Append any necessary closing quote and a separator character to the + just-inserted match. If the user has specified that directories + should be marked by a trailing `/', append one of those instead. The + default trailing character is a space. Returns the number of characters + appended. If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS + has them) and don't add a suffix for a symlink to a directory. A + nontrivial match is one that actually adds to the word being completed. + The variable rl_completion_mark_symlink_dirs controls this behavior + (it's initially set to the what the user has chosen, indicated by the + value of _rl_complete_mark_symlink_dirs, but may be modified by an + application's completion function). */ +static int +append_to_match (text, delimiter, quote_char, nontrivial_match) + char *text; + int delimiter, quote_char, nontrivial_match; +{ + char temp_string[4], *filename; + int temp_string_index, s; + struct stat finfo; + + temp_string_index = 0; + if (quote_char && rl_point && rl_completion_suppress_quote == 0 && + rl_line_buffer[rl_point - 1] != quote_char) + temp_string[temp_string_index++] = quote_char; + + if (delimiter) + temp_string[temp_string_index++] = delimiter; + else if (rl_completion_suppress_append == 0 && rl_completion_append_character) + temp_string[temp_string_index++] = rl_completion_append_character; + + temp_string[temp_string_index++] = '\0'; + + if (rl_filename_completion_desired) + { + filename = tilde_expand (text); + if (rl_filename_stat_hook) + (*rl_filename_stat_hook) (&filename); + s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0) + ? LSTAT (filename, &finfo) + : stat (filename, &finfo); + if (s == 0 && S_ISDIR (finfo.st_mode)) + { + if (_rl_complete_mark_directories /* && rl_completion_suppress_append == 0 */) + { + /* This is clumsy. Avoid putting in a double slash if point + is at the end of the line and the previous character is a + slash. */ + if (rl_point && rl_line_buffer[rl_point] == '\0' && rl_line_buffer[rl_point - 1] == '/') + ; + else if (rl_line_buffer[rl_point] != '/') + rl_insert_text ("/"); + } + } +#ifdef S_ISLNK + /* Don't add anything if the filename is a symlink and resolves to a + directory. */ + else if (s == 0 && S_ISLNK (finfo.st_mode) && path_isdir (filename)) + ; +#endif + else + { + if (rl_point == rl_end && temp_string_index) + rl_insert_text (temp_string); + } + xfree (filename); + } + else + { + if (rl_point == rl_end && temp_string_index) + rl_insert_text (temp_string); + } + + return (temp_string_index); +} + +static void +insert_all_matches (matches, point, qc) + char **matches; + int point; + char *qc; +{ + int i; + char *rp; + + rl_begin_undo_group (); + /* remove any opening quote character; make_quoted_replacement will add + it back. */ + if (qc && *qc && point && rl_line_buffer[point - 1] == *qc) + point--; + rl_delete_text (point, rl_point); + rl_point = point; + + if (matches[1]) + { + for (i = 1; matches[i]; i++) + { + rp = make_quoted_replacement (matches[i], SINGLE_MATCH, qc); + rl_insert_text (rp); + rl_insert_text (" "); + if (rp != matches[i]) + xfree (rp); + } + } + else + { + rp = make_quoted_replacement (matches[0], SINGLE_MATCH, qc); + rl_insert_text (rp); + rl_insert_text (" "); + if (rp != matches[0]) + xfree (rp); + } + rl_end_undo_group (); +} + +void +_rl_free_match_list (matches) + char **matches; +{ + register int i; + + if (matches == 0) + return; + + for (i = 0; matches[i]; i++) + xfree (matches[i]); + xfree (matches); +} + +/* Complete the word at or before point. + WHAT_TO_DO says what to do with the completion. + `?' means list the possible completions. + TAB means do standard completion. + `*' means insert all of the possible completions. + `!' means to do standard completion, and list all possible completions if + there is more than one. + `@' means to do standard completion, and list all possible completions if + there is more than one and partial completion is not possible. */ +int +rl_complete_internal (what_to_do) + int what_to_do; +{ + char **matches; + rl_compentry_func_t *our_func; + int start, end, delimiter, found_quote, i, nontrivial_lcd; + char *text, *saved_line_buffer; + char quote_char; +#if 1 + int tlen, mlen; +#endif + + RL_SETSTATE(RL_STATE_COMPLETING); + + set_completion_defaults (what_to_do); + + saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL; + our_func = rl_completion_entry_function + ? rl_completion_entry_function + : rl_filename_completion_function; + /* We now look backwards for the start of a filename/variable word. */ + end = rl_point; + found_quote = delimiter = 0; + quote_char = '\0'; + + if (rl_point) + /* This (possibly) changes rl_point. If it returns a non-zero char, + we know we have an open quote. */ + quote_char = _rl_find_completion_word (&found_quote, &delimiter); + + start = rl_point; + rl_point = end; + + text = rl_copy_text (start, end); + matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char); + /* nontrivial_lcd is set if the common prefix adds something to the word + being completed. */ + nontrivial_lcd = matches && strcmp (text, matches[0]) != 0; + if (what_to_do == '!' || what_to_do == '@') + tlen = strlen (text); + xfree (text); + + if (matches == 0) + { + rl_ding (); + FREE (saved_line_buffer); + completion_changed_buffer = 0; + RL_UNSETSTATE(RL_STATE_COMPLETING); + _rl_reset_completion_state (); + return (0); + } + + /* If we are matching filenames, the attempted completion function will + have set rl_filename_completion_desired to a non-zero value. The basic + rl_filename_completion_function does this. */ + i = rl_filename_completion_desired; + + if (postprocess_matches (&matches, i) == 0) + { + rl_ding (); + FREE (saved_line_buffer); + completion_changed_buffer = 0; + RL_UNSETSTATE(RL_STATE_COMPLETING); + _rl_reset_completion_state (); + return (0); + } + + switch (what_to_do) + { + case TAB: + case '!': + case '@': + /* Insert the first match with proper quoting. */ + if (what_to_do == TAB) + { + if (*matches[0]) + insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); + } + else if (*matches[0] && matches[1] == 0) + /* should we perform the check only if there are multiple matches? */ + insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); + else if (*matches[0]) /* what_to_do != TAB && multiple matches */ + { + mlen = *matches[0] ? strlen (matches[0]) : 0; + if (mlen >= tlen) + insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); + } + + /* If there are more matches, ring the bell to indicate. + If we are in vi mode, Posix.2 says to not ring the bell. + If the `show-all-if-ambiguous' variable is set, display + all the matches immediately. Otherwise, if this was the + only match, and we are hacking files, check the file to + see if it was a directory. If so, and the `mark-directories' + variable is set, add a '/' to the name. If not, and we + are at the end of the line, then add a space. */ + if (matches[1]) + { + if (what_to_do == '!') + { + display_matches (matches); + break; + } + else if (what_to_do == '@') + { + if (nontrivial_lcd == 0) + display_matches (matches); + break; + } + else if (rl_editing_mode != vi_mode) + rl_ding (); /* There are other matches remaining. */ + } + else + append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd); + + break; + + case '*': + insert_all_matches (matches, start, "e_char); + break; + + case '?': + if (rl_completion_display_matches_hook == 0) + { + _rl_sigcleanup = _rl_complete_sigcleanup; + _rl_sigcleanarg = matches; + } + display_matches (matches); + _rl_sigcleanup = 0; + _rl_sigcleanarg = 0; + break; + + default: + _rl_ttymsg ("bad value %d for what_to_do in rl_complete", what_to_do); + rl_ding (); + FREE (saved_line_buffer); + RL_UNSETSTATE(RL_STATE_COMPLETING); + _rl_free_match_list (matches); + _rl_reset_completion_state (); + return 1; + } + + _rl_free_match_list (matches); + + /* Check to see if the line has changed through all of this manipulation. */ + if (saved_line_buffer) + { + completion_changed_buffer = strcmp (rl_line_buffer, saved_line_buffer) != 0; + xfree (saved_line_buffer); + } + + RL_UNSETSTATE(RL_STATE_COMPLETING); + _rl_reset_completion_state (); + return 0; +} + +/***************************************************************/ +/* */ +/* Application-callable completion match generator functions */ +/* */ +/***************************************************************/ + +/* Return an array of (char *) which is a list of completions for TEXT. + If there are no completions, return a NULL pointer. + The first entry in the returned array is the substitution for TEXT. + The remaining entries are the possible completions. + The array is terminated with a NULL pointer. + + ENTRY_FUNCTION is a function of two args, and returns a (char *). + The first argument is TEXT. + The second is a state argument; it should be zero on the first call, and + non-zero on subsequent calls. It returns a NULL pointer to the caller + when there are no more matches. + */ +char ** +rl_completion_matches (text, entry_function) + const char *text; + rl_compentry_func_t *entry_function; +{ + register int i; + + /* Number of slots in match_list. */ + int match_list_size; + + /* The list of matches. */ + char **match_list; + + /* Number of matches actually found. */ + int matches; + + /* Temporary string binder. */ + char *string; + + matches = 0; + match_list_size = 10; + match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); + match_list[1] = (char *)NULL; + + while (string = (*entry_function) (text, matches)) + { + if (RL_SIG_RECEIVED ()) + { + /* Start at 1 because we don't set matches[0] in this function. + Only free the list members if we're building match list from + rl_filename_completion_function, since we know that doesn't + free the strings it returns. */ + if (entry_function == rl_filename_completion_function) + { + for (i = 1; match_list[i]; i++) + xfree (match_list[i]); + } + xfree (match_list); + match_list = 0; + match_list_size = 0; + RL_CHECK_SIGNALS (); + } + + if (matches + 1 == match_list_size) + match_list = (char **)xrealloc + (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); + + match_list[++matches] = string; + match_list[matches + 1] = (char *)NULL; + } + + /* If there were any matches, then look through them finding out the + lowest common denominator. That then becomes match_list[0]. */ + if (matches) + compute_lcd_of_matches (match_list, matches, text); + else /* There were no matches. */ + { + xfree (match_list); + match_list = (char **)NULL; + } + return (match_list); +} + +/* A completion function for usernames. + TEXT contains a partial username preceded by a random + character (usually `~'). */ +char * +rl_username_completion_function (text, state) + const char *text; + int state; +{ +#if defined (__WIN32__) || defined (__OPENNT) + return (char *)NULL; +#else /* !__WIN32__ && !__OPENNT) */ + static char *username = (char *)NULL; + static struct passwd *entry; + static int namelen, first_char, first_char_loc; + char *value; + + if (state == 0) + { + FREE (username); + + first_char = *text; + first_char_loc = first_char == '~'; + + username = savestring (&text[first_char_loc]); + namelen = strlen (username); + setpwent (); + } + +#if defined (HAVE_GETPWENT) + while (entry = getpwent ()) + { + /* Null usernames should result in all users as possible completions. */ + if (namelen == 0 || (STREQN (username, entry->pw_name, namelen))) + break; + } +#endif + + if (entry == 0) + { +#if defined (HAVE_GETPWENT) + endpwent (); +#endif + return ((char *)NULL); + } + else + { + value = (char *)xmalloc (2 + strlen (entry->pw_name)); + + *value = *text; + + strcpy (value + first_char_loc, entry->pw_name); + + if (first_char == '~') + rl_filename_completion_desired = 1; + + return (value); + } +#endif /* !__WIN32__ && !__OPENNT */ +} + +/* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME + (FILENAME_LEN). If _rl_completion_case_fold is set, compare without + regard to the alphabetic case of characters. CONVFN is the possibly- + converted directory entry; FILENAME is what the user typed. */ +static int +complete_fncmp (convfn, convlen, filename, filename_len) + const char *convfn; + int convlen; + const char *filename; + int filename_len; +{ + register char *s1, *s2; + int d, len; + + /* Otherwise, if these match up to the length of filename, then + it is a match. */ + if (_rl_completion_case_fold && _rl_completion_case_map) + { + /* Case-insensitive comparison treating _ and - as equivalent */ + if (filename_len == 0) + return 1; + if (convlen < filename_len) + return 0; + s1 = (char *)convfn; + s2 = (char *)filename; + len = filename_len; + do + { + d = _rl_to_lower (*s1) - _rl_to_lower (*s2); + /* *s1 == [-_] && *s2 == [-_] */ + if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_')) + d = 0; + if (d != 0) + return 0; + s1++; s2++; /* already checked convlen >= filename_len */ + } + while (--len != 0); + return 1; + } + else if (_rl_completion_case_fold) + { + if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) && + (convlen >= filename_len) && + (_rl_strnicmp (filename, convfn, filename_len) == 0)) + return 1; + } + else + { + if ((convfn[0] == filename[0]) && + (convlen >= filename_len) && + (strncmp (filename, convfn, filename_len) == 0)) + return 1; + } + return 0; +} + +/* Okay, now we write the entry_function for filename completion. In the + general case. Note that completion in the shell is a little different + because of all the pathnames that must be followed when looking up the + completion for a command. */ +char * +rl_filename_completion_function (text, state) + const char *text; + int state; +{ + static DIR *directory = (DIR *)NULL; + static char *filename = (char *)NULL; + static char *dirname = (char *)NULL; + static char *users_dirname = (char *)NULL; + static int filename_len; + char *temp, *dentry, *convfn; + int dirlen, dentlen, convlen; + struct dirent *entry; + + /* If we don't have any state, then do some initialization. */ + if (state == 0) + { + /* If we were interrupted before closing the directory or reading + all of its contents, close it. */ + if (directory) + { + closedir (directory); + directory = (DIR *)NULL; + } + FREE (dirname); + FREE (filename); + FREE (users_dirname); + + filename = savestring (text); + if (*text == 0) + text = "."; + dirname = savestring (text); + + temp = strrchr (dirname, '/'); + +#if defined (__MSDOS__) + /* special hack for //X/... */ + if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/') + temp = strrchr (dirname + 3, '/'); +#endif + + if (temp) + { + strcpy (filename, ++temp); + *temp = '\0'; + } +#if defined (__MSDOS__) + /* searches from current directory on the drive */ + else if (ISALPHA ((unsigned char)dirname[0]) && dirname[1] == ':') + { + strcpy (filename, dirname + 2); + dirname[2] = '\0'; + } +#endif + else + { + dirname[0] = '.'; + dirname[1] = '\0'; + } + + /* We aren't done yet. We also support the "~user" syntax. */ + + /* Save the version of the directory that the user typed, dequoting + it if necessary. */ + if (rl_completion_found_quote && rl_filename_dequoting_function) + users_dirname = (*rl_filename_dequoting_function) (dirname, rl_completion_quote_character); + else + users_dirname = savestring (dirname); + + if (*dirname == '~') + { + temp = tilde_expand (dirname); + xfree (dirname); + dirname = temp; + } + + /* We have saved the possibly-dequoted version of the directory name + the user typed. Now transform the directory name we're going to + pass to opendir(2). The directory rewrite hook modifies only the + directory name; the directory completion hook modifies both the + directory name passed to opendir(2) and the version the user + typed. Both the directory completion and rewrite hooks should perform + any necessary dequoting. The hook functions return 1 if they modify + the directory name argument. If either hook returns 0, it should + not modify the directory name pointer passed as an argument. */ + if (rl_directory_rewrite_hook) + (*rl_directory_rewrite_hook) (&dirname); + else if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname)) + { + xfree (users_dirname); + users_dirname = savestring (dirname); + } + else if (rl_completion_found_quote && rl_filename_dequoting_function) + { + /* delete single and double quotes */ + xfree (dirname); + dirname = savestring (users_dirname); + } + directory = opendir (dirname); + + /* Now dequote a non-null filename. FILENAME will not be NULL, but may + be empty. */ + if (*filename && rl_completion_found_quote && rl_filename_dequoting_function) + { + /* delete single and double quotes */ + temp = (*rl_filename_dequoting_function) (filename, rl_completion_quote_character); + xfree (filename); + filename = temp; + } + filename_len = strlen (filename); + + rl_filename_completion_desired = 1; + } + + /* At this point we should entertain the possibility of hacking wildcarded + filenames, like /usr/man/man/te. If the directory name + contains globbing characters, then build an array of directories, and + then map over that list while completing. */ + /* *** UNIMPLEMENTED *** */ + + /* Now that we have some state, we can read the directory. */ + + entry = (struct dirent *)NULL; + while (directory && (entry = readdir (directory))) + { + convfn = dentry = entry->d_name; + convlen = dentlen = D_NAMLEN (entry); + + if (rl_filename_rewrite_hook) + { + convfn = (*rl_filename_rewrite_hook) (dentry, dentlen); + convlen = (convfn == dentry) ? dentlen : strlen (convfn); + } + + /* Special case for no filename. If the user has disabled the + `match-hidden-files' variable, skip filenames beginning with `.'. + All other entries except "." and ".." match. */ + if (filename_len == 0) + { + if (_rl_match_hidden_files == 0 && HIDDEN_FILE (convfn)) + continue; + + if (convfn[0] != '.' || + (convfn[1] && (convfn[1] != '.' || convfn[2]))) + break; + } + else + { + if (complete_fncmp (convfn, convlen, filename, filename_len)) + break; + } + } + + if (entry == 0) + { + if (directory) + { + closedir (directory); + directory = (DIR *)NULL; + } + if (dirname) + { + xfree (dirname); + dirname = (char *)NULL; + } + if (filename) + { + xfree (filename); + filename = (char *)NULL; + } + if (users_dirname) + { + xfree (users_dirname); + users_dirname = (char *)NULL; + } + + return (char *)NULL; + } + else + { + /* dirname && (strcmp (dirname, ".") != 0) */ + if (dirname && (dirname[0] != '.' || dirname[1])) + { + if (rl_complete_with_tilde_expansion && *users_dirname == '~') + { + dirlen = strlen (dirname); + temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); + strcpy (temp, dirname); + /* Canonicalization cuts off any final slash present. We + may need to add it back. */ + if (dirname[dirlen - 1] != '/') + { + temp[dirlen++] = '/'; + temp[dirlen] = '\0'; + } + } + else + { + dirlen = strlen (users_dirname); + temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); + strcpy (temp, users_dirname); + /* Make sure that temp has a trailing slash here. */ + if (users_dirname[dirlen - 1] != '/') + temp[dirlen++] = '/'; + } + + strcpy (temp + dirlen, convfn); + } + else + temp = savestring (convfn); + + if (convfn != dentry) + xfree (convfn); + + return (temp); + } +} + +/* An initial implementation of a menu completion function a la tcsh. The + first time (if the last readline command was not rl_old_menu_complete), we + generate the list of matches. This code is very similar to the code in + rl_complete_internal -- there should be a way to combine the two. Then, + for each item in the list of matches, we insert the match in an undoable + fashion, with the appropriate character appended (this happens on the + second and subsequent consecutive calls to rl_old_menu_complete). When we + hit the end of the match list, we restore the original unmatched text, + ring the bell, and reset the counter to zero. */ +int +rl_old_menu_complete (count, invoking_key) + int count, invoking_key; +{ + rl_compentry_func_t *our_func; + int matching_filenames, found_quote; + + static char *orig_text; + static char **matches = (char **)0; + static int match_list_index = 0; + static int match_list_size = 0; + static int orig_start, orig_end; + static char quote_char; + static int delimiter; + + /* The first time through, we generate the list of matches and set things + up to insert them. */ + if (rl_last_func != rl_old_menu_complete) + { + /* Clean up from previous call, if any. */ + FREE (orig_text); + if (matches) + _rl_free_match_list (matches); + + match_list_index = match_list_size = 0; + matches = (char **)NULL; + + rl_completion_invoking_key = invoking_key; + + RL_SETSTATE(RL_STATE_COMPLETING); + + /* Only the completion entry function can change these. */ + set_completion_defaults ('%'); + + our_func = rl_menu_completion_entry_function; + if (our_func == 0) + our_func = rl_completion_entry_function + ? rl_completion_entry_function + : rl_filename_completion_function; + + /* We now look backwards for the start of a filename/variable word. */ + orig_end = rl_point; + found_quote = delimiter = 0; + quote_char = '\0'; + + if (rl_point) + /* This (possibly) changes rl_point. If it returns a non-zero char, + we know we have an open quote. */ + quote_char = _rl_find_completion_word (&found_quote, &delimiter); + + orig_start = rl_point; + rl_point = orig_end; + + orig_text = rl_copy_text (orig_start, orig_end); + matches = gen_completion_matches (orig_text, orig_start, orig_end, + our_func, found_quote, quote_char); + + /* If we are matching filenames, the attempted completion function will + have set rl_filename_completion_desired to a non-zero value. The basic + rl_filename_completion_function does this. */ + matching_filenames = rl_filename_completion_desired; + + if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0) + { + rl_ding (); + FREE (matches); + matches = (char **)0; + FREE (orig_text); + orig_text = (char *)0; + completion_changed_buffer = 0; + RL_UNSETSTATE(RL_STATE_COMPLETING); + return (0); + } + + RL_UNSETSTATE(RL_STATE_COMPLETING); + + for (match_list_size = 0; matches[match_list_size]; match_list_size++) + ; + /* matches[0] is lcd if match_list_size > 1, but the circular buffer + code below should take care of it. */ + + if (match_list_size > 1 && _rl_complete_show_all) + display_matches (matches); + } + + /* Now we have the list of matches. Replace the text between + rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with + matches[match_list_index], and add any necessary closing char. */ + + if (matches == 0 || match_list_size == 0) + { + rl_ding (); + FREE (matches); + matches = (char **)0; + completion_changed_buffer = 0; + return (0); + } + + match_list_index += count; + if (match_list_index < 0) + { + while (match_list_index < 0) + match_list_index += match_list_size; + } + else + match_list_index %= match_list_size; + + if (match_list_index == 0 && match_list_size > 1) + { + rl_ding (); + insert_match (orig_text, orig_start, MULT_MATCH, "e_char); + } + else + { + insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char); + append_to_match (matches[match_list_index], delimiter, quote_char, + strcmp (orig_text, matches[match_list_index])); + } + + completion_changed_buffer = 1; + return (0); +} + +int +rl_menu_complete (count, ignore) + int count, ignore; +{ + rl_compentry_func_t *our_func; + int matching_filenames, found_quote; + + static char *orig_text; + static char **matches = (char **)0; + static int match_list_index = 0; + static int match_list_size = 0; + static int nontrivial_lcd = 0; + static int full_completion = 0; /* set to 1 if menu completion should reinitialize on next call */ + static int orig_start, orig_end; + static char quote_char; + static int delimiter, cstate; + + /* The first time through, we generate the list of matches and set things + up to insert them. */ + if ((rl_last_func != rl_menu_complete && rl_last_func != rl_backward_menu_complete) || full_completion) + { + /* Clean up from previous call, if any. */ + FREE (orig_text); + if (matches) + _rl_free_match_list (matches); + + match_list_index = match_list_size = 0; + matches = (char **)NULL; + + full_completion = 0; + + RL_SETSTATE(RL_STATE_COMPLETING); + + /* Only the completion entry function can change these. */ + set_completion_defaults ('%'); + + our_func = rl_menu_completion_entry_function; + if (our_func == 0) + our_func = rl_completion_entry_function + ? rl_completion_entry_function + : rl_filename_completion_function; + + /* We now look backwards for the start of a filename/variable word. */ + orig_end = rl_point; + found_quote = delimiter = 0; + quote_char = '\0'; + + if (rl_point) + /* This (possibly) changes rl_point. If it returns a non-zero char, + we know we have an open quote. */ + quote_char = _rl_find_completion_word (&found_quote, &delimiter); + + orig_start = rl_point; + rl_point = orig_end; + + orig_text = rl_copy_text (orig_start, orig_end); + matches = gen_completion_matches (orig_text, orig_start, orig_end, + our_func, found_quote, quote_char); + + nontrivial_lcd = matches && strcmp (orig_text, matches[0]) != 0; + + /* If we are matching filenames, the attempted completion function will + have set rl_filename_completion_desired to a non-zero value. The basic + rl_filename_completion_function does this. */ + matching_filenames = rl_filename_completion_desired; + + if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0) + { + rl_ding (); + FREE (matches); + matches = (char **)0; + FREE (orig_text); + orig_text = (char *)0; + completion_changed_buffer = 0; + RL_UNSETSTATE(RL_STATE_COMPLETING); + return (0); + } + + RL_UNSETSTATE(RL_STATE_COMPLETING); + + for (match_list_size = 0; matches[match_list_size]; match_list_size++) + ; + + if (match_list_size == 0) + { + rl_ding (); + FREE (matches); + matches = (char **)0; + match_list_index = 0; + completion_changed_buffer = 0; + return (0); + } + + /* matches[0] is lcd if match_list_size > 1, but the circular buffer + code below should take care of it. */ + if (*matches[0]) + { + insert_match (matches[0], orig_start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); + orig_end = orig_start + strlen (matches[0]); + completion_changed_buffer = STREQ (orig_text, matches[0]) == 0; + } + + if (match_list_size > 1 && _rl_complete_show_all) + { + display_matches (matches); + /* If there are so many matches that the user has to be asked + whether or not he wants to see the matches, menu completion + is unwieldy. */ + if (rl_completion_query_items > 0 && match_list_size >= rl_completion_query_items) + { + rl_ding (); + FREE (matches); + matches = (char **)0; + full_completion = 1; + return (0); + } + } + else if (match_list_size <= 1) + { + append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd); + full_completion = 1; + return (0); + } + else if (_rl_menu_complete_prefix_first && match_list_size > 1) + { + rl_ding (); + return (0); + } + } + + /* Now we have the list of matches. Replace the text between + rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with + matches[match_list_index], and add any necessary closing char. */ + + if (matches == 0 || match_list_size == 0) + { + rl_ding (); + FREE (matches); + matches = (char **)0; + completion_changed_buffer = 0; + return (0); + } + + match_list_index += count; + if (match_list_index < 0) + { + while (match_list_index < 0) + match_list_index += match_list_size; + } + else + match_list_index %= match_list_size; + + if (match_list_index == 0 && match_list_size > 1) + { + rl_ding (); + insert_match (matches[0], orig_start, MULT_MATCH, "e_char); + } + else + { + insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char); + append_to_match (matches[match_list_index], delimiter, quote_char, + strcmp (orig_text, matches[match_list_index])); + } + + completion_changed_buffer = 1; + return (0); +} + +int +rl_backward_menu_complete (count, key) + int count, key; +{ + /* Positive arguments to backward-menu-complete translate into negative + arguments for menu-complete, and vice versa. */ + return (rl_menu_complete (-count, key)); +} diff --git a/lib/readline/doc/Makefile.old b/lib/readline/doc/Makefile.old new file mode 100644 index 000000000..58d4dd762 --- /dev/null +++ b/lib/readline/doc/Makefile.old @@ -0,0 +1,76 @@ +# This makefile for Readline library documentation is in -*- text -*- mode. +# Emacs likes it that way. +RM = rm -f + +MAKEINFO = makeinfo +TEXI2DVI = texi2dvi +TEXI2HTML = texi2html +QUIETPS = #set this to -q to shut up dvips +DVIPS = dvips -D 300 $(QUIETPS) -o $@ # tricky + +INSTALL_DATA = cp +infodir = /usr/local/info + +RLSRC = rlman.texinfo rluser.texinfo rltech.texinfo +HISTSRC = hist.texinfo hsuser.texinfo hstech.texinfo + +DVIOBJ = readline.dvi history.dvi +INFOOBJ = readline.info history.info +PSOBJ = readline.ps history.ps +HTMLOBJ = readline.html history.html + +all: info dvi html ps +nodvi: info html + +readline.dvi: $(RLSRC) + $(TEXI2DVI) rlman.texinfo + mv rlman.dvi readline.dvi + +readline.info: $(RLSRC) + $(MAKEINFO) --no-split -o $@ rlman.texinfo + +history.dvi: ${HISTSRC} + $(TEXI2DVI) hist.texinfo + mv hist.dvi history.dvi + +history.info: ${HISTSRC} + $(MAKEINFO) --no-split -o $@ hist.texinfo + +readline.ps: readline.dvi + $(RM) $@ + $(DVIPS) readline.dvi + +history.ps: history.dvi + $(RM) $@ + $(DVIPS) history.dvi + +readline.html: ${RLSRC} + $(TEXI2HTML) rlman.texinfo + sed -e 's:rlman.html:readline.html:' -e 's:rlman_toc.html:readline_toc.html:' rlman.html > readline.html + sed -e 's:rlman.html:readline.html:' -e 's:rlman_toc.html:readline_toc.html:' rlman_toc.html > readline_toc.html + $(RM) rlman.html rlman_toc.html + +history.html: ${HISTSRC} + $(TEXI2HTML) hist.texinfo + sed -e 's:hist.html:history.html:' -e 's:hist_toc.html:history_toc.html:' hist.html > history.html + sed -e 's:hist.html:history.html:' -e 's:hist_toc.html:history_toc.html:' hist_toc.html > history_toc.html + $(RM) hist.html hist_toc.html + +info: $(INFOOBJ) +dvi: $(DVIOBJ) +ps: $(PSOBJ) +html: $(HTMLOBJ) + +clean: + $(RM) *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \ + *.fns *.kys *.tps *.vrs *.o core + +distclean: clean +mostlyclean: clean + +maintainer-clean: clean + $(RM) *.dvi *.info *.info-* *.ps *.html + +install: info + ${INSTALL_DATA} readline.info $(infodir)/readline.info + ${INSTALL_DATA} history.info $(infodir)/history.info diff --git a/subst.c b/subst.c index d6928cdc5..fea3127f6 100644 --- a/subst.c +++ b/subst.c @@ -8159,6 +8159,14 @@ add_string: temp = tword ? tword->word : (char *)NULL; dispose_word_desc (tword); + /* Kill quoted nulls; we will add them back at the end of + expand_word_internal if nothing else in the string */ + if (had_quoted_null && temp && QUOTED_NULL (temp)) + { + FREE (temp); + temp = (char *)NULL; + } + goto add_string; break; @@ -8313,7 +8321,7 @@ add_twochars: dequote_list (list); if (list && list->word && (list->word->flags & W_HASQUOTEDNULL)) - had_quoted_null = 1; + had_quoted_null = 1; /* XXX */ if (has_dollar_at) { @@ -8383,7 +8391,7 @@ add_twochars: temp = (char *)NULL; /* We do not want to add quoted nulls to strings that are only - partially quoted; we can throw them away. The execption to + partially quoted; we can throw them away. The exception to this is when we are going to be performing word splitting, since we have to preserve a null argument if the next character will cause word splitting. */ @@ -8567,7 +8575,7 @@ finished_with_string: tword->flags |= W_NOEXPAND; /* XXX */ if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) tword->flags |= W_QUOTED; - if (had_quoted_null) + if (had_quoted_null && QUOTED_NULL (istring)) tword->flags |= W_HASQUOTEDNULL; list = make_word_list (tword, (WORD_LIST *)NULL); } @@ -8598,7 +8606,7 @@ finished_with_string: tword->flags |= W_NOGLOB; if (word->flags & W_NOEXPAND) tword->flags |= W_NOEXPAND; - if (had_quoted_null) + if (had_quoted_null && QUOTED_NULL (istring)) tword->flags |= W_HASQUOTEDNULL; /* XXX */ list = make_word_list (tword, (WORD_LIST *)NULL); } diff --git a/subst.c~ b/subst.c~ new file mode 100644 index 000000000..1904f9ba7 --- /dev/null +++ b/subst.c~ @@ -0,0 +1,9439 @@ +/* subst.c -- The part of the shell that does parameter, command, arithmetic, + and globbing substitutions. */ + +/* ``Have a little faith, there's magic in the night. You ain't a + beauty, but, hey, you're alright.'' */ + +/* Copyright (C) 1987-2012 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bash. If not, see . +*/ + +#include "config.h" + +#include "bashtypes.h" +#include +#include "chartypes.h" +#if defined (HAVE_PWD_H) +# include +#endif +#include +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include "bashansi.h" +#include "posixstat.h" +#include "bashintl.h" + +#include "shell.h" +#include "parser.h" +#include "flags.h" +#include "jobs.h" +#include "execute_cmd.h" +#include "filecntl.h" +#include "trap.h" +#include "pathexp.h" +#include "mailcheck.h" + +#include "shmbutil.h" +#include "typemax.h" + +#include "builtins/getopt.h" +#include "builtins/common.h" + +#include "builtins/builtext.h" + +#include +#include + +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +/* The size that strings change by. */ +#define DEFAULT_INITIAL_ARRAY_SIZE 112 +#define DEFAULT_ARRAY_SIZE 128 + +/* Variable types. */ +#define VT_VARIABLE 0 +#define VT_POSPARMS 1 +#define VT_ARRAYVAR 2 +#define VT_ARRAYMEMBER 3 +#define VT_ASSOCVAR 4 + +#define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */ + +/* Flags for quoted_strchr */ +#define ST_BACKSL 0x01 +#define ST_CTLESC 0x02 +#define ST_SQUOTE 0x04 /* unused yet */ +#define ST_DQUOTE 0x08 /* unused yet */ + +/* Flags for the `pflags' argument to param_expand() */ +#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */ +#define PF_IGNUNBOUND 0x02 /* ignore unbound vars even if -u set */ +#define PF_NOSPLIT2 0x04 /* same as W_NOSPLIT2 */ +#define PF_ASSIGNRHS 0x08 /* same as W_ASSIGNRHS */ + +/* These defs make it easier to use the editor. */ +#define LBRACE '{' +#define RBRACE '}' +#define LPAREN '(' +#define RPAREN ')' + +#if defined (HANDLE_MULTIBYTE) +#define WLPAREN L'(' +#define WRPAREN L')' +#endif + +/* Evaluates to 1 if C is one of the shell's special parameters whose length + can be taken, but is also one of the special expansion characters. */ +#define VALID_SPECIAL_LENGTH_PARAM(c) \ + ((c) == '-' || (c) == '?' || (c) == '#') + +/* Evaluates to 1 if C is one of the shell's special parameters for which an + indirect variable reference may be made. */ +#define VALID_INDIR_PARAM(c) \ + ((posixly_correct == 0 && (c) == '#') || (posixly_correct == 0 && (c) == '?') || (c) == '@' || (c) == '*') + +/* Evaluates to 1 if C is one of the OP characters that follows the parameter + in ${parameter[:]OPword}. */ +#define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP) + +/* Evaluates to 1 if this is one of the shell's special variables. */ +#define SPECIAL_VAR(name, wi) \ + ((DIGIT (*name) && all_digits (name)) || \ + (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \ + (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1]))) + +/* An expansion function that takes a string and a quoted flag and returns + a WORD_LIST *. Used as the type of the third argument to + expand_string_if_necessary(). */ +typedef WORD_LIST *EXPFUNC __P((char *, int)); + +/* Process ID of the last command executed within command substitution. */ +pid_t last_command_subst_pid = NO_PID; +pid_t current_command_subst_pid = NO_PID; + +/* Variables used to keep track of the characters in IFS. */ +SHELL_VAR *ifs_var; +char *ifs_value; +unsigned char ifs_cmap[UCHAR_MAX + 1]; + +#if defined (HANDLE_MULTIBYTE) +unsigned char ifs_firstc[MB_LEN_MAX]; +size_t ifs_firstc_len; +#else +unsigned char ifs_firstc; +#endif + +/* Sentinel to tell when we are performing variable assignments preceding a + command name and putting them into the environment. Used to make sure + we use the temporary environment when looking up variable values. */ +int assigning_in_environment; + +/* Used to hold a list of variable assignments preceding a command. Global + so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a + SIGCHLD trap and so it can be saved and restored by the trap handlers. */ +WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL; + +/* Extern functions and variables from different files. */ +extern int last_command_exit_value, last_command_exit_signal; +extern int subshell_environment, line_number; +extern int subshell_level, parse_and_execute_level, sourcelevel; +extern int eof_encountered; +extern int return_catch_flag, return_catch_value; +extern pid_t dollar_dollar_pid; +extern int posixly_correct; +extern char *this_command_name; +extern struct fd_bitmap *current_fds_to_close; +extern int wordexp_only; +extern int expanding_redir; +extern int tempenv_assign_error; + +#if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE) +extern wchar_t *wcsdup __P((const wchar_t *)); +#endif + +/* Non-zero means to allow unmatched globbed filenames to expand to + a null file. */ +int allow_null_glob_expansion; + +/* Non-zero means to throw an error when globbing fails to match anything. */ +int fail_glob_expansion; + +#if 0 +/* Variables to keep track of which words in an expanded word list (the + output of expand_word_list_internal) are the result of globbing + expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c. + (CURRENTLY UNUSED). */ +char *glob_argv_flags; +static int glob_argv_flags_size; +#endif + +static WORD_LIST expand_word_error, expand_word_fatal; +static WORD_DESC expand_wdesc_error, expand_wdesc_fatal; +static char expand_param_error, expand_param_fatal; +static char extract_string_error, extract_string_fatal; + +/* Tell the expansion functions to not longjmp back to top_level on fatal + errors. Enabled when doing completion and prompt string expansion. */ +static int no_longjmp_on_fatal_error = 0; + +/* Set by expand_word_unsplit; used to inhibit splitting and re-joining + $* on $IFS, primarily when doing assignment statements. */ +static int expand_no_split_dollar_star = 0; + +/* A WORD_LIST of words to be expanded by expand_word_list_internal, + without any leading variable assignments. */ +static WORD_LIST *garglist = (WORD_LIST *)NULL; + +static char *quoted_substring __P((char *, int, int)); +static int quoted_strlen __P((char *)); +static char *quoted_strchr __P((char *, int, int)); + +static char *expand_string_if_necessary __P((char *, int, EXPFUNC *)); +static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *)); +static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *)); +static WORD_LIST *expand_string_internal __P((char *, int)); +static WORD_LIST *expand_string_leave_quoted __P((char *, int)); +static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *)); + +static WORD_LIST *list_quote_escapes __P((WORD_LIST *)); +static char *make_quoted_char __P((int)); +static WORD_LIST *quote_list __P((WORD_LIST *)); + +static int unquoted_substring __P((char *, char *)); +static int unquoted_member __P((int, char *)); + +#if defined (ARRAY_VARS) +static SHELL_VAR *do_compound_assignment __P((char *, char *, int)); +#endif +static int do_assignment_internal __P((const WORD_DESC *, int)); + +static char *string_extract_verbatim __P((char *, size_t, int *, char *, int)); +static char *string_extract __P((char *, int *, char *, int)); +static char *string_extract_double_quoted __P((char *, int *, int)); +static inline char *string_extract_single_quoted __P((char *, int *)); +static inline int skip_single_quoted __P((const char *, size_t, int)); +static int skip_double_quoted __P((char *, size_t, int)); +static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int)); +static char *extract_dollar_brace_string __P((char *, int *, int, int)); +static int skip_matched_pair __P((const char *, int, int, int, int)); + +static char *pos_params __P((char *, int, int, int)); + +static unsigned char *mb_getcharlens __P((char *, int)); + +static char *remove_upattern __P((char *, char *, int)); +#if defined (HANDLE_MULTIBYTE) +static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int)); +#endif +static char *remove_pattern __P((char *, char *, int)); + +static int match_upattern __P((char *, char *, int, char **, char **)); +#if defined (HANDLE_MULTIBYTE) +static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **)); +#endif +static int match_pattern __P((char *, char *, int, char **, char **)); +static int getpatspec __P((int, char *)); +static char *getpattern __P((char *, int, int)); +static char *variable_remove_pattern __P((char *, char *, int, int)); +static char *list_remove_pattern __P((WORD_LIST *, char *, int, int, int)); +static char *parameter_list_remove_pattern __P((int, char *, int, int)); +#ifdef ARRAY_VARS +static char *array_remove_pattern __P((SHELL_VAR *, char *, int, char *, int)); +#endif +static char *parameter_brace_remove_pattern __P((char *, char *, int, char *, int, int, int)); + +static char *process_substitute __P((char *, int)); + +static char *read_comsub __P((int, int, int *)); + +#ifdef ARRAY_VARS +static arrayind_t array_length_reference __P((char *)); +#endif + +static int valid_brace_expansion_word __P((char *, int)); +static int chk_atstar __P((char *, int, int *, int *)); +static int chk_arithsub __P((const char *, int)); + +static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int, arrayind_t *)); +static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *)); +static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *)); +static void parameter_brace_expand_error __P((char *, char *)); + +static int valid_length_expression __P((char *)); +static intmax_t parameter_brace_expand_length __P((char *)); + +static char *skiparith __P((char *, int)); +static int verify_substring_values __P((SHELL_VAR *, char *, char *, int, intmax_t *, intmax_t *)); +static int get_var_and_type __P((char *, char *, arrayind_t, int, int, SHELL_VAR **, char **)); +static char *mb_substring __P((char *, int, int)); +static char *parameter_brace_substring __P((char *, char *, int, char *, int, int)); + +static int shouldexp_replacement __P((char *)); + +static char *pos_params_pat_subst __P((char *, char *, char *, int)); + +static char *parameter_brace_patsub __P((char *, char *, int, char *, int, int)); + +static char *pos_params_casemod __P((char *, char *, int, int)); +static char *parameter_brace_casemod __P((char *, char *, int, int, char *, int, int)); + +static WORD_DESC *parameter_brace_expand __P((char *, int *, int, int, int *, int *)); +static WORD_DESC *param_expand __P((char *, int *, int, int *, int *, int *, int *, int)); + +static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *)); + +static WORD_LIST *word_list_split __P((WORD_LIST *)); + +static void exp_jump_to_top_level __P((int)); + +static WORD_LIST *separate_out_assignments __P((WORD_LIST *)); +static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int)); +#ifdef BRACE_EXPANSION +static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int)); +#endif +#if defined (ARRAY_VARS) +static int make_internal_declare __P((char *, char *)); +#endif +static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int)); +static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int)); + +/* **************************************************************** */ +/* */ +/* Utility Functions */ +/* */ +/* **************************************************************** */ + +#if defined (DEBUG) +void +dump_word_flags (flags) + int flags; +{ + int f; + + f = flags; + fprintf (stderr, "%d -> ", f); + if (f & W_ASSIGNASSOC) + { + f &= ~W_ASSIGNASSOC; + fprintf (stderr, "W_ASSIGNASSOC%s", f ? "|" : ""); + } + if (f & W_HASCTLESC) + { + f &= ~W_HASCTLESC; + fprintf (stderr, "W_HASCTLESC%s", f ? "|" : ""); + } + if (f & W_NOPROCSUB) + { + f &= ~W_NOPROCSUB; + fprintf (stderr, "W_NOPROCSUB%s", f ? "|" : ""); + } + if (f & W_DQUOTE) + { + f &= ~W_DQUOTE; + fprintf (stderr, "W_DQUOTE%s", f ? "|" : ""); + } + if (f & W_HASQUOTEDNULL) + { + f &= ~W_HASQUOTEDNULL; + fprintf (stderr, "W_HASQUOTEDNULL%s", f ? "|" : ""); + } + if (f & W_ASSIGNARG) + { + f &= ~W_ASSIGNARG; + fprintf (stderr, "W_ASSIGNARG%s", f ? "|" : ""); + } + if (f & W_ASSNBLTIN) + { + f &= ~W_ASSNBLTIN; + fprintf (stderr, "W_ASSNBLTIN%s", f ? "|" : ""); + } + if (f & W_ASSNGLOBAL) + { + f &= ~W_ASSNGLOBAL; + fprintf (stderr, "W_ASSNGLOBAL%s", f ? "|" : ""); + } + if (f & W_COMPASSIGN) + { + f &= ~W_COMPASSIGN; + fprintf (stderr, "W_COMPASSIGN%s", f ? "|" : ""); + } + if (f & W_NOEXPAND) + { + f &= ~W_NOEXPAND; + fprintf (stderr, "W_NOEXPAND%s", f ? "|" : ""); + } + if (f & W_ITILDE) + { + f &= ~W_ITILDE; + fprintf (stderr, "W_ITILDE%s", f ? "|" : ""); + } + if (f & W_NOTILDE) + { + f &= ~W_NOTILDE; + fprintf (stderr, "W_NOTILDE%s", f ? "|" : ""); + } + if (f & W_ASSIGNRHS) + { + f &= ~W_ASSIGNRHS; + fprintf (stderr, "W_ASSIGNRHS%s", f ? "|" : ""); + } + if (f & W_NOCOMSUB) + { + f &= ~W_NOCOMSUB; + fprintf (stderr, "W_NOCOMSUB%s", f ? "|" : ""); + } + if (f & W_DOLLARSTAR) + { + f &= ~W_DOLLARSTAR; + fprintf (stderr, "W_DOLLARSTAR%s", f ? "|" : ""); + } + if (f & W_DOLLARAT) + { + f &= ~W_DOLLARAT; + fprintf (stderr, "W_DOLLARAT%s", f ? "|" : ""); + } + if (f & W_TILDEEXP) + { + f &= ~W_TILDEEXP; + fprintf (stderr, "W_TILDEEXP%s", f ? "|" : ""); + } + if (f & W_NOSPLIT2) + { + f &= ~W_NOSPLIT2; + fprintf (stderr, "W_NOSPLIT2%s", f ? "|" : ""); + } + if (f & W_NOGLOB) + { + f &= ~W_NOGLOB; + fprintf (stderr, "W_NOGLOB%s", f ? "|" : ""); + } + if (f & W_NOSPLIT) + { + f &= ~W_NOSPLIT; + fprintf (stderr, "W_NOSPLIT%s", f ? "|" : ""); + } + if (f & W_GLOBEXP) + { + f &= ~W_GLOBEXP; + fprintf (stderr, "W_GLOBEXP%s", f ? "|" : ""); + } + if (f & W_ASSIGNMENT) + { + f &= ~W_ASSIGNMENT; + fprintf (stderr, "W_ASSIGNMENT%s", f ? "|" : ""); + } + if (f & W_QUOTED) + { + f &= ~W_QUOTED; + fprintf (stderr, "W_QUOTED%s", f ? "|" : ""); + } + if (f & W_HASDOLLAR) + { + f &= ~W_HASDOLLAR; + fprintf (stderr, "W_HASDOLLAR%s", f ? "|" : ""); + } + fprintf (stderr, "\n"); + fflush (stderr); +} +#endif + +#ifdef INCLUDE_UNUSED +static char * +quoted_substring (string, start, end) + char *string; + int start, end; +{ + register int len, l; + register char *result, *s, *r; + + len = end - start; + + /* Move to string[start], skipping quoted characters. */ + for (s = string, l = 0; *s && l < start; ) + { + if (*s == CTLESC) + { + s++; + continue; + } + l++; + if (*s == 0) + break; + } + + r = result = (char *)xmalloc (2*len + 1); /* save room for quotes */ + + /* Copy LEN characters, including quote characters. */ + s = string + l; + for (l = 0; l < len; s++) + { + if (*s == CTLESC) + *r++ = *s++; + *r++ = *s; + l++; + if (*s == 0) + break; + } + *r = '\0'; + return result; +} +#endif + +#ifdef INCLUDE_UNUSED +/* Return the length of S, skipping over quoted characters */ +static int +quoted_strlen (s) + char *s; +{ + register char *p; + int i; + + i = 0; + for (p = s; *p; p++) + { + if (*p == CTLESC) + { + p++; + if (*p == 0) + return (i + 1); + } + i++; + } + + return i; +} +#endif + +/* Find the first occurrence of character C in string S, obeying shell + quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped + characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters + escaped with CTLESC are skipped. */ +static char * +quoted_strchr (s, c, flags) + char *s; + int c, flags; +{ + register char *p; + + for (p = s; *p; p++) + { + if (((flags & ST_BACKSL) && *p == '\\') + || ((flags & ST_CTLESC) && *p == CTLESC)) + { + p++; + if (*p == '\0') + return ((char *)NULL); + continue; + } + else if (*p == c) + return p; + } + return ((char *)NULL); +} + +/* Return 1 if CHARACTER appears in an unquoted portion of + STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */ +static int +unquoted_member (character, string) + int character; + char *string; +{ + size_t slen; + int sindex, c; + DECLARE_MBSTATE; + + slen = strlen (string); + sindex = 0; + while (c = string[sindex]) + { + if (c == character) + return (1); + + switch (c) + { + default: + ADVANCE_CHAR (string, slen, sindex); + break; + + case '\\': + sindex++; + if (string[sindex]) + ADVANCE_CHAR (string, slen, sindex); + break; + + case '\'': + sindex = skip_single_quoted (string, slen, ++sindex); + break; + + case '"': + sindex = skip_double_quoted (string, slen, ++sindex); + break; + } + } + return (0); +} + +/* Return 1 if SUBSTR appears in an unquoted portion of STRING. */ +static int +unquoted_substring (substr, string) + char *substr, *string; +{ + size_t slen; + int sindex, c, sublen; + DECLARE_MBSTATE; + + if (substr == 0 || *substr == '\0') + return (0); + + slen = strlen (string); + sublen = strlen (substr); + for (sindex = 0; c = string[sindex]; ) + { + if (STREQN (string + sindex, substr, sublen)) + return (1); + + switch (c) + { + case '\\': + sindex++; + if (string[sindex]) + ADVANCE_CHAR (string, slen, sindex); + break; + + case '\'': + sindex = skip_single_quoted (string, slen, ++sindex); + break; + + case '"': + sindex = skip_double_quoted (string, slen, ++sindex); + break; + + default: + ADVANCE_CHAR (string, slen, sindex); + break; + } + } + return (0); +} + +/* Most of the substitutions must be done in parallel. In order + to avoid using tons of unclear goto's, I have some functions + for manipulating malloc'ed strings. They all take INDX, a + pointer to an integer which is the offset into the string + where manipulation is taking place. They also take SIZE, a + pointer to an integer which is the current length of the + character array for this string. */ + +/* Append SOURCE to TARGET at INDEX. SIZE is the current amount + of space allocated to TARGET. SOURCE can be NULL, in which + case nothing happens. Gets rid of SOURCE by freeing it. + Returns TARGET in case the location has changed. */ +INLINE char * +sub_append_string (source, target, indx, size) + char *source, *target; + int *indx, *size; +{ + if (source) + { + int srclen, n; + + srclen = STRLEN (source); + if (srclen >= (int)(*size - *indx)) + { + n = srclen + *indx; + n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE); + target = (char *)xrealloc (target, (*size = n)); + } + + FASTCOPY (source, target + *indx, srclen); + *indx += srclen; + target[*indx] = '\0'; + + free (source); + } + return (target); +} + +#if 0 +/* UNUSED */ +/* Append the textual representation of NUMBER to TARGET. + INDX and SIZE are as in SUB_APPEND_STRING. */ +char * +sub_append_number (number, target, indx, size) + intmax_t number; + int *indx, *size; + char *target; +{ + char *temp; + + temp = itos (number); + return (sub_append_string (temp, target, indx, size)); +} +#endif + +/* Extract a substring from STRING, starting at SINDEX and ending with + one of the characters in CHARLIST. Don't make the ending character + part of the string. Leave SINDEX pointing at the ending character. + Understand about backslashes in the string. If (flags & SX_VARNAME) + is non-zero, and array variables have been compiled into the shell, + everything between a `[' and a corresponding `]' is skipped over. + If (flags & SX_NOALLOC) is non-zero, don't return the substring, just + update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must + contain a closing character from CHARLIST. */ +static char * +string_extract (string, sindex, charlist, flags) + char *string; + int *sindex; + char *charlist; + int flags; +{ + register int c, i; + int found; + size_t slen; + char *temp; + DECLARE_MBSTATE; + + slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0; + i = *sindex; + found = 0; + while (c = string[i]) + { + if (c == '\\') + { + if (string[i + 1]) + i++; + else + break; + } +#if defined (ARRAY_VARS) + else if ((flags & SX_VARNAME) && c == '[') + { + int ni; + /* If this is an array subscript, skip over it and continue. */ + ni = skipsubscript (string, i, 0); + if (string[ni] == ']') + i = ni; + } +#endif + else if (MEMBER (c, charlist)) + { + found = 1; + break; + } + + ADVANCE_CHAR (string, slen, i); + } + + /* If we had to have a matching delimiter and didn't find one, return an + error and let the caller deal with it. */ + if ((flags & SX_REQMATCH) && found == 0) + { + *sindex = i; + return (&extract_string_error); + } + + temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i); + *sindex = i; + + return (temp); +} + +/* Extract the contents of STRING as if it is enclosed in double quotes. + SINDEX, when passed in, is the offset of the character immediately + following the opening double quote; on exit, SINDEX is left pointing after + the closing double quote. If STRIPDQ is non-zero, unquoted double + quotes are stripped and the string is terminated by a null byte. + Backslashes between the embedded double quotes are processed. If STRIPDQ + is zero, an unquoted `"' terminates the string. */ +static char * +string_extract_double_quoted (string, sindex, stripdq) + char *string; + int *sindex, stripdq; +{ + size_t slen; + char *send; + int j, i, t; + unsigned char c; + char *temp, *ret; /* The new string we return. */ + int pass_next, backquote, si; /* State variables for the machine. */ + int dquote; + DECLARE_MBSTATE; + + slen = strlen (string + *sindex) + *sindex; + send = string + slen; + + pass_next = backquote = dquote = 0; + temp = (char *)xmalloc (1 + slen - *sindex); + + j = 0; + i = *sindex; + while (c = string[i]) + { + /* Process a character that was quoted by a backslash. */ + if (pass_next) + { + /* XXX - take another look at this in light of Interp 221 */ + /* Posix.2 sez: + + ``The backslash shall retain its special meaning as an escape + character only when followed by one of the characters: + $ ` " \ ''. + + If STRIPDQ is zero, we handle the double quotes here and let + expand_word_internal handle the rest. If STRIPDQ is non-zero, + we have already been through one round of backslash stripping, + and want to strip these backslashes only if DQUOTE is non-zero, + indicating that we are inside an embedded double-quoted string. */ + + /* If we are in an embedded quoted string, then don't strip + backslashes before characters for which the backslash + retains its special meaning, but remove backslashes in + front of other characters. If we are not in an + embedded quoted string, don't strip backslashes at all. + This mess is necessary because the string was already + surrounded by double quotes (and sh has some really weird + quoting rules). + The returned string will be run through expansion as if + it were double-quoted. */ + if ((stripdq == 0 && c != '"') || + (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0))) + temp[j++] = '\\'; + pass_next = 0; + +add_one_character: + COPY_CHAR_I (temp, j, string, send, i); + continue; + } + + /* A backslash protects the next character. The code just above + handles preserving the backslash in front of any character but + a double quote. */ + if (c == '\\') + { + pass_next++; + i++; + continue; + } + + /* Inside backquotes, ``the portion of the quoted string from the + initial backquote and the characters up to the next backquote + that is not preceded by a backslash, having escape characters + removed, defines that command''. */ + if (backquote) + { + if (c == '`') + backquote = 0; + temp[j++] = c; + i++; + continue; + } + + if (c == '`') + { + temp[j++] = c; + backquote++; + i++; + continue; + } + + /* Pass everything between `$(' and the matching `)' or a quoted + ${ ... } pair through according to the Posix.2 specification. */ + if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE))) + { + int free_ret = 1; + + si = i + 2; + if (string[i + 1] == LPAREN) + ret = extract_command_subst (string, &si, 0); + else + ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, 0); + + temp[j++] = '$'; + temp[j++] = string[i + 1]; + + /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error + is set. */ + if (ret == 0 && no_longjmp_on_fatal_error) + { + free_ret = 0; + ret = string + i + 2; + } + + for (t = 0; ret[t]; t++, j++) + temp[j] = ret[t]; + temp[j] = string[si]; + + if (string[si]) + { + j++; + i = si + 1; + } + else + i = si; + + if (free_ret) + free (ret); + continue; + } + + /* Add any character but a double quote to the quoted string we're + accumulating. */ + if (c != '"') + goto add_one_character; + + /* c == '"' */ + if (stripdq) + { + dquote ^= 1; + i++; + continue; + } + + break; + } + temp[j] = '\0'; + + /* Point to after the closing quote. */ + if (c) + i++; + *sindex = i; + + return (temp); +} + +/* This should really be another option to string_extract_double_quoted. */ +static int +skip_double_quoted (string, slen, sind) + char *string; + size_t slen; + int sind; +{ + int c, i; + char *ret; + int pass_next, backquote, si; + DECLARE_MBSTATE; + + pass_next = backquote = 0; + i = sind; + while (c = string[i]) + { + if (pass_next) + { + pass_next = 0; + ADVANCE_CHAR (string, slen, i); + continue; + } + else if (c == '\\') + { + pass_next++; + i++; + continue; + } + else if (backquote) + { + if (c == '`') + backquote = 0; + ADVANCE_CHAR (string, slen, i); + continue; + } + else if (c == '`') + { + backquote++; + i++; + continue; + } + else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE))) + { + si = i + 2; + if (string[i + 1] == LPAREN) + ret = extract_command_subst (string, &si, SX_NOALLOC); + else + ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, SX_NOALLOC); + + i = si + 1; + continue; + } + else if (c != '"') + { + ADVANCE_CHAR (string, slen, i); + continue; + } + else + break; + } + + if (c) + i++; + + return (i); +} + +/* Extract the contents of STRING as if it is enclosed in single quotes. + SINDEX, when passed in, is the offset of the character immediately + following the opening single quote; on exit, SINDEX is left pointing after + the closing single quote. */ +static inline char * +string_extract_single_quoted (string, sindex) + char *string; + int *sindex; +{ + register int i; + size_t slen; + char *t; + DECLARE_MBSTATE; + + /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */ + slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0; + i = *sindex; + while (string[i] && string[i] != '\'') + ADVANCE_CHAR (string, slen, i); + + t = substring (string, *sindex, i); + + if (string[i]) + i++; + *sindex = i; + + return (t); +} + +static inline int +skip_single_quoted (string, slen, sind) + const char *string; + size_t slen; + int sind; +{ + register int c; + DECLARE_MBSTATE; + + c = sind; + while (string[c] && string[c] != '\'') + ADVANCE_CHAR (string, slen, c); + + if (string[c]) + c++; + return c; +} + +/* Just like string_extract, but doesn't hack backslashes or any of + that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */ +static char * +string_extract_verbatim (string, slen, sindex, charlist, flags) + char *string; + size_t slen; + int *sindex; + char *charlist; + int flags; +{ + register int i; +#if defined (HANDLE_MULTIBYTE) + size_t clen; + wchar_t *wcharlist; +#endif + int c; + char *temp; + DECLARE_MBSTATE; + + if (charlist[0] == '\'' && charlist[1] == '\0') + { + temp = string_extract_single_quoted (string, sindex); + --*sindex; /* leave *sindex at separator character */ + return temp; + } + + i = *sindex; +#if 0 + /* See how the MBLEN and ADVANCE_CHAR macros work to understand why we need + this only if MB_CUR_MAX > 1. */ + slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 1; +#endif +#if defined (HANDLE_MULTIBYTE) + clen = strlen (charlist); + wcharlist = 0; +#endif + while (c = string[i]) + { +#if defined (HANDLE_MULTIBYTE) + size_t mblength; +#endif + if ((flags & SX_NOCTLESC) == 0 && c == CTLESC) + { + i += 2; + continue; + } + /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL + through, to protect the CTLNULs from later calls to + remove_quoted_nulls. */ + else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL) + { + i += 2; + continue; + } + +#if defined (HANDLE_MULTIBYTE) + mblength = MBLEN (string + i, slen - i); + if (mblength > 1) + { + wchar_t wc; + mblength = mbtowc (&wc, string + i, slen - i); + if (MB_INVALIDCH (mblength)) + { + if (MEMBER (c, charlist)) + break; + } + else + { + if (wcharlist == 0) + { + size_t len; + len = mbstowcs (wcharlist, charlist, 0); + if (len == -1) + len = 0; + wcharlist = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1)); + mbstowcs (wcharlist, charlist, len + 1); + } + + if (wcschr (wcharlist, wc)) + break; + } + } + else +#endif + if (MEMBER (c, charlist)) + break; + + ADVANCE_CHAR (string, slen, i); + } + +#if defined (HANDLE_MULTIBYTE) + FREE (wcharlist); +#endif + + temp = substring (string, *sindex, i); + *sindex = i; + + return (temp); +} + +/* Extract the $( construct in STRING, and return a new string. + Start extracting at (SINDEX) as if we had just seen "$(". + Make (SINDEX) get the position of the matching ")". ) + XFLAGS is additional flags to pass to other extraction functions. */ +char * +extract_command_subst (string, sindex, xflags) + char *string; + int *sindex; + int xflags; +{ + if (string[*sindex] == LPAREN) + return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/ + else + { + xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0); + return (xparse_dolparen (string, string+*sindex, sindex, xflags)); + } +} + +/* Extract the $[ construct in STRING, and return a new string. (]) + Start extracting at (SINDEX) as if we had just seen "$[". + Make (SINDEX) get the position of the matching "]". */ +char * +extract_arithmetic_subst (string, sindex) + char *string; + int *sindex; +{ + return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/ +} + +#if defined (PROCESS_SUBSTITUTION) +/* Extract the <( or >( construct in STRING, and return a new string. + Start extracting at (SINDEX) as if we had just seen "<(". + Make (SINDEX) get the position of the matching ")". */ /*))*/ +char * +extract_process_subst (string, starter, sindex) + char *string; + char *starter; + int *sindex; +{ + return (extract_delimited_string (string, sindex, starter, "(", ")", SX_COMMAND)); +} +#endif /* PROCESS_SUBSTITUTION */ + +#if defined (ARRAY_VARS) +/* This can be fooled by unquoted right parens in the passed string. If + each caller verifies that the last character in STRING is a right paren, + we don't even need to call extract_delimited_string. */ +char * +extract_array_assignment_list (string, sindex) + char *string; + int *sindex; +{ + int slen; + char *ret; + + slen = strlen (string); /* ( */ + if (string[slen - 1] == ')') + { + ret = substring (string, *sindex, slen - 1); + *sindex = slen - 1; + return ret; + } + return 0; +} +#endif + +/* Extract and create a new string from the contents of STRING, a + character string delimited with OPENER and CLOSER. SINDEX is + the address of an int describing the current offset in STRING; + it should point to just after the first OPENER found. On exit, + SINDEX gets the position of the last character of the matching CLOSER. + If OPENER is more than a single character, ALT_OPENER, if non-null, + contains a character string that can also match CLOSER and thus + needs to be skipped. */ +static char * +extract_delimited_string (string, sindex, opener, alt_opener, closer, flags) + char *string; + int *sindex; + char *opener, *alt_opener, *closer; + int flags; +{ + int i, c, si; + size_t slen; + char *t, *result; + int pass_character, nesting_level, in_comment; + int len_closer, len_opener, len_alt_opener; + DECLARE_MBSTATE; + + slen = strlen (string + *sindex) + *sindex; + len_opener = STRLEN (opener); + len_alt_opener = STRLEN (alt_opener); + len_closer = STRLEN (closer); + + pass_character = in_comment = 0; + + nesting_level = 1; + i = *sindex; + + while (nesting_level) + { + c = string[i]; + + if (c == 0) + break; + + if (in_comment) + { + if (c == '\n') + in_comment = 0; + ADVANCE_CHAR (string, slen, i); + continue; + } + + if (pass_character) /* previous char was backslash */ + { + pass_character = 0; + ADVANCE_CHAR (string, slen, i); + continue; + } + + /* Not exactly right yet; should handle shell metacharacters and + multibyte characters, too. See COMMENT_BEGIN define in parse.y */ + if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1]))) + { + in_comment = 1; + ADVANCE_CHAR (string, slen, i); + continue; + } + + if (c == CTLESC || c == '\\') + { + pass_character++; + i++; + continue; + } + + /* Process a nested command substitution, but only if we're parsing an + arithmetic substitution. */ + if ((flags & SX_COMMAND) && string[i] == '$' && string[i+1] == LPAREN) + { + si = i + 2; + t = extract_command_subst (string, &si, flags|SX_NOALLOC); + i = si + 1; + continue; + } + + /* Process a nested OPENER. */ + if (STREQN (string + i, opener, len_opener)) + { + si = i + len_opener; + t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|SX_NOALLOC); + i = si + 1; + continue; + } + + /* Process a nested ALT_OPENER */ + if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener)) + { + si = i + len_alt_opener; + t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|SX_NOALLOC); + i = si + 1; + continue; + } + + /* If the current substring terminates the delimited string, decrement + the nesting level. */ + if (STREQN (string + i, closer, len_closer)) + { + i += len_closer - 1; /* move to last byte of the closer */ + nesting_level--; + if (nesting_level == 0) + break; + } + + /* Pass old-style command substitution through verbatim. */ + if (c == '`') + { + si = i + 1; + t = string_extract (string, &si, "`", flags|SX_NOALLOC); + i = si + 1; + continue; + } + + /* Pass single-quoted and double-quoted strings through verbatim. */ + if (c == '\'' || c == '"') + { + si = i + 1; + i = (c == '\'') ? skip_single_quoted (string, slen, si) + : skip_double_quoted (string, slen, si); + continue; + } + + /* move past this character, which was not special. */ + ADVANCE_CHAR (string, slen, i); + } + + if (c == 0 && nesting_level) + { + if (no_longjmp_on_fatal_error == 0) + { + last_command_exit_value = EXECUTION_FAILURE; + report_error (_("bad substitution: no closing `%s' in %s"), closer, string); + exp_jump_to_top_level (DISCARD); + } + else + { + *sindex = i; + return (char *)NULL; + } + } + + si = i - *sindex - len_closer + 1; + if (flags & SX_NOALLOC) + result = (char *)NULL; + else + { + result = (char *)xmalloc (1 + si); + strncpy (result, string + *sindex, si); + result[si] = '\0'; + } + *sindex = i; + + return (result); +} + +/* Extract a parameter expansion expression within ${ and } from STRING. + Obey the Posix.2 rules for finding the ending `}': count braces while + skipping over enclosed quoted strings and command substitutions. + SINDEX is the address of an int describing the current offset in STRING; + it should point to just after the first `{' found. On exit, SINDEX + gets the position of the matching `}'. QUOTED is non-zero if this + occurs inside double quotes. */ +/* XXX -- this is very similar to extract_delimited_string -- XXX */ +static char * +extract_dollar_brace_string (string, sindex, quoted, flags) + char *string; + int *sindex, quoted, flags; +{ + register int i, c; + size_t slen; + int pass_character, nesting_level, si, dolbrace_state; + char *result, *t; + DECLARE_MBSTATE; + + pass_character = 0; + nesting_level = 1; + slen = strlen (string + *sindex) + *sindex; + + /* The handling of dolbrace_state needs to agree with the code in parse.y: + parse_matched_pair(). The different initial value is to handle the + case where this function is called to parse the word in + ${param op word} (SX_WORD). */ + dolbrace_state = (flags & SX_WORD) ? DOLBRACE_WORD : DOLBRACE_PARAM; + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && (flags & SX_POSIXEXP)) + dolbrace_state = DOLBRACE_QUOTE; + + i = *sindex; + while (c = string[i]) + { + if (pass_character) + { + pass_character = 0; + ADVANCE_CHAR (string, slen, i); + continue; + } + + /* CTLESCs and backslashes quote the next character. */ + if (c == CTLESC || c == '\\') + { + pass_character++; + i++; + continue; + } + + if (string[i] == '$' && string[i+1] == LBRACE) + { + nesting_level++; + i += 2; + continue; + } + + if (c == RBRACE) + { + nesting_level--; + if (nesting_level == 0) + break; + i++; + continue; + } + + /* Pass the contents of old-style command substitutions through + verbatim. */ + if (c == '`') + { + si = i + 1; + t = string_extract (string, &si, "`", flags|SX_NOALLOC); + i = si + 1; + continue; + } + + /* Pass the contents of new-style command substitutions and + arithmetic substitutions through verbatim. */ + if (string[i] == '$' && string[i+1] == LPAREN) + { + si = i + 2; + t = extract_command_subst (string, &si, flags|SX_NOALLOC); + i = si + 1; + continue; + } + +#if 0 + /* Pass the contents of single-quoted and double-quoted strings + through verbatim. */ + if (c == '\'' || c == '"') + { + si = i + 1; + i = (c == '\'') ? skip_single_quoted (string, slen, si) + : skip_double_quoted (string, slen, si); + /* skip_XXX_quoted leaves index one past close quote */ + continue; + } +#else /* XXX - bash-4.2 */ + /* Pass the contents of double-quoted strings through verbatim. */ + if (c == '"') + { + si = i + 1; + i = skip_double_quoted (string, slen, si); + /* skip_XXX_quoted leaves index one past close quote */ + continue; + } + + if (c == '\'') + { +/*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/ + if (posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) + ADVANCE_CHAR (string, slen, i); + else + { + si = i + 1; + i = skip_single_quoted (string, slen, si); + } + + continue; + } +#endif + + /* move past this character, which was not special. */ + ADVANCE_CHAR (string, slen, i); + + /* This logic must agree with parse.y:parse_matched_pair, since they + share the same defines. */ + if (dolbrace_state == DOLBRACE_PARAM && c == '%' && (i - *sindex) > 1) + dolbrace_state = DOLBRACE_QUOTE; + else if (dolbrace_state == DOLBRACE_PARAM && c == '#' && (i - *sindex) > 1) + dolbrace_state = DOLBRACE_QUOTE; + else if (dolbrace_state == DOLBRACE_PARAM && c == '/' && (i - *sindex) > 1) + dolbrace_state = DOLBRACE_QUOTE; + else if (dolbrace_state == DOLBRACE_PARAM && c == '^' && (i - *sindex) > 1) + dolbrace_state = DOLBRACE_QUOTE; + else if (dolbrace_state == DOLBRACE_PARAM && c == ',' && (i - *sindex) > 1) + dolbrace_state = DOLBRACE_QUOTE; + else if (dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", c) != 0) + dolbrace_state = DOLBRACE_OP; + else if (dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", c) == 0) + dolbrace_state = DOLBRACE_WORD; + } + + if (c == 0 && nesting_level) + { + if (no_longjmp_on_fatal_error == 0) + { /* { */ + last_command_exit_value = EXECUTION_FAILURE; + report_error (_("bad substitution: no closing `%s' in %s"), "}", string); + exp_jump_to_top_level (DISCARD); + } + else + { + *sindex = i; + return ((char *)NULL); + } + } + + result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i); + *sindex = i; + + return (result); +} + +/* Remove backslashes which are quoting backquotes from STRING. Modifies + STRING, and returns a pointer to it. */ +char * +de_backslash (string) + char *string; +{ + register size_t slen; + register int i, j, prev_i; + DECLARE_MBSTATE; + + slen = strlen (string); + i = j = 0; + + /* Loop copying string[i] to string[j], i >= j. */ + while (i < slen) + { + if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' || + string[i + 1] == '$')) + i++; + prev_i = i; + ADVANCE_CHAR (string, slen, i); + if (j < prev_i) + do string[j++] = string[prev_i++]; while (prev_i < i); + else + j = i; + } + string[j] = '\0'; + + return (string); +} + +#if 0 +/*UNUSED*/ +/* Replace instances of \! in a string with !. */ +void +unquote_bang (string) + char *string; +{ + register int i, j; + register char *temp; + + temp = (char *)xmalloc (1 + strlen (string)); + + for (i = 0, j = 0; (temp[j] = string[i]); i++, j++) + { + if (string[i] == '\\' && string[i + 1] == '!') + { + temp[j] = '!'; + i++; + } + } + strcpy (string, temp); + free (temp); +} +#endif + +#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0) + +/* This function assumes s[i] == open; returns with s[ret] == close; used to + parse array subscripts. FLAGS & 1 means to not attempt to skip over + matched pairs of quotes or backquotes, or skip word expansions; it is + intended to be used after expansion has been performed and during final + assignment parsing (see arrayfunc.c:assign_compound_array_list()). */ +static int +skip_matched_pair (string, start, open, close, flags) + const char *string; + int start, open, close, flags; +{ + int i, pass_next, backq, si, c, count; + size_t slen; + char *temp, *ss; + DECLARE_MBSTATE; + + slen = strlen (string + start) + start; + no_longjmp_on_fatal_error = 1; + + i = start + 1; /* skip over leading bracket */ + count = 1; + pass_next = backq = 0; + ss = (char *)string; + while (c = string[i]) + { + if (pass_next) + { + pass_next = 0; + if (c == 0) + CQ_RETURN(i); + ADVANCE_CHAR (string, slen, i); + continue; + } + else if (c == '\\') + { + pass_next = 1; + i++; + continue; + } + else if (backq) + { + if (c == '`') + backq = 0; + ADVANCE_CHAR (string, slen, i); + continue; + } + else if ((flags & 1) == 0 && c == '`') + { + backq = 1; + i++; + continue; + } + else if ((flags & 1) == 0 && c == open) + { + count++; + i++; + continue; + } + else if (c == close) + { + count--; + if (count == 0) + break; + i++; + continue; + } + else if ((flags & 1) == 0 && (c == '\'' || c == '"')) + { + i = (c == '\'') ? skip_single_quoted (ss, slen, ++i) + : skip_double_quoted (ss, slen, ++i); + /* no increment, the skip functions increment past the closing quote. */ + } + else if ((flags&1) == 0 && c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE)) + { + si = i + 2; + if (string[si] == '\0') + CQ_RETURN(si); + + if (string[i+1] == LPAREN) + temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */ + else + temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC); + i = si; + if (string[i] == '\0') /* don't increment i past EOS in loop */ + break; + i++; + continue; + } + else + ADVANCE_CHAR (string, slen, i); + } + + CQ_RETURN(i); +} + +#if defined (ARRAY_VARS) +int +skipsubscript (string, start, flags) + const char *string; + int start, flags; +{ + return (skip_matched_pair (string, start, '[', ']', flags)); +} +#endif + +/* Skip characters in STRING until we find a character in DELIMS, and return + the index of that character. START is the index into string at which we + begin. This is similar in spirit to strpbrk, but it returns an index into + STRING and takes a starting index. This little piece of code knows quite + a lot of shell syntax. It's very similar to skip_double_quoted and other + functions of that ilk. */ +int +skip_to_delim (string, start, delims, flags) + char *string; + int start; + char *delims; + int flags; +{ + int i, pass_next, backq, si, c, invert, skipquote, skipcmd; + size_t slen; + char *temp, open[3]; + DECLARE_MBSTATE; + + slen = strlen (string + start) + start; + if (flags & SD_NOJMP) + no_longjmp_on_fatal_error = 1; + invert = (flags & SD_INVERT); + skipcmd = (flags & SD_NOSKIPCMD) == 0; + + i = start; + pass_next = backq = 0; + while (c = string[i]) + { + /* If this is non-zero, we should not let quote characters be delimiters + and the current character is a single or double quote. We should not + test whether or not it's a delimiter until after we skip single- or + double-quoted strings. */ + skipquote = ((flags & SD_NOQUOTEDELIM) && (c == '\'' || c =='"')); + if (pass_next) + { + pass_next = 0; + if (c == 0) + CQ_RETURN(i); + ADVANCE_CHAR (string, slen, i); + continue; + } + else if (c == '\\') + { + pass_next = 1; + i++; + continue; + } + else if (backq) + { + if (c == '`') + backq = 0; + ADVANCE_CHAR (string, slen, i); + continue; + } + else if (c == '`') + { + backq = 1; + i++; + continue; + } + else if (skipquote == 0 && invert == 0 && member (c, delims)) + break; + else if (c == '\'' || c == '"') + { + i = (c == '\'') ? skip_single_quoted (string, slen, ++i) + : skip_double_quoted (string, slen, ++i); + /* no increment, the skip functions increment past the closing quote. */ + } + else if (c == '$' && ((skipcmd && string[i+1] == LPAREN) || string[i+1] == LBRACE)) + { + si = i + 2; + if (string[si] == '\0') + CQ_RETURN(si); + + if (string[i+1] == LPAREN) + temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */ + else + temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC); + i = si; + if (string[i] == '\0') /* don't increment i past EOS in loop */ + break; + i++; + continue; + } +#if defined (PROCESS_SUBSTITUTION) + else if (skipcmd && (c == '<' || c == '>') && string[i+1] == LPAREN) + { + si = i + 2; + if (string[si] == '\0') + CQ_RETURN(si); + temp = extract_process_subst (string, (c == '<') ? "<(" : ">(", &si); + free (temp); /* no SX_ALLOC here */ + i = si; + if (string[i] == '\0') + break; + i++; + continue; + } +#endif /* PROCESS_SUBSTITUTION */ +#if defined (EXTENDED_GLOB) + else if ((flags & SD_EXTGLOB) && extended_glob && string[i+1] == LPAREN && member (c, "?*+!@")) + { + si = i + 2; + if (string[si] == '\0') + CQ_RETURN(si); + + open[0] = c; + open[1] = LPAREN; + open[2] = '\0'; + temp = extract_delimited_string (string, &si, open, "(", ")", SX_NOALLOC); /* ) */ + + i = si; + if (string[i] == '\0') /* don't increment i past EOS in loop */ + break; + i++; + continue; + } +#endif + else if ((skipquote || invert) && (member (c, delims) == 0)) + break; + else + ADVANCE_CHAR (string, slen, i); + } + + CQ_RETURN(i); +} + +#if defined (READLINE) +/* Return 1 if the portion of STRING ending at EINDEX is quoted (there is + an unclosed quoted string), or if the character at EINDEX is quoted + by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various + single and double-quoted string parsing functions should not return an + error if there are unclosed quotes or braces. The characters that this + recognizes need to be the same as the contents of + rl_completer_quote_characters. */ + +int +char_is_quoted (string, eindex) + char *string; + int eindex; +{ + int i, pass_next, c; + size_t slen; + DECLARE_MBSTATE; + + slen = strlen (string); + no_longjmp_on_fatal_error = 1; + i = pass_next = 0; + while (i <= eindex) + { + c = string[i]; + + if (pass_next) + { + pass_next = 0; + if (i >= eindex) /* XXX was if (i >= eindex - 1) */ + CQ_RETURN(1); + ADVANCE_CHAR (string, slen, i); + continue; + } + else if (c == '\\') + { + pass_next = 1; + i++; + continue; + } + else if (c == '\'' || c == '"') + { + i = (c == '\'') ? skip_single_quoted (string, slen, ++i) + : skip_double_quoted (string, slen, ++i); + if (i > eindex) + CQ_RETURN(1); + /* no increment, the skip_xxx functions go one past end */ + } + else + ADVANCE_CHAR (string, slen, i); + } + + CQ_RETURN(0); +} + +int +unclosed_pair (string, eindex, openstr) + char *string; + int eindex; + char *openstr; +{ + int i, pass_next, openc, olen; + size_t slen; + DECLARE_MBSTATE; + + slen = strlen (string); + olen = strlen (openstr); + i = pass_next = openc = 0; + while (i <= eindex) + { + if (pass_next) + { + pass_next = 0; + if (i >= eindex) /* XXX was if (i >= eindex - 1) */ + return 0; + ADVANCE_CHAR (string, slen, i); + continue; + } + else if (string[i] == '\\') + { + pass_next = 1; + i++; + continue; + } + else if (STREQN (string + i, openstr, olen)) + { + openc = 1 - openc; + i += olen; + } + else if (string[i] == '\'' || string[i] == '"') + { + i = (string[i] == '\'') ? skip_single_quoted (string, slen, i) + : skip_double_quoted (string, slen, i); + if (i > eindex) + return 0; + } + else + ADVANCE_CHAR (string, slen, i); + } + return (openc); +} + +/* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the + individual words. If DELIMS is NULL, the current value of $IFS is used + to split the string, and the function follows the shell field splitting + rules. SENTINEL is an index to look for. NWP, if non-NULL, + gets the number of words in the returned list. CWP, if non-NULL, gets + the index of the word containing SENTINEL. Non-whitespace chars in + DELIMS delimit separate fields. */ +WORD_LIST * +split_at_delims (string, slen, delims, sentinel, flags, nwp, cwp) + char *string; + int slen; + char *delims; + int sentinel, flags; + int *nwp, *cwp; +{ + int ts, te, i, nw, cw, ifs_split, dflags; + char *token, *d, *d2; + WORD_LIST *ret, *tl; + + if (string == 0 || *string == '\0') + { + if (nwp) + *nwp = 0; + if (cwp) + *cwp = 0; + return ((WORD_LIST *)NULL); + } + + d = (delims == 0) ? ifs_value : delims; + ifs_split = delims == 0; + + /* Make d2 the non-whitespace characters in delims */ + d2 = 0; + if (delims) + { + size_t slength; +#if defined (HANDLE_MULTIBYTE) + size_t mblength = 1; +#endif + DECLARE_MBSTATE; + + slength = strlen (delims); + d2 = (char *)xmalloc (slength + 1); + i = ts = 0; + while (delims[i]) + { +#if defined (HANDLE_MULTIBYTE) + mbstate_t state_bak; + state_bak = state; + mblength = MBRLEN (delims + i, slength, &state); + if (MB_INVALIDCH (mblength)) + state = state_bak; + else if (mblength > 1) + { + memcpy (d2 + ts, delims + i, mblength); + ts += mblength; + i += mblength; + slength -= mblength; + continue; + } +#endif + if (whitespace (delims[i]) == 0) + d2[ts++] = delims[i]; + + i++; + slength--; + } + d2[ts] = '\0'; + } + + ret = (WORD_LIST *)NULL; + + /* Remove sequences of whitespace characters at the start of the string, as + long as those characters are delimiters. */ + for (i = 0; member (string[i], d) && spctabnl (string[i]); i++) + ; + if (string[i] == '\0') + return (ret); + + ts = i; + nw = 0; + cw = -1; + dflags = flags|SD_NOJMP; + while (1) + { + te = skip_to_delim (string, ts, d, dflags); + + /* If we have a non-whitespace delimiter character, use it to make a + separate field. This is just about what $IFS splitting does and + is closer to the behavior of the shell parser. */ + if (ts == te && d2 && member (string[ts], d2)) + { + te = ts + 1; + /* If we're using IFS splitting, the non-whitespace delimiter char + and any additional IFS whitespace delimits a field. */ + if (ifs_split) + while (member (string[te], d) && spctabnl (string[te])) + te++; + else + while (member (string[te], d2)) + te++; + } + + token = substring (string, ts, te); + + ret = add_string_to_list (token, ret); + free (token); + nw++; + + if (sentinel >= ts && sentinel <= te) + cw = nw; + + /* If the cursor is at whitespace just before word start, set the + sentinel word to the current word. */ + if (cwp && cw == -1 && sentinel == ts-1) + cw = nw; + + /* If the cursor is at whitespace between two words, make a new, empty + word, add it before (well, after, since the list is in reverse order) + the word we just added, and set the current word to that one. */ + if (cwp && cw == -1 && sentinel < ts) + { + tl = make_word_list (make_word (""), ret->next); + ret->next = tl; + cw = nw; + nw++; + } + + if (string[te] == 0) + break; + + i = te; + while (member (string[i], d) && (ifs_split || spctabnl(string[i]))) + i++; + + if (string[i]) + ts = i; + else + break; + } + + /* Special case for SENTINEL at the end of STRING. If we haven't found + the word containing SENTINEL yet, and the index we're looking for is at + the end of STRING (or past the end of the previously-found token, + possible if the end of the line is composed solely of IFS whitespace) + add an additional null argument and set the current word pointer to that. */ + if (cwp && cw == -1 && (sentinel >= slen || sentinel >= te)) + { + if (whitespace (string[sentinel - 1])) + { + token = ""; + ret = add_string_to_list (token, ret); + nw++; + } + cw = nw; + } + + if (nwp) + *nwp = nw; + if (cwp) + *cwp = cw; + + FREE (d2); + + return (REVERSE_LIST (ret, WORD_LIST *)); +} +#endif /* READLINE */ + +#if 0 +/* UNUSED */ +/* Extract the name of the variable to bind to from the assignment string. */ +char * +assignment_name (string) + char *string; +{ + int offset; + char *temp; + + offset = assignment (string, 0); + if (offset == 0) + return (char *)NULL; + temp = substring (string, 0, offset); + return (temp); +} +#endif + +/* **************************************************************** */ +/* */ +/* Functions to convert strings to WORD_LISTs and vice versa */ +/* */ +/* **************************************************************** */ + +/* Return a single string of all the words in LIST. SEP is the separator + to put between individual elements of LIST in the output string. */ +char * +string_list_internal (list, sep) + WORD_LIST *list; + char *sep; +{ + register WORD_LIST *t; + char *result, *r; + int word_len, sep_len, result_size; + + if (list == 0) + return ((char *)NULL); + + /* Short-circuit quickly if we don't need to separate anything. */ + if (list->next == 0) + return (savestring (list->word->word)); + + /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */ + sep_len = STRLEN (sep); + result_size = 0; + + for (t = list; t; t = t->next) + { + if (t != list) + result_size += sep_len; + result_size += strlen (t->word->word); + } + + r = result = (char *)xmalloc (result_size + 1); + + for (t = list; t; t = t->next) + { + if (t != list && sep_len) + { + if (sep_len > 1) + { + FASTCOPY (sep, r, sep_len); + r += sep_len; + } + else + *r++ = sep[0]; + } + + word_len = strlen (t->word->word); + FASTCOPY (t->word->word, r, word_len); + r += word_len; + } + + *r = '\0'; + return (result); +} + +/* Return a single string of all the words present in LIST, separating + each word with a space. */ +char * +string_list (list) + WORD_LIST *list; +{ + return (string_list_internal (list, " ")); +} + +/* An external interface that can be used by the rest of the shell to + obtain a string containing the first character in $IFS. Handles all + the multibyte complications. If LENP is non-null, it is set to the + length of the returned string. */ +char * +ifs_firstchar (lenp) + int *lenp; +{ + char *ret; + int len; + + ret = xmalloc (MB_LEN_MAX + 1); +#if defined (HANDLE_MULTIBYTE) + if (ifs_firstc_len == 1) + { + ret[0] = ifs_firstc[0]; + ret[1] = '\0'; + len = ret[0] ? 1 : 0; + } + else + { + memcpy (ret, ifs_firstc, ifs_firstc_len); + ret[len = ifs_firstc_len] = '\0'; + } +#else + ret[0] = ifs_firstc; + ret[1] = '\0'; + len = ret[0] ? 0 : 1; +#endif + + if (lenp) + *lenp = len; + + return ret; +} + +/* Return a single string of all the words present in LIST, obeying the + quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the + expansion [of $*] appears within a double quoted string, it expands + to a single field with the value of each parameter separated by the + first character of the IFS variable, or by a if IFS is unset." */ +char * +string_list_dollar_star (list) + WORD_LIST *list; +{ + char *ret; +#if defined (HANDLE_MULTIBYTE) +# if defined (__GNUC__) + char sep[MB_CUR_MAX + 1]; +# else + char *sep = 0; +# endif +#else + char sep[2]; +#endif + +#if defined (HANDLE_MULTIBYTE) +# if !defined (__GNUC__) + sep = (char *)xmalloc (MB_CUR_MAX + 1); +# endif /* !__GNUC__ */ + if (ifs_firstc_len == 1) + { + sep[0] = ifs_firstc[0]; + sep[1] = '\0'; + } + else + { + memcpy (sep, ifs_firstc, ifs_firstc_len); + sep[ifs_firstc_len] = '\0'; + } +#else + sep[0] = ifs_firstc; + sep[1] = '\0'; +#endif + + ret = string_list_internal (list, sep); +#if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__) + free (sep); +#endif + return ret; +} + +/* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) + is non-zero, the $@ appears within double quotes, and we should quote + the list before converting it into a string. If IFS is unset, and the + word is not quoted, we just need to quote CTLESC and CTLNUL characters + in the words in the list, because the default value of $IFS is + , IFS characters in the words in the list should + also be split. If IFS is null, and the word is not quoted, we need + to quote the words in the list to preserve the positional parameters + exactly. */ +char * +string_list_dollar_at (list, quoted) + WORD_LIST *list; + int quoted; +{ + char *ifs, *ret; +#if defined (HANDLE_MULTIBYTE) +# if defined (__GNUC__) + char sep[MB_CUR_MAX + 1]; +# else + char *sep = 0; +# endif /* !__GNUC__ */ +#else + char sep[2]; +#endif + WORD_LIST *tlist; + + /* XXX this could just be ifs = ifs_value; */ + ifs = ifs_var ? value_cell (ifs_var) : (char *)0; + +#if defined (HANDLE_MULTIBYTE) +# if !defined (__GNUC__) + sep = (char *)xmalloc (MB_CUR_MAX + 1); +# endif /* !__GNUC__ */ + if (ifs && *ifs) + { + if (ifs_firstc_len == 1) + { + sep[0] = ifs_firstc[0]; + sep[1] = '\0'; + } + else + { + memcpy (sep, ifs_firstc, ifs_firstc_len); + sep[ifs_firstc_len] = '\0'; + } + } + else + { + sep[0] = ' '; + sep[1] = '\0'; + } +#else + sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs; + sep[1] = '\0'; +#endif + + /* XXX -- why call quote_list if ifs == 0? we can get away without doing + it now that quote_escapes quotes spaces */ + tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE)) + ? quote_list (list) + : list_quote_escapes (list); + + ret = string_list_internal (tlist, sep); +#if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__) + free (sep); +#endif + return ret; +} + +/* Turn the positional paramters into a string, understanding quoting and + the various subtleties of using the first character of $IFS as the + separator. Calls string_list_dollar_at, string_list_dollar_star, and + string_list as appropriate. */ +char * +string_list_pos_params (pchar, list, quoted) + int pchar; + WORD_LIST *list; + int quoted; +{ + char *ret; + WORD_LIST *tlist; + + if (pchar == '*' && (quoted & Q_DOUBLE_QUOTES)) + { + tlist = quote_list (list); + word_list_remove_quoted_nulls (tlist); + ret = string_list_dollar_star (tlist); + } + else if (pchar == '*' && (quoted & Q_HERE_DOCUMENT)) + { + tlist = quote_list (list); + word_list_remove_quoted_nulls (tlist); + ret = string_list (tlist); + } + else if (pchar == '*') + { + /* Even when unquoted, string_list_dollar_star does the right thing + making sure that the first character of $IFS is used as the + separator. */ + ret = string_list_dollar_star (list); + } + else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) + /* We use string_list_dollar_at, but only if the string is quoted, since + that quotes the escapes if it's not, which we don't want. We could + use string_list (the old code did), but that doesn't do the right + thing if the first character of $IFS is not a space. We use + string_list_dollar_star if the string is unquoted so we make sure that + the elements of $@ are separated by the first character of $IFS for + later splitting. */ + ret = string_list_dollar_at (list, quoted); + else if (pchar == '@') + ret = string_list_dollar_star (list); + else + ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list); + + return ret; +} + +/* Return the list of words present in STRING. Separate the string into + words at any of the characters found in SEPARATORS. If QUOTED is + non-zero then word in the list will have its quoted flag set, otherwise + the quoted flag is left as make_word () deemed fit. + + This obeys the P1003.2 word splitting semantics. If `separators' is + exactly , then the splitting algorithm is that of + the Bourne shell, which treats any sequence of characters from `separators' + as a delimiter. If IFS is unset, which results in `separators' being set + to "", no splitting occurs. If separators has some other value, the + following rules are applied (`IFS white space' means zero or more + occurrences of , , or , as long as those characters + are in `separators'): + + 1) IFS white space is ignored at the start and the end of the + string. + 2) Each occurrence of a character in `separators' that is not + IFS white space, along with any adjacent occurrences of + IFS white space delimits a field. + 3) Any nonzero-length sequence of IFS white space delimits a field. + */ + +/* BEWARE! list_string strips null arguments. Don't call it twice and + expect to have "" preserved! */ + +/* This performs word splitting and quoted null character removal on + STRING. */ +#define issep(c) \ + (((separators)[0]) ? ((separators)[1] ? isifs(c) \ + : (c) == (separators)[0]) \ + : 0) + +WORD_LIST * +list_string (string, separators, quoted) + register char *string, *separators; + int quoted; +{ + WORD_LIST *result; + WORD_DESC *t; + char *current_word, *s; + int sindex, sh_style_split, whitesep, xflags; + size_t slen; + + if (!string || !*string) + return ((WORD_LIST *)NULL); + + sh_style_split = separators && separators[0] == ' ' && + separators[1] == '\t' && + separators[2] == '\n' && + separators[3] == '\0'; + for (xflags = 0, s = ifs_value; s && *s; s++) + { + if (*s == CTLESC) xflags |= SX_NOCTLESC; + else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL; + } + + slen = 0; + /* Remove sequences of whitespace at the beginning of STRING, as + long as those characters appear in IFS. Do not do this if + STRING is quoted or if there are no separator characters. */ + if (!quoted || !separators || !*separators) + { + for (s = string; *s && spctabnl (*s) && issep (*s); s++); + + if (!*s) + return ((WORD_LIST *)NULL); + + string = s; + } + + /* OK, now STRING points to a word that does not begin with white space. + The splitting algorithm is: + extract a word, stopping at a separator + skip sequences of spc, tab, or nl as long as they are separators + This obeys the field splitting rules in Posix.2. */ + slen = (MB_CUR_MAX > 1) ? strlen (string) : 1; + for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; ) + { + /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim + unless multibyte chars are possible. */ + current_word = string_extract_verbatim (string, slen, &sindex, separators, xflags); + if (current_word == 0) + break; + + /* If we have a quoted empty string, add a quoted null argument. We + want to preserve the quoted null character iff this is a quoted + empty string; otherwise the quoted null characters are removed + below. */ + if (QUOTED_NULL (current_word)) + { + t = alloc_word_desc (); + t->word = make_quoted_char ('\0'); + t->flags |= W_QUOTED|W_HASQUOTEDNULL; + result = make_word_list (t, result); + } + else if (current_word[0] != '\0') + { + /* If we have something, then add it regardless. However, + perform quoted null character removal on the current word. */ + remove_quoted_nulls (current_word); + result = add_string_to_list (current_word, result); + result->word->flags &= ~W_HASQUOTEDNULL; /* just to be sure */ + if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) + result->word->flags |= W_QUOTED; + } + + /* If we're not doing sequences of separators in the traditional + Bourne shell style, then add a quoted null argument. */ + else if (!sh_style_split && !spctabnl (string[sindex])) + { + t = alloc_word_desc (); + t->word = make_quoted_char ('\0'); + t->flags |= W_QUOTED|W_HASQUOTEDNULL; + result = make_word_list (t, result); + } + + free (current_word); + + /* Note whether or not the separator is IFS whitespace, used later. */ + whitesep = string[sindex] && spctabnl (string[sindex]); + + /* Move past the current separator character. */ + if (string[sindex]) + { + DECLARE_MBSTATE; + ADVANCE_CHAR (string, slen, sindex); + } + + /* Now skip sequences of space, tab, or newline characters if they are + in the list of separators. */ + while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex])) + sindex++; + + /* If the first separator was IFS whitespace and the current character + is a non-whitespace IFS character, it should be part of the current + field delimiter, not a separate delimiter that would result in an + empty field. Look at POSIX.2, 3.6.5, (3)(b). */ + if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex])) + { + sindex++; + /* An IFS character that is not IFS white space, along with any + adjacent IFS white space, shall delimit a field. (SUSv3) */ + while (string[sindex] && spctabnl (string[sindex]) && isifs (string[sindex])) + sindex++; + } + } + return (REVERSE_LIST (result, WORD_LIST *)); +} + +/* Parse a single word from STRING, using SEPARATORS to separate fields. + ENDPTR is set to the first character after the word. This is used by + the `read' builtin. This is never called with SEPARATORS != $IFS; + it should be simplified. + + XXX - this function is very similar to list_string; they should be + combined - XXX */ +char * +get_word_from_string (stringp, separators, endptr) + char **stringp, *separators, **endptr; +{ + register char *s; + char *current_word; + int sindex, sh_style_split, whitesep, xflags; + size_t slen; + + if (!stringp || !*stringp || !**stringp) + return ((char *)NULL); + + sh_style_split = separators && separators[0] == ' ' && + separators[1] == '\t' && + separators[2] == '\n' && + separators[3] == '\0'; + for (xflags = 0, s = ifs_value; s && *s; s++) + { + if (*s == CTLESC) xflags |= SX_NOCTLESC; + if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL; + } + + s = *stringp; + slen = 0; + + /* Remove sequences of whitespace at the beginning of STRING, as + long as those characters appear in IFS. */ + if (sh_style_split || !separators || !*separators) + { + for (; *s && spctabnl (*s) && isifs (*s); s++); + + /* If the string is nothing but whitespace, update it and return. */ + if (!*s) + { + *stringp = s; + if (endptr) + *endptr = s; + return ((char *)NULL); + } + } + + /* OK, S points to a word that does not begin with white space. + Now extract a word, stopping at a separator, save a pointer to + the first character after the word, then skip sequences of spc, + tab, or nl as long as they are separators. + + This obeys the field splitting rules in Posix.2. */ + sindex = 0; + /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim + unless multibyte chars are possible. */ + slen = (MB_CUR_MAX > 1) ? strlen (s) : 1; + current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags); + + /* Set ENDPTR to the first character after the end of the word. */ + if (endptr) + *endptr = s + sindex; + + /* Note whether or not the separator is IFS whitespace, used later. */ + whitesep = s[sindex] && spctabnl (s[sindex]); + + /* Move past the current separator character. */ + if (s[sindex]) + { + DECLARE_MBSTATE; + ADVANCE_CHAR (s, slen, sindex); + } + + /* Now skip sequences of space, tab, or newline characters if they are + in the list of separators. */ + while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex])) + sindex++; + + /* If the first separator was IFS whitespace and the current character is + a non-whitespace IFS character, it should be part of the current field + delimiter, not a separate delimiter that would result in an empty field. + Look at POSIX.2, 3.6.5, (3)(b). */ + if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex])) + { + sindex++; + /* An IFS character that is not IFS white space, along with any adjacent + IFS white space, shall delimit a field. */ + while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex])) + sindex++; + } + + /* Update STRING to point to the next field. */ + *stringp = s + sindex; + return (current_word); +} + +/* Remove IFS white space at the end of STRING. Start at the end + of the string and walk backwards until the beginning of the string + or we find a character that's not IFS white space and not CTLESC. + Only let CTLESC escape a white space character if SAW_ESCAPE is + non-zero. */ +char * +strip_trailing_ifs_whitespace (string, separators, saw_escape) + char *string, *separators; + int saw_escape; +{ + char *s; + + s = string + STRLEN (string) - 1; + while (s > string && ((spctabnl (*s) && isifs (*s)) || + (saw_escape && *s == CTLESC && spctabnl (s[1])))) + s--; + *++s = '\0'; + return string; +} + +#if 0 +/* UNUSED */ +/* Split STRING into words at whitespace. Obeys shell-style quoting with + backslashes, single and double quotes. */ +WORD_LIST * +list_string_with_quotes (string) + char *string; +{ + WORD_LIST *list; + char *token, *s; + size_t s_len; + int c, i, tokstart, len; + + for (s = string; s && *s && spctabnl (*s); s++) + ; + if (s == 0 || *s == 0) + return ((WORD_LIST *)NULL); + + s_len = strlen (s); + tokstart = i = 0; + list = (WORD_LIST *)NULL; + while (1) + { + c = s[i]; + if (c == '\\') + { + i++; + if (s[i]) + i++; + } + else if (c == '\'') + i = skip_single_quoted (s, s_len, ++i); + else if (c == '"') + i = skip_double_quoted (s, s_len, ++i); + else if (c == 0 || spctabnl (c)) + { + /* We have found the end of a token. Make a word out of it and + add it to the word list. */ + token = substring (s, tokstart, i); + list = add_string_to_list (token, list); + free (token); + while (spctabnl (s[i])) + i++; + if (s[i]) + tokstart = i; + else + break; + } + else + i++; /* normal character */ + } + return (REVERSE_LIST (list, WORD_LIST *)); +} +#endif + +/********************************************************/ +/* */ +/* Functions to perform assignment statements */ +/* */ +/********************************************************/ + +#if defined (ARRAY_VARS) +static SHELL_VAR * +do_compound_assignment (name, value, flags) + char *name, *value; + int flags; +{ + SHELL_VAR *v; + int mklocal, mkassoc; + WORD_LIST *list; + + mklocal = flags & ASS_MKLOCAL; + mkassoc = flags & ASS_MKASSOC; + + if (mklocal && variable_context) + { + v = find_variable (name); + list = expand_compound_array_assignment (v, value, flags); + if (mkassoc) + v = make_local_assoc_variable (name); + else if (v == 0 || (array_p (v) == 0 && assoc_p (v) == 0) || v->context != variable_context) + v = make_local_array_variable (name, 0); + assign_compound_array_list (v, list, flags); + } + else + v = assign_array_from_string (name, value, flags); + + return (v); +} +#endif + +/* Given STRING, an assignment string, get the value of the right side + of the `=', and bind it to the left side. If EXPAND is true, then + perform parameter expansion, command substitution, and arithmetic + expansion on the right-hand side. Perform tilde expansion in any + case. Do not perform word splitting on the result of expansion. */ +static int +do_assignment_internal (word, expand) + const WORD_DESC *word; + int expand; +{ + int offset, appendop, assign_list, aflags, retval; + char *name, *value, *temp; + SHELL_VAR *entry; +#if defined (ARRAY_VARS) + char *t; + int ni; +#endif + const char *string; + + if (word == 0 || word->word == 0) + return 0; + + appendop = assign_list = aflags = 0; + string = word->word; + offset = assignment (string, 0); + name = savestring (string); + value = (char *)NULL; + + if (name[offset] == '=') + { + if (name[offset - 1] == '+') + { + appendop = 1; + name[offset - 1] = '\0'; + } + + name[offset] = 0; /* might need this set later */ + temp = name + offset + 1; + +#if defined (ARRAY_VARS) + if (expand && (word->flags & W_COMPASSIGN)) + { + assign_list = ni = 1; + value = extract_array_assignment_list (temp, &ni); + } + else +#endif + if (expand && temp[0]) + value = expand_string_if_necessary (temp, 0, expand_string_assignment); + else + value = savestring (temp); + } + + if (value == 0) + { + value = (char *)xmalloc (1); + value[0] = '\0'; + } + + if (echo_command_at_execute) + { + if (appendop) + name[offset - 1] = '+'; + xtrace_print_assignment (name, value, assign_list, 1); + if (appendop) + name[offset - 1] = '\0'; + } + +#define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0) + + if (appendop) + aflags |= ASS_APPEND; + +#if defined (ARRAY_VARS) + if (t = mbschr (name, '[')) /*]*/ + { + if (assign_list) + { + report_error (_("%s: cannot assign list to array member"), name); + ASSIGN_RETURN (0); + } + entry = assign_array_element (name, value, aflags); + if (entry == 0) + ASSIGN_RETURN (0); + } + else if (assign_list) + { + if ((word->flags & W_ASSIGNARG) && (word->flags & W_ASSNGLOBAL) == 0) + aflags |= ASS_MKLOCAL; + if (word->flags & W_ASSIGNASSOC) + aflags |= ASS_MKASSOC; + entry = do_compound_assignment (name, value, aflags); + } + else +#endif /* ARRAY_VARS */ + entry = bind_variable (name, value, aflags); + + stupidly_hack_special_variables (name); + +#if 1 + /* Return 1 if the assignment seems to have been performed correctly. */ + if (entry == 0 || readonly_p (entry)) + retval = 0; /* assignment failure */ + else if (noassign_p (entry)) + { + last_command_exit_value = EXECUTION_FAILURE; + retval = 1; /* error status, but not assignment failure */ + } + else + retval = 1; + + if (entry && retval != 0 && noassign_p (entry) == 0) + VUNSETATTR (entry, att_invisible); + + ASSIGN_RETURN (retval); +#else + if (entry) + VUNSETATTR (entry, att_invisible); + + ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0); +#endif +} + +/* Perform the assignment statement in STRING, and expand the + right side by doing tilde, command and parameter expansion. */ +int +do_assignment (string) + char *string; +{ + WORD_DESC td; + + td.flags = W_ASSIGNMENT; + td.word = string; + + return do_assignment_internal (&td, 1); +} + +int +do_word_assignment (word, flags) + WORD_DESC *word; + int flags; +{ + return do_assignment_internal (word, 1); +} + +/* Given STRING, an assignment string, get the value of the right side + of the `=', and bind it to the left side. Do not perform any word + expansions on the right hand side. */ +int +do_assignment_no_expand (string) + char *string; +{ + WORD_DESC td; + + td.flags = W_ASSIGNMENT; + td.word = string; + + return (do_assignment_internal (&td, 0)); +} + +/*************************************************** + * * + * Functions to manage the positional parameters * + * * + ***************************************************/ + +/* Return the word list that corresponds to `$*'. */ +WORD_LIST * +list_rest_of_args () +{ + register WORD_LIST *list, *args; + int i; + + /* Break out of the loop as soon as one of the dollar variables is null. */ + for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++) + list = make_word_list (make_bare_word (dollar_vars[i]), list); + + for (args = rest_of_args; args; args = args->next) + list = make_word_list (make_bare_word (args->word->word), list); + + return (REVERSE_LIST (list, WORD_LIST *)); +} + +int +number_of_args () +{ + register WORD_LIST *list; + int n; + + for (n = 0; n < 9 && dollar_vars[n+1]; n++) + ; + for (list = rest_of_args; list; list = list->next) + n++; + return n; +} + +/* Return the value of a positional parameter. This handles values > 10. */ +char * +get_dollar_var_value (ind) + intmax_t ind; +{ + char *temp; + WORD_LIST *p; + + if (ind < 10) + temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL; + else /* We want something like ${11} */ + { + ind -= 10; + for (p = rest_of_args; p && ind--; p = p->next) + ; + temp = p ? savestring (p->word->word) : (char *)NULL; + } + return (temp); +} + +/* Make a single large string out of the dollar digit variables, + and the rest_of_args. If DOLLAR_STAR is 1, then obey the special + case of "$*" with respect to IFS. */ +char * +string_rest_of_args (dollar_star) + int dollar_star; +{ + register WORD_LIST *list; + char *string; + + list = list_rest_of_args (); + string = dollar_star ? string_list_dollar_star (list) : string_list (list); + dispose_words (list); + return (string); +} + +/* Return a string containing the positional parameters from START to + END, inclusive. If STRING[0] == '*', we obey the rules for $*, + which only makes a difference if QUOTED is non-zero. If QUOTED includes + Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise + no quoting chars are added. */ +static char * +pos_params (string, start, end, quoted) + char *string; + int start, end, quoted; +{ + WORD_LIST *save, *params, *h, *t; + char *ret; + int i; + + /* see if we can short-circuit. if start == end, we want 0 parameters. */ + if (start == end) + return ((char *)NULL); + + save = params = list_rest_of_args (); + if (save == 0) + return ((char *)NULL); + + if (start == 0) /* handle ${@:0[:x]} specially */ + { + t = make_word_list (make_word (dollar_vars[0]), params); + save = params = t; + } + + for (i = start ? 1 : 0; params && i < start; i++) + params = params->next; + if (params == 0) + return ((char *)NULL); + for (h = t = params; params && i < end; i++) + { + t = params; + params = params->next; + } + + t->next = (WORD_LIST *)NULL; + + ret = string_list_pos_params (string[0], h, quoted); + + if (t != params) + t->next = params; + + dispose_words (save); + return (ret); +} + +/******************************************************************/ +/* */ +/* Functions to expand strings to strings or WORD_LISTs */ +/* */ +/******************************************************************/ + +#if defined (PROCESS_SUBSTITUTION) +#define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~') +#else +#define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~') +#endif + +/* If there are any characters in STRING that require full expansion, + then call FUNC to expand STRING; otherwise just perform quote + removal if necessary. This returns a new string. */ +static char * +expand_string_if_necessary (string, quoted, func) + char *string; + int quoted; + EXPFUNC *func; +{ + WORD_LIST *list; + size_t slen; + int i, saw_quote; + char *ret; + DECLARE_MBSTATE; + + /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */ + slen = (MB_CUR_MAX > 1) ? strlen (string) : 0; + i = saw_quote = 0; + while (string[i]) + { + if (EXP_CHAR (string[i])) + break; + else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"') + saw_quote = 1; + ADVANCE_CHAR (string, slen, i); + } + + if (string[i]) + { + list = (*func) (string, quoted); + if (list) + { + ret = string_list (list); + dispose_words (list); + } + else + ret = (char *)NULL; + } + else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0)) + ret = string_quote_removal (string, quoted); + else + ret = savestring (string); + + return ret; +} + +static inline char * +expand_string_to_string_internal (string, quoted, func) + char *string; + int quoted; + EXPFUNC *func; +{ + WORD_LIST *list; + char *ret; + + if (string == 0 || *string == '\0') + return ((char *)NULL); + + list = (*func) (string, quoted); + if (list) + { + ret = string_list (list); + dispose_words (list); + } + else + ret = (char *)NULL; + + return (ret); +} + +char * +expand_string_to_string (string, quoted) + char *string; + int quoted; +{ + return (expand_string_to_string_internal (string, quoted, expand_string)); +} + +char * +expand_string_unsplit_to_string (string, quoted) + char *string; + int quoted; +{ + return (expand_string_to_string_internal (string, quoted, expand_string_unsplit)); +} + +char * +expand_assignment_string_to_string (string, quoted) + char *string; + int quoted; +{ + return (expand_string_to_string_internal (string, quoted, expand_string_assignment)); +} + +char * +expand_arith_string (string, quoted) + char *string; + int quoted; +{ + return (expand_string_if_necessary (string, quoted, expand_string)); +} + +#if defined (COND_COMMAND) +/* Just remove backslashes in STRING. Returns a new string. */ +char * +remove_backslashes (string) + char *string; +{ + char *r, *ret, *s; + + r = ret = (char *)xmalloc (strlen (string) + 1); + for (s = string; s && *s; ) + { + if (*s == '\\') + s++; + if (*s == 0) + break; + *r++ = *s++; + } + *r = '\0'; + return ret; +} + +/* This needs better error handling. */ +/* Expand W for use as an argument to a unary or binary operator in a + [[...]] expression. If SPECIAL is 1, this is the rhs argument + to the != or == operator, and should be treated as a pattern. In + this case, we quote the string specially for the globbing code. If + SPECIAL is 2, this is an rhs argument for the =~ operator, and should + be quoted appropriately for regcomp/regexec. The caller is responsible + for removing the backslashes if the unquoted word is needed later. */ +char * +cond_expand_word (w, special) + WORD_DESC *w; + int special; +{ + char *r, *p; + WORD_LIST *l; + int qflags; + + if (w->word == 0 || w->word[0] == '\0') + return ((char *)NULL); + + w->flags |= W_NOSPLIT2; + l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0); + if (l) + { + if (special == 0) + { + dequote_list (l); + r = string_list (l); + } + else + { + qflags = QGLOB_CVTNULL; + if (special == 2) + qflags |= QGLOB_REGEXP; + p = string_list (l); + r = quote_string_for_globbing (p, qflags); + free (p); + } + dispose_words (l); + } + else + r = (char *)NULL; + + return r; +} +#endif + +/* Call expand_word_internal to expand W and handle error returns. + A convenience function for functions that don't want to handle + any errors or free any memory before aborting. */ +static WORD_LIST * +call_expand_word_internal (w, q, i, c, e) + WORD_DESC *w; + int q, i, *c, *e; +{ + WORD_LIST *result; + + result = expand_word_internal (w, q, i, c, e); + if (result == &expand_word_error || result == &expand_word_fatal) + { + /* By convention, each time this error is returned, w->word has + already been freed (it sometimes may not be in the fatal case, + but that doesn't result in a memory leak because we're going + to exit in most cases). */ + w->word = (char *)NULL; + last_command_exit_value = EXECUTION_FAILURE; + exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF); + /* NOTREACHED */ + } + else + return (result); +} + +/* Perform parameter expansion, command substitution, and arithmetic + expansion on STRING, as if it were a word. Leave the result quoted. + Since this does not perform word splitting, it leaves quoted nulls + in the result. */ +static WORD_LIST * +expand_string_internal (string, quoted) + char *string; + int quoted; +{ + WORD_DESC td; + WORD_LIST *tresult; + + if (string == 0 || *string == 0) + return ((WORD_LIST *)NULL); + + td.flags = 0; + td.word = savestring (string); + + tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL); + + FREE (td.word); + return (tresult); +} + +/* Expand STRING by performing parameter expansion, command substitution, + and arithmetic expansion. Dequote the resulting WORD_LIST before + returning it, but do not perform word splitting. The call to + remove_quoted_nulls () is in here because word splitting normally + takes care of quote removal. */ +WORD_LIST * +expand_string_unsplit (string, quoted) + char *string; + int quoted; +{ + WORD_LIST *value; + + if (string == 0 || *string == '\0') + return ((WORD_LIST *)NULL); + + expand_no_split_dollar_star = 1; + value = expand_string_internal (string, quoted); + expand_no_split_dollar_star = 0; + + if (value) + { + if (value->word) + { + remove_quoted_nulls (value->word->word); + value->word->flags &= ~W_HASQUOTEDNULL; + } + dequote_list (value); + } + return (value); +} + +/* Expand the rhs of an assignment statement */ +WORD_LIST * +expand_string_assignment (string, quoted) + char *string; + int quoted; +{ + WORD_DESC td; + WORD_LIST *value; + + if (string == 0 || *string == '\0') + return ((WORD_LIST *)NULL); + + expand_no_split_dollar_star = 1; + + td.flags = W_ASSIGNRHS; + td.word = savestring (string); + value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL); + FREE (td.word); + + expand_no_split_dollar_star = 0; + + if (value) + { + if (value->word) + { + remove_quoted_nulls (value->word->word); + value->word->flags &= ~W_HASQUOTEDNULL; + } + dequote_list (value); + } + return (value); +} + + +/* Expand one of the PS? prompt strings. This is a sort of combination of + expand_string_unsplit and expand_string_internal, but returns the + passed string when an error occurs. Might want to trap other calls + to jump_to_top_level here so we don't endlessly loop. */ +WORD_LIST * +expand_prompt_string (string, quoted, wflags) + char *string; + int quoted; + int wflags; +{ + WORD_LIST *value; + WORD_DESC td; + + if (string == 0 || *string == 0) + return ((WORD_LIST *)NULL); + + td.flags = wflags; + td.word = savestring (string); + + no_longjmp_on_fatal_error = 1; + value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL); + no_longjmp_on_fatal_error = 0; + + if (value == &expand_word_error || value == &expand_word_fatal) + { + value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL); + return value; + } + FREE (td.word); + if (value) + { + if (value->word) + { + remove_quoted_nulls (value->word->word); + value->word->flags &= ~W_HASQUOTEDNULL; + } + dequote_list (value); + } + return (value); +} + +/* Expand STRING just as if you were expanding a word, but do not dequote + the resultant WORD_LIST. This is called only from within this file, + and is used to correctly preserve quoted characters when expanding + things like ${1+"$@"}. This does parameter expansion, command + substitution, arithmetic expansion, and word splitting. */ +static WORD_LIST * +expand_string_leave_quoted (string, quoted) + char *string; + int quoted; +{ + WORD_LIST *tlist; + WORD_LIST *tresult; + + if (string == 0 || *string == '\0') + return ((WORD_LIST *)NULL); + + tlist = expand_string_internal (string, quoted); + + if (tlist) + { + tresult = word_list_split (tlist); + dispose_words (tlist); + return (tresult); + } + return ((WORD_LIST *)NULL); +} + +/* This does not perform word splitting or dequote the WORD_LIST + it returns. */ +static WORD_LIST * +expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at) + char *string; + int quoted, *dollar_at_p, *has_dollar_at; +{ + WORD_DESC td; + WORD_LIST *tresult; + + if (string == 0 || *string == '\0') + return (WORD_LIST *)NULL; + + td.flags = W_NOSPLIT2; /* no splitting, remove "" and '' */ + td.word = string; + tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at); + return (tresult); +} + +/* Expand STRING just as if you were expanding a word. This also returns + a list of words. Note that filename globbing is *NOT* done for word + or string expansion, just when the shell is expanding a command. This + does parameter expansion, command substitution, arithmetic expansion, + and word splitting. Dequote the resultant WORD_LIST before returning. */ +WORD_LIST * +expand_string (string, quoted) + char *string; + int quoted; +{ + WORD_LIST *result; + + if (string == 0 || *string == '\0') + return ((WORD_LIST *)NULL); + + result = expand_string_leave_quoted (string, quoted); + return (result ? dequote_list (result) : result); +} + +/*************************************************** + * * + * Functions to handle quoting chars * + * * + ***************************************************/ + +/* Conventions: + + A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string. + The parser passes CTLNUL as CTLESC CTLNUL. */ + +/* Quote escape characters in string s, but no other characters. This is + used to protect CTLESC and CTLNUL in variable values from the rest of + the word expansion process after the variable is expanded (word splitting + and filename generation). If IFS is null, we quote spaces as well, just + in case we split on spaces later (in the case of unquoted $@, we will + eventually attempt to split the entire word on spaces). Corresponding + code exists in dequote_escapes. Even if we don't end up splitting on + spaces, quoting spaces is not a problem. This should never be called on + a string that is quoted with single or double quotes or part of a here + document (effectively double-quoted). */ +char * +quote_escapes (string) + char *string; +{ + register char *s, *t; + size_t slen; + char *result, *send; + int quote_spaces, skip_ctlesc, skip_ctlnul; + DECLARE_MBSTATE; + + slen = strlen (string); + send = string + slen; + + quote_spaces = (ifs_value && *ifs_value == 0); + + for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++) + skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL; + + t = result = (char *)xmalloc ((slen * 2) + 1); + s = string; + + while (*s) + { + if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' ')) + *t++ = CTLESC; + COPY_CHAR_P (t, s, send); + } + *t = '\0'; + return (result); +} + +static WORD_LIST * +list_quote_escapes (list) + WORD_LIST *list; +{ + register WORD_LIST *w; + char *t; + + for (w = list; w; w = w->next) + { + t = w->word->word; + w->word->word = quote_escapes (t); + free (t); + } + return list; +} + +/* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL. + + The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL. + This is necessary to make unquoted CTLESC and CTLNUL characters in the + data stream pass through properly. + + We need to remove doubled CTLESC characters inside quoted strings before + quoting the entire string, so we do not double the number of CTLESC + characters. + + Also used by parts of the pattern substitution code. */ +char * +dequote_escapes (string) + char *string; +{ + register char *s, *t, *s1; + size_t slen; + char *result, *send; + int quote_spaces; + DECLARE_MBSTATE; + + if (string == 0) + return string; + + slen = strlen (string); + send = string + slen; + + t = result = (char *)xmalloc (slen + 1); + + if (strchr (string, CTLESC) == 0) + return (strcpy (result, string)); + + quote_spaces = (ifs_value && *ifs_value == 0); + + s = string; + while (*s) + { + if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' '))) + { + s++; + if (*s == '\0') + break; + } + COPY_CHAR_P (t, s, send); + } + *t = '\0'; + return result; +} + +/* Return a new string with the quoted representation of character C. + This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be + set in any resultant WORD_DESC where this value is the word. */ +static char * +make_quoted_char (c) + int c; +{ + char *temp; + + temp = (char *)xmalloc (3); + if (c == 0) + { + temp[0] = CTLNUL; + temp[1] = '\0'; + } + else + { + temp[0] = CTLESC; + temp[1] = c; + temp[2] = '\0'; + } + return (temp); +} + +/* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so + the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where + this value is the word. */ +char * +quote_string (string) + char *string; +{ + register char *t; + size_t slen; + char *result, *send; + + if (*string == 0) + { + result = (char *)xmalloc (2); + result[0] = CTLNUL; + result[1] = '\0'; + } + else + { + DECLARE_MBSTATE; + + slen = strlen (string); + send = string + slen; + + result = (char *)xmalloc ((slen * 2) + 1); + + for (t = result; string < send; ) + { + *t++ = CTLESC; + COPY_CHAR_P (t, string, send); + } + *t = '\0'; + } + return (result); +} + +/* De-quote quoted characters in STRING. */ +char * +dequote_string (string) + char *string; +{ + register char *s, *t; + size_t slen; + char *result, *send; + DECLARE_MBSTATE; + + slen = strlen (string); + + t = result = (char *)xmalloc (slen + 1); + + if (QUOTED_NULL (string)) + { + result[0] = '\0'; + return (result); + } + + /* If no character in the string can be quoted, don't bother examining + each character. Just return a copy of the string passed to us. */ + if (strchr (string, CTLESC) == NULL) + return (strcpy (result, string)); + + send = string + slen; + s = string; + while (*s) + { + if (*s == CTLESC) + { + s++; + if (*s == '\0') + break; + } + COPY_CHAR_P (t, s, send); + } + + *t = '\0'; + return (result); +} + +/* Quote the entire WORD_LIST list. */ +static WORD_LIST * +quote_list (list) + WORD_LIST *list; +{ + register WORD_LIST *w; + char *t; + + for (w = list; w; w = w->next) + { + t = w->word->word; + w->word->word = quote_string (t); + if (*t == 0) + w->word->flags |= W_HASQUOTEDNULL; /* XXX - turn on W_HASQUOTEDNULL here? */ + w->word->flags |= W_QUOTED; + free (t); + } + return list; +} + +/* De-quote quoted characters in each word in LIST. */ +WORD_LIST * +dequote_list (list) + WORD_LIST *list; +{ + register char *s; + register WORD_LIST *tlist; + + for (tlist = list; tlist; tlist = tlist->next) + { + s = dequote_string (tlist->word->word); + if (QUOTED_NULL (tlist->word->word)) + tlist->word->flags &= ~W_HASQUOTEDNULL; + free (tlist->word->word); + tlist->word->word = s; + } + return list; +} + +/* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed + string. */ +char * +remove_quoted_escapes (string) + char *string; +{ + char *t; + + if (string) + { + t = dequote_escapes (string); + strcpy (string, t); + free (t); + } + + return (string); +} + +/* Perform quoted null character removal on STRING. We don't allow any + quoted null characters in the middle or at the ends of strings because + of how expand_word_internal works. remove_quoted_nulls () turns + STRING into an empty string iff it only consists of a quoted null, + and removes all unquoted CTLNUL characters. */ +char * +remove_quoted_nulls (string) + char *string; +{ + register size_t slen; + register int i, j, prev_i; + DECLARE_MBSTATE; + + if (strchr (string, CTLNUL) == 0) /* XXX */ + return string; /* XXX */ + + slen = strlen (string); + i = j = 0; + + while (i < slen) + { + if (string[i] == CTLESC) + { + /* Old code had j++, but we cannot assume that i == j at this + point -- what if a CTLNUL has already been removed from the + string? We don't want to drop the CTLESC or recopy characters + that we've already copied down. */ + i++; string[j++] = CTLESC; + if (i == slen) + break; + } + else if (string[i] == CTLNUL) + { + i++; + continue; + } + + prev_i = i; + ADVANCE_CHAR (string, slen, i); + if (j < prev_i) + { + do string[j++] = string[prev_i++]; while (prev_i < i); + } + else + j = i; + } + string[j] = '\0'; + + return (string); +} + +/* Perform quoted null character removal on each element of LIST. + This modifies LIST. */ +void +word_list_remove_quoted_nulls (list) + WORD_LIST *list; +{ + register WORD_LIST *t; + + for (t = list; t; t = t->next) + { + remove_quoted_nulls (t->word->word); + t->word->flags &= ~W_HASQUOTEDNULL; + } +} + +/* **************************************************************** */ +/* */ +/* Functions for Matching and Removing Patterns */ +/* */ +/* **************************************************************** */ + +#if defined (HANDLE_MULTIBYTE) +#if 0 /* Currently unused */ +static unsigned char * +mb_getcharlens (string, len) + char *string; + int len; +{ + int i, offset, last; + unsigned char *ret; + char *p; + DECLARE_MBSTATE; + + i = offset = 0; + last = 0; + ret = (unsigned char *)xmalloc (len); + memset (ret, 0, len); + while (string[last]) + { + ADVANCE_CHAR (string, len, offset); + ret[last] = offset - last; + last = offset; + } + return ret; +} +#endif +#endif + +/* Remove the portion of PARAM matched by PATTERN according to OP, where OP + can have one of 4 values: + RP_LONG_LEFT remove longest matching portion at start of PARAM + RP_SHORT_LEFT remove shortest matching portion at start of PARAM + RP_LONG_RIGHT remove longest matching portion at end of PARAM + RP_SHORT_RIGHT remove shortest matching portion at end of PARAM +*/ + +#define RP_LONG_LEFT 1 +#define RP_SHORT_LEFT 2 +#define RP_LONG_RIGHT 3 +#define RP_SHORT_RIGHT 4 + +/* Returns its first argument if nothing matched; new memory otherwise */ +static char * +remove_upattern (param, pattern, op) + char *param, *pattern; + int op; +{ + register int len; + register char *end; + register char *p, *ret, c; + + len = STRLEN (param); + end = param + len; + + switch (op) + { + case RP_LONG_LEFT: /* remove longest match at start */ + for (p = end; p >= param; p--) + { + c = *p; *p = '\0'; + if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH) + { + *p = c; + return (savestring (p)); + } + *p = c; + + } + break; + + case RP_SHORT_LEFT: /* remove shortest match at start */ + for (p = param; p <= end; p++) + { + c = *p; *p = '\0'; + if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH) + { + *p = c; + return (savestring (p)); + } + *p = c; + } + break; + + case RP_LONG_RIGHT: /* remove longest match at end */ + for (p = param; p <= end; p++) + { + if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH) + { + c = *p; *p = '\0'; + ret = savestring (param); + *p = c; + return (ret); + } + } + break; + + case RP_SHORT_RIGHT: /* remove shortest match at end */ + for (p = end; p >= param; p--) + { + if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH) + { + c = *p; *p = '\0'; + ret = savestring (param); + *p = c; + return (ret); + } + } + break; + } + + return (param); /* no match, return original string */ +} + +#if defined (HANDLE_MULTIBYTE) +/* Returns its first argument if nothing matched; new memory otherwise */ +static wchar_t * +remove_wpattern (wparam, wstrlen, wpattern, op) + wchar_t *wparam; + size_t wstrlen; + wchar_t *wpattern; + int op; +{ + wchar_t wc, *ret; + int n; + + switch (op) + { + case RP_LONG_LEFT: /* remove longest match at start */ + for (n = wstrlen; n >= 0; n--) + { + wc = wparam[n]; wparam[n] = L'\0'; + if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH) + { + wparam[n] = wc; + return (wcsdup (wparam + n)); + } + wparam[n] = wc; + } + break; + + case RP_SHORT_LEFT: /* remove shortest match at start */ + for (n = 0; n <= wstrlen; n++) + { + wc = wparam[n]; wparam[n] = L'\0'; + if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH) + { + wparam[n] = wc; + return (wcsdup (wparam + n)); + } + wparam[n] = wc; + } + break; + + case RP_LONG_RIGHT: /* remove longest match at end */ + for (n = 0; n <= wstrlen; n++) + { + if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH) + { + wc = wparam[n]; wparam[n] = L'\0'; + ret = wcsdup (wparam); + wparam[n] = wc; + return (ret); + } + } + break; + + case RP_SHORT_RIGHT: /* remove shortest match at end */ + for (n = wstrlen; n >= 0; n--) + { + if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH) + { + wc = wparam[n]; wparam[n] = L'\0'; + ret = wcsdup (wparam); + wparam[n] = wc; + return (ret); + } + } + break; + } + + return (wparam); /* no match, return original string */ +} +#endif /* HANDLE_MULTIBYTE */ + +static char * +remove_pattern (param, pattern, op) + char *param, *pattern; + int op; +{ + char *xret; + + if (param == NULL) + return (param); + if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */ + return (savestring (param)); + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1) + { + wchar_t *ret, *oret; + size_t n; + wchar_t *wparam, *wpattern; + mbstate_t ps; + + n = xdupmbstowcs (&wpattern, NULL, pattern); + if (n == (size_t)-1) + { + xret = remove_upattern (param, pattern, op); + return ((xret == param) ? savestring (param) : xret); + } + n = xdupmbstowcs (&wparam, NULL, param); + if (n == (size_t)-1) + { + free (wpattern); + xret = remove_upattern (param, pattern, op); + return ((xret == param) ? savestring (param) : xret); + } + oret = ret = remove_wpattern (wparam, n, wpattern, op); + /* Don't bother to convert wparam back to multibyte string if nothing + matched; just return copy of original string */ + if (ret == wparam) + { + free (wparam); + free (wpattern); + return (savestring (param)); + } + + free (wparam); + free (wpattern); + + n = strlen (param); + xret = (char *)xmalloc (n + 1); + memset (&ps, '\0', sizeof (mbstate_t)); + n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps); + xret[n] = '\0'; /* just to make sure */ + free (oret); + return xret; + } + else +#endif + { + xret = remove_upattern (param, pattern, op); + return ((xret == param) ? savestring (param) : xret); + } +} + +/* Match PAT anywhere in STRING and return the match boundaries. + This returns 1 in case of a successful match, 0 otherwise. SP + and EP are pointers into the string where the match begins and + ends, respectively. MTYPE controls what kind of match is attempted. + MATCH_BEG and MATCH_END anchor the match at the beginning and end + of the string, respectively. The longest match is returned. */ +static int +match_upattern (string, pat, mtype, sp, ep) + char *string, *pat; + int mtype; + char **sp, **ep; +{ + int c, len, mlen; + register char *p, *p1, *npat; + char *end; + int n1; + + /* If the pattern doesn't match anywhere in the string, go ahead and + short-circuit right away. A minor optimization, saves a bunch of + unnecessary calls to strmatch (up to N calls for a string of N + characters) if the match is unsuccessful. To preserve the semantics + of the substring matches below, we make sure that the pattern has + `*' as first and last character, making a new pattern if necessary. */ + /* XXX - check this later if I ever implement `**' with special meaning, + since this will potentially result in `**' at the beginning or end */ + len = STRLEN (pat); + if (pat[0] != '*' || (pat[0] == '*' && pat[1] == LPAREN && extended_glob) || pat[len - 1] != '*') + { + p = npat = (char *)xmalloc (len + 3); + p1 = pat; + if (*p1 != '*' || (*p1 == '*' && p1[1] == LPAREN && extended_glob)) + *p++ = '*'; + while (*p1) + *p++ = *p1++; + if (p1[-1] != '*' || p[-2] == '\\') + *p++ = '*'; + *p = '\0'; + } + else + npat = pat; + c = strmatch (npat, string, FNMATCH_EXTFLAG); + if (npat != pat) + free (npat); + if (c == FNM_NOMATCH) + return (0); + + len = STRLEN (string); + end = string + len; + + mlen = umatchlen (pat, len); + + switch (mtype) + { + case MATCH_ANY: + for (p = string; p <= end; p++) + { + if (match_pattern_char (pat, p)) + { +#if 0 + for (p1 = end; p1 >= p; p1--) +#else + p1 = (mlen == -1) ? end : p + mlen; + /* p1 - p = length of portion of string to be considered + p = current position in string + mlen = number of characters consumed by match (-1 for entire string) + end = end of string + we want to break immediately if the potential match len + is greater than the number of characters remaining in the + string + */ + if (p1 > end) + break; + for ( ; p1 >= p; p1--) +#endif + { + c = *p1; *p1 = '\0'; + if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0) + { + *p1 = c; + *sp = p; + *ep = p1; + return 1; + } + *p1 = c; +#if 1 + /* If MLEN != -1, we have a fixed length pattern. */ + if (mlen != -1) + break; +#endif + } + } + } + + return (0); + + case MATCH_BEG: + if (match_pattern_char (pat, string) == 0) + return (0); + +#if 0 + for (p = end; p >= string; p--) +#else + for (p = (mlen == -1) ? end : string + mlen; p >= string; p--) +#endif + { + c = *p; *p = '\0'; + if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0) + { + *p = c; + *sp = string; + *ep = p; + return 1; + } + *p = c; +#if 1 + /* If MLEN != -1, we have a fixed length pattern. */ + if (mlen != -1) + break; +#endif + } + + return (0); + + case MATCH_END: +#if 0 + for (p = string; p <= end; p++) +#else + for (p = end - ((mlen == -1) ? len : mlen); p <= end; p++) +#endif + { + if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0) + { + *sp = p; + *ep = end; + return 1; + } +#if 1 + /* If MLEN != -1, we have a fixed length pattern. */ + if (mlen != -1) + break; +#endif + } + + return (0); + } + + return (0); +} + +#if defined (HANDLE_MULTIBYTE) +/* Match WPAT anywhere in WSTRING and return the match boundaries. + This returns 1 in case of a successful match, 0 otherwise. Wide + character version. */ +static int +match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep) + wchar_t *wstring; + char **indices; + size_t wstrlen; + wchar_t *wpat; + int mtype; + char **sp, **ep; +{ + wchar_t wc, *wp, *nwpat, *wp1; + size_t len; + int mlen; + int n, n1, n2, simple; + + simple = (wpat[0] != L'\\' && wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'['); +#if defined (EXTENDED_GLOB) + if (extended_glob) + simple &= (wpat[1] != L'(' || (wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'+' && wpat[0] != L'!' && wpat[0] != L'@')); /*)*/ +#endif + + /* If the pattern doesn't match anywhere in the string, go ahead and + short-circuit right away. A minor optimization, saves a bunch of + unnecessary calls to strmatch (up to N calls for a string of N + characters) if the match is unsuccessful. To preserve the semantics + of the substring matches below, we make sure that the pattern has + `*' as first and last character, making a new pattern if necessary. */ + len = wcslen (wpat); + if (wpat[0] != L'*' || (wpat[0] == L'*' && wpat[1] == WLPAREN && extended_glob) || wpat[len - 1] != L'*') + { + wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t)); + wp1 = wpat; + if (*wp1 != L'*' || (*wp1 == '*' && wp1[1] == WLPAREN && extended_glob)) + *wp++ = L'*'; + while (*wp1 != L'\0') + *wp++ = *wp1++; + if (wp1[-1] != L'*' || wp1[-2] == L'\\') + *wp++ = L'*'; + *wp = '\0'; + } + else + nwpat = wpat; + len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG); + if (nwpat != wpat) + free (nwpat); + if (len == FNM_NOMATCH) + return (0); + + mlen = wmatchlen (wpat, wstrlen); + +/* itrace("wmatchlen (%ls) -> %d", wpat, mlen); */ + switch (mtype) + { + case MATCH_ANY: + for (n = 0; n <= wstrlen; n++) + { +#if 1 + n2 = simple ? (*wpat == wstring[n]) : match_pattern_wchar (wpat, wstring + n); +#else + n2 = match_pattern_wchar (wpat, wstring + n); +#endif + if (n2) + { +#if 0 + for (n1 = wstrlen; n1 >= n; n1--) +#else + n1 = (mlen == -1) ? wstrlen : n + mlen; + if (n1 > wstrlen) + break; + + for ( ; n1 >= n; n1--) +#endif + { + wc = wstring[n1]; wstring[n1] = L'\0'; + if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0) + { + wstring[n1] = wc; + *sp = indices[n]; + *ep = indices[n1]; + return 1; + } + wstring[n1] = wc; +#if 1 + /* If MLEN != -1, we have a fixed length pattern. */ + if (mlen != -1) + break; +#endif + } + } + } + + return (0); + + case MATCH_BEG: + if (match_pattern_wchar (wpat, wstring) == 0) + return (0); + +#if 0 + for (n = wstrlen; n >= 0; n--) +#else + for (n = (mlen == -1) ? wstrlen : mlen; n >= 0; n--) +#endif + { + wc = wstring[n]; wstring[n] = L'\0'; + if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0) + { + wstring[n] = wc; + *sp = indices[0]; + *ep = indices[n]; + return 1; + } + wstring[n] = wc; +#if 1 + /* If MLEN != -1, we have a fixed length pattern. */ + if (mlen != -1) + break; +#endif + } + + return (0); + + case MATCH_END: +#if 0 + for (n = 0; n <= wstrlen; n++) +#else + for (n = wstrlen - ((mlen == -1) ? wstrlen : mlen); n <= wstrlen; n++) +#endif + { + if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0) + { + *sp = indices[n]; + *ep = indices[wstrlen]; + return 1; + } +#if 1 + /* If MLEN != -1, we have a fixed length pattern. */ + if (mlen != -1) + break; +#endif + } + + return (0); + } + + return (0); +} +#endif /* HANDLE_MULTIBYTE */ + +static int +match_pattern (string, pat, mtype, sp, ep) + char *string, *pat; + int mtype; + char **sp, **ep; +{ +#if defined (HANDLE_MULTIBYTE) + int ret; + size_t n; + wchar_t *wstring, *wpat; + char **indices; + size_t slen, plen, mslen, mplen; +#endif + + if (string == 0 || *string == 0 || pat == 0 || *pat == 0) + return (0); + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1) + { +#if 0 + slen = STRLEN (string); + mslen = MBSLEN (string); + plen = STRLEN (pat); + mplen = MBSLEN (pat); + if (slen == mslen && plen == mplen) +#else + if (mbsmbchar (string) == 0 && mbsmbchar (pat) == 0) +#endif + return (match_upattern (string, pat, mtype, sp, ep)); + + n = xdupmbstowcs (&wpat, NULL, pat); + if (n == (size_t)-1) + return (match_upattern (string, pat, mtype, sp, ep)); + n = xdupmbstowcs (&wstring, &indices, string); + if (n == (size_t)-1) + { + free (wpat); + return (match_upattern (string, pat, mtype, sp, ep)); + } + ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep); + + free (wpat); + free (wstring); + free (indices); + + return (ret); + } + else +#endif + return (match_upattern (string, pat, mtype, sp, ep)); +} + +static int +getpatspec (c, value) + int c; + char *value; +{ + if (c == '#') + return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT); + else /* c == '%' */ + return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT); +} + +/* Posix.2 says that the WORD should be run through tilde expansion, + parameter expansion, command substitution and arithmetic expansion. + This leaves the result quoted, so quote_string_for_globbing () has + to be called to fix it up for strmatch (). If QUOTED is non-zero, + it means that the entire expression was enclosed in double quotes. + This means that quoting characters in the pattern do not make any + special pattern characters quoted. For example, the `*' in the + following retains its special meaning: "${foo#'*'}". */ +static char * +getpattern (value, quoted, expandpat) + char *value; + int quoted, expandpat; +{ + char *pat, *tword; + WORD_LIST *l; +#if 0 + int i; +#endif + /* There is a problem here: how to handle single or double quotes in the + pattern string when the whole expression is between double quotes? + POSIX.2 says that enclosing double quotes do not cause the pattern to + be quoted, but does that leave us a problem with @ and array[@] and their + expansions inside a pattern? */ +#if 0 + if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword) + { + i = 0; + pat = string_extract_double_quoted (tword, &i, 1); + free (tword); + tword = pat; + } +#endif + + /* expand_string_for_rhs () leaves WORD quoted and does not perform + word splitting. */ + l = *value ? expand_string_for_rhs (value, + (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted, + (int *)NULL, (int *)NULL) + : (WORD_LIST *)0; + pat = string_list (l); + dispose_words (l); + if (pat) + { + tword = quote_string_for_globbing (pat, QGLOB_CVTNULL); + free (pat); + pat = tword; + } + return (pat); +} + +#if 0 +/* Handle removing a pattern from a string as a result of ${name%[%]value} + or ${name#[#]value}. */ +static char * +variable_remove_pattern (value, pattern, patspec, quoted) + char *value, *pattern; + int patspec, quoted; +{ + char *tword; + + tword = remove_pattern (value, pattern, patspec); + + return (tword); +} +#endif + +static char * +list_remove_pattern (list, pattern, patspec, itype, quoted) + WORD_LIST *list; + char *pattern; + int patspec, itype, quoted; +{ + WORD_LIST *new, *l; + WORD_DESC *w; + char *tword; + + for (new = (WORD_LIST *)NULL, l = list; l; l = l->next) + { + tword = remove_pattern (l->word->word, pattern, patspec); + w = alloc_word_desc (); + w->word = tword ? tword : savestring (""); + new = make_word_list (w, new); + } + + l = REVERSE_LIST (new, WORD_LIST *); + tword = string_list_pos_params (itype, l, quoted); + dispose_words (l); + + return (tword); +} + +static char * +parameter_list_remove_pattern (itype, pattern, patspec, quoted) + int itype; + char *pattern; + int patspec, quoted; +{ + char *ret; + WORD_LIST *list; + + list = list_rest_of_args (); + if (list == 0) + return ((char *)NULL); + ret = list_remove_pattern (list, pattern, patspec, itype, quoted); + dispose_words (list); + return (ret); +} + +#if defined (ARRAY_VARS) +static char * +array_remove_pattern (var, pattern, patspec, varname, quoted) + SHELL_VAR *var; + char *pattern; + int patspec; + char *varname; /* so we can figure out how it's indexed */ + int quoted; +{ + ARRAY *a; + HASH_TABLE *h; + int itype; + char *ret; + WORD_LIST *list; + SHELL_VAR *v; + + /* compute itype from varname here */ + v = array_variable_part (varname, &ret, 0); + itype = ret[0]; + + a = (v && array_p (v)) ? array_cell (v) : 0; + h = (v && assoc_p (v)) ? assoc_cell (v) : 0; + + list = a ? array_to_word_list (a) : (h ? assoc_to_word_list (h) : 0); + if (list == 0) + return ((char *)NULL); + ret = list_remove_pattern (list, pattern, patspec, itype, quoted); + dispose_words (list); + + return ret; +} +#endif /* ARRAY_VARS */ + +static char * +parameter_brace_remove_pattern (varname, value, ind, patstr, rtype, quoted, flags) + char *varname, *value; + int ind; + char *patstr; + int rtype, quoted, flags; +{ + int vtype, patspec, starsub; + char *temp1, *val, *pattern; + SHELL_VAR *v; + + if (value == 0) + return ((char *)NULL); + + this_command_name = varname; + + vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); + if (vtype == -1) + return ((char *)NULL); + + starsub = vtype & VT_STARSUB; + vtype &= ~VT_STARSUB; + + patspec = getpatspec (rtype, patstr); + if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT) + patstr++; + + /* Need to pass getpattern newly-allocated memory in case of expansion -- + the expansion code will free the passed string on an error. */ + temp1 = savestring (patstr); + pattern = getpattern (temp1, quoted, 1); + free (temp1); + + temp1 = (char *)NULL; /* shut up gcc */ + switch (vtype) + { + case VT_VARIABLE: + case VT_ARRAYMEMBER: + temp1 = remove_pattern (val, pattern, patspec); + if (vtype == VT_VARIABLE) + FREE (val); + if (temp1) + { + val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) + ? quote_string (temp1) + : quote_escapes (temp1); + free (temp1); + temp1 = val; + } + break; +#if defined (ARRAY_VARS) + case VT_ARRAYVAR: + temp1 = array_remove_pattern (v, pattern, patspec, varname, quoted); + if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0)) + { + val = quote_escapes (temp1); + free (temp1); + temp1 = val; + } + break; +#endif + case VT_POSPARMS: + temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted); + if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0)) + { + val = quote_escapes (temp1); + free (temp1); + temp1 = val; + } + break; + } + + FREE (pattern); + return temp1; +} + +/******************************************* + * * + * Functions to expand WORD_DESCs * + * * + *******************************************/ + +/* Expand WORD, performing word splitting on the result. This does + parameter expansion, command substitution, arithmetic expansion, + word splitting, and quote removal. */ + +WORD_LIST * +expand_word (word, quoted) + WORD_DESC *word; + int quoted; +{ + WORD_LIST *result, *tresult; + + tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL); + result = word_list_split (tresult); + dispose_words (tresult); + return (result ? dequote_list (result) : result); +} + +/* Expand WORD, but do not perform word splitting on the result. This + does parameter expansion, command substitution, arithmetic expansion, + and quote removal. */ +WORD_LIST * +expand_word_unsplit (word, quoted) + WORD_DESC *word; + int quoted; +{ + WORD_LIST *result; + + expand_no_split_dollar_star = 1; +#if defined (HANDLE_MULTIBYTE) + if (ifs_firstc[0] == 0) +#else + if (ifs_firstc == 0) +#endif + word->flags |= W_NOSPLIT; + word->flags |= W_NOSPLIT2; + result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL); + expand_no_split_dollar_star = 0; + + return (result ? dequote_list (result) : result); +} + +/* Perform shell expansions on WORD, but do not perform word splitting or + quote removal on the result. Virtually identical to expand_word_unsplit; + could be combined if implementations don't diverge. */ +WORD_LIST * +expand_word_leave_quoted (word, quoted) + WORD_DESC *word; + int quoted; +{ + WORD_LIST *result; + + expand_no_split_dollar_star = 1; +#if defined (HANDLE_MULTIBYTE) + if (ifs_firstc[0] == 0) +#else + if (ifs_firstc == 0) +#endif + word->flags |= W_NOSPLIT; + word->flags |= W_NOSPLIT2; + result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL); + expand_no_split_dollar_star = 0; + + return result; +} + +#if defined (PROCESS_SUBSTITUTION) + +/*****************************************************************/ +/* */ +/* Hacking Process Substitution */ +/* */ +/*****************************************************************/ + +#if !defined (HAVE_DEV_FD) +/* Named pipes must be removed explicitly with `unlink'. This keeps a list + of FIFOs the shell has open. unlink_fifo_list will walk the list and + unlink all of them. add_fifo_list adds the name of an open FIFO to the + list. NFIFO is a count of the number of FIFOs in the list. */ +#define FIFO_INCR 20 + +struct temp_fifo { + char *file; + pid_t proc; +}; + +static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL; +static int nfifo; +static int fifo_list_size; + +char * +copy_fifo_list (sizep) + int *sizep; +{ + if (sizep) + *sizep = 0; + return (char *)NULL; +} + +static void +add_fifo_list (pathname) + char *pathname; +{ + if (nfifo >= fifo_list_size - 1) + { + fifo_list_size += FIFO_INCR; + fifo_list = (struct temp_fifo *)xrealloc (fifo_list, + fifo_list_size * sizeof (struct temp_fifo)); + } + + fifo_list[nfifo].file = savestring (pathname); + nfifo++; +} + +void +unlink_fifo (i) + int i; +{ + if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1)) + { + unlink (fifo_list[i].file); + free (fifo_list[i].file); + fifo_list[i].file = (char *)NULL; + fifo_list[i].proc = -1; + } +} + +void +unlink_fifo_list () +{ + int saved, i, j; + + if (nfifo == 0) + return; + + for (i = saved = 0; i < nfifo; i++) + { + if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1)) + { + unlink (fifo_list[i].file); + free (fifo_list[i].file); + fifo_list[i].file = (char *)NULL; + fifo_list[i].proc = -1; + } + else + saved++; + } + + /* If we didn't remove some of the FIFOs, compact the list. */ + if (saved) + { + for (i = j = 0; i < nfifo; i++) + if (fifo_list[i].file) + { + fifo_list[j].file = fifo_list[i].file; + fifo_list[j].proc = fifo_list[i].proc; + j++; + } + nfifo = j; + } + else + nfifo = 0; +} + +/* Take LIST, which is a bitmap denoting active FIFOs in fifo_list + from some point in the past, and close all open FIFOs in fifo_list + that are not marked as active in LIST. If LIST is NULL, close + everything in fifo_list. LSIZE is the number of elements in LIST, in + case it's larger than fifo_list_size (size of fifo_list). */ +void +close_new_fifos (list, lsize) + char *list; + int lsize; +{ + int i; + + if (list == 0) + { + unlink_fifo_list (); + return; + } + + for (i = 0; i < lsize; i++) + if (list[i] == 0 && i < fifo_list_size && fifo_list[i].proc != -1) + unlink_fifo (i); + + for (i = lsize; i < fifo_list_size; i++) + unlink_fifo (i); +} + +int +fifos_pending () +{ + return nfifo; +} + +int +num_fifos () +{ + return nfifo; +} + +static char * +make_named_pipe () +{ + char *tname; + + tname = sh_mktmpname ("sh-np", MT_USERANDOM|MT_USETMPDIR); + if (mkfifo (tname, 0600) < 0) + { + free (tname); + return ((char *)NULL); + } + + add_fifo_list (tname); + return (tname); +} + +#else /* HAVE_DEV_FD */ + +/* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell + has open to children. NFDS is a count of the number of bits currently + set in DEV_FD_LIST. TOTFDS is a count of the highest possible number + of open files. */ +static char *dev_fd_list = (char *)NULL; +static int nfds; +static int totfds; /* The highest possible number of open files. */ + +char * +copy_fifo_list (sizep) + int *sizep; +{ + char *ret; + + if (nfds == 0 || totfds == 0) + { + if (sizep) + *sizep = 0; + return (char *)NULL; + } + + if (sizep) + *sizep = totfds; + ret = (char *)xmalloc (totfds); + return (memcpy (ret, dev_fd_list, totfds)); +} + +static void +add_fifo_list (fd) + int fd; +{ + if (dev_fd_list == 0 || fd >= totfds) + { + int ofds; + + ofds = totfds; + totfds = getdtablesize (); + if (totfds < 0 || totfds > 256) + totfds = 256; + if (fd >= totfds) + totfds = fd + 2; + + dev_fd_list = (char *)xrealloc (dev_fd_list, totfds); + memset (dev_fd_list + ofds, '\0', totfds - ofds); + } + + dev_fd_list[fd] = 1; + nfds++; +} + +int +fifos_pending () +{ + return 0; /* used for cleanup; not needed with /dev/fd */ +} + +int +num_fifos () +{ + return nfds; +} + +void +unlink_fifo (fd) + int fd; +{ + if (dev_fd_list[fd]) + { + close (fd); + dev_fd_list[fd] = 0; + nfds--; + } +} + +void +unlink_fifo_list () +{ + register int i; + + if (nfds == 0) + return; + + for (i = 0; nfds && i < totfds; i++) + unlink_fifo (i); + + nfds = 0; +} + +/* Take LIST, which is a snapshot copy of dev_fd_list from some point in + the past, and close all open fds in dev_fd_list that are not marked + as open in LIST. If LIST is NULL, close everything in dev_fd_list. + LSIZE is the number of elements in LIST, in case it's larger than + totfds (size of dev_fd_list). */ +void +close_new_fifos (list, lsize) + char *list; + int lsize; +{ + int i; + + if (list == 0) + { + unlink_fifo_list (); + return; + } + + for (i = 0; i < lsize; i++) + if (list[i] == 0 && i < totfds && dev_fd_list[i]) + unlink_fifo (i); + + for (i = lsize; i < totfds; i++) + unlink_fifo (i); +} + +#if defined (NOTDEF) +print_dev_fd_list () +{ + register int i; + + fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ()); + fflush (stderr); + + for (i = 0; i < totfds; i++) + { + if (dev_fd_list[i]) + fprintf (stderr, " %d", i); + } + fprintf (stderr, "\n"); +} +#endif /* NOTDEF */ + +static char * +make_dev_fd_filename (fd) + int fd; +{ + char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p; + + ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 8); + + strcpy (ret, DEV_FD_PREFIX); + p = inttostr (fd, intbuf, sizeof (intbuf)); + strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p); + + add_fifo_list (fd); + return (ret); +} + +#endif /* HAVE_DEV_FD */ + +/* Return a filename that will open a connection to the process defined by + executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return + a filename in /dev/fd corresponding to a descriptor that is one of the + ends of the pipe. If not defined, we use named pipes on systems that have + them. Systems without /dev/fd and named pipes are out of luck. + + OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or + use the read end of the pipe and dup that file descriptor to fd 0 in + the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for + writing or use the write end of the pipe in the child, and dup that + file descriptor to fd 1 in the child. The parent does the opposite. */ + +static char * +process_substitute (string, open_for_read_in_child) + char *string; + int open_for_read_in_child; +{ + char *pathname; + int fd, result; + pid_t old_pid, pid; +#if defined (HAVE_DEV_FD) + int parent_pipe_fd, child_pipe_fd; + int fildes[2]; +#endif /* HAVE_DEV_FD */ +#if defined (JOB_CONTROL) + pid_t old_pipeline_pgrp; +#endif + + if (!string || !*string || wordexp_only) + return ((char *)NULL); + +#if !defined (HAVE_DEV_FD) + pathname = make_named_pipe (); +#else /* HAVE_DEV_FD */ + if (pipe (fildes) < 0) + { + sys_error (_("cannot make pipe for process substitution")); + return ((char *)NULL); + } + /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of + the pipe in the parent, otherwise the read end. */ + parent_pipe_fd = fildes[open_for_read_in_child]; + child_pipe_fd = fildes[1 - open_for_read_in_child]; + /* Move the parent end of the pipe to some high file descriptor, to + avoid clashes with FDs used by the script. */ + parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64); + + pathname = make_dev_fd_filename (parent_pipe_fd); +#endif /* HAVE_DEV_FD */ + + if (pathname == 0) + { + sys_error (_("cannot make pipe for process substitution")); + return ((char *)NULL); + } + + old_pid = last_made_pid; + +#if defined (JOB_CONTROL) + old_pipeline_pgrp = pipeline_pgrp; + pipeline_pgrp = shell_pgrp; + save_pipeline (1); +#endif /* JOB_CONTROL */ + + pid = make_child ((char *)NULL, 1); + if (pid == 0) + { + reset_terminating_signals (); /* XXX */ + free_pushed_string_input (); + /* Cancel traps, in trap.c. */ + restore_original_signals (); /* XXX - what about special builtins? bash-4.2 */ + setup_async_signals (); + subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB; + } + +#if defined (JOB_CONTROL) + set_sigchld_handler (); + stop_making_children (); + /* XXX - should we only do this in the parent? (as in command subst) */ + pipeline_pgrp = old_pipeline_pgrp; +#endif /* JOB_CONTROL */ + + if (pid < 0) + { + sys_error (_("cannot make child for process substitution")); + free (pathname); +#if defined (HAVE_DEV_FD) + close (parent_pipe_fd); + close (child_pipe_fd); +#endif /* HAVE_DEV_FD */ + return ((char *)NULL); + } + + if (pid > 0) + { +#if defined (JOB_CONTROL) + restore_pipeline (1); +#endif + +#if !defined (HAVE_DEV_FD) + fifo_list[nfifo-1].proc = pid; +#endif + + last_made_pid = old_pid; + +#if defined (JOB_CONTROL) && defined (PGRP_PIPE) + close_pgrp_pipe (); +#endif /* JOB_CONTROL && PGRP_PIPE */ + +#if defined (HAVE_DEV_FD) + close (child_pipe_fd); +#endif /* HAVE_DEV_FD */ + + return (pathname); + } + + set_sigint_handler (); + +#if defined (JOB_CONTROL) + set_job_control (0); +#endif /* JOB_CONTROL */ + +#if !defined (HAVE_DEV_FD) + /* Open the named pipe in the child. */ + fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY); + if (fd < 0) + { + /* Two separate strings for ease of translation. */ + if (open_for_read_in_child) + sys_error (_("cannot open named pipe %s for reading"), pathname); + else + sys_error (_("cannot open named pipe %s for writing"), pathname); + + exit (127); + } + if (open_for_read_in_child) + { + if (sh_unset_nodelay_mode (fd) < 0) + { + sys_error (_("cannot reset nodelay mode for fd %d"), fd); + exit (127); + } + } +#else /* HAVE_DEV_FD */ + fd = child_pipe_fd; +#endif /* HAVE_DEV_FD */ + + if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0) + { + sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname, + open_for_read_in_child ? 0 : 1); + exit (127); + } + + if (fd != (open_for_read_in_child ? 0 : 1)) + close (fd); + + /* Need to close any files that this process has open to pipes inherited + from its parent. */ + if (current_fds_to_close) + { + close_fd_bitmap (current_fds_to_close); + current_fds_to_close = (struct fd_bitmap *)NULL; + } + +#if defined (HAVE_DEV_FD) + /* Make sure we close the parent's end of the pipe and clear the slot + in the fd list so it is not closed later, if reallocated by, for + instance, pipe(2). */ + close (parent_pipe_fd); + dev_fd_list[parent_pipe_fd] = 0; +#endif /* HAVE_DEV_FD */ + + result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST)); + +#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 */ + + exit (result); + /*NOTREACHED*/ +} +#endif /* PROCESS_SUBSTITUTION */ + +/***********************************/ +/* */ +/* Command Substitution */ +/* */ +/***********************************/ + +static char * +read_comsub (fd, quoted, rflag) + int fd, quoted; + int *rflag; +{ + char *istring, buf[128], *bufp, *s; + int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul; + ssize_t bufn; + + istring = (char *)NULL; + istring_index = istring_size = bufn = tflag = 0; + + for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++) + skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL; + + /* Read the output of the command through the pipe. This may need to be + changed to understand multibyte characters in the future. */ + while (1) + { + if (fd < 0) + break; + if (--bufn <= 0) + { + bufn = zread (fd, buf, sizeof (buf)); + if (bufn <= 0) + break; + bufp = buf; + } + c = *bufp++; + + if (c == 0) + { +#if 0 + internal_warning ("read_comsub: ignored null byte in input"); +#endif + continue; + } + + /* Add the character to ISTRING, possibly after resizing it. */ + RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE); + + /* This is essentially quote_string inline */ + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */) + istring[istring_index++] = CTLESC; + /* Escape CTLESC and CTLNUL in the output to protect those characters + from the rest of the word expansions (word splitting and globbing.) + This is essentially quote_escapes inline. */ + else if (skip_ctlesc == 0 && c == CTLESC) + { + tflag |= W_HASCTLESC; + istring[istring_index++] = CTLESC; + } + else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0))) + istring[istring_index++] = CTLESC; + + istring[istring_index++] = c; + +#if 0 +#if defined (__CYGWIN__) + if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r') + { + istring_index--; + istring[istring_index - 1] = '\n'; + } +#endif +#endif + } + + if (istring) + istring[istring_index] = '\0'; + + /* If we read no output, just return now and save ourselves some + trouble. */ + if (istring_index == 0) + { + FREE (istring); + if (rflag) + *rflag = tflag; + return (char *)NULL; + } + + /* Strip trailing newlines from the output of the command. */ + if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) + { + while (istring_index > 0) + { + if (istring[istring_index - 1] == '\n') + { + --istring_index; + + /* If the newline was quoted, remove the quoting char. */ + if (istring[istring_index - 1] == CTLESC) + --istring_index; + } + else + break; + } + istring[istring_index] = '\0'; + } + else + strip_trailing (istring, istring_index - 1, 1); + + if (rflag) + *rflag = tflag; + return istring; +} + +/* Perform command substitution on STRING. This returns a WORD_DESC * with the + contained string possibly quoted. */ +WORD_DESC * +command_substitute (string, quoted) + char *string; + int quoted; +{ + pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid; + char *istring; + int result, fildes[2], function_value, pflags, rc, tflag; + WORD_DESC *ret; + + istring = (char *)NULL; + + /* Don't fork () if there is no need to. In the case of no command to + run, just return NULL. */ + if (!string || !*string || (string[0] == '\n' && !string[1])) + return ((WORD_DESC *)NULL); + + if (wordexp_only && read_but_dont_execute) + { + last_command_exit_value = EX_WEXPCOMSUB; + jump_to_top_level (EXITPROG); + } + + /* We're making the assumption here that the command substitution will + eventually run a command from the file system. Since we'll run + maybe_make_export_env in this subshell before executing that command, + the parent shell and any other shells it starts will have to remake + the environment. If we make it before we fork, other shells won't + have to. Don't bother if we have any temporary variable assignments, + though, because the export environment will be remade after this + command completes anyway, but do it if all the words to be expanded + are variable assignments. */ + if (subst_assign_varlist == 0 || garglist == 0) + maybe_make_export_env (); /* XXX */ + + /* Flags to pass to parse_and_execute() */ + pflags = (interactive && sourcelevel == 0) ? SEVAL_RESETLINE : 0; + + /* Pipe the output of executing STRING into the current shell. */ + if (pipe (fildes) < 0) + { + sys_error (_("cannot make pipe for command substitution")); + goto error_exit; + } + + old_pid = last_made_pid; +#if defined (JOB_CONTROL) + old_pipeline_pgrp = pipeline_pgrp; + /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */ + if ((subshell_environment & SUBSHELL_PIPE) == 0) + pipeline_pgrp = shell_pgrp; + cleanup_the_pipeline (); +#endif /* JOB_CONTROL */ + + old_async_pid = last_asynchronous_pid; + pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC); + last_asynchronous_pid = old_async_pid; + + if (pid == 0) + { + /* Reset the signal handlers in the child, but don't free the + trap strings. Set a flag noting that we have to free the + trap strings if we run trap to change a signal disposition. */ + reset_signal_handlers (); + subshell_environment |= SUBSHELL_RESETTRAP; + } + +#if defined (JOB_CONTROL) + /* XXX DO THIS ONLY IN PARENT ? XXX */ + set_sigchld_handler (); + stop_making_children (); + if (pid != 0) + pipeline_pgrp = old_pipeline_pgrp; +#else + stop_making_children (); +#endif /* JOB_CONTROL */ + + if (pid < 0) + { + sys_error (_("cannot make child for command substitution")); + error_exit: + + FREE (istring); + close (fildes[0]); + close (fildes[1]); + return ((WORD_DESC *)NULL); + } + + if (pid == 0) + { + set_sigint_handler (); /* XXX */ + + free_pushed_string_input (); + + if (dup2 (fildes[1], 1) < 0) + { + sys_error (_("command_substitute: cannot duplicate pipe as fd 1")); + exit (EXECUTION_FAILURE); + } + + /* If standard output is closed in the parent shell + (such as after `exec >&-'), file descriptor 1 will be + the lowest available file descriptor, and end up in + fildes[0]. This can happen for stdin and stderr as well, + but stdout is more important -- it will cause no output + to be generated from this command. */ + if ((fildes[1] != fileno (stdin)) && + (fildes[1] != fileno (stdout)) && + (fildes[1] != fileno (stderr))) + close (fildes[1]); + + if ((fildes[0] != fileno (stdin)) && + (fildes[0] != fileno (stdout)) && + (fildes[0] != fileno (stderr))) + close (fildes[0]); + +#ifdef __CYGWIN__ + /* Let stdio know the fd may have changed from text to binary mode, and + make sure to preserve stdout line buffering. */ + freopen (NULL, "w", stdout); + sh_setlinebuf (stdout); +#endif /* __CYGWIN__ */ + + /* The currently executing shell is not interactive. */ + interactive = 0; + + /* This is a subshell environment. */ + subshell_environment |= SUBSHELL_COMSUB; + + /* When not in POSIX mode, command substitution does not inherit + the -e flag. */ + if (posixly_correct == 0) + exit_immediately_on_error = 0; + + remove_quoted_escapes (string); + + startup_state = 2; /* see if we can avoid a fork */ + /* Give command substitution a place to jump back to on failure, + so we don't go back up to main (). */ + result = setjmp (top_level); + + /* If we're running a command 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 (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, "command substitution", pflags|SEVAL_NOHIST); + subshell_level--; + } + + last_command_exit_value = rc; + rc = run_exit_trap (); +#if defined (PROCESS_SUBSTITUTION) + unlink_fifo_list (); +#endif + exit (rc); + } + else + { +#if defined (JOB_CONTROL) && defined (PGRP_PIPE) + close_pgrp_pipe (); +#endif /* JOB_CONTROL && PGRP_PIPE */ + + close (fildes[1]); + + tflag = 0; + istring = read_comsub (fildes[0], quoted, &tflag); + + close (fildes[0]); + + current_command_subst_pid = pid; + last_command_exit_value = wait_for (pid); + last_command_subst_pid = pid; + last_made_pid = old_pid; + +#if defined (JOB_CONTROL) + /* If last_command_exit_value > 128, then the substituted command + was terminated by a signal. If that signal was SIGINT, then send + SIGINT to ourselves. This will break out of loops, for instance. */ + if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT) + kill (getpid (), SIGINT); + + /* wait_for gives the terminal back to shell_pgrp. If some other + process group should have it, give it away to that group here. + pipeline_pgrp is non-zero only while we are constructing a + pipline, so what we are concerned about is whether or not that + pipeline was started in the background. A pipeline started in + the background should never get the tty back here. */ + if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0) + give_terminal_to (pipeline_pgrp, 0); +#endif /* JOB_CONTROL */ + + ret = alloc_word_desc (); + ret->word = istring; + ret->flags = tflag; + + return ret; + } +} + +/******************************************************** + * * + * Utility functions for parameter expansion * + * * + ********************************************************/ + +#if defined (ARRAY_VARS) + +static arrayind_t +array_length_reference (s) + char *s; +{ + int len; + arrayind_t ind; + char *akey; + char *t, c; + ARRAY *array; + HASH_TABLE *h; + SHELL_VAR *var; + + var = array_variable_part (s, &t, &len); + + /* If unbound variables should generate an error, report one and return + failure. */ + if ((var == 0 || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error) + { + c = *--t; + *t = '\0'; + last_command_exit_value = EXECUTION_FAILURE; + err_unboundvar (s); + *t = c; + return (-1); + } + else if (var == 0) + return 0; + + /* We support a couple of expansions for variables that are not arrays. + We'll return the length of the value for v[0], and 1 for v[@] or + v[*]. Return 0 for everything else. */ + + array = array_p (var) ? array_cell (var) : (ARRAY *)NULL; + h = assoc_p (var) ? assoc_cell (var) : (HASH_TABLE *)NULL; + + if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']') + { + if (assoc_p (var)) + return (h ? assoc_num_elements (h) : 0); + else if (array_p (var)) + return (array ? array_num_elements (array) : 0); + else + return (var_isset (var) ? 1 : 0); + } + + if (assoc_p (var)) + { + t[len - 1] = '\0'; + akey = expand_assignment_string_to_string (t, 0); /* [ */ + t[len - 1] = ']'; + if (akey == 0 || *akey == 0) + { + err_badarraysub (t); + FREE (akey); + return (-1); + } + t = assoc_reference (assoc_cell (var), akey); + free (akey); + } + else + { + ind = array_expand_index (var, t, len); + if (ind < 0) + { + err_badarraysub (t); + return (-1); + } + if (array_p (var)) + t = array_reference (array, ind); + else + t = (ind == 0) ? value_cell (var) : (char *)NULL; + } + + len = MB_STRLEN (t); + return (len); +} +#endif /* ARRAY_VARS */ + +static int +valid_brace_expansion_word (name, var_is_special) + char *name; + int var_is_special; +{ + if (DIGIT (*name) && all_digits (name)) + return 1; + else if (var_is_special) + return 1; +#if defined (ARRAY_VARS) + else if (valid_array_reference (name)) + return 1; +#endif /* ARRAY_VARS */ + else if (legal_identifier (name)) + return 1; + else + return 0; +} + +static int +chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at) + char *name; + int quoted; + int *quoted_dollar_atp, *contains_dollar_at; +{ + char *temp1; + + if (name == 0) + { + if (quoted_dollar_atp) + *quoted_dollar_atp = 0; + if (contains_dollar_at) + *contains_dollar_at = 0; + return 0; + } + + /* check for $@ and $* */ + if (name[0] == '@' && name[1] == 0) + { + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) + *quoted_dollar_atp = 1; + if (contains_dollar_at) + *contains_dollar_at = 1; + return 1; + } + else if (name[0] == '*' && name[1] == '\0' && quoted == 0) + { + if (contains_dollar_at) + *contains_dollar_at = 1; + return 1; + } + + /* Now check for ${array[@]} and ${array[*]} */ +#if defined (ARRAY_VARS) + else if (valid_array_reference (name)) + { + temp1 = mbschr (name, '['); + if (temp1 && temp1[1] == '@' && temp1[2] == ']') + { + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) + *quoted_dollar_atp = 1; + if (contains_dollar_at) + *contains_dollar_at = 1; + return 1; + } /* [ */ + /* ${array[*]}, when unquoted, should be treated like ${array[@]}, + which should result in separate words even when IFS is unset. */ + if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0) + { + if (contains_dollar_at) + *contains_dollar_at = 1; + return 1; + } + } +#endif + return 0; +} + +/* Parameter expand NAME, and return a new string which is the expansion, + or NULL if there was no expansion. + VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in + the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that + NAME was found inside of a double-quoted expression. */ +static WORD_DESC * +parameter_brace_expand_word (name, var_is_special, quoted, pflags, indp) + char *name; + int var_is_special, quoted, pflags; + arrayind_t *indp; +{ + WORD_DESC *ret; + char *temp, *tt; + intmax_t arg_index; + SHELL_VAR *var; + int atype, rflags; + arrayind_t ind; + + ret = 0; + temp = 0; + rflags = 0; + + if (indp) + *indp = INTMAX_MIN; + + /* Handle multiple digit arguments, as in ${11}. */ + if (legal_number (name, &arg_index)) + { + tt = get_dollar_var_value (arg_index); + if (tt) + temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) + ? quote_string (tt) + : quote_escapes (tt); + else + temp = (char *)NULL; + FREE (tt); + } + else if (var_is_special) /* ${@} */ + { + int sindex; + tt = (char *)xmalloc (2 + strlen (name)); + tt[sindex = 0] = '$'; + strcpy (tt + 1, name); + + ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL, + (int *)NULL, (int *)NULL, pflags); + free (tt); + } +#if defined (ARRAY_VARS) + else if (valid_array_reference (name)) + { + /* XXX - does this leak if name[@] or name[*]? */ + temp = array_value (name, quoted, 0, &atype, &ind); + if (atype == 0 && temp) + { + temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) + ? quote_string (temp) + : quote_escapes (temp); + rflags |= W_ARRAYIND; + if (indp) + *indp = ind; + } + else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) + rflags |= W_HASQUOTEDNULL; + } +#endif + else if (var = find_variable (name)) + { + if (var_isset (var) && invisible_p (var) == 0) + { +#if defined (ARRAY_VARS) + if (assoc_p (var)) + temp = assoc_reference (assoc_cell (var), "0"); + else if (array_p (var)) + temp = array_reference (array_cell (var), 0); + else + temp = value_cell (var); +#else + temp = value_cell (var); +#endif + + if (temp) + temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) + ? quote_string (temp) + : quote_escapes (temp); + } + else + temp = (char *)NULL; + } + else + temp = (char *)NULL; + + if (ret == 0) + { + ret = alloc_word_desc (); + ret->word = temp; + ret->flags |= rflags; + } + return ret; +} + +/* Expand an indirect reference to a variable: ${!NAME} expands to the + value of the variable whose name is the value of NAME. */ +static WORD_DESC * +parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at) + char *name; + int var_is_special, quoted; + int *quoted_dollar_atp, *contains_dollar_at; +{ + char *temp, *t; + WORD_DESC *w; + + w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND, 0); + t = w->word; + /* Have to dequote here if necessary */ + if (t) + { + temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) + ? dequote_string (t) + : dequote_escapes (t); + free (t); + t = temp; + } + dispose_word_desc (w); + + chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at); + if (t == 0) + return (WORD_DESC *)NULL; + + w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0, 0); + free (t); + + return w; +} + +/* Expand the right side of a parameter expansion of the form ${NAMEcVALUE}, + depending on the value of C, the separating character. C can be one of + "-", "+", or "=". QUOTED is true if the entire brace expression occurs + between double quotes. */ +static WORD_DESC * +parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat) + char *name, *value; + int c, quoted, *qdollaratp, *hasdollarat; +{ + WORD_DESC *w; + WORD_LIST *l; + char *t, *t1, *temp; + int hasdol; + + /* If the entire expression is between double quotes, we want to treat + the value as a double-quoted string, with the exception that we strip + embedded unescaped double quotes (for sh backwards compatibility). */ + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value) + { + hasdol = 0; + temp = string_extract_double_quoted (value, &hasdol, 1); + } + else + temp = value; + + w = alloc_word_desc (); + hasdol = 0; + /* XXX was 0 not quoted */ + l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL) + : (WORD_LIST *)0; + if (hasdollarat) + *hasdollarat = hasdol || (l && l->next); + if (temp != value) + free (temp); + if (l) + { + /* The expansion of TEMP returned something. We need to treat things + slightly differently if HASDOL is non-zero. If we have "$@", the + individual words have already been quoted. We need to turn them + into a string with the words separated by the first character of + $IFS without any additional quoting, so string_list_dollar_at won't + do the right thing. We use string_list_dollar_star instead. */ + temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l); + + /* If l->next is not null, we know that TEMP contained "$@", since that + is the only expansion that creates more than one word. */ + if (qdollaratp && ((hasdol && quoted) || l->next)) + *qdollaratp = 1; + /* If we have a quoted null result (QUOTED_NULL(temp)) and the word is + a quoted null (l->next == 0 && QUOTED_NULL(l->word->word)), the + flags indicate it (l->word->flags & W_HASQUOTEDNULL), and the + expansion is quoted (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) + (which is more paranoia than anything else), we need to return the + quoted null string and set the flags to indicate it. */ + if (l->next == 0 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL (temp) && QUOTED_NULL (l->word->word) && (l->word->flags & W_HASQUOTEDNULL)) + { + w->flags |= W_HASQUOTEDNULL; + } + dispose_words (l); + } + else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol) + { + /* The brace expansion occurred between double quotes and there was + a $@ in TEMP. It does not matter if the $@ is quoted, as long as + it does not expand to anything. In this case, we want to return + a quoted empty string. */ + temp = make_quoted_char ('\0'); + w->flags |= W_HASQUOTEDNULL; + } + else + temp = (char *)NULL; + + if (c == '-' || c == '+') + { + w->word = temp; + return w; + } + + /* c == '=' */ + t = temp ? savestring (temp) : savestring (""); + t1 = dequote_string (t); + free (t); +#if defined (ARRAY_VARS) + if (valid_array_reference (name)) + assign_array_element (name, t1, 0); + else +#endif /* ARRAY_VARS */ + bind_variable (name, t1, 0); + + /* From Posix group discussion Feb-March 2010. Issue 7 0000221 */ + free (temp); + + w->word = t1; + return w; +} + +/* Deal with the right hand side of a ${name:?value} expansion in the case + that NAME is null or not set. If VALUE is non-null it is expanded and + used as the error message to print, otherwise a standard message is + printed. */ +static void +parameter_brace_expand_error (name, value) + char *name, *value; +{ + WORD_LIST *l; + char *temp; + + last_command_exit_value = EXECUTION_FAILURE; /* ensure it's non-zero */ + if (value && *value) + { + l = expand_string (value, 0); + temp = string_list (l); + report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */ + FREE (temp); + dispose_words (l); + } + else + report_error (_("%s: parameter null or not set"), name); + + /* Free the data we have allocated during this expansion, since we + are about to longjmp out. */ + free (name); + FREE (value); +} + +/* Return 1 if NAME is something for which parameter_brace_expand_length is + OK to do. */ +static int +valid_length_expression (name) + char *name; +{ + return (name[1] == '\0' || /* ${#} */ + ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */ + (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */ +#if defined (ARRAY_VARS) + valid_array_reference (name + 1) || /* ${#a[7]} */ +#endif + legal_identifier (name + 1)); /* ${#PS1} */ +} + +/* Handle the parameter brace expansion that requires us to return the + length of a parameter. */ +static intmax_t +parameter_brace_expand_length (name) + char *name; +{ + char *t, *newname; + intmax_t number, arg_index; + WORD_LIST *list; +#if defined (ARRAY_VARS) + SHELL_VAR *var; +#endif + + if (name[1] == '\0') /* ${#} */ + number = number_of_args (); + else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */ + number = number_of_args (); + else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') + { + /* Take the lengths of some of the shell's special parameters. */ + switch (name[1]) + { + case '-': + t = which_set_flags (); + break; + case '?': + t = itos (last_command_exit_value); + break; + case '$': + t = itos (dollar_dollar_pid); + break; + case '!': + if (last_asynchronous_pid == NO_PID) + t = (char *)NULL; /* XXX - error if set -u set? */ + else + t = itos (last_asynchronous_pid); + break; + case '#': + t = itos (number_of_args ()); + break; + } + number = STRLEN (t); + FREE (t); + } +#if defined (ARRAY_VARS) + else if (valid_array_reference (name + 1)) + number = array_length_reference (name + 1); +#endif /* ARRAY_VARS */ + else + { + number = 0; + + if (legal_number (name + 1, &arg_index)) /* ${#1} */ + { + t = get_dollar_var_value (arg_index); + if (t == 0 && unbound_vars_is_error) + return INTMAX_MIN; + number = MB_STRLEN (t); + FREE (t); + } +#if defined (ARRAY_VARS) + else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var))) + { + if (assoc_p (var)) + t = assoc_reference (assoc_cell (var), "0"); + else + t = array_reference (array_cell (var), 0); + if (t == 0 && unbound_vars_is_error) + return INTMAX_MIN; + number = MB_STRLEN (t); + } +#endif + else /* ${#PS1} */ + { + newname = savestring (name); + newname[0] = '$'; + list = expand_string (newname, Q_DOUBLE_QUOTES); + t = list ? string_list (list) : (char *)NULL; + free (newname); + if (list) + dispose_words (list); + + number = t ? MB_STRLEN (t) : 0; + FREE (t); + } + } + + return (number); +} + +/* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression, + so we do some ad-hoc parsing of an arithmetic expression to find + the first DELIM, instead of using strchr(3). Two rules: + 1. If the substring contains a `(', read until closing `)'. + 2. If the substring contains a `?', read past one `:' for each `?'. +*/ + +static char * +skiparith (substr, delim) + char *substr; + int delim; +{ + size_t sublen; + int skipcol, pcount, i; + DECLARE_MBSTATE; + + sublen = strlen (substr); + i = skipcol = pcount = 0; + while (substr[i]) + { + /* Balance parens */ + if (substr[i] == LPAREN) + { + pcount++; + i++; + continue; + } + if (substr[i] == RPAREN && pcount) + { + pcount--; + i++; + continue; + } + if (pcount) + { + ADVANCE_CHAR (substr, sublen, i); + continue; + } + + /* Skip one `:' for each `?' */ + if (substr[i] == ':' && skipcol) + { + skipcol--; + i++; + continue; + } + if (substr[i] == delim) + break; + if (substr[i] == '?') + { + skipcol++; + i++; + continue; + } + ADVANCE_CHAR (substr, sublen, i); + } + + return (substr + i); +} + +/* Verify and limit the start and end of the desired substring. If + VTYPE == 0, a regular shell variable is being used; if it is 1, + then the positional parameters are being used; if it is 2, then + VALUE is really a pointer to an array variable that should be used. + Return value is 1 if both values were OK, 0 if there was a problem + with an invalid expression, or -1 if the values were out of range. */ +static int +verify_substring_values (v, value, substr, vtype, e1p, e2p) + SHELL_VAR *v; + char *value, *substr; + int vtype; + intmax_t *e1p, *e2p; +{ + char *t, *temp1, *temp2; + arrayind_t len; + int expok; +#if defined (ARRAY_VARS) + ARRAY *a; + HASH_TABLE *h; +#endif + + /* duplicate behavior of strchr(3) */ + t = skiparith (substr, ':'); + if (*t && *t == ':') + *t = '\0'; + else + t = (char *)0; + + temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES); + *e1p = evalexp (temp1, &expok); + free (temp1); + if (expok == 0) + return (0); + + len = -1; /* paranoia */ + switch (vtype) + { + case VT_VARIABLE: + case VT_ARRAYMEMBER: + len = MB_STRLEN (value); + break; + case VT_POSPARMS: + len = number_of_args () + 1; + if (*e1p == 0) + len++; /* add one arg if counting from $0 */ + break; +#if defined (ARRAY_VARS) + case VT_ARRAYVAR: + /* For arrays, the first value deals with array indices. Negative + offsets count from one past the array's maximum index. Associative + arrays treat the number of elements as the maximum index. */ + if (assoc_p (v)) + { + h = assoc_cell (v); + len = assoc_num_elements (h) + (*e1p < 0); + } + else + { + a = (ARRAY *)value; + len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */ + } + break; +#endif + } + + if (len == -1) /* paranoia */ + return -1; + + if (*e1p < 0) /* negative offsets count from end */ + *e1p += len; + + if (*e1p > len || *e1p < 0) + return (-1); + +#if defined (ARRAY_VARS) + /* For arrays, the second offset deals with the number of elements. */ + if (vtype == VT_ARRAYVAR) + len = assoc_p (v) ? assoc_num_elements (h) : array_num_elements (a); +#endif + + if (t) + { + t++; + temp2 = savestring (t); + temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES); + free (temp2); + t[-1] = ':'; + *e2p = evalexp (temp1, &expok); + free (temp1); + if (expok == 0) + return (0); + if ((vtype == VT_ARRAYVAR || vtype == VT_POSPARMS) && *e2p < 0) + { + internal_error (_("%s: substring expression < 0"), t); + return (0); + } +#if defined (ARRAY_VARS) + /* In order to deal with sparse arrays, push the intelligence about how + to deal with the number of elements desired down to the array- + specific functions. */ + if (vtype != VT_ARRAYVAR) +#endif + { + if (*e2p < 0) + { + *e2p += len; + if (*e2p < 0 || *e2p < *e1p) + { + internal_error (_("%s: substring expression < 0"), t); + return (0); + } + } + else + *e2p += *e1p; /* want E2 chars starting at E1 */ + if (*e2p > len) + *e2p = len; + } + } + else + *e2p = len; + + return (1); +} + +/* Return the type of variable specified by VARNAME (simple variable, + positional param, or array variable). Also return the value specified + by VARNAME (value of a variable or a reference to an array element). + QUOTED is the standard description of quoting state, using Q_* defines. + FLAGS is currently a set of flags to pass to array_value. If IND is + non-null and not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is + passed to array_value so the array index is not computed again. + If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL + characters in the value are quoted with CTLESC and takes appropriate + steps. For convenience, *VALP is set to the dequoted VALUE. */ +static int +get_var_and_type (varname, value, ind, quoted, flags, varp, valp) + char *varname, *value; + arrayind_t ind; + int quoted, flags; + SHELL_VAR **varp; + char **valp; +{ + int vtype; + char *temp; +#if defined (ARRAY_VARS) + SHELL_VAR *v; +#endif + arrayind_t lind; + + /* This sets vtype to VT_VARIABLE or VT_POSPARMS */ + vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0'; + if (vtype == VT_POSPARMS && varname[0] == '*') + vtype |= VT_STARSUB; + *varp = (SHELL_VAR *)NULL; + +#if defined (ARRAY_VARS) + if (valid_array_reference (varname)) + { + v = array_variable_part (varname, &temp, (int *)0); + /* If we want to signal array_value to use an already-computed index, + set LIND to that index */ + lind = (ind != INTMAX_MIN && (flags & AV_USEIND)) ? ind : 0; + if (v && (array_p (v) || assoc_p (v))) + { /* [ */ + if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']') + { + /* Callers have to differentiate betwen indexed and associative */ + vtype = VT_ARRAYVAR; + if (temp[0] == '*') + vtype |= VT_STARSUB; + *valp = array_p (v) ? (char *)array_cell (v) : (char *)assoc_cell (v); + } + else + { + vtype = VT_ARRAYMEMBER; + *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind); + } + *varp = v; + } + else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')) + { + vtype = VT_VARIABLE; + *varp = v; + if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) + *valp = dequote_string (value); + else + *valp = dequote_escapes (value); + } + else + { + vtype = VT_ARRAYMEMBER; + *varp = v; + *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind); + } + } + else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v))) + { + vtype = VT_ARRAYMEMBER; + *varp = v; + *valp = assoc_p (v) ? assoc_reference (assoc_cell (v), "0") : array_reference (array_cell (v), 0); + } + else +#endif + { + if (value && vtype == VT_VARIABLE) + { + if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) + *valp = dequote_string (value); + else + *valp = dequote_escapes (value); + } + else + *valp = value; + } + + return vtype; +} + +/******************************************************/ +/* */ +/* Functions to extract substrings of variable values */ +/* */ +/******************************************************/ + +#if defined (HANDLE_MULTIBYTE) +/* Character-oriented rather than strictly byte-oriented substrings. S and + E, rather being strict indices into STRING, indicate character (possibly + multibyte character) positions that require calculation. + Used by the ${param:offset[:length]} expansion. */ +static char * +mb_substring (string, s, e) + char *string; + int s, e; +{ + char *tt; + int start, stop, i, slen; + DECLARE_MBSTATE; + + start = 0; + /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */ + slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0; + + i = s; + while (string[start] && i--) + ADVANCE_CHAR (string, slen, start); + stop = start; + i = e - s; + while (string[stop] && i--) + ADVANCE_CHAR (string, slen, stop); + tt = substring (string, start, stop); + return tt; +} +#endif + +/* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME + is `@', use the positional parameters; otherwise, use the value of + VARNAME. If VARNAME is an array variable, use the array elements. */ + +static char * +parameter_brace_substring (varname, value, ind, substr, quoted, flags) + char *varname, *value; + int ind; + char *substr; + int quoted, flags; +{ + intmax_t e1, e2; + int vtype, r, starsub; + char *temp, *val, *tt, *oname; + SHELL_VAR *v; + + if (value == 0) + return ((char *)NULL); + + oname = this_command_name; + this_command_name = varname; + + vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); + if (vtype == -1) + { + this_command_name = oname; + return ((char *)NULL); + } + + starsub = vtype & VT_STARSUB; + vtype &= ~VT_STARSUB; + + r = verify_substring_values (v, val, substr, vtype, &e1, &e2); + this_command_name = oname; + if (r <= 0) + { + if (vtype == VT_VARIABLE) + FREE (val); + return ((r == 0) ? &expand_param_error : (char *)NULL); + } + + switch (vtype) + { + case VT_VARIABLE: + case VT_ARRAYMEMBER: +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1) + tt = mb_substring (val, e1, e2); + else +#endif + tt = substring (val, e1, e2); + + if (vtype == VT_VARIABLE) + FREE (val); + if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) + temp = quote_string (tt); + else + temp = tt ? quote_escapes (tt) : (char *)NULL; + FREE (tt); + break; + case VT_POSPARMS: + tt = pos_params (varname, e1, e2, quoted); + if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0) + { + temp = tt ? quote_escapes (tt) : (char *)NULL; + FREE (tt); + } + else + temp = tt; + break; +#if defined (ARRAY_VARS) + case VT_ARRAYVAR: + if (assoc_p (v)) + /* we convert to list and take first e2 elements starting at e1th + element -- officially undefined for now */ + temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted); + else + /* We want E2 to be the number of elements desired (arrays can be sparse, + so verify_substring_values just returns the numbers specified and we + rely on array_subrange to understand how to deal with them). */ + temp = array_subrange (array_cell (v), e1, e2, starsub, quoted); + /* array_subrange now calls array_quote_escapes as appropriate, so the + caller no longer needs to. */ + break; +#endif + default: + temp = (char *)NULL; + } + + return temp; +} + +/****************************************************************/ +/* */ +/* Functions to perform pattern substitution on variable values */ +/* */ +/****************************************************************/ + +static int +shouldexp_replacement (s) + char *s; +{ + register char *p; + + for (p = s; p && *p; p++) + { + if (*p == '\\') + p++; + else if (*p == '&') + return 1; + } + return 0; +} + +char * +pat_subst (string, pat, rep, mflags) + char *string, *pat, *rep; + int mflags; +{ + char *ret, *s, *e, *str, *rstr, *mstr; + int rsize, rptr, l, replen, mtype, rxpand, rslen, mlen; + + if (string == 0) + return (savestring ("")); + + mtype = mflags & MATCH_TYPEMASK; + +#if 0 /* bash-4.2 ? */ + rxpand = (rep && *rep) ? shouldexp_replacement (rep) : 0; +#else + rxpand = 0; +#endif + + /* Special cases: + * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING + * with REP and return the result. + * 2. A null pattern with mtype == MATCH_END means to append REP to + * STRING and return the result. + * These don't understand or process `&' in the replacement string. + */ + if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END)) + { + replen = STRLEN (rep); + l = STRLEN (string); + ret = (char *)xmalloc (replen + l + 2); + if (replen == 0) + strcpy (ret, string); + else if (mtype == MATCH_BEG) + { + strcpy (ret, rep); + strcpy (ret + replen, string); + } + else + { + strcpy (ret, string); + strcpy (ret + l, rep); + } + return (ret); + } + + ret = (char *)xmalloc (rsize = 64); + ret[0] = '\0'; + + for (replen = STRLEN (rep), rptr = 0, str = string;;) + { + if (match_pattern (str, pat, mtype, &s, &e) == 0) + break; + l = s - str; + + if (rxpand) + { + int x; + mlen = e - s; + mstr = xmalloc (mlen + 1); + for (x = 0; x < mlen; x++) + mstr[x] = s[x]; + mstr[mlen] = '\0'; + rstr = strcreplace (rep, '&', mstr, 0); + rslen = strlen (rstr); + } + else + { + rstr = rep; + rslen = replen; + } + + RESIZE_MALLOCED_BUFFER (ret, rptr, (l + rslen), rsize, 64); + + /* OK, now copy the leading unmatched portion of the string (from + str to s) to ret starting at rptr (the current offset). Then copy + the replacement string at ret + rptr + (s - str). Increment + rptr (if necessary) and str and go on. */ + if (l) + { + strncpy (ret + rptr, str, l); + rptr += l; + } + if (replen) + { + strncpy (ret + rptr, rstr, rslen); + rptr += rslen; + } + str = e; /* e == end of match */ + + if (rstr != rep) + free (rstr); + + if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY) + break; + + if (s == e) + { + /* On a zero-length match, make sure we copy one character, since + we increment one character to avoid infinite recursion. */ + RESIZE_MALLOCED_BUFFER (ret, rptr, 1, rsize, 64); + ret[rptr++] = *str++; + e++; /* avoid infinite recursion on zero-length match */ + } + } + + /* Now copy the unmatched portion of the input string */ + if (str && *str) + { + RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64); + strcpy (ret + rptr, str); + } + else + ret[rptr] = '\0'; + + return ret; +} + +/* Do pattern match and replacement on the positional parameters. */ +static char * +pos_params_pat_subst (string, pat, rep, mflags) + char *string, *pat, *rep; + int mflags; +{ + WORD_LIST *save, *params; + WORD_DESC *w; + char *ret; + int pchar, qflags; + + save = params = list_rest_of_args (); + if (save == 0) + return ((char *)NULL); + + for ( ; params; params = params->next) + { + ret = pat_subst (params->word->word, pat, rep, mflags); + w = alloc_word_desc (); + w->word = ret ? ret : savestring (""); + dispose_word (params->word); + params->word = w; + } + + pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@'; + qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0; + +#if 0 + if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB)) + ret = string_list_dollar_star (quote_list (save)); + else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB) + ret = string_list_dollar_star (save); + else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED) + ret = string_list_dollar_at (save, qflags); + else + ret = string_list_dollar_star (save); +#else + ret = string_list_pos_params (pchar, save, qflags); +#endif + + dispose_words (save); + + return (ret); +} + +/* Perform pattern substitution on VALUE, which is the expansion of + VARNAME. PATSUB is an expression supplying the pattern to match + and the string to substitute. QUOTED is a flags word containing + the type of quoting currently in effect. */ +static char * +parameter_brace_patsub (varname, value, ind, patsub, quoted, flags) + char *varname, *value; + int ind; + char *patsub; + int quoted, flags; +{ + int vtype, mflags, starsub, delim; + char *val, *temp, *pat, *rep, *p, *lpatsub, *tt; + SHELL_VAR *v; + + if (value == 0) + return ((char *)NULL); + + this_command_name = varname; + + vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); + if (vtype == -1) + return ((char *)NULL); + + starsub = vtype & VT_STARSUB; + vtype &= ~VT_STARSUB; + + mflags = 0; + /* PATSUB is never NULL when this is called. */ + if (*patsub == '/') + { + mflags |= MATCH_GLOBREP; + patsub++; + } + + /* Malloc this because expand_string_if_necessary or one of the expansion + functions in its call chain may free it on a substitution error. */ + lpatsub = savestring (patsub); + + if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) + mflags |= MATCH_QUOTED; + + if (starsub) + mflags |= MATCH_STARSUB; + + /* If the pattern starts with a `/', make sure we skip over it when looking + for the replacement delimiter. */ + delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0); + if (lpatsub[delim] == '/') + { + lpatsub[delim] = 0; + rep = lpatsub + delim + 1; + } + else + rep = (char *)NULL; + + if (rep && *rep == '\0') + rep = (char *)NULL; + + /* Perform the same expansions on the pattern as performed by the + pattern removal expansions. */ + pat = getpattern (lpatsub, quoted, 1); + + if (rep) + /* We want to perform quote removal on the expanded replacement even if + the entire expansion is double-quoted because the parser and string + extraction functions treated quotes in the replacement string as + special. */ + rep = expand_string_if_necessary (rep, quoted & ~(Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT), expand_string_unsplit); + + /* ksh93 doesn't allow the match specifier to be a part of the expanded + pattern. This is an extension. Make sure we don't anchor the pattern + at the beginning or end of the string if we're doing global replacement, + though. */ + p = pat; + if (mflags & MATCH_GLOBREP) + mflags |= MATCH_ANY; + else if (pat && pat[0] == '#') + { + mflags |= MATCH_BEG; + p++; + } + else if (pat && pat[0] == '%') + { + mflags |= MATCH_END; + p++; + } + else + mflags |= MATCH_ANY; + + /* OK, we now want to substitute REP for PAT in VAL. If + flags & MATCH_GLOBREP is non-zero, the substitution is done + everywhere, otherwise only the first occurrence of PAT is + replaced. The pattern matching code doesn't understand + CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable + values passed in (VT_VARIABLE) so the pattern substitution + code works right. We need to requote special chars after + we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the + other cases if QUOTED == 0, since the posparams and arrays + indexed by * or @ do special things when QUOTED != 0. */ + + switch (vtype) + { + case VT_VARIABLE: + case VT_ARRAYMEMBER: + temp = pat_subst (val, p, rep, mflags); + if (vtype == VT_VARIABLE) + FREE (val); + if (temp) + { + tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp); + free (temp); + temp = tt; + } + break; + case VT_POSPARMS: + temp = pos_params_pat_subst (val, p, rep, mflags); + if (temp && (mflags & MATCH_QUOTED) == 0) + { + tt = quote_escapes (temp); + free (temp); + temp = tt; + } + break; +#if defined (ARRAY_VARS) + case VT_ARRAYVAR: + temp = assoc_p (v) ? assoc_patsub (assoc_cell (v), p, rep, mflags) + : array_patsub (array_cell (v), p, rep, mflags); + /* Don't call quote_escapes anymore; array_patsub calls + array_quote_escapes as appropriate before adding the + space separators; ditto for assoc_patsub. */ + break; +#endif + } + + FREE (pat); + FREE (rep); + free (lpatsub); + + return temp; +} + +/****************************************************************/ +/* */ +/* Functions to perform case modification on variable values */ +/* */ +/****************************************************************/ + +/* Do case modification on the positional parameters. */ + +static char * +pos_params_modcase (string, pat, modop, mflags) + char *string, *pat; + int modop; + int mflags; +{ + WORD_LIST *save, *params; + WORD_DESC *w; + char *ret; + int pchar, qflags; + + save = params = list_rest_of_args (); + if (save == 0) + return ((char *)NULL); + + for ( ; params; params = params->next) + { + ret = sh_modcase (params->word->word, pat, modop); + w = alloc_word_desc (); + w->word = ret ? ret : savestring (""); + dispose_word (params->word); + params->word = w; + } + + pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@'; + qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0; + + ret = string_list_pos_params (pchar, save, qflags); + dispose_words (save); + + return (ret); +} + +/* Perform case modification on VALUE, which is the expansion of + VARNAME. MODSPEC is an expression supplying the type of modification + to perform. QUOTED is a flags word containing the type of quoting + currently in effect. */ +static char * +parameter_brace_casemod (varname, value, ind, modspec, patspec, quoted, flags) + char *varname, *value; + int ind, modspec; + char *patspec; + int quoted, flags; +{ + int vtype, starsub, modop, mflags, x; + char *val, *temp, *pat, *p, *lpat, *tt; + SHELL_VAR *v; + + if (value == 0) + return ((char *)NULL); + + this_command_name = varname; + + vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); + if (vtype == -1) + return ((char *)NULL); + + starsub = vtype & VT_STARSUB; + vtype &= ~VT_STARSUB; + + modop = 0; + mflags = 0; + if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) + mflags |= MATCH_QUOTED; + if (starsub) + mflags |= MATCH_STARSUB; + + p = patspec; + if (modspec == '^') + { + x = p && p[0] == modspec; + modop = x ? CASE_UPPER : CASE_UPFIRST; + p += x; + } + else if (modspec == ',') + { + x = p && p[0] == modspec; + modop = x ? CASE_LOWER : CASE_LOWFIRST; + p += x; + } + else if (modspec == '~') + { + x = p && p[0] == modspec; + modop = x ? CASE_TOGGLEALL : CASE_TOGGLE; + p += x; + } + + lpat = p ? savestring (p) : 0; + /* Perform the same expansions on the pattern as performed by the + pattern removal expansions. FOR LATER */ + pat = lpat ? getpattern (lpat, quoted, 1) : 0; + + /* OK, now we do the case modification. */ + switch (vtype) + { + case VT_VARIABLE: + case VT_ARRAYMEMBER: + temp = sh_modcase (val, pat, modop); + if (vtype == VT_VARIABLE) + FREE (val); + if (temp) + { + tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp); + free (temp); + temp = tt; + } + break; + + case VT_POSPARMS: + temp = pos_params_modcase (val, pat, modop, mflags); + if (temp && (mflags & MATCH_QUOTED) == 0) + { + tt = quote_escapes (temp); + free (temp); + temp = tt; + } + break; + +#if defined (ARRAY_VARS) + case VT_ARRAYVAR: + temp = assoc_p (v) ? assoc_modcase (assoc_cell (v), pat, modop, mflags) + : array_modcase (array_cell (v), pat, modop, mflags); + /* Don't call quote_escapes; array_modcase calls array_quote_escapes + as appropriate before adding the space separators; ditto for + assoc_modcase. */ + break; +#endif + } + + FREE (pat); + free (lpat); + + return temp; +} + +/* Check for unbalanced parens in S, which is the contents of $(( ... )). If + any occur, this must be a nested command substitution, so return 0. + Otherwise, return 1. A valid arithmetic expression must always have a + ( before a matching ), so any cases where there are more right parens + means that this must not be an arithmetic expression, though the parser + will not accept it without a balanced total number of parens. */ +static int +chk_arithsub (s, len) + const char *s; + int len; +{ + int i, count; + DECLARE_MBSTATE; + + i = count = 0; + while (i < len) + { + if (s[i] == LPAREN) + count++; + else if (s[i] == RPAREN) + { + count--; + if (count < 0) + return 0; + } + + switch (s[i]) + { + default: + ADVANCE_CHAR (s, len, i); + break; + + case '\\': + i++; + if (s[i]) + ADVANCE_CHAR (s, len, i); + break; + + case '\'': + i = skip_single_quoted (s, len, ++i); + break; + + case '"': + i = skip_double_quoted ((char *)s, len, ++i); + break; + } + } + + return (count == 0); +} + +/****************************************************************/ +/* */ +/* Functions to perform parameter expansion on a string */ +/* */ +/****************************************************************/ + +/* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */ +static WORD_DESC * +parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, contains_dollar_at) + char *string; + int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at, pflags; +{ + int check_nullness, var_is_set, var_is_null, var_is_special; + int want_substring, want_indir, want_patsub, want_casemod; + char *name, *value, *temp, *temp1; + WORD_DESC *tdesc, *ret; + int t_index, sindex, c, tflag, modspec; + intmax_t number; + arrayind_t ind; + + temp = temp1 = value = (char *)NULL; + var_is_set = var_is_null = var_is_special = check_nullness = 0; + want_substring = want_indir = want_patsub = want_casemod = 0; + + sindex = *indexp; + t_index = ++sindex; + /* ${#var} doesn't have any of the other parameter expansions on it. */ + if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */ + name = string_extract (string, &t_index, "}", SX_VARNAME); + else +#if defined (CASEMOD_EXPANSIONS) + /* To enable case-toggling expansions using the `~' operator character + change the 1 to 0. */ +# if defined (CASEMOD_CAPCASE) + name = string_extract (string, &t_index, "#%^,~:-=?+/}", SX_VARNAME); +# else + name = string_extract (string, &t_index, "#%^,:-=?+/}", SX_VARNAME); +# endif /* CASEMOD_CAPCASE */ +#else + name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME); +#endif /* CASEMOD_EXPANSIONS */ + + ret = 0; + tflag = 0; + + ind = INTMAX_MIN; + + /* If the name really consists of a special variable, then make sure + that we have the entire name. We don't allow indirect references + to special variables except `#', `?', `@' and `*'. */ + if ((sindex == t_index && VALID_SPECIAL_LENGTH_PARAM (string[t_index])) || + (sindex == t_index - 1 && string[sindex] == '!' && VALID_INDIR_PARAM (string[t_index]))) + { + t_index++; + temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0); + name = (char *)xrealloc (name, 3 + (strlen (temp1))); + *name = string[sindex]; + if (string[sindex] == '!') + { + /* indirect reference of $#, $?, $@, or $* */ + name[1] = string[sindex + 1]; + strcpy (name + 2, temp1); + } + else + strcpy (name + 1, temp1); + free (temp1); + } + sindex = t_index; + + /* Find out what character ended the variable name. Then + do the appropriate thing. */ + if (c = string[sindex]) + sindex++; + + /* If c is followed by one of the valid parameter expansion + characters, move past it as normal. If not, assume that + a substring specification is being given, and do not move + past it. */ + if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex])) + { + check_nullness++; + if (c = string[sindex]) + sindex++; + } + else if (c == ':' && string[sindex] != RBRACE) + want_substring = 1; + else if (c == '/' /* && string[sindex] != RBRACE */) /* XXX */ + want_patsub = 1; +#if defined (CASEMOD_EXPANSIONS) + else if (c == '^' || c == ',' || c == '~') + { + modspec = c; + want_casemod = 1; + } +#endif + + /* Catch the valid and invalid brace expressions that made it through the + tests above. */ + /* ${#-} is a valid expansion and means to take the length of $-. + Similarly for ${#?} and ${##}... */ + if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 && + VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE) + { + name = (char *)xrealloc (name, 3); + name[1] = c; + name[2] = '\0'; + c = string[sindex++]; + } + + /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */ + if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 && + member (c, "%:=+/") && string[sindex] == RBRACE) + { + temp = (char *)NULL; + goto bad_substitution; + } + + /* Indirect expansion begins with a `!'. A valid indirect expansion is + either a variable name, one of the positional parameters or a special + variable that expands to one of the positional parameters. */ + want_indir = *name == '!' && + (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1]) + || VALID_INDIR_PARAM (name[1])); + + /* Determine the value of this variable. */ + + /* Check for special variables, directly referenced. */ + if (SPECIAL_VAR (name, want_indir)) + var_is_special++; + + /* Check for special expansion things, like the length of a parameter */ + if (*name == '#' && name[1]) + { + /* If we are not pointing at the character just after the + closing brace, then we haven't gotten all of the name. + Since it begins with a special character, this is a bad + substitution. Also check NAME for validity before trying + to go on. */ + if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0)) + { + temp = (char *)NULL; + goto bad_substitution; + } + + number = parameter_brace_expand_length (name); + if (number == INTMAX_MIN && unbound_vars_is_error) + { + last_command_exit_value = EXECUTION_FAILURE; + err_unboundvar (name+1); + free (name); + return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); + } + free (name); + + *indexp = sindex; + if (number < 0) + return (&expand_wdesc_error); + else + { + ret = alloc_word_desc (); + ret->word = itos (number); + return ret; + } + } + + /* ${@} is identical to $@. */ + if (name[0] == '@' && name[1] == '\0') + { + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) + *quoted_dollar_atp = 1; + + if (contains_dollar_at) + *contains_dollar_at = 1; + } + + /* Process ${!PREFIX*} expansion. */ + if (want_indir && string[sindex - 1] == RBRACE && + (string[sindex - 2] == '*' || string[sindex - 2] == '@') && + legal_variable_starter ((unsigned char) name[1])) + { + char **x; + WORD_LIST *xlist; + + temp1 = savestring (name + 1); + number = strlen (temp1); + temp1[number - 1] = '\0'; + x = all_variables_matching_prefix (temp1); + xlist = strvec_to_word_list (x, 0, 0); + if (string[sindex - 2] == '*') + temp = string_list_dollar_star (xlist); + else + { + temp = string_list_dollar_at (xlist, quoted); + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) + *quoted_dollar_atp = 1; + if (contains_dollar_at) + *contains_dollar_at = 1; + } + free (x); + dispose_words (xlist); + free (temp1); + *indexp = sindex; + + free (name); + + ret = alloc_word_desc (); + ret->word = temp; + return ret; + } + +#if defined (ARRAY_VARS) + /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */ + if (want_indir && string[sindex - 1] == RBRACE && + string[sindex - 2] == ']' && valid_array_reference (name+1)) + { + char *x, *x1; + + temp1 = savestring (name + 1); + x = array_variable_name (temp1, &x1, (int *)0); /* [ */ + FREE (x); + if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']') + { + temp = array_keys (temp1, quoted); /* handles assoc vars too */ + if (x1[0] == '@') + { + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) + *quoted_dollar_atp = 1; + if (contains_dollar_at) + *contains_dollar_at = 1; + } + + free (temp1); + *indexp = sindex; + + ret = alloc_word_desc (); + ret->word = temp; + return ret; + } + + free (temp1); + } +#endif /* ARRAY_VARS */ + + /* Make sure that NAME is valid before trying to go on. */ + if (valid_brace_expansion_word (want_indir ? name + 1 : name, + var_is_special) == 0) + { + temp = (char *)NULL; + goto bad_substitution; + } + + if (want_indir) + tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at); + else + tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND|(pflags&PF_NOSPLIT2), &ind); + + if (tdesc) + { + temp = tdesc->word; + tflag = tdesc->flags; + dispose_word_desc (tdesc); + } + else + temp = (char *)0; + +#if defined (ARRAY_VARS) + if (valid_array_reference (name)) + chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at); +#endif + + var_is_set = temp != (char *)0; + var_is_null = check_nullness && (var_is_set == 0 || *temp == 0); + + /* Get the rest of the stuff inside the braces. */ + if (c && c != RBRACE) + { + /* Extract the contents of the ${ ... } expansion + according to the Posix.2 rules. */ + value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#' || c =='/' || c == '^' || c == ',' || c ==':') ? SX_POSIXEXP|SX_WORD : SX_WORD); + if (string[sindex] == RBRACE) + sindex++; + else + goto bad_substitution; + } + else + value = (char *)NULL; + + *indexp = sindex; + + /* All the cases where an expansion can possibly generate an unbound + variable error. */ + if (want_substring || want_patsub || want_casemod || c == '#' || c == '%' || c == RBRACE) + { + if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1])) + { + last_command_exit_value = EXECUTION_FAILURE; + err_unboundvar (name); + FREE (value); + FREE (temp); + free (name); + return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); + } + } + + /* If this is a substring spec, process it and add the result. */ + if (want_substring) + { + temp1 = parameter_brace_substring (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0); + FREE (name); + FREE (value); + FREE (temp); + + if (temp1 == &expand_param_error) + return (&expand_wdesc_error); + else if (temp1 == &expand_param_fatal) + return (&expand_wdesc_fatal); + + ret = alloc_word_desc (); + ret->word = temp1; + if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) + ret->flags |= W_QUOTED|W_HASQUOTEDNULL; + return ret; + } + else if (want_patsub) + { + temp1 = parameter_brace_patsub (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0); + FREE (name); + FREE (value); + FREE (temp); + + if (temp1 == &expand_param_error) + return (&expand_wdesc_error); + else if (temp1 == &expand_param_fatal) + return (&expand_wdesc_fatal); + + ret = alloc_word_desc (); + ret->word = temp1; + if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) + ret->flags |= W_QUOTED|W_HASQUOTEDNULL; + return ret; + } +#if defined (CASEMOD_EXPANSIONS) + else if (want_casemod) + { + temp1 = parameter_brace_casemod (name, temp, ind, modspec, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0); + FREE (name); + FREE (value); + FREE (temp); + + if (temp1 == &expand_param_error) + return (&expand_wdesc_error); + else if (temp1 == &expand_param_fatal) + return (&expand_wdesc_fatal); + + ret = alloc_word_desc (); + ret->word = temp1; + if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) + ret->flags |= W_QUOTED|W_HASQUOTEDNULL; + return ret; + } +#endif + + /* Do the right thing based on which character ended the variable name. */ + switch (c) + { + default: + case '\0': + bad_substitution: + last_command_exit_value = EXECUTION_FAILURE; + report_error (_("%s: bad substitution"), string ? string : "??"); + FREE (value); + FREE (temp); + free (name); + return &expand_wdesc_error; + + case RBRACE: + break; + + case '#': /* ${param#[#]pattern} */ + case '%': /* ${param%[%]pattern} */ + if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0') + { + FREE (value); + break; + } + temp1 = parameter_brace_remove_pattern (name, temp, ind, value, c, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0); + free (temp); + free (value); + free (name); + + ret = alloc_word_desc (); + ret->word = temp1; + if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) + ret->flags |= W_QUOTED|W_HASQUOTEDNULL; + return ret; + + case '-': + case '=': + case '?': + case '+': + if (var_is_set && var_is_null == 0) + { + /* If the operator is `+', we don't want the value of the named + variable for anything, just the value of the right hand side. */ + if (c == '+') + { + /* XXX -- if we're double-quoted and the named variable is "$@", + we want to turn off any special handling of "$@" -- + we're not using it, so whatever is on the rhs applies. */ + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) + *quoted_dollar_atp = 0; + if (contains_dollar_at) + *contains_dollar_at = 0; + + FREE (temp); + if (value) + { + /* From Posix discussion on austin-group list. Issue 221 + requires that backslashes escaping `}' inside + double-quoted ${...} be removed. */ + if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) + quoted |= Q_DOLBRACE; + ret = parameter_brace_expand_rhs (name, value, c, + quoted, + quoted_dollar_atp, + contains_dollar_at); + /* XXX - fix up later, esp. noting presence of + W_HASQUOTEDNULL in ret->flags */ + free (value); + } + else + temp = (char *)NULL; + } + else + { + FREE (value); + } + /* Otherwise do nothing; just use the value in TEMP. */ + } + else /* VAR not set or VAR is NULL. */ + { + FREE (temp); + temp = (char *)NULL; + if (c == '=' && var_is_special) + { + last_command_exit_value = EXECUTION_FAILURE; + report_error (_("$%s: cannot assign in this way"), name); + free (name); + free (value); + return &expand_wdesc_error; + } + else if (c == '?') + { + parameter_brace_expand_error (name, value); + return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); + } + else if (c != '+') + { + /* XXX -- if we're double-quoted and the named variable is "$@", + we want to turn off any special handling of "$@" -- + we're not using it, so whatever is on the rhs applies. */ + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) + *quoted_dollar_atp = 0; + if (contains_dollar_at) + *contains_dollar_at = 0; + + /* From Posix discussion on austin-group list. Issue 221 requires + that backslashes escaping `}' inside double-quoted ${...} be + removed. */ + if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) + quoted |= Q_DOLBRACE; + ret = parameter_brace_expand_rhs (name, value, c, quoted, + quoted_dollar_atp, + contains_dollar_at); + /* XXX - fix up later, esp. noting presence of + W_HASQUOTEDNULL in tdesc->flags */ + } + free (value); + } + + break; + } + free (name); + + if (ret == 0) + { + ret = alloc_word_desc (); + ret->flags = tflag; + ret->word = temp; + } + return (ret); +} + +/* Expand a single ${xxx} expansion. The braces are optional. When + the braces are used, parameter_brace_expand() does the work, + possibly calling param_expand recursively. */ +static WORD_DESC * +param_expand (string, sindex, quoted, expanded_something, + contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p, + pflags) + char *string; + int *sindex, quoted, *expanded_something, *contains_dollar_at; + int *quoted_dollar_at_p, *had_quoted_null_p, pflags; +{ + char *temp, *temp1, uerror[3]; + int zindex, t_index, expok; + unsigned char c; + intmax_t number; + SHELL_VAR *var; + WORD_LIST *list; + WORD_DESC *tdesc, *ret; + int tflag; + + zindex = *sindex; + c = string[++zindex]; + + temp = (char *)NULL; + ret = tdesc = (WORD_DESC *)NULL; + tflag = 0; + + /* Do simple cases first. Switch on what follows '$'. */ + switch (c) + { + /* $0 .. $9? */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + temp1 = dollar_vars[TODIGIT (c)]; + if (unbound_vars_is_error && temp1 == (char *)NULL) + { + uerror[0] = '$'; + uerror[1] = c; + uerror[2] = '\0'; + last_command_exit_value = EXECUTION_FAILURE; + err_unboundvar (uerror); + return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); + } + if (temp1) + temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) + ? quote_string (temp1) + : quote_escapes (temp1); + else + temp = (char *)NULL; + + break; + + /* $$ -- pid of the invoking shell. */ + case '$': + temp = itos (dollar_dollar_pid); + break; + + /* $# -- number of positional parameters. */ + case '#': + temp = itos (number_of_args ()); + break; + + /* $? -- return value of the last synchronous command. */ + case '?': + temp = itos (last_command_exit_value); + break; + + /* $- -- flags supplied to the shell on invocation or by `set'. */ + case '-': + temp = which_set_flags (); + break; + + /* $! -- Pid of the last asynchronous command. */ + case '!': + /* If no asynchronous pids have been created, expand to nothing. + If `set -u' has been executed, and no async processes have + been created, this is an expansion error. */ + if (last_asynchronous_pid == NO_PID) + { + if (expanded_something) + *expanded_something = 0; + temp = (char *)NULL; + if (unbound_vars_is_error) + { + uerror[0] = '$'; + uerror[1] = c; + uerror[2] = '\0'; + last_command_exit_value = EXECUTION_FAILURE; + err_unboundvar (uerror); + return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); + } + } + else + temp = itos (last_asynchronous_pid); + break; + + /* The only difference between this and $@ is when the arg is quoted. */ + case '*': /* `$*' */ + list = list_rest_of_args (); + +#if 0 + /* According to austin-group posix proposal by Geoff Clare in + <20090505091501.GA10097@squonk.masqnet> of 5 May 2009: + + "The shell shall write a message to standard error and + immediately exit when it tries to expand an unset parameter + other than the '@' and '*' special parameters." + */ + + if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0) + { + uerror[0] = '$'; + uerror[1] = '*'; + uerror[2] = '\0'; + last_command_exit_value = EXECUTION_FAILURE; + err_unboundvar (uerror); + return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); + } +#endif + + /* If there are no command-line arguments, this should just + disappear if there are other characters in the expansion, + even if it's quoted. */ + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0) + temp = (char *)NULL; + else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE)) + { + /* If we have "$*" we want to make a string of the positional + parameters, separated by the first character of $IFS, and + quote the whole string, including the separators. If IFS + is unset, the parameters are separated by ' '; if $IFS is + null, the parameters are concatenated. */ + temp = (quoted & (Q_DOUBLE_QUOTES|Q_PATQUOTE)) ? string_list_dollar_star (list) : string_list (list); + if (temp) + { + temp1 = quote_string (temp); + if (*temp == 0) + tflag |= W_HASQUOTEDNULL; + free (temp); + temp = temp1; + } + } + else + { + /* We check whether or not we're eventually going to split $* here, + for example when IFS is empty and we are processing the rhs of + an assignment statement. In that case, we don't separate the + arguments at all. Otherwise, if the $* is not quoted it is + identical to $@ */ +#if 1 +# if defined (HANDLE_MULTIBYTE) + if (expand_no_split_dollar_star && ifs_firstc[0] == 0) +# else + if (expand_no_split_dollar_star && ifs_firstc == 0) +# endif + temp = string_list_dollar_star (list); + else + temp = string_list_dollar_at (list, quoted); +#else + temp = string_list_dollar_at (list, quoted); +#endif + if (expand_no_split_dollar_star == 0 && contains_dollar_at) + *contains_dollar_at = 1; + } + + dispose_words (list); + break; + + /* When we have "$@" what we want is "$1" "$2" "$3" ... This + means that we have to turn quoting off after we split into + the individually quoted arguments so that the final split + on the first character of $IFS is still done. */ + case '@': /* `$@' */ + list = list_rest_of_args (); + +#if 0 + /* According to austin-group posix proposal by Geoff Clare in + <20090505091501.GA10097@squonk.masqnet> of 5 May 2009: + + "The shell shall write a message to standard error and + immediately exit when it tries to expand an unset parameter + other than the '@' and '*' special parameters." + */ + + if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0) + { + uerror[0] = '$'; + uerror[1] = '@'; + uerror[2] = '\0'; + last_command_exit_value = EXECUTION_FAILURE; + err_unboundvar (uerror); + return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); + } +#endif + + /* We want to flag the fact that we saw this. We can't turn + off quoting entirely, because other characters in the + string might need it (consider "\"$@\""), but we need some + way to signal that the final split on the first character + of $IFS should be done, even though QUOTED is 1. */ + /* XXX - should this test include Q_PATQUOTE? */ + if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) + *quoted_dollar_at_p = 1; + if (contains_dollar_at) + *contains_dollar_at = 1; + + /* We want to separate the positional parameters with the first + character of $IFS in case $IFS is something other than a space. + We also want to make sure that splitting is done no matter what -- + according to POSIX.2, this expands to a list of the positional + parameters no matter what IFS is set to. */ +#if 0 + temp = string_list_dollar_at (list, quoted); +#else + temp = string_list_dollar_at (list, (pflags & PF_ASSIGNRHS) ? (quoted|Q_DOUBLE_QUOTES) : quoted); +#endif + + dispose_words (list); + break; + + case LBRACE: + tdesc = parameter_brace_expand (string, &zindex, quoted, pflags, + quoted_dollar_at_p, + contains_dollar_at); + + if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal) + return (tdesc); + temp = tdesc ? tdesc->word : (char *)0; + + /* XXX */ + /* Quoted nulls should be removed if there is anything else + in the string. */ + /* Note that we saw the quoted null so we can add one back at + the end of this function if there are no other characters + in the string, discard TEMP, and go on. The exception to + this is when we have "${@}" and $1 is '', since $@ needs + special handling. */ + if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp)) + { + if (had_quoted_null_p) + *had_quoted_null_p = 1; + if (*quoted_dollar_at_p == 0) + { + free (temp); + tdesc->word = temp = (char *)NULL; + } + + } + + ret = tdesc; + goto return0; + + /* Do command or arithmetic substitution. */ + case LPAREN: + /* We have to extract the contents of this paren substitution. */ + t_index = zindex + 1; + temp = extract_command_subst (string, &t_index, 0); + zindex = t_index; + + /* For Posix.2-style `$(( ))' arithmetic substitution, + extract the expression and pass it to the evaluator. */ + if (temp && *temp == LPAREN) + { + char *temp2; + temp1 = temp + 1; + temp2 = savestring (temp1); + t_index = strlen (temp2) - 1; + + if (temp2[t_index] != RPAREN) + { + free (temp2); + goto comsub; + } + + /* Cut off ending `)' */ + temp2[t_index] = '\0'; + + if (chk_arithsub (temp2, t_index) == 0) + { + free (temp2); +#if 0 + internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution")); +#endif + goto comsub; + } + + /* Expand variables found inside the expression. */ + temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES); + free (temp2); + +arithsub: + /* No error messages. */ + this_command_name = (char *)NULL; + number = evalexp (temp1, &expok); + free (temp); + free (temp1); + if (expok == 0) + { + if (interactive_shell == 0 && posixly_correct) + { + last_command_exit_value = EXECUTION_FAILURE; + return (&expand_wdesc_fatal); + } + else + return (&expand_wdesc_error); + } + temp = itos (number); + break; + } + +comsub: + if (pflags & PF_NOCOMSUB) + /* we need zindex+1 because string[zindex] == RPAREN */ + temp1 = substring (string, *sindex, zindex+1); + else + { + tdesc = command_substitute (temp, quoted); + temp1 = tdesc ? tdesc->word : (char *)NULL; + if (tdesc) + dispose_word_desc (tdesc); + } + FREE (temp); + temp = temp1; + break; + + /* Do POSIX.2d9-style arithmetic substitution. This will probably go + away in a future bash release. */ + case '[': + /* Extract the contents of this arithmetic substitution. */ + t_index = zindex + 1; + temp = extract_arithmetic_subst (string, &t_index); + zindex = t_index; + if (temp == 0) + { + temp = savestring (string); + if (expanded_something) + *expanded_something = 0; + goto return0; + } + + /* Do initial variable expansion. */ + temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES); + + goto arithsub; + + default: + /* Find the variable in VARIABLE_LIST. */ + temp = (char *)NULL; + + for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++) + ; + temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL; + + /* If this isn't a variable name, then just output the `$'. */ + if (temp1 == 0 || *temp1 == '\0') + { + FREE (temp1); + temp = (char *)xmalloc (2); + temp[0] = '$'; + temp[1] = '\0'; + if (expanded_something) + *expanded_something = 0; + goto return0; + } + + /* If the variable exists, return its value cell. */ + var = find_variable (temp1); + + if (var && invisible_p (var) == 0 && var_isset (var)) + { +#if defined (ARRAY_VARS) + if (assoc_p (var) || array_p (var)) + { + temp = array_p (var) ? array_reference (array_cell (var), 0) + : assoc_reference (assoc_cell (var), "0"); + if (temp) + temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) + ? quote_string (temp) + : quote_escapes (temp); + else if (unbound_vars_is_error) + goto unbound_variable; + } + else +#endif + { + temp = value_cell (var); + + temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) + ? quote_string (temp) + : quote_escapes (temp); + } + + free (temp1); + + goto return0; + } + + temp = (char *)NULL; + +unbound_variable: + if (unbound_vars_is_error) + { + last_command_exit_value = EXECUTION_FAILURE; + err_unboundvar (temp1); + } + else + { + free (temp1); + goto return0; + } + + free (temp1); + last_command_exit_value = EXECUTION_FAILURE; + return ((unbound_vars_is_error && interactive_shell == 0) + ? &expand_wdesc_fatal + : &expand_wdesc_error); + } + + if (string[zindex]) + zindex++; + +return0: + *sindex = zindex; + + if (ret == 0) + { + ret = alloc_word_desc (); + ret->flags = tflag; /* XXX */ + ret->word = temp; + } + return ret; +} + +/* Make a word list which is the result of parameter and variable + expansion, command substitution, arithmetic substitution, and + quote removal of WORD. Return a pointer to a WORD_LIST which is + the result of the expansion. If WORD contains a null word, the + word list returned is also null. + + QUOTED contains flag values defined in shell.h. + + ISEXP is used to tell expand_word_internal that the word should be + treated as the result of an expansion. This has implications for + how IFS characters in the word are treated. + + CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null + they point to an integer value which receives information about expansion. + CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero. + EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions, + else zero. + + This only does word splitting in the case of $@ expansion. In that + case, we split on ' '. */ + +/* Values for the local variable quoted_state. */ +#define UNQUOTED 0 +#define PARTIALLY_QUOTED 1 +#define WHOLLY_QUOTED 2 + +static WORD_LIST * +expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something) + WORD_DESC *word; + int quoted, isexp; + int *contains_dollar_at; + int *expanded_something; +{ + WORD_LIST *list; + WORD_DESC *tword; + + /* The intermediate string that we build while expanding. */ + char *istring; + + /* The current size of the above object. */ + int istring_size; + + /* Index into ISTRING. */ + int istring_index; + + /* Temporary string storage. */ + char *temp, *temp1; + + /* The text of WORD. */ + register char *string; + + /* The size of STRING. */ + size_t string_size; + + /* The index into STRING. */ + int sindex; + + /* This gets 1 if we see a $@ while quoted. */ + int quoted_dollar_at; + + /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on + whether WORD contains no quoting characters, a partially quoted + string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */ + int quoted_state; + + /* State flags */ + int had_quoted_null; + int has_dollar_at; + int tflag; + int pflags; /* flags passed to param_expand */ + + int assignoff; /* If assignment, offset of `=' */ + + register unsigned char c; /* Current character. */ + int t_index; /* For calls to string_extract_xxx. */ + + char twochars[2]; + + DECLARE_MBSTATE; + + istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE); + istring[istring_index = 0] = '\0'; + quoted_dollar_at = had_quoted_null = has_dollar_at = 0; + quoted_state = UNQUOTED; + + string = word->word; + if (string == 0) + goto finished_with_string; + /* Don't need the string length for the SADD... and COPY_ macros unless + multibyte characters are possible. */ + string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1; + + if (contains_dollar_at) + *contains_dollar_at = 0; + + assignoff = -1; + + /* Begin the expansion. */ + + for (sindex = 0; ;) + { + c = string[sindex]; + + /* Case on toplevel character. */ + switch (c) + { + case '\0': + goto finished_with_string; + + case CTLESC: + sindex++; +#if HANDLE_MULTIBYTE + if (MB_CUR_MAX > 1 && string[sindex]) + { + SADD_MBQCHAR_BODY(temp, string, sindex, string_size); + } + else +#endif + { + temp = (char *)xmalloc (3); + temp[0] = CTLESC; + temp[1] = c = string[sindex]; + temp[2] = '\0'; + } + +dollar_add_string: + if (string[sindex]) + sindex++; + +add_string: + if (temp) + { + istring = sub_append_string (temp, istring, &istring_index, &istring_size); + temp = (char *)0; + } + + break; + +#if defined (PROCESS_SUBSTITUTION) + /* Process substitution. */ + case '<': + case '>': + { + if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct) + { + sindex--; /* add_character: label increments sindex */ + goto add_character; + } + else + t_index = sindex + 1; /* skip past both '<' and LPAREN */ + + temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/ + sindex = t_index; + + /* If the process substitution specification is `<()', we want to + open the pipe for writing in the child and produce output; if + it is `>()', we want to open the pipe for reading in the child + and consume input. */ + temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0; + + FREE (temp1); + + goto dollar_add_string; + } +#endif /* PROCESS_SUBSTITUTION */ + + case '=': + /* Posix.2 section 3.6.1 says that tildes following `=' in words + which are not assignment statements are not expanded. If the + shell isn't in posix mode, though, we perform tilde expansion + on `likely candidate' unquoted assignment statements (flags + include W_ASSIGNMENT but not W_QUOTED). A likely candidate + contains an unquoted :~ or =~. Something to think about: we + now have a flag that says to perform tilde expansion on arguments + to `assignment builtins' like declare and export that look like + assignment statements. We now do tilde expansion on such words + even in POSIX mode. */ + if (word->flags & (W_ASSIGNRHS|W_NOTILDE)) + { + if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c)) + goto add_ifs_character; + else + goto add_character; + } + /* If we're not in posix mode or forcing assignment-statement tilde + expansion, note where the `=' appears in the word and prepare to + do tilde expansion following the first `='. */ + if ((word->flags & W_ASSIGNMENT) && + (posixly_correct == 0 || (word->flags & W_TILDEEXP)) && + assignoff == -1 && sindex > 0) + assignoff = sindex; + if (sindex == assignoff && string[sindex+1] == '~') /* XXX */ + word->flags |= W_ITILDE; +#if 0 + else if ((word->flags & W_ASSIGNMENT) && + (posixly_correct == 0 || (word->flags & W_TILDEEXP)) && + string[sindex+1] == '~') + word->flags |= W_ITILDE; +#endif + if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c)) + goto add_ifs_character; + else + goto add_character; + + case ':': + if (word->flags & W_NOTILDE) + { + if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c)) + goto add_ifs_character; + else + goto add_character; + } + + if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) && + string[sindex+1] == '~') + word->flags |= W_ITILDE; + + if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c)) + goto add_ifs_character; + else + goto add_character; + + case '~': + /* If the word isn't supposed to be tilde expanded, or we're not + at the start of a word or after an unquoted : or = in an + assignment statement, we don't do tilde expansion. */ + if ((word->flags & (W_NOTILDE|W_DQUOTE)) || + (sindex > 0 && ((word->flags & W_ITILDE) == 0)) || + (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) + { + word->flags &= ~W_ITILDE; + if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0) + goto add_ifs_character; + else + goto add_character; + } + + if (word->flags & W_ASSIGNRHS) + tflag = 2; + else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP)) + tflag = 1; + else + tflag = 0; + + temp = bash_tilde_find_word (string + sindex, tflag, &t_index); + + word->flags &= ~W_ITILDE; + + if (temp && *temp && t_index > 0) + { + temp1 = bash_tilde_expand (temp, tflag); + if (temp1 && *temp1 == '~' && STREQ (temp, temp1)) + { + FREE (temp); + FREE (temp1); + goto add_character; /* tilde expansion failed */ + } + free (temp); + temp = temp1; + sindex += t_index; + goto add_quoted_string; /* XXX was add_string */ + } + else + { + FREE (temp); + goto add_character; + } + + case '$': + if (expanded_something) + *expanded_something = 1; + + has_dollar_at = 0; + pflags = (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0; + if (word->flags & W_NOSPLIT2) + pflags |= PF_NOSPLIT2; + if (word->flags & W_ASSIGNRHS) + pflags |= PF_ASSIGNRHS; + tword = param_expand (string, &sindex, quoted, expanded_something, + &has_dollar_at, "ed_dollar_at, + &had_quoted_null, pflags); + + if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal) + { + free (string); + free (istring); + return ((tword == &expand_wdesc_error) ? &expand_word_error + : &expand_word_fatal); + } + if (contains_dollar_at && has_dollar_at) + *contains_dollar_at = 1; + + if (tword && (tword->flags & W_HASQUOTEDNULL)) + had_quoted_null = 1; + + temp = tword ? tword->word : (char *)NULL; + dispose_word_desc (tword); /* nulls tword->word so ok */ + + /* Kill quoted nulls; we will add them back at the end of + expand_word_internal if nothing else in the string */ + if (had_quoted_null && temp && QUOTED_NULL (temp)) + { + FREE (temp); + temp = (char *)NULL; + } + + goto add_string; + break; + + case '`': /* Backquoted command substitution. */ + { + t_index = sindex++; + + temp = string_extract (string, &sindex, "`", SX_REQMATCH); + /* The test of sindex against t_index is to allow bare instances of + ` to pass through, for backwards compatibility. */ + if (temp == &extract_string_error || temp == &extract_string_fatal) + { + if (sindex - 1 == t_index) + { + sindex = t_index; + goto add_character; + } + last_command_exit_value = EXECUTION_FAILURE; + report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index); + free (string); + free (istring); + return ((temp == &extract_string_error) ? &expand_word_error + : &expand_word_fatal); + } + + if (expanded_something) + *expanded_something = 1; + + if (word->flags & W_NOCOMSUB) + /* sindex + 1 because string[sindex] == '`' */ + temp1 = substring (string, t_index, sindex + 1); + else + { + de_backslash (temp); + tword = command_substitute (temp, quoted); + temp1 = tword ? tword->word : (char *)NULL; + if (tword) + dispose_word_desc (tword); + } + FREE (temp); + temp = temp1; + goto dollar_add_string; + } + + case '\\': + if (string[sindex + 1] == '\n') + { + sindex += 2; + continue; + } + + c = string[++sindex]; + + if (quoted & Q_HERE_DOCUMENT) + tflag = CBSHDOC; + else if (quoted & Q_DOUBLE_QUOTES) + tflag = CBSDQUOTE; + else + tflag = 0; + + /* From Posix discussion on austin-group list: Backslash escaping + a } in ${...} is removed. Issue 0000221 */ + if ((quoted & Q_DOLBRACE) && c == RBRACE) + { + SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size); + } + else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0)) + { + SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size); + } + else if (c == 0) + { + c = CTLNUL; + sindex--; /* add_character: label increments sindex */ + goto add_character; + } + else + { + SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size); + } + + sindex++; +add_twochars: + /* BEFORE jumping here, we need to increment sindex if appropriate */ + RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, + DEFAULT_ARRAY_SIZE); + istring[istring_index++] = twochars[0]; + istring[istring_index++] = twochars[1]; + istring[istring_index] = '\0'; + + break; + + case '"': +#if 0 + if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE)) +#else + if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) +#endif + goto add_character; + + t_index = ++sindex; + temp = string_extract_double_quoted (string, &sindex, 0); + + /* If the quotes surrounded the entire string, then the + whole word was quoted. */ + quoted_state = (t_index == 1 && string[sindex] == '\0') + ? WHOLLY_QUOTED + : PARTIALLY_QUOTED; + + if (temp && *temp) + { + tword = alloc_word_desc (); + tword->word = temp; + + temp = (char *)NULL; + + has_dollar_at = 0; + /* Need to get W_HASQUOTEDNULL flag through this function. */ + list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL); + + if (list == &expand_word_error || list == &expand_word_fatal) + { + free (istring); + free (string); + /* expand_word_internal has already freed temp_word->word + for us because of the way it prints error messages. */ + tword->word = (char *)NULL; + dispose_word (tword); + return list; + } + + dispose_word (tword); + + /* "$@" (a double-quoted dollar-at) expands into nothing, + not even a NULL word, when there are no positional + parameters. */ + if (list == 0 && has_dollar_at) + { + quoted_dollar_at++; + break; + } + + /* If we get "$@", we know we have expanded something, so we + need to remember it for the final split on $IFS. This is + a special case; it's the only case where a quoted string + can expand into more than one word. It's going to come back + from the above call to expand_word_internal as a list with + a single word, in which all characters are quoted and + separated by blanks. What we want to do is to turn it back + into a list for the next piece of code. */ + if (list) + dequote_list (list); + + if (list && list->word && (list->word->flags & W_HASQUOTEDNULL)) + had_quoted_null = 1; /* XXX */ + + if (has_dollar_at) + { + quoted_dollar_at++; + if (contains_dollar_at) + *contains_dollar_at = 1; + if (expanded_something) + *expanded_something = 1; + } + } + else + { + /* What we have is "". This is a minor optimization. */ + FREE (temp); + list = (WORD_LIST *)NULL; + } + + /* The code above *might* return a list (consider the case of "$@", + where it returns "$1", "$2", etc.). We can't throw away the + rest of the list, and we have to make sure each word gets added + as quoted. We test on tresult->next: if it is non-NULL, we + quote the whole list, save it to a string with string_list, and + add that string. We don't need to quote the results of this + (and it would be wrong, since that would quote the separators + as well), so we go directly to add_string. */ + if (list) + { + if (list->next) + { +#if 0 + if (quoted_dollar_at && (word->flags & W_NOSPLIT2)) + temp = string_list_internal (quote_list (list), " "); + else +#endif + /* Testing quoted_dollar_at makes sure that "$@" is + split correctly when $IFS does not contain a space. */ + temp = quoted_dollar_at + ? string_list_dollar_at (list, Q_DOUBLE_QUOTES) + : string_list (quote_list (list)); + dispose_words (list); + goto add_string; + } + else + { + temp = savestring (list->word->word); + tflag = list->word->flags; + dispose_words (list); + + /* If the string is not a quoted null string, we want + to remove any embedded unquoted CTLNUL characters. + We do not want to turn quoted null strings back into + the empty string, though. We do this because we + want to remove any quoted nulls from expansions that + contain other characters. For example, if we have + x"$*"y or "x$*y" and there are no positional parameters, + the $* should expand into nothing. */ + /* We use the W_HASQUOTEDNULL flag to differentiate the + cases: a quoted null character as above and when + CTLNUL is contained in the (non-null) expansion + of some variable. We use the had_quoted_null flag to + pass the value through this function to its caller. */ + if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0) + remove_quoted_nulls (temp); /* XXX */ + } + } + else + temp = (char *)NULL; + + /* We do not want to add quoted nulls to strings that are only + partially quoted; we can throw them away. The exception to + this is when we are going to be performing word splitting, + since we have to preserve a null argument if the next character + will cause word splitting. */ + if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2))) + continue; + + add_quoted_string: + + if (temp) + { + temp1 = temp; + temp = quote_string (temp); + free (temp1); + goto add_string; + } + else + { + /* Add NULL arg. */ + c = CTLNUL; + sindex--; /* add_character: label increments sindex */ + goto add_character; + } + + /* break; */ + + case '\'': +#if 0 + if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE)) +#else + if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) +#endif + goto add_character; + + t_index = ++sindex; + temp = string_extract_single_quoted (string, &sindex); + + /* If the entire STRING was surrounded by single quotes, + then the string is wholly quoted. */ + quoted_state = (t_index == 1 && string[sindex] == '\0') + ? WHOLLY_QUOTED + : PARTIALLY_QUOTED; + + /* If all we had was '', it is a null expansion. */ + if (*temp == '\0') + { + free (temp); + temp = (char *)NULL; + } + else + remove_quoted_escapes (temp); /* ??? */ + + /* We do not want to add quoted nulls to strings that are only + partially quoted; such nulls are discarded. */ + if (temp == 0 && (quoted_state == PARTIALLY_QUOTED)) + continue; + + /* If we have a quoted null expansion, add a quoted NULL to istring. */ + if (temp == 0) + { + c = CTLNUL; + sindex--; /* add_character: label increments sindex */ + goto add_character; + } + else + goto add_quoted_string; + + /* break; */ + + default: + /* This is the fix for " $@ " */ + add_ifs_character: + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c))) + { + if (string[sindex]) /* from old goto dollar_add_string */ + sindex++; + if (c == 0) + { + c = CTLNUL; + goto add_character; + } + else + { +#if HANDLE_MULTIBYTE + if (MB_CUR_MAX > 1) + sindex--; + + if (MB_CUR_MAX > 1) + { + SADD_MBQCHAR_BODY(temp, string, sindex, string_size); + } + else +#endif + { + twochars[0] = CTLESC; + twochars[1] = c; + goto add_twochars; + } + } + } + + SADD_MBCHAR (temp, string, sindex, string_size); + + add_character: + RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size, + DEFAULT_ARRAY_SIZE); + istring[istring_index++] = c; + istring[istring_index] = '\0'; + + /* Next character. */ + sindex++; + } + } + +finished_with_string: + /* OK, we're ready to return. If we have a quoted string, and + quoted_dollar_at is not set, we do no splitting at all; otherwise + we split on ' '. The routines that call this will handle what to + do if nothing has been expanded. */ + + /* Partially and wholly quoted strings which expand to the empty + string are retained as an empty arguments. Unquoted strings + which expand to the empty string are discarded. The single + exception is the case of expanding "$@" when there are no + positional parameters. In that case, we discard the expansion. */ + + /* Because of how the code that handles "" and '' in partially + quoted strings works, we need to make ISTRING into a QUOTED_NULL + if we saw quoting characters, but the expansion was empty. + "" and '' are tossed away before we get to this point when + processing partially quoted strings. This makes "" and $xxx"" + equivalent when xxx is unset. We also look to see whether we + saw a quoted null from a ${} expansion and add one back if we + need to. */ + + /* If we expand to nothing and there were no single or double quotes + in the word, we throw it away. Otherwise, we return a NULL word. + The single exception is for $@ surrounded by double quotes when + there are no positional parameters. In that case, we also throw + the word away. */ + + if (*istring == '\0') + { + if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED)) + { + istring[0] = CTLNUL; + istring[1] = '\0'; + tword = make_bare_word (istring); + tword->flags |= W_HASQUOTEDNULL; /* XXX */ + list = make_word_list (tword, (WORD_LIST *)NULL); + if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) + tword->flags |= W_QUOTED; + } + /* According to sh, ksh, and Posix.2, if a word expands into nothing + and a double-quoted "$@" appears anywhere in it, then the entire + word is removed. */ + else if (quoted_state == UNQUOTED || quoted_dollar_at) + list = (WORD_LIST *)NULL; +#if 0 + else + { + tword = make_bare_word (istring); + if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) + tword->flags |= W_QUOTED; + list = make_word_list (tword, (WORD_LIST *)NULL); + } +#else + else + list = (WORD_LIST *)NULL; +#endif + } + else if (word->flags & W_NOSPLIT) + { + tword = make_bare_word (istring); + if (word->flags & W_ASSIGNMENT) + tword->flags |= W_ASSIGNMENT; /* XXX */ + if (word->flags & W_COMPASSIGN) + tword->flags |= W_COMPASSIGN; /* XXX */ + if (word->flags & W_NOGLOB) + tword->flags |= W_NOGLOB; /* XXX */ + if (word->flags & W_NOEXPAND) + tword->flags |= W_NOEXPAND; /* XXX */ + if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) + tword->flags |= W_QUOTED; + if (had_quoted_null && QUOTED_NULL (istring)) + tword->flags |= W_HASQUOTEDNULL; + list = make_word_list (tword, (WORD_LIST *)NULL); + } + else + { + char *ifs_chars; + + ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL; + + /* If we have $@, we need to split the results no matter what. If + IFS is unset or NULL, string_list_dollar_at has separated the + positional parameters with a space, so we split on space (we have + set ifs_chars to " \t\n" above if ifs is unset). If IFS is set, + string_list_dollar_at has separated the positional parameters + with the first character of $IFS, so we split on $IFS. */ + if (has_dollar_at && ifs_chars) + list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1); + else + { + tword = make_bare_word (istring); + if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED)) + tword->flags |= W_QUOTED; + if (word->flags & W_ASSIGNMENT) + tword->flags |= W_ASSIGNMENT; + if (word->flags & W_COMPASSIGN) + tword->flags |= W_COMPASSIGN; + if (word->flags & W_NOGLOB) + tword->flags |= W_NOGLOB; + if (word->flags & W_NOEXPAND) + tword->flags |= W_NOEXPAND; + if (had_quoted_null && QUOTED_NULL (istring)) + tword->flags |= W_HASQUOTEDNULL; /* XXX */ + list = make_word_list (tword, (WORD_LIST *)NULL); + } + } + + free (istring); + return (list); +} + +/* **************************************************************** */ +/* */ +/* Functions for Quote Removal */ +/* */ +/* **************************************************************** */ + +/* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the + backslash quoting rules for within double quotes or a here document. */ +char * +string_quote_removal (string, quoted) + char *string; + int quoted; +{ + size_t slen; + char *r, *result_string, *temp, *send; + int sindex, tindex, dquote; + unsigned char c; + DECLARE_MBSTATE; + + /* The result can be no longer than the original string. */ + slen = strlen (string); + send = string + slen; + + r = result_string = (char *)xmalloc (slen + 1); + + for (dquote = sindex = 0; c = string[sindex];) + { + switch (c) + { + case '\\': + c = string[++sindex]; + if (c == 0) + { + *r++ = '\\'; + break; + } + if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0) + *r++ = '\\'; + /* FALLTHROUGH */ + + default: + SCOPY_CHAR_M (r, string, send, sindex); + break; + + case '\'': + if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) + { + *r++ = c; + sindex++; + break; + } + tindex = sindex + 1; + temp = string_extract_single_quoted (string, &tindex); + if (temp) + { + strcpy (r, temp); + r += strlen (r); + free (temp); + } + sindex = tindex; + break; + + case '"': + dquote = 1 - dquote; + sindex++; + break; + } + } + *r = '\0'; + return (result_string); +} + +#if 0 +/* UNUSED */ +/* Perform quote removal on word WORD. This allocates and returns a new + WORD_DESC *. */ +WORD_DESC * +word_quote_removal (word, quoted) + WORD_DESC *word; + int quoted; +{ + WORD_DESC *w; + char *t; + + t = string_quote_removal (word->word, quoted); + w = alloc_word_desc (); + w->word = t ? t : savestring (""); + return (w); +} + +/* Perform quote removal on all words in LIST. If QUOTED is non-zero, + the members of the list are treated as if they are surrounded by + double quotes. Return a new list, or NULL if LIST is NULL. */ +WORD_LIST * +word_list_quote_removal (list, quoted) + WORD_LIST *list; + int quoted; +{ + WORD_LIST *result, *t, *tresult, *e; + + for (t = list, result = (WORD_LIST *)NULL; t; t = t->next) + { + tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL); +#if 0 + result = (WORD_LIST *) list_append (result, tresult); +#else + if (result == 0) + result = e = tresult; + else + { + e->next = tresult; + while (e->next) + e = e->next; + } +#endif + } + return (result); +} +#endif + +/******************************************* + * * + * Functions to perform word splitting * + * * + *******************************************/ + +void +setifs (v) + SHELL_VAR *v; +{ + char *t; + unsigned char uc; + + ifs_var = v; + ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n"; + + /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet + handle multibyte chars in IFS */ + memset (ifs_cmap, '\0', sizeof (ifs_cmap)); + for (t = ifs_value ; t && *t; t++) + { + uc = *t; + ifs_cmap[uc] = 1; + } + +#if defined (HANDLE_MULTIBYTE) + if (ifs_value == 0) + { + ifs_firstc[0] = '\0'; + ifs_firstc_len = 1; + } + else + { + size_t ifs_len; + ifs_len = strnlen (ifs_value, MB_CUR_MAX); + ifs_firstc_len = MBLEN (ifs_value, ifs_len); + if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len)) + { + ifs_firstc[0] = ifs_value[0]; + ifs_firstc[1] = '\0'; + ifs_firstc_len = 1; + } + else + memcpy (ifs_firstc, ifs_value, ifs_firstc_len); + } +#else + ifs_firstc = ifs_value ? *ifs_value : 0; +#endif +} + +char * +getifs () +{ + return ifs_value; +} + +/* This splits a single word into a WORD LIST on $IFS, but only if the word + is not quoted. list_string () performs quote removal for us, even if we + don't do any splitting. */ +WORD_LIST * +word_split (w, ifs_chars) + WORD_DESC *w; + char *ifs_chars; +{ + WORD_LIST *result; + + if (w) + { + char *xifs; + + xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars; + result = list_string (w->word, xifs, w->flags & W_QUOTED); + } + else + result = (WORD_LIST *)NULL; + + return (result); +} + +/* Perform word splitting on LIST and return the RESULT. It is possible + to return (WORD_LIST *)NULL. */ +static WORD_LIST * +word_list_split (list) + WORD_LIST *list; +{ + WORD_LIST *result, *t, *tresult, *e; + + for (t = list, result = (WORD_LIST *)NULL; t; t = t->next) + { + tresult = word_split (t->word, ifs_value); + if (result == 0) + result = e = tresult; + else + { + e->next = tresult; + while (e->next) + e = e->next; + } + } + return (result); +} + +/************************************************** + * * + * Functions to expand an entire WORD_LIST * + * * + **************************************************/ + +/* Do any word-expansion-specific cleanup and jump to top_level */ +static void +exp_jump_to_top_level (v) + int v; +{ + set_pipestatus_from_exit (last_command_exit_value); + + /* Cleanup code goes here. */ + expand_no_split_dollar_star = 0; /* XXX */ + expanding_redir = 0; + assigning_in_environment = 0; + + if (parse_and_execute_level == 0) + top_level_cleanup (); /* from sig.c */ + + jump_to_top_level (v); +} + +/* Put NLIST (which is a WORD_LIST * of only one element) at the front of + ELIST, and set ELIST to the new list. */ +#define PREPEND_LIST(nlist, elist) \ + do { nlist->next = elist; elist = nlist; } while (0) + +/* Separate out any initial variable assignments from TLIST. If set -k has + been executed, remove all assignment statements from TLIST. Initial + variable assignments and other environment assignments are placed + on SUBST_ASSIGN_VARLIST. */ +static WORD_LIST * +separate_out_assignments (tlist) + WORD_LIST *tlist; +{ + register WORD_LIST *vp, *lp; + + if (tlist == 0) + return ((WORD_LIST *)NULL); + + if (subst_assign_varlist) + dispose_words (subst_assign_varlist); /* Clean up after previous error */ + + subst_assign_varlist = (WORD_LIST *)NULL; + vp = lp = tlist; + + /* Separate out variable assignments at the start of the command. + Loop invariant: vp->next == lp + Loop postcondition: + lp = list of words left after assignment statements skipped + tlist = original list of words + */ + while (lp && (lp->word->flags & W_ASSIGNMENT)) + { + vp = lp; + lp = lp->next; + } + + /* If lp != tlist, we have some initial assignment statements. + We make SUBST_ASSIGN_VARLIST point to the list of assignment + words and TLIST point to the remaining words. */ + if (lp != tlist) + { + subst_assign_varlist = tlist; + /* ASSERT(vp->next == lp); */ + vp->next = (WORD_LIST *)NULL; /* terminate variable list */ + tlist = lp; /* remainder of word list */ + } + + /* vp == end of variable list */ + /* tlist == remainder of original word list without variable assignments */ + if (!tlist) + /* All the words in tlist were assignment statements */ + return ((WORD_LIST *)NULL); + + /* ASSERT(tlist != NULL); */ + /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */ + + /* If the -k option is in effect, we need to go through the remaining + words, separate out the assignment words, and place them on + SUBST_ASSIGN_VARLIST. */ + if (place_keywords_in_env) + { + WORD_LIST *tp; /* tp == running pointer into tlist */ + + tp = tlist; + lp = tlist->next; + + /* Loop Invariant: tp->next == lp */ + /* Loop postcondition: tlist == word list without assignment statements */ + while (lp) + { + if (lp->word->flags & W_ASSIGNMENT) + { + /* Found an assignment statement, add this word to end of + subst_assign_varlist (vp). */ + if (!subst_assign_varlist) + subst_assign_varlist = vp = lp; + else + { + vp->next = lp; + vp = lp; + } + + /* Remove the word pointed to by LP from TLIST. */ + tp->next = lp->next; + /* ASSERT(vp == lp); */ + lp->next = (WORD_LIST *)NULL; + lp = tp->next; + } + else + { + tp = lp; + lp = lp->next; + } + } + } + return (tlist); +} + +#define WEXP_VARASSIGN 0x001 +#define WEXP_BRACEEXP 0x002 +#define WEXP_TILDEEXP 0x004 +#define WEXP_PARAMEXP 0x008 +#define WEXP_PATHEXP 0x010 + +/* All of the expansions, including variable assignments at the start of + the list. */ +#define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP) + +/* All of the expansions except variable assignments at the start of + the list. */ +#define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP) + +/* All of the `shell expansions': brace expansion, tilde expansion, parameter + expansion, command substitution, arithmetic expansion, word splitting, and + quote removal. */ +#define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP) + +/* Take the list of words in LIST and do the various substitutions. Return + a new list of words which is the expanded list, and without things like + variable assignments. */ + +WORD_LIST * +expand_words (list) + WORD_LIST *list; +{ + return (expand_word_list_internal (list, WEXP_ALL)); +} + +/* Same as expand_words (), but doesn't hack variable or environment + variables. */ +WORD_LIST * +expand_words_no_vars (list) + WORD_LIST *list; +{ + return (expand_word_list_internal (list, WEXP_NOVARS)); +} + +WORD_LIST * +expand_words_shellexp (list) + WORD_LIST *list; +{ + return (expand_word_list_internal (list, WEXP_SHELLEXP)); +} + +static WORD_LIST * +glob_expand_word_list (tlist, eflags) + WORD_LIST *tlist; + int eflags; +{ + char **glob_array, *temp_string; + register int glob_index; + WORD_LIST *glob_list, *output_list, *disposables, *next; + WORD_DESC *tword; + + output_list = disposables = (WORD_LIST *)NULL; + glob_array = (char **)NULL; + while (tlist) + { + /* For each word, either globbing is attempted or the word is + added to orig_list. If globbing succeeds, the results are + added to orig_list and the word (tlist) is added to the list + of disposable words. If globbing fails and failed glob + expansions are left unchanged (the shell default), the + original word is added to orig_list. If globbing fails and + failed glob expansions are removed, the original word is + added to the list of disposable words. orig_list ends up + in reverse order and requires a call to REVERSE_LIST to + be set right. After all words are examined, the disposable + words are freed. */ + next = tlist->next; + + /* If the word isn't an assignment and contains an unquoted + pattern matching character, then glob it. */ + if ((tlist->word->flags & W_NOGLOB) == 0 && + unquoted_glob_pattern_p (tlist->word->word)) + { + glob_array = shell_glob_filename (tlist->word->word); + + /* Handle error cases. + I don't think we should report errors like "No such file + or directory". However, I would like to report errors + like "Read failed". */ + + if (glob_array == 0 || GLOB_FAILED (glob_array)) + { + glob_array = (char **)xmalloc (sizeof (char *)); + glob_array[0] = (char *)NULL; + } + + /* Dequote the current word in case we have to use it. */ + if (glob_array[0] == NULL) + { + temp_string = dequote_string (tlist->word->word); + free (tlist->word->word); + tlist->word->word = temp_string; + } + + /* Make the array into a word list. */ + glob_list = (WORD_LIST *)NULL; + for (glob_index = 0; glob_array[glob_index]; glob_index++) + { + tword = make_bare_word (glob_array[glob_index]); + tword->flags |= W_GLOBEXP; /* XXX */ + glob_list = make_word_list (tword, glob_list); + } + + if (glob_list) + { + output_list = (WORD_LIST *)list_append (glob_list, output_list); + PREPEND_LIST (tlist, disposables); + } + else if (fail_glob_expansion != 0) + { + last_command_exit_value = EXECUTION_FAILURE; + report_error (_("no match: %s"), tlist->word->word); + exp_jump_to_top_level (DISCARD); + } + else if (allow_null_glob_expansion == 0) + { + /* Failed glob expressions are left unchanged. */ + PREPEND_LIST (tlist, output_list); + } + else + { + /* Failed glob expressions are removed. */ + PREPEND_LIST (tlist, disposables); + } + } + else + { + /* Dequote the string. */ + temp_string = dequote_string (tlist->word->word); + free (tlist->word->word); + tlist->word->word = temp_string; + PREPEND_LIST (tlist, output_list); + } + + strvec_dispose (glob_array); + glob_array = (char **)NULL; + + tlist = next; + } + + if (disposables) + dispose_words (disposables); + + if (output_list) + output_list = REVERSE_LIST (output_list, WORD_LIST *); + + return (output_list); +} + +#if defined (BRACE_EXPANSION) +static WORD_LIST * +brace_expand_word_list (tlist, eflags) + WORD_LIST *tlist; + int eflags; +{ + register char **expansions; + char *temp_string; + WORD_LIST *disposables, *output_list, *next; + WORD_DESC *w; + int eindex; + + for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next) + { + next = tlist->next; + + if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG)) + { +/*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/ + PREPEND_LIST (tlist, output_list); + continue; + } + + /* Only do brace expansion if the word has a brace character. If + not, just add the word list element to BRACES and continue. In + the common case, at least when running shell scripts, this will + degenerate to a bunch of calls to `mbschr', and then what is + basically a reversal of TLIST into BRACES, which is corrected + by a call to REVERSE_LIST () on BRACES when the end of TLIST + is reached. */ + if (mbschr (tlist->word->word, LBRACE)) + { + expansions = brace_expand (tlist->word->word); + + for (eindex = 0; temp_string = expansions[eindex]; eindex++) + { + w = alloc_word_desc (); + w->word = temp_string; + + /* If brace expansion didn't change the word, preserve + the flags. We may want to preserve the flags + unconditionally someday -- XXX */ + if (STREQ (temp_string, tlist->word->word)) + w->flags = tlist->word->flags; + else + w = make_word_flags (w, temp_string); + + output_list = make_word_list (w, output_list); + } + free (expansions); + + /* Add TLIST to the list of words to be freed after brace + expansion has been performed. */ + PREPEND_LIST (tlist, disposables); + } + else + PREPEND_LIST (tlist, output_list); + } + + if (disposables) + dispose_words (disposables); + + if (output_list) + output_list = REVERSE_LIST (output_list, WORD_LIST *); + + return (output_list); +} +#endif + +#if defined (ARRAY_VARS) +/* Take WORD, a compound associative array assignment, and internally run + 'declare -A w', where W is the variable name portion of WORD. */ +static int +make_internal_declare (word, option) + char *word; + char *option; +{ + int t; + WORD_LIST *wl; + WORD_DESC *w; + + w = make_word (word); + + t = assignment (w->word, 0); + w->word[t] = '\0'; + + wl = make_word_list (w, (WORD_LIST *)NULL); + wl = make_word_list (make_word (option), wl); + + return (declare_builtin (wl)); +} +#endif + +static WORD_LIST * +shell_expand_word_list (tlist, eflags) + WORD_LIST *tlist; + int eflags; +{ + WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list; + int expanded_something, has_dollar_at; + char *temp_string; + + /* We do tilde expansion all the time. This is what 1003.2 says. */ + new_list = (WORD_LIST *)NULL; + for (orig_list = tlist; tlist; tlist = next) + { + temp_string = tlist->word->word; + + next = tlist->next; + +#if defined (ARRAY_VARS) + /* If this is a compound array assignment to a builtin that accepts + such assignments (e.g., `declare'), take the assignment and perform + it separately, handling the semantics of declarations inside shell + functions. This avoids the double-evaluation of such arguments, + because `declare' does some evaluation of compound assignments on + its own. */ + if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG)) + { + int t; + + if (tlist->word->flags & W_ASSIGNASSOC) + make_internal_declare (tlist->word->word, "-A"); + + t = do_word_assignment (tlist->word, 0); + if (t == 0) + { + last_command_exit_value = EXECUTION_FAILURE; + exp_jump_to_top_level (DISCARD); + } + + /* Now transform the word as ksh93 appears to do and go on */ + t = assignment (tlist->word->word, 0); + tlist->word->word[t] = '\0'; + tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC); + } +#endif + + expanded_something = 0; + expanded = expand_word_internal + (tlist->word, 0, 0, &has_dollar_at, &expanded_something); + + if (expanded == &expand_word_error || expanded == &expand_word_fatal) + { + /* By convention, each time this error is returned, + tlist->word->word has already been freed. */ + tlist->word->word = (char *)NULL; + + /* Dispose our copy of the original list. */ + dispose_words (orig_list); + /* Dispose the new list we're building. */ + dispose_words (new_list); + + last_command_exit_value = EXECUTION_FAILURE; + if (expanded == &expand_word_error) + exp_jump_to_top_level (DISCARD); + else + exp_jump_to_top_level (FORCE_EOF); + } + + /* Don't split words marked W_NOSPLIT. */ + if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0) + { + temp_list = word_list_split (expanded); + dispose_words (expanded); + } + else + { + /* If no parameter expansion, command substitution, process + substitution, or arithmetic substitution took place, then + do not do word splitting. We still have to remove quoted + null characters from the result. */ + word_list_remove_quoted_nulls (expanded); + temp_list = expanded; + } + + expanded = REVERSE_LIST (temp_list, WORD_LIST *); + new_list = (WORD_LIST *)list_append (expanded, new_list); + } + + if (orig_list) + dispose_words (orig_list); + + if (new_list) + new_list = REVERSE_LIST (new_list, WORD_LIST *); + + return (new_list); +} + +/* The workhorse for expand_words () and expand_words_no_vars (). + First arg is LIST, a WORD_LIST of words. + Second arg EFLAGS is a flags word controlling which expansions are + performed. + + This does all of the substitutions: brace expansion, tilde expansion, + parameter expansion, command substitution, arithmetic expansion, + process substitution, word splitting, and pathname expansion, according + to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits + set, or for which no expansion is done, do not undergo word splitting. + Words with the W_NOGLOB bit set do not undergo pathname expansion. */ +static WORD_LIST * +expand_word_list_internal (list, eflags) + WORD_LIST *list; + int eflags; +{ + WORD_LIST *new_list, *temp_list; + int tint; + + if (list == 0) + return ((WORD_LIST *)NULL); + + garglist = new_list = copy_word_list (list); + if (eflags & WEXP_VARASSIGN) + { + garglist = new_list = separate_out_assignments (new_list); + if (new_list == 0) + { + if (subst_assign_varlist) + { + /* All the words were variable assignments, so they are placed + into the shell's environment. */ + for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next) + { + this_command_name = (char *)NULL; /* no arithmetic errors */ + tint = do_word_assignment (temp_list->word, 0); + /* Variable assignment errors in non-interactive shells + running in Posix.2 mode cause the shell to exit. */ + if (tint == 0) + { + last_command_exit_value = EXECUTION_FAILURE; + if (interactive_shell == 0 && posixly_correct) + exp_jump_to_top_level (FORCE_EOF); + else + exp_jump_to_top_level (DISCARD); + } + } + dispose_words (subst_assign_varlist); + subst_assign_varlist = (WORD_LIST *)NULL; + } + return ((WORD_LIST *)NULL); + } + } + + /* Begin expanding the words that remain. The expansions take place on + things that aren't really variable assignments. */ + +#if defined (BRACE_EXPANSION) + /* Do brace expansion on this word if there are any brace characters + in the string. */ + if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list) + new_list = brace_expand_word_list (new_list, eflags); +#endif /* BRACE_EXPANSION */ + + /* Perform the `normal' shell expansions: tilde expansion, parameter and + variable substitution, command substitution, arithmetic expansion, + and word splitting. */ + new_list = shell_expand_word_list (new_list, eflags); + + /* Okay, we're almost done. Now let's just do some filename + globbing. */ + if (new_list) + { + if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0) + /* Glob expand the word list unless globbing has been disabled. */ + new_list = glob_expand_word_list (new_list, eflags); + else + /* Dequote the words, because we're not performing globbing. */ + new_list = dequote_list (new_list); + } + + if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist) + { + sh_wassign_func_t *assign_func; + int is_special_builtin, is_builtin_or_func; + + /* If the remainder of the words expand to nothing, Posix.2 requires + that the variable and environment assignments affect the shell's + environment. */ + assign_func = new_list ? assign_in_env : do_word_assignment; + tempenv_assign_error = 0; + + is_builtin_or_func = (new_list && new_list->word && (find_shell_builtin (new_list->word->word) || find_function (new_list->word->word))); + /* Posix says that special builtins exit if a variable assignment error + occurs in an assignment preceding it. */ + is_special_builtin = (posixly_correct && new_list && new_list->word && find_special_builtin (new_list->word->word)); + + for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next) + { + this_command_name = (char *)NULL; + assigning_in_environment = (assign_func == assign_in_env); + tint = (*assign_func) (temp_list->word, is_builtin_or_func); + assigning_in_environment = 0; + /* Variable assignment errors in non-interactive shells running + in Posix.2 mode cause the shell to exit. */ + if (tint == 0) + { + if (assign_func == do_word_assignment) + { + last_command_exit_value = EXECUTION_FAILURE; + if (interactive_shell == 0 && posixly_correct && is_special_builtin) + exp_jump_to_top_level (FORCE_EOF); + else + exp_jump_to_top_level (DISCARD); + } + else + tempenv_assign_error++; + } + } + + dispose_words (subst_assign_varlist); + subst_assign_varlist = (WORD_LIST *)NULL; + } + +#if 0 + tint = list_length (new_list) + 1; + RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16); + for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next) + glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0'; + glob_argv_flags[tint] = '\0'; +#endif + + return (new_list); +} diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 3efcf32d6..72ec06a2c 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -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 diff --git a/tests/RUN-ONE-TEST~ b/tests/RUN-ONE-TEST~ new file mode 100755 index 000000000..3efcf32d6 --- /dev/null +++ b/tests/RUN-ONE-TEST~ @@ -0,0 +1,9 @@ +BUILD_DIR=/usr/local/build/chet/bash/bash-current +THIS_SH=$BUILD_DIR/bash +PATH=$PATH:$BUILD_DIR + +export THIS_SH PATH + +rm -f /tmp/xx + +/bin/sh "$@" diff --git a/tests/history.tests b/tests/history.tests index 688095d59..25d7834fc 100644 --- a/tests/history.tests +++ b/tests/history.tests @@ -109,5 +109,6 @@ shopt -q -o history echo $? ${THIS_SH} ./history1.sub +rm foohist-* ${THIS_SH} ./history2.sub diff --git a/tests/history.tests~ b/tests/history.tests~ new file mode 100644 index 000000000..688095d59 --- /dev/null +++ b/tests/history.tests~ @@ -0,0 +1,113 @@ +trap 'rm /tmp/newhistory' 0 + +# bad options +history -x +# cannot use -r and -w at the same time +history -r -w /dev/null + +# bad option +fc -v + +unset HISTFILESIZE + +# all of these should result in an empty history list +history -c +history -r /dev/null +history -n /dev/null +history -c + +HISTFILE=history.list +HISTCONTROL=ignoreboth +HISTIGNORE='&:history*:fc*' +HISTSIZE=32 + +shopt -s cmdhist +set -o history + +history + +fc -l +fc -nl + +fc -lr +fc -nlr + +history -s "echo line for history" +history + +history -p '!!' + +fc -nl + +HISTFILE=/tmp/newhistory +history -a +echo displaying \$HISTFILE after history -a +cat $HISTFILE + +history +history -w +cat $HISTFILE + +history -s "echo line 2 for history" +history +history -p '!e' +history -p '!!' + +# this should show up as one history entry +for x in one two three +do + : +done +history + +# just a basic test. a full test suite for history expansion should be +# created +set -H +!! +!e + +unset HISTSIZE +unset HISTFILE + +fc -l 4 +fc -l 4 8 + +fc -l one=two three=four 502 + +history 4 + +shopt -so history +shopt -s expand_aliases + +alias r="fc -s" + +echo aa ab ac + +r a=x +r x=4 b=8 + +# this had better fail with `no command found' +r cc + +unalias -a +alias + +# these two blocks had better both result in the same output +echo aa +echo bb +echo cc +fc -e cat + +echo aa +echo bb +echo cc +fc -e cat -1 + +set +o history + +shopt -q -o history +echo $? + +${THIS_SH} ./history1.sub + +${THIS_SH} ./history2.sub diff --git a/tests/history1.sub b/tests/history1.sub index 543a3e8eb..fa51ffc16 100644 --- a/tests/history1.sub +++ b/tests/history1.sub @@ -1,3 +1,5 @@ +trap 'rm -f $HISTFILE' 0 1 2 3 6 15 + HISTFILE=foohist-$$ unset HISTIGNORE HISTCONTROL set -o history diff --git a/tests/iquote.right b/tests/iquote.right index d164f1051..9476128c3 100644 --- a/tests/iquote.right +++ b/tests/iquote.right @@ -59,3 +59,34 @@ argv[1] = argv[1] = argv[1] = argv[1] = +argv[1] = +argv[1] = +argv[1] = +argv[1] = +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <^?> +argv[1] = <^? > +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?x> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?x> +argv[1] = <^?x> +argv[1] = <^?> +argv[1] = < ^? x> +argv[1] = <^? x> +argv[1] = <^? > diff --git a/tests/iquote.tests b/tests/iquote.tests index a2cdf4f71..a1e63622e 100644 --- a/tests/iquote.tests +++ b/tests/iquote.tests @@ -141,3 +141,5 @@ recho aaa$'\177'bbb recho ccc""ddd recho "eeefff" recho ggg"$(echo $'\177')"hhh + +${THIS_SH} ./iquote1.sub diff --git a/tests/iquote.tests~ b/tests/iquote.tests~ new file mode 100644 index 000000000..a2cdf4f71 --- /dev/null +++ b/tests/iquote.tests~ @@ -0,0 +1,143 @@ +# bug in bash up to and including bash-3.0 (including patches) +# +# problem is conflict between CTLNUL used internally to denote quoted null +# characters and its value (0x7f) appearing in the expansion of a variable +# +unset x +recho "xxx${x}yyy" + +y=$'\177' +recho "xxx${y}yyy" + +unset y + +unset undef + +set "" +recho ${undef-"x$*y"} + +set $'\177' +recho ${undef-"x$*y"} + +shift $# + +f() +{ + recho "-${*-x}-" +} + +f '' +f $'\177' + +unset -f f + +x=12345 + +recho "${x:6:1}" + +x= +recho "${x:0:1}" + +y=$'\177' +recho "${y:0:1}" + +y=xxx$'\177'yyy +recho "${y:3:3}" + +unset x y + +eval tmp=`printf "$'\\\\\x%x'\n" 127` +printf "%#1x\n" "'$tmp" + +x=$'\177' +printf "%#1x\n" "'$x" + +a=127 +eval c=\$\'\\$(printf '%o' $a)\' +printf "%#1x\n" "'$c" + +recho "$c" +recho "$c"@ +recho @"$c"@ +recho @"$c" + +recho "$c" +recho "$c@" +recho "@$c@" +recho "@$c" + +unset tmp x a c + +qtest() +{ + recho ${#q} "${q}" ${q} +} + +q=$'\x7f' +qtest + +q=${q}a +qtest + +q=$'\x7fa' +qtest + +q="${q}a" +qtest + +unset -f qtest +unset q + +set -- '' +recho "${*:1}" +recho ${*:1} +recho -${*:1}- +recho -"${*:1}"- + +set $'\177' +recho "${*:1}" +recho "-${*:1}-" + +recho ${*:1} +recho -${*:1}- + +shift $# + +DEL=`awk 'END{printf("%c", 0+127)}' +bgwait sleep done... wait 6187 + + +bash: +<&$fd ok +nlbq Mon Aug 3 02:45:09 EDT 1992 +bang geoff +quote 712824311 +setbq defmsgid=<1992Aug3.024512.6212@host> +bgwait sleep done... wait 6223 + + +ash: +<&$fd shx1: 4: Syntax error: Bad fd number +nlbq Mon Aug 3 02:45:19 EDT 1992 +bang geoff +quote getdate: `"now"' not a valid date + +setbq defmsgid=<1992Aug3.` echo 024521 +bgwait sleep done... wait 6241 + + +ksh: +<&$fd ok +nlbq ./shx: 6248 Memory fault - core dumped +bang geoff +quote getdate: `"now"' not a valid date + +setbq defmsgid=<1992Aug3.024530.6257@host> +bgwait no such job: 6265 +wait 6265 +sleep done... + +zsh: +<&$fd ok +nlbq Mon Aug 3 02:45:36 EDT 1992 +bang shx3: event not found: /s/ [4] +quote 712824337 +setbq defmsgid=<..6290@host> +bgwait shx7: unmatched " [9] +sleep done... +:; diff --git a/tests/misc/regress/shx.orig b/tests/misc/regress/shx.orig new file mode 100644 index 000000000..4b3bf2b82 --- /dev/null +++ b/tests/misc/regress/shx.orig @@ -0,0 +1,10 @@ +#! /bin/sh +for cmd in sh bash ash ksh zsh +do + echo + echo $cmd: + for demo in shx? + do + $cmd $demo + done +done diff --git a/tests/printf3.sub.save1 b/tests/printf3.sub.save1 new file mode 100644 index 000000000..dac2f7d11 --- /dev/null +++ b/tests/printf3.sub.save1 @@ -0,0 +1,61 @@ +LC_ALL=C +LANG=C + +SHELLSTART=$(date +%s) +SECS=1275250155 +export TZ=EST5EDT + +case $SHELLSTART in +*s*) SHELLSTART=$(perl -e 'print time') ;; # take a shot +esac + +printf "%()T\n" $SECS +printf "%(abde)Z\n" -1 + +printf "%(%e-%b-%Y %T)T\n" $SECS + +printf -v v1 "%(%e-%b-%Y %T)T\n" $(date +%s) +printf -v v2 "%(%e-%b-%Y %T)T\n" -1 + +case $v1 in +$v2) ;; +*) echo "current time and -1 possible mismatch|$v1|$v2|" >&2 ;; +esac +unset v1 v2 + +v1=$(date +%s) +printf -v v2 "%(%s)T" -1 + +case $v1 in +$v2) ;; +*) echo "current time mismatch:$v1|$v2|" >&2 ;; +esac +unset v1 v2 + +printf "%(%x %X)T\n" $(( $SECS - 3600 )) + +printf -v v1 "%(%F %r)T\n" $SHELLSTART +printf -v v2 "%(%F %r)T\n" -2 + +case $v1 in +$v2) ;; +*) echo "shell start time and -2 possible mismatch|$v1|$v2|" >&2 ;; +esac +unset v1 v2 + +printf "current time: %(%F %r)T\n" $SECS + +printf "epoch time: %(%F %r %z)T\n" 0 +printf "random time: %(%F %r %z)T\n" $SECS + +printf "local time: %(%a %b %e %H:%M:%S %Z %Y)T\n" $SECS + +# test fieldwidth, justification, precision +printf "%-40.50(%a %b %e %H:%M:%S %Z %Y)T date-style time\n" $SECS + +# test fieldwidth, justification, precision, embedded parens +printf "%-40.50(%x (foo) %X)T date-style time\n" $SECS + +# problem introduced in bash-4.2 patch 5 +unset TZ +printf '%(%Y-%m-%d %H:%M:%S %Z)T\n' >/dev/null