From: Chet Ramey Date: Mon, 12 Jan 2015 16:04:17 +0000 (-0500) Subject: bash-20150109 remove leftover and stray files X-Git-Tag: bash-4.4-alpha~28 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3ff27f82dad09390b3255d0b522033e6df26af82;p=thirdparty%2Fbash.git bash-20150109 remove leftover and stray files --- diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ deleted file mode 100644 index 41fc5deb9..000000000 --- a/CWRU/CWRU.chlog~ +++ /dev/null @@ -1,7831 +0,0 @@ - 2/14/2011 - --------- -[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 glob_asciirange is 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 - - 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 - - 5/9 - --- -variables.c - - bind_variable_internal: if we get an array variable here (implicit - assignment to index 0), call make_array_variable_value, which - dummies up a fake SHELL_VAR * from array[0]. This matters when - we're appending and have to use the current value - - bind_variable_internal: after computing the new value, treat assoc - variables with higher precedence than simple array variables; it - might be that a variable has both attributes set - -arrayfunc.c - - bind_array_var_internal: break code out that handles creating the - new value to be assigned to an array variable index into a new - function, make_array_variable_value. This handles creating a - dummy SHELL_VAR * for implicit array[0] assignment. Fixes bug - reported by Dan Douglas - -arrayfunc.h - - make_array_variable_value: new extern declaration - - 5/19 - ---- -variables.c - - bind_int_variable: if an assignment statement like x=y comes in - from the expression evaluator, and x is an array, handle it like - x[0]=y. Fixes bug reported by Dan Douglas - - 5/24 - ---- - -braces.c - - mkseq: handle possible overflow and break the sequence generating - loop if it occurs. Fixes OpenSUSE bug 763591: - https://bugzilla.novell.com/show_bug.cgi?id=763591 - - 5/25 - ---- -Makefile.in - - LDFLAGS_FOR_BUILD: add to compilation recipes for build tools - buildversion, mksignames, mksyntax - - LDFLAGS_FOR_BUILD: add to compilation recipes for test tools - recho, zecho, printenv, xcase - -builtins/Makefile.in - - LDFLAGS_FOR_BUILD: add to compilation recipes for build tools - gen-helpfiles, psize.aux - -variables.c - - bind_int_variable: if LHS is a simple variable name without an array - reference, but resolves to an array variable, call - bind_array_variable with index 0 to make x=1 equivalent to x[0]=1. - Fixes bug reported by Dan Douglas - - 5/27 - ---- -subst.c - - expand_word_internal: make sure has_dollar_at doesn't get reset before - recursive calls to param_expand or expand_word_internal, since it has - to save state of what came before. Use temp variable and make sure - has_dollar_at is incremented if recursive call processes "$@". - Fixes bug reported by gregrwm and - supplemented by Dan Douglas - -doc/{bash.1,bashref.texi} - - changes to the description of substring expansion inspired by - suggestions from Bill Gradwohl - -doc/bashref.texi - - added substring expansion examples inspired by suggestions from - Bill Gradwohl - -variables.c - - find_shell_variable: search for a variable in the list of shell - contexts, ignore the temporary environment - - find_variable_tempenv: search for a variable in the list of shell - contexts, force search of the temporary environment - - find_variable_notempenv: search for a variable in the list of shell - contexts, don't force search of the temporary environment - -variables.h - - find_shell_variable: extern declaration - - find_variable_tempenv: extern declaration - - find_variable_notempenv: extern declaration - -arrayfunc.c - - bind_array_variable: call find_shell_variable instead of calling - var_lookup directly - -findcmd.c - - search_for_command: call find_variable_tempenv instead of - find_variable_internal directly - - _find_user_command_internal: call find_variable_tempenv instead of - find_variable_internal directly - -builtins/setattr.def - - set_var_attribute: call find_variable_notempenv instead of - find_variable_internal directly - - show_name_attributes: call find_variable_tempenv instead of - find_variable_internal directly - - 6/1 - --- -sig.c - - termsig_handler: don't try to save the shell history on a terminating - signal any more, since it just causes too many problems on Linux - systems using glibc and glibc malloc - -lib/readline/vi_mode.c - - rl_vi_change_to: change to correctly redo `cc', since `c' is not a vi - motion character. From Red Hat bug 813289 - - rl_vi_delete_to: change to correctly redo `dd', since `d' is not a vi - motion character - - rl_vi_yank_to: change to correctly redo `yy', since `y' is not a vi - motion character - - 6/4 - --- -lib/sh/mktime.c - - current versions of VMS do not need to include . Fix from - John E. Malmberg - - 6/5 - --- -lib/sh/eaccess.c - - sh_stat: instead of using a static buffer to do the DEV_FD_PREFIX - translation, use a dynamically-allocated buffer that we keep - resizing. Fixes potential security hole reported by David Leverton - - - 6/5 - --- -braces.c - - expand_seqterm: check errno == ERANGE after calling strtoimax for - rhs and incr. Part of a set of fixes from Scott McMillan - - - expand_seqterm: incr now of type `intmax_t', which changes - arguments to mkseq - - mkseq: a better fix for detecting overflow and underflow since it's - undefined in C and compilers `optimize' out overflow checks. Uses - ADDOVERFLOW and SUBOVERFLOW macros - - mkseq: use sh_imaxabs (new macro) instead of abs() for intmax_t - variables - - mkseq: don't allow incr to be converted to -INTMAX_MIN - - mkseq: make sure that strvec_create isn't called with a size argument - greater than INT_MAX, since it only takes an int - - 6/6 - --- -braces.c - - mkseq: try and be smarter about not overallocating elements in - the return array if the increment is not 1 or -1 - - 6/7 - --- -parse.y - - history_delimiting_chars: if the parser says we're in the middle of - a compound assignment (PST_COMPASSIGN), just return a space to avoid - adding a stray semicolon to the history entry. Fixes bug reported - by "Davide Brini" - - 6/8 - --- -bashline.c - - bash_directory_completion_hook: don't attempt spelling correction - on the directory name unless the direxpand option is set and we are - going to replace the directory name with the corrected one in the - readline line. Suggested by Linda Walsh - -lib/sh/shquote.c - - sh_backslash_quote: now takes a third argument: flags. If non-zero, - tildes are not backslash-escaped. Have to handle both printf %q, - where they should be escaped, and filename completion, where they - should not when used as usernames - -externs.h - - sh_backslash_quote: declaration now takes a third argument - -builtins/printf.def - - printf_builtin: call sh_backslash_quote with 1 as third argument - so tildes get escaped - -{bashline,bracecomp}.c - - call sh_backslash_quote with 0 as third argument so tildes are not - escaped in completed words - -doc/bash.1 - - add `coproc' to the list of reserved words. From a report by - Jens Schweikhardt - - 6/10 - ---- -execute_cmd.c - - line_number_for_err_trap: now global, so parse_and_execute can save - and restore it with unwind-protect - -builtins/evalstring.c - - parse_prologue: save and restore line_number_for_err_trap along - with line_number - - restore_lastcom: new function, unwind-protect to restore - the_printed_command_except_trap - - parse_prologue: use restore_lastcom to save and restore the value - of the_printed_command_except_trap around calls to parse_and_execute - (eval/source/.) - - 6/15 - ---- -lib/readline/complete.c - - complete_fncmp: change filename comparison code to understand - multibyte characters, even when doing case-sensitive or case-mapping - comparisons. Fixes problem reported by Nikolay Shirokovskiy - - - 6/20 - ---- -builtins/mapfile.def - - mapfile: move the line count increment and check for having read - the specified number of lines to the end of the loop to avoid - reading an additional line with zgetline. Fixes bug reported by - Dan Douglas - - 6/21 - ---- - -execute_cmd.c - - execute_pipeline: make sure `lastpipe_flag' is initialized to 0 on - all systems, since it's tested later in the function. Fixes bug - reported by John E. Malmberg - - 6/22 - ---- -mailcheck.c - - file_mod_date_changed: return 0 right away if mailstat() does not - return success. Fixes bug with using uninitialized values reported - by szymon.kalasz@uj.edu.pl - -builtins/set.def - - the `monitor' option is not available when the shell is compiled - without job control, since the underlying `m' flag is not available - -nojobs.c - - job_control: now declared as int variable, initialized to 0, never - modified - -jobs.h - - job_control: extern declaration no longer dependent on JOB_CONTROL - -execute_cmd.c - - execute_pipeline: made necessary changes so `lastpipe' shell option - is now available in all shells, even those compiled without - JOB_CONTROL defined - - 6/23 - ---- -lib/glob/glob.c - - glob_filename: check for interrupts before returning if glob_vector - returns NULL or an error. Bug reported by Serge van den Boom - , fix from Andreas Schwab - - call run_pending_traps after each call to QUIT or test of - interrupt_state, like we do in mainline shell code - - glob_vector: don't call QUIT; in `if (lose)' code block; just free - memory, return NULL, and let callers deal with interrupt_state or - other signals and traps - - 6/25 - ---- -lib/readline/input.c - - rl_read_key: restructure the loop that calls the event hook a little, - so that the hook is called only after rl_gather_tyi returns no input, - and any pending input is returned first. This results in better - efficiency for processing pending input without calling the hook - on every input character as bash-4.1 did. From a report from - Max Horn - - 6/26 - ---- -trap.c - - signal_is_pending: return TRUE if SIG argument has been received and - a trap is waiting to execute - -trap.h - - signal_is_pending: extern declaration - -lib/glob/glob.c - - glob_vector: check for pending SIGINT trap each time through the loop, - just like we check for interrupt_state or terminating_signal, and - set `lose = 1' so we clean up after ourselves and interrupt the - operation before running the trap. This may require a change later, - maybe call run_pending_traps and do that if run_pending_traps returns? - -variables.c - - sv_histtimefmt: set history_comment_character to default (`#') if - it's 0 when we're turning on history timestamps. The history code - uses the history comment character to prefix timestamps, and - leaving it at 0 effectively removes them from the history. From a - report to help-bash by Dennis Williamson - - 6/27 - ---- -lib/readline/signals.c - - rl_maybe_restore_sighandler: new function, sets handler for SIG to - HANDLER->sa_handler only if it's not SIG_IGN. Needs to be called - on same signals set using rl_maybe_set_sighandler, which does not - override an existing SIG_IGN handler (SIGALRM is ok since it does - the check inline; doesn't mess with SIGWINCH) - - 6/30 - ---- -variables.h - - additional defines for the new `nameref' variable attribute - (att_nameref): nameref_p, nameref_cell, var_setref - -variables.c - - find_variable_nameref: resolve SHELL_VAR V through chain of namerefs - - find_variable_last_nameref: resolve variable NAME until last in a - chain of possibly more than one nameref starting at shell_variables - - find_global_variable_last_nameref: resolve variable NAME until last - in a chain of possibly more than one nameref starting at - global_variables - - find_nameref_at_context: resolve SHELL_VAR V through chain of namerefs - in a specific variable context (usually a local variable hash table) - - find_variable_nameref_context: resolve SHELL_VAR V through chain of - namerefs following a chain of varible contexts - - find_variable_last_nameref_context: resolve SHELL_VAR V as in - find_variable_last_context, but return the final nameref instead of - what the final nameref resolves to - - find_variable_tempenv, find_variable_notempenv, find_global_variable, - find_shell_variable, find_variable: modified to follow namerefs - - find_global_variable_noref: look up a global variable without following - any namerefs - - find_variable_noref: look up a shell variable without following any - namerefs - - bind_variable_internal: modify to follow a chain of namerefs in the - global variables table; change to handle assignments to a nameref by - following nameref chain - - bind_variable: modify to follow chain of namerefs when binding to a - local variable - - unbind_variable: changes to unset nameref variables (unsets both - nameref and variable it resolves to) - -subst.c - - parameter_brace_expand_word: change to handle expanding nameref whose - value is x[n] - - parameter_brace_expand_indir: change to expand in ksh93-compatible - way if variable to be indirected is nameref and a simple (non-array) - expansion - - param_expand: change to expand $foo where foo is a nameref whose value - is x[n] - -execute_cmd.c - - execute_for_command: changes to implement ksh93 semantics when index - variable is a nameref - -builtins/setattr.def - - show_var_attributes: change to add `n' to flags list if att_nameref - is set - -builtins/set.def - - unset_builtin: changes to error messages to follow nameref variables - -builtins/declare.def - - document new -n option - - declare_internal: new `-n' and `+n' options - - declare_internal: handle declare -n var[=value] and - declare +n var[=value] for existing and non-existant variables. - Enforce restriction that nameref variables cannot be arrays. - Implement semi-peculiar ksh93 semantics for typeset +n ref=value - - 7/5 - --- -variables.c - - unbind_variable: unset whatever a nameref resolves to, leaving the - nameref variable itself alone - - unbind_nameref: new function, unsets a nameref variable, not the - variable it references - -variables.h - - unbind_nameref: extern declaration - -builtins/set.def - - unset_builtin: modify to add -n option, which calls unbind_nameref - leaving unbind_variable for the usual case. This required slight - changes and additions to the test suite - -doc/{bash.1,bashref.texi} - - document namerefs and typeset/declare/local/unset -n - - 7/13 - ---- -lib/sh/casemod.c - - include shmbchar.h for is_basic and supporting pieces - - sh_casemod: use _to_wupper and _to_wlower to convert wide character - case instead of TOUPPER and TOLOWER. Fixes bug reported by - Dennis Williamson , fix from - Andreas Schwab - - cval: short-circuit and return ascii value if is_basic tests true - - sh_casemod: short-circuit and use non-multibyte case modification - and toggling code if is_basic tests true - -lib/readline/signals.c - - _rl_{block,release}_sigint: remove the code that actually blocks and - releases the signals, since we defer signal handling until calls to - RL_CHECK_SIGNALS() - -lib/readline/{callback,readline,util}.c - - if HAVE_POSIX_SIGSETJMP is defined, use sigsetjmp/siglongjmp without - saving and restoring the signal mask instead of setjmp/longjmp - -lib/readline/rltty.c - - prepare_terminal_settings: don't mess with IXOFF setting if - USE_XON_XOFF defined - -doc/{bash.1,bashref.texi} - - add some text to the description of set -e clarifying its effect - on shell functions and shell function execution. Suggested by - Rainer Blome - -bashline.c - - edit_and_execute_command: increment current_command_line_count before - adding partial line to command history (for command-oriented-history - because of rl_newline at beginning of function), then reset it to 0 - before adding the dummy history entry to make sure the dummy entry - doesn't get added to previous incomplete command. Partial fix for - problem reported by Peng Yu - - 7/24 - ---- -configure.in - - interix: define RECYCLES_PIDS. Based on a report from Michael - Haubenwallner - - 7/26 - ---- -jobs.c - - make_child: call bgp_delete on the newly-created pid unconditionally. - Some systems reuse pids before cycling through an entire set of - CHILD_MAX/_SC_CHILD_MAX unique pids. This is no longer dependent - on RECYCLES_PIDS. Based on a report from Michael Haubenwallner - - -support/shobj-conf - - Mac OS X: drop MACOSX_DEPLOYMENT_TARGET=10.3 from the LDFLAGS. We - can finally kill Panther - - 7/28 - ---- -subst.c - - command_substitute: make sure last_made_pid gets reset if make_child - fails - -execute_cmd.c - - execute_command_internal: case cm_simple: decide whether or not to - wait_for a child if already_making_children is non-zero, indicates - that there is an unwaited-for child. More of fix for bug report - from Michael Haubenwallner - -jobs.c - - make_child: call delete_old_job (new_pid) unconditionally, don't - bother to check whether or not pid wrap occurred. Rest of fix for - bug report from Michael Haubenwallner - - - 7/29 - ---- -shell.c - - subshell_exit: new function, exits the shell (via call to sh_exit()) - after calling any defined exit trap - -externs.h - - subshell_exit: new extern declaration - -execute_cmd.c - - execute_command_internal: make sure to call subshell_exit for - {} group commands executed asynchronously (&). Part of fix for - EXIT trap bug reported by Maarten Billemont - -sig.c - - reset_terminating_signals: make sure to set termsigs_initialized back - to 0, so a subsequent call to initialize_terminating_signals works - right. Rest of fix for bug reported by Maarten Billemont - - -{execute_cmd,general,jobs,mailcheck,mksyntax,test}.c -builtins/{cd,fc,pushd,ulimit}.def -lib/malloc/getpagesize.h -lib/sh/{clktck,fpurge,inet_aton,mailstat,oslib,pathcanon,pathphys,spell,strerror}.c - - make inclusion of dependent on HAVE_SYS_PARAM_H - consistently - - 8/6 - --- -lib/readline/histexpand.c - - history_expand_internal: now takes an additional argument saying - whether the history expansion occurs within a quoted string, set to - the open quote character - - history_expand_internal: use new argument instead of checking prev - char and initializing quoted_search_delimiter, pass qc directly to - get_history_event, where it allows a matching quote to terminate a - string defining an event - - history_expand: change single-quote handling code so that if - history_quotes_inhibit_expansion is 0, single quotes are treated - like double quotes - - history_expand: change call to history_expand_internal to pass new - argument of `"' if double-quoted string, `'' if single-quoted string; - this lets history_expand decide what is a quoted string and what - is not - - 8/7 - --- -configure.in - - AC_CANONICAL_BUILD: invoke for later use - -lib/readline/macro.c - - _rl_prev_macro_key: new function, inverse of _rl_next_macro_key: - backs up the index into the current macro by 1 - -lib/readline/rlprivate.h - - _rl_prev_macro_key: extern declaration - - -lib/readline/readline.c - - _rl_dispatch_subseq, _rl_subseq_result: don't call _rl_unget_char - if we're currently reading from a macro; call _rl_prev_macro_key - instead. Fixes bug reported by Clark Wang - - 8/13 - ---- -builtins/evalstring.c - - evalstring(): new function, wrapper around parse_and_execute. - make sure we handle cases where parse_and_execute can call `return' - and short-circuit without cleaning up properly. We call - parse_and_execute_cleanup() then jump to the previous-saved return - location - -builtins/common.h - - extern declaration for evalstring() - -builtins/eval.def - - eval_builtin: make sure we handle `eval " ... return"' in contexts - where `return' is valid by calling evalstring(). Fixes bug with - `eval return' in sourced files reported by Clark Wang - - -trap.c - - run_pending_traps: call evalstring instead of parse_and_execute. - XXX - still needs to handle saving and restoring token state in the - presence of `return'; could use unwind_protects for that - -builtins/mapfile.def - - run_callback: call evalstring instead of parse_and_execute - - 8/15 - ---- -bashline.c - - bash_filename_stat_hook: make sure we don't free local_dirname - before using it to canonicalize any expanded filename. Make sure - it always points to *dirname and only free it if we're replacing - it. - -lib/readline/complete.c - - append_to_match: make sure we call rl_filename_stat_hook with - newly-allocated memory to avoid problems with freeing it twice - - 8/17 - ---- -variables.c,config-top.h - - if ARRAY_EXPORT is defined to 1 when variables.c is compiled, the - code that allows indexed arrays to be exported is enabled and - included - - 8/19 - ---- -shell.c - - call start_debugger from main() only if dollar_vars[1] != 0 (close - enough to a non-interactive shell, since we can be interactive with - -i while running a shell script). Fixes oddity reported by - Techlive Zheng - - 8/20 - ---- -arrayfunc.c - - quote_array_assignment_chars: don't bother quoting if the word has - not been marked as an assignment (W_ASSIGNMENT) - - quote_array_assignment_chars: turn on W_NOGLOB in the word flags - so assignment statements don't undergo globbing. Partial fix for - problems reported by Dan Douglas - - 8/21 - ---- -command.h - - W_NOBRACE: new word flag that means to inhibit brace expansion - -subst.c - - brace_expand_word_list: suppress brace expansion for words with - W_NOBRACE flag - - 8/22 - ---- -builtins/read.def - - read_builtin: don't call dequote_string on what we've read, even if - we saw an escape character, unless (input_string && *input_string). - We may have escaped an IFS whitespace character. Fixes seg fault - reported by - -execute_cmd.c - - execute_command_internal: set the_printed_command_except trap when - about to execute a ( ... ) user subshell. For now, set it only if - ERR is trapped; can relax that later. Fixes bug reported by - Mike Frysinger - - 8/23 - ---- -jobs.c - - remove references to first_pid and pid_wrap, since we're not using - them for anything anymore - - 8/24 - ---- -subst.c - - changes for W_NOBRACE everywhere appropriate: so it can be displayed - for debugging, and passed out of expand_word_internal - -doc/{bash.1,bashref.texi} - - small changes to make it clearer that the = and == operators are - equivalent, and will cause pattern matching when used with [[. - From a question from Michal Soltys - -doc/bashref.texi - - some small formatting changes from Karl Berry - - 8/27 - ---- -lib/readline/doc/{history,rlman,rluserman}.texi - - some small formatting changes from Karl Berry - -arrayfunc.c - - assign_array_element_internal, assign_compound_array_list, - unbind_array_element, array_value_internal: changes to make - assignment statements to negative indices (a[-1]=2) and unsetting - array elements using negative indices (unset 'a[-1]') work. - From suggestions by Dennis Williamson - and Chris F. A. Johnson - -subst.c - - array_length_reference: changes to make length references to array - elements using negative indices (${#a[-1]}) work - - 8/28 - ---- -doc/{bash.1,bashref.texi} - - document new treatment of negative indices to indexed arrays when - assigning, referencing, calculating length, and unsetting - - 8/29 - ---- -shell.c - - show_shell_usage: add -l to list of shell invocation options (short - for --login). From Red Hat bug 852469 - -configure.ac - - renamed from configure.in, as latest autoconf versions want. Patches - Stefano Lattarini - -MANIFEST,Makefile.in,doc/bashref.texi,support/mkconffiles - - configure.in -> configure.ac - - 9/1 - --- - -parse.y - - read_token_word: allow words like {array[ind]} to be valid redirection - words for constructs like {x} - -lib/readline/display.c - - update_line: if the first difference between the old and new lines - is completely before any invisible characters in the prompt, we - should not adjust _rl_last_c_pos, since it's before any invisible - characters. Fixed in two places - - prompt_modechar: return a character indicating the editing mode: - emacs (@), vi command (:), or vi insert (+) - - _rl_reset_prompt: new function, just calls rl_expand_prompt. Will be - inlined, placeholder for more changes - - expand_prompt: if show-mode-in-prompt is enabled, add a character to - the front of the prompt indicating the editing mode, adjusting the - various variables as appropriate to keep track of the number of - visible characters and number of screen positions - -lib/readline/bind.c - - show-mode-in-prompt: new bindable boolean variable, shadowed by - _rl_show_mode_in_prompt variable - - hack_special_boolean_var: call _rl_reset_prompt when toggling or - setting show-mode-in-prompt - -lib/readline/readline.c - - readline_internal_setup: make sure the correct vi mode keymap is set - before expanding the prompt string for the first time - -lib/readline/misc.c - - rl_emacs_editing_mode: make sure to call _rl_reset_prompt if we're - showing the editing mode in the prompt - -lib/readline/rlprivate.h - - _rl_reset_prompt, _rl_show_mode_in_prompt: extern declarations - -lib/readline/vi_mode.c - - rl_vi_insertion_mode: call _rl_reset_prompt - - rl_vi_movement_mode: call _rl_reset_prompt. Finishes changes for - showing mode in prompt string, originally requested by Miroslav - Koskar and most recently by Jordan Michael - Ziegler - -doc/bash.1,lib/readline/doc/{readline.3,rluser.texi} - - document new show-mode-in-prompt variable, off by default - - 9/3 - --- - -jobs.c - - set_childmax: new function, external mechanism for other parts of - the shell to set js.c_childmax, the number of saved exited child - statuses to remember -jobs.h - - set_childmax: extern declaration - -variables.c - - CHILD_MAX: new special variable, with sv_childmax function to - run when it changes. Setting CHILD_MAX to a value greater than - zero but less than some maximum (currently 8192) sets the number of - exited child statuses to remember. set_childmax (jobs.c) ensures - that the number does not drop below the posix-mandated minimum - (CHILD_MAX) - -doc/{bash.1,bashref.texi} - - CHILD_MAX: document new meaning and action when variable is set - - 9/5 - --- -redir.c - - redir_varassign: call stupidly_hack_special_variables after - assigning fd number to specified variable, so we can use constructs - like {BASH_XTRACEFD}>foo. Suggested by Pierre Gaston - - - 9/8 - --- -expr.c - - readtok: invalidate previous contents of `curlval' before freeing - and reallocating tokstr (which, chances are, will get the same - pointer as before and render curlval inconsistent). Fixes other - bug reported by Dan Douglas - - 9/9 - --- -lib/readline/complete.c - - rl_username_completion_function: protect call to setpwent() with - #ifdef (HAVE_GETPWENT)/#endif. Fixes bug reported by - Gerd Hofmann - -lib/readline/display.c - - rl_message: second and subsequent calls to rl_message can result in - local_prompt being overwritten with new values (e.g., from the - successive calls displaying the incremental search string). Need - to free before overwriting if it's not the same as the value saved - in saved_local_prompt. Fixes memory leak reported by - Wouter Vermaelen - -lib/readline/{terminal.c,rlprivate.h} - - move CUSTOM_REDISPLAY_FUNC and CUSTOM_INPUT_FUNC defines from - terminal.c to rlprivate.h so other files can use them - -expr.c - - expr_streval: if noeval is non-zero, just return 0 right away, - short-circuiting evaluation completely. readtok will leave curtok - set correctly without re-entering the evaluator at all. Rest of - fix for bug reported by Dan Douglas - - 9/11 - ---- - -parse.y - - parse_comsub: make sure the `reserved word ok in this context' flag - is preserved after we read `do' followed by whitespace. Fixes bug - reported by Benoit Vaugon - - 9/13 - ---- -configure.ac,config.h.in - - enable-direxpand-default: new configure option, turns the `direxpand' - shell option on by default - -bashline.c - - dircomplete_expand, dircomplete_expand_relpath: initialize to 1 if - DIRCOMPLETE_EXPAND_DEFAULT is defined and non-zero - -doc/bashref.texi - - enable-direxpand-default: document new configure option - - 9/14 - ---- -shell.c - - --protected: make option valid only when wordexp is compiled into - the shell. Fix from Roman Rakus - -configure.ac - - HP NonStop (*-nsk*): compile --without-bash-malloc. Change from - Joachim Schmitz - - 9/16 - ---- -subst.c,execute_cmd.c,lib/glob/sm_loop.c,lib/sh/shquote.c - - minor code cleanups from Joachim Schmitz - -lib/readline/colors.h - - workaround for HP NonStop compiler issue with from - Joachim Schmitz - - 9/17 - ---- -builtins/printf.def - - printf_builtin: handle localtime returning NULL, as can happen when - encountering overflow. Bug report and initial fix from - Eduardo A. Bustamante López - -doc/{bash.1,bashref.texi} - - emphasize that brace expansion using character ranges ({a..c}) acts - as if the C locale were in use. Prompted by message from - Marcel Giannelia - - 9/20 - ---- -lib/sh/wcsnwidth.c - - wcsnwidth: new function, variant of wcwidth, returns the number of - wide characters from a string that will be displayed to not exceed - a specified max column position - - 9/21 - ---- -builtins/help.def - - show_builtin_command_help: break code that displays the short-doc - for each builtin in two columns into a new function: dispcolumn - - wdispcolumn: multibyte-char version of dispcolumn; uses wide - chars and printf "%ls" format. Fixes problem reported by - Nguyá»n Thái Ngá»c Duy - - 9/22 - ---- -execute_cmd.c - - execute_disk_command: before running the command-not-found hook, - call kill_current_pipeline() to make sure we don't add processes - to an existing pipeline or wait for processes erroneously - - 9/23 - ---- -lib/readline/input.c - - rl_input_available_hook: new hook function, called from - _rl_input_available (or _rl_input_queued) to return whether or not - input is available wherever the input source is - -lib/readline/doc/rltech.texi - - rl_input_available_hook: document - - 9/27 - ---- -lib/glob/sm_loop.c: - - GMATCH: after one or more `*', an instance of ?(x) can match zero or - 1 times (unlike ?, which has to match one character). The old code - failed if it didn't match at least once. Fixes `a*?(x)' bug. - - GMATCH: if we hit the end of the search string, but not the end of - the pattern, and the rest of the pattern is something that can - match the NUL at the end of the search string, we should successfully - match. Fixes `a*!(x)' bug reported by - - 10/2 - ---- -command.h - - add c_lock member to coproc structure for future use to tell who is - manipulating it - -execute_cmd.c - - execute_coproc: block SIGCHLD while parent is forking coproc - process and adding pid to sh_coproc struct to avoid race condition - where child is reaped before the pid is assigned and the coproc is - never marked as having died. Fixes race condition identified by - Davide Baldini - - add assignments to c_lock member of struct coproc in various - functions that manipulate it; was used to identify race condition - - coproc_pidchk: don't call coproc_dispose to avoid using malloc and - other functions in a signal handler context - - coproc_dispose: call BLOCK_SIGNAL/UNBLOCK_SIGNAL for SIGCHLD while - manipulating the sh_coproc struct - - 10/6 - ---- -lib/readline/complete.c - - rl_display_match_list: if printing completions horizontally, don't - bother with spacing calculations if limit == 1, which means we are - printing one completion per line no matter what. Fixes bug - reported by David Kaasen - - 10/7 - ---- -builtins/declare.def - - declare_internal: add error checking for nameref attribute and - variable assignments: self-references, attempts to make an array - variable a nameref - -subst.c - - parameter_brace_expand: handle parameter_brace_expand_word returning - &expand_param_fatal or &expand_param_error and return the appropriate - error value - - parameter_brace_expand_word: if a nameref variable's value is not a - valid identifier, return an error - - param_expand: if a nameref variable's value is not a valid identifier, - return an error - -test.c - - unary_operator: add new -R variable, returns true if variable is set - and has the nameref attribute. From ksh93 - -builtins/test.def - - add -R to description of conditional commands for help test - -doc/{bash.1,bashref.texi} - - document new -R unary conditional operator - - 10/13 - ----- -trap.c - - check_signals_and_traps: new function, convenience function for the - rest of the shell to check for pending terminating and interrupt - signals, and to check for and process any pending traps - - any_signals_trapped: new function, returns non-zero if any signals - are trapped and -1 if not - -trap.h - - extern declaration for check_signals_and_traps - -bashline.c - - bashline_reset: make sure we reset the event hook - - bash_event_hook: call check_signals_and_traps instead of just - checking for terminating signals so we can run pending traps and - react to interrupts, and reset the event hook when we're done - - - 10/14 - ----- -trap.c - - trap_handler: if executing in a readline signal handler context, - call bashline_set_event_hook to install bash_event_hook to process - the signal (if bash cares about it) - -sig.c - - sigint_sighandler: call bashline_set_event_hook to set the event - hook if we're executing in a readline signal handler context - -lib/readline/input.c - - rl_getc: call RL_CHECK_SIGNALS if read returns -1/EINTR and the caught - signal is SIGINT or SIGQUIT rather than waiting until the next time - around the loop - - rl_getc: call rl_event_hook after calling RL_CHECK_SIGNALS to allow - an application signal handler to set the event hook in its own - signal handler (e.g., like bash trap_handler or sigint_sighandler) - - -parse.y - - yy_readline_get: don't set interrupt_immediately before we call - readline(). Inspired by report from lanshun zhou - - -input.c - - getc_with_restart: add call to run_pending_traps after call to - CHECK_TERMSIG - -lib/sh/zread.c - - zread: call check_signals_and_traps if read() returns -1/EINTR - instead of just ignoring the EINTR and deferring handling any - signal that generated it - -builtins/mapfile.def - - mapfile: don't set interrupt_immediately before calling zgetline() - (which uses zread internally) - -builtins/read.def - - read_builtin: don't set interrupt_immediately before calling zread - (moved code around so that it was only being set right around calls - to zread to avoid signal handler conflicts). Inspired by report - from lanshun zhou - - edit_line: don't set interrupt_immediately around call to readline() - - include shmbutil.h - - read_builtin: don't call read_mbchar unless is_basic(c) returns - false for the character we just read - - 10/15 - ----- -sig.c - - throw_to_top_level: if interrupt_state is non-zero, make sure that - last_command_exit_value reflects 128+SIGINT if it's not already - greater than 128 - - 10/20 - ----- -builtins/wait.def - - WAIT_RETURN: set wait_signal_received back to 0 for the potential - next call to wait - -quit.h - - CHECK_WAIT_INTR: macro to check whether trap_handler handled a - signal and set wait_signal_received; longjmp to wait_intr_buf in - that case - -jobs.c - - wait_for, waitchld: call CHECK_WAIT_INTR at the same places we call - CHECK_TERMSIG to check for terminating signals - - wait_sigint_handler: don't longjmp out of the wait builtin unless - interrupt_immediately is set; otherwise just SIGRETURN from the - handler - - wait_sigint_handler: if interrupt_immediately not set, but we are - executing in the wait builtin and SIGINT is not trapped, treat it - as a `normally received' SIGINT: restore the signal handler and - send SIGINT to ourselves - - waitchld: when in posix mode and running SIGCHLD traps, don't longjmp - to wait_intr_buf (and let wait be interrupted) if we're running from - a signal handler. Wait for CHECK_WAIT_INTR to do the longjmp. - run_pending_traps will run the SIGCHLD trap later - -nojobs.c - - reap_zombie_children, wait_for_single_pid, wait_for: call - CHECK_WAIT_INTR where we call CHECK_TERMSIG - - wait_sigint_handler: don't longjmp out of the wait builtin unless - interrupt_immediately is set; otherwise just SIGRETURN from the - handler - -trap.c - - trap_handler: make sure wait_signal_received is set if the wait - builtin is executing, and only longjmp if interrupt_immediately is - set. This whole set of fixes was prompted by report from - lanshun zhou - - 10/24 - ----- -lib/glob/glob.c - - glob_filename: only check directory_name for globbing chars if - it's of non-zero length - -lib/sh/strchrnul.c - - new simpler implementation - -subst.c - - command_substitute: call set_shellopts after turning off errexit - in subshells so it's reflected in $SHELLOPTS - - 11/7 - ---- -builtins/evalstring.c - - parse_and_execute: treat ERREXIT case like reader_loop does: set - variable_context to 0 before longjmping back to top_level. Don't - run the unwind-protect context to avoid side effects from popping - function contexts. Part of fix for problem reported by Nikolai - Kondrashov - -execute_cmd.c - - execute_simple_command: call unlink_fifo_list only if this is the - last element of a pipeline (or not in a pipeline), rather than for - every child. Fixes difference in behavior between /dev/fd and - FIFOs reported by Zev Weiss - - execute_null_command: do the same thing in the parent branch after - make_child - - 11/14 - ----- -subst.c - - parameter_brace_expand: a variable is null if it's special ($@, $*), - the expansion occurs within double quotes, and the expansion turns - into a quoted null. Fixes debian bug 692447 reported by - Matrosov Dmitriy - -jobs.c - - run_sigchld_trap: make sure `running_trap' sentinel is set - appropriately - - waitchld: only run the sigchld trap if we're not in a signal - handler, not running a trap, and executing the wait builtin. - Otherwise, queue for later handling. We still run one instance - of the trap handler per exited child. Bulk of fix for bug - reported by Elliott Forney - -trap.c - - queue_sigchld_trap: set catch_flag so run_pending_traps notices, - and set trapped_signal_received for completeness. Rest of fix - for bug reported by Elliott Forney - -lib/malloc/malloc.c - - block_signals: renamed to _malloc_block_signals, made public - - unblock_signals: renamed to _malloc_unblock_signals, made public - -lib/malloc/imalloc.h - - extern declarations for _malloc_{un,}block_signals - -lib/malloc/table.c - - mregister_alloc, mregister_free: block signals around table - manipulation - - 11/15 - ----- -trap.c - - run_pending_traps: set SIG_INPROGRESS flag around calls to - run_sigchld_handler so other parts of the shell know that the - SIGCHLD trap handler is executing - - run_pending_traps: if we get a situation where we are looking at - running a SIGCHLD trap but the trap string is IMPOSSIBLE_TRAP_HANDLER - and the SIG_INPROGRESS flag is set, just skip it. This is possible - if run_pending_traps is called from a SIGCHLD trap handler run by - run_sigchld_trap - -doc/bash.1,lib/readline/doc/{rluser.texi,readline.3} - - corrected description of the effect of `set history-size 0'. Report - from Vesa-Matti J Kari - -include/stdc.h - - CPP_STRING: new define, replaces __STRING - -lib/malloc/{malloc.c,imalloc.h} - - replace __STRING with CPP_STRING - - 11/16 - ----- -lib/readline/bind.c - - sv_histsize: if argument evaluates to a value < 0, unstifle the - history - - 11/22 - ----- -redir.c - - do_redirection_internal: if we have REDIR_VARASSIGN set in the - redirection flags and we set up `redirector' using fcntl or dup2, - don't add a redirect to make sure it stays open. Let the - script programmer manage the file handle. Fixes bug reported by - Sam Liddicott - - 11/24 - ----- -jobs.c - - wait_for_any_job: new function, waits for an unspecified background - job to exit and returns its exit status. Returns -1 on no background - jobs or no children or other errors. Calls wait_for with new - sentinel value ANY_PID - - wait_for: changes to handle argument of ANY_PID: don't look up or - try to modify the child struct, only go through the wait loop once. - Return -1 if waitpid returns no children - -jobs.h - - ANY_PID: new define - -builtins/wait.def - - new option: -n. Means to wait for the next job and return its exit - status. Returns 127 if there are no background jobs (or no - children). Feature most recently requested by Elliott Forney - - -doc/{bash.1,bashref.texi} - - document new `wait -n' option - -execute_cmd.c - - execute_command_internal: save make_command_string () result in a - temp variable before calling savestring() on it; avoids evaluating - make_command_string() result twice. Fix from John E. Malmberg - - - 11/28 - ----- - -builtins/declare.def - - declare_internal: if an array variable is declared using `declare -a' - or `declare -A', but not assigned a value, set the `invisible' - attribute so the variable does not show up as set. Fix for bug - about variable initialization reported by Tim Friske - -builtins/{mapfile,read}.def - - after calling find_or_make_array_variable, make sure the invisible - flag is turned off, in case the variable was declared previously - using `declare -a' or `declare -A'. Side effect of above change to - declare_internal - -subst.c - - shell_expand_word_list: handle the W_ASSNGLOBAL flag and put -g into - the list of options passed to make_internal_declare as appropriate. - Fix for bug reported by Tim Friske - - 11/30 - ----- -test.c - - unary_op: make sure -v and -n check that the variable is not marked - as invisible before calling var_isset. Fix for bug reported by Tim - Friske - - 12/2 - ---- -subst.c - - process_substitute: turn off the `expanding_redir' flag, which - controls whether or not variables.c:find_variable_internal uses the - temporary environment to find variables. We want to use the - temp environment, since we don't have to worry about order of - evaluation in a subshell. Fixes bug reported by Andrey Borzenkov - - - 12/4 - ---- -lib/glob/glob.c - - glob_filename: changes to avoid null filenames and multiple entries - returned for patterns like **/** (globstar enabled). Fixes bug - reported by Ulf Magnusson - - 12/10 - ----- -lib/glob/glob.c - - glob_filename: finish up a series of changes to make globstar-style - globbing more efficient, avoid more duplicate filenames, and be more - compatible with other shells that implement it - o collapse a sequence of **/**/** to one ** - o note when the directory name is all ** or ends in ** so we - can treat it specially when the filename is ** - All inspired by report from Andrey Borzenkov - -lib/sh/zread.c - - zreadn: new function, like zread, but takes an additional argument - saying how many bytes to read into the local buffer. Can be used to - implement `read -N' without so many one-byte calls to zreadc. Code - from Mike Frysinger - - 12/12 - ----- -lib/glob/sm_loop.c - - PATSCAN (glob_patscan): if passed string already points to end of - pattern, return NULL immediately. Fixes problem with - extglob_skipname reported by Raphaël Droz - - 12/13 - ----- -execute_cmd.c - - execute_coproc: handle the command's exit status being inverted - (an oversight). Fixes bug reported by DJ Mills - and Andreas Schwab - - 12/14 - ----- -lib/readline/readline.c - - bind_arrow_keys_internal: add MINGW key bindings for Home, End, - Delete, and Insert keys. Fix from Pierre Muller - - -builtins/printf.def - - printf_builtin: '%()T' conversion: if there is no argument supplied, - behave as if -1 had been supplied (current time). ksh93-like feature - suggested by Clark Wang - -doc/{bash.1,bashref.texi} - - document new printf %()T default argument behavior - - 12/15 - ----- -lib/readline/display.c - - displaying_prompt_first_line: new variable, indicates whether or - not the first line of output is displaying the prompt. Always true - in normal mode, sometimes false in horizontal scrolling mode - - rl_redisplay: set displaying_prompt_first_line to true unless we - are in horizontal mode; set to false in horizontal mode if the left - margin of the displayed line is greater than the end of the prompt - string - - rl_redisplay: when in horizontal scroll mode, don't adjust - _rl_last_c_pos by the wrap offset unless the line is displaying - a prompt containing invisible chars - - update line: don't adjust _rl_last_c_pos by the wrap offset unless - the line is displaying a prompt containing invisible chars - - update_line: if shrinking the line by reducing the number of - displayed characters, but we have already moved the cursor to the - beginning of the line where the first difference starts, don't - try to delete characters - -builtins/read.def - - unbuffered_read: set to 2 if invoked as `read -N' - - if unbuffered_read is set to 2, compute the number of chars we - need to read and read that many with zreadn. Posix mode still - uses zreadintr. Code from Mike Frysinger - -doc/{bash.1,bashref.texi} - - read: make it clear that if read times out, it saves any input - read to that point into the variable arguments. Report from - Fiedler Roman - -subst.c - - command_substitute: change direct assignment of exit_immediately_on_error - to use change_flag ('e', FLAG_OFF) instead - -flags.c - - use errexit_flag as the variable modified by changes to the -e - option, reflect those changes to exit_immediately_on_error - -execute_cmd.c - - execute_builtin: new global variable, builtin_ignoring_errexit, set - to 0 by default and set to 1 if eval/source/command executing in a - context where -e should be ignored - - execute_builtin: set exit_immediately_on_error to errextit_flag - after executing eval/source/command in a context where -e should - be ignored - -flags.c - - if builtin_ignoring_errexit is set, changes to errexit_flag are - not reflected in the setting of exit_immediately_on_error. Fixes - bug reported by Robert Schiele - - 12/23 - ----- -include/posixjmp.h - - setjmp_nosigs: new define, call setjmp in such a way that it will - not manipulate the signal mask - -{expr,test,trap}.c - - setjmp_nosigs: call instead of setjmp; don't need to manipulate - signal mask - -builtins/read.def - - read_builtin: setjmp_nosigs: call instead of setjmp; don't need - to manipulate signal mask - -builtins/evalstring.c: - - parse_and_execute: setjmp_nosigs: call instead of setjmp; don't need - to manipulate signal mask - - parse_string: setjmp_nosigs: call instead of setjmp; don't need - to manipulate signal mask - - parse_and_execute: save and restore the signal mask if we get a - longjmp that doesn't cause us to return or exit (case DISCARD) - - 12/24 - ----- -general.c - - bash_tilde_expand: only set interrupt_immediately if there are no - signals trapped; we want to jump to top level if interrupted but - not run any trap commands - - 12/25 - ----- -jobs.c - - run_sigchld_trap: no longer set interrupt_immediately before calling - parse_and_execute, even if this is no longer run in a signal handler - context - -input.c - - getc_with_restart: add call to QUIT instead of CHECK_TERMSIG - -parse.y - - yy_stream_get: now that getc_with_restart calls QUIT, don't need to - set interrupt_immediately (already had call to run_pending_traps) - -execute_cmd.c - - execute_subshell_builtin_or_function,execute_function,execute_in_subshell: - setjmp_nosigs: call instead of setjmp when saving return_catch; don't - need to manipulate signal mask - - execute_subshell_builtin_or_function,execute_in_subshell: - setjmp_nosigs: call instead of setjmp where appropriate when saving - top_level; don't need to manipulate signal mask if we're going to - exit right away - -subst.c - - command_substitute: setjmp_nosigs: call instead of setjmp when saving - return_catch; don't need to manipulate signal mask - - command_substitute: setjmp_nosigs: call instead of setjmp where - appropriate when saving top_level; don't need to manipulate signal - mask if we're going to exit right away - -trap.c - - run_exit_trap: setjmp_nosigs: call instead of setjmp when saving - return_catch; don't need to manipulate signal mask - - run_exit_trap: setjmp_nosigs: call instead of setjmp where - appropriate when saving top_level; don't need to manipulate signal - mask if we're going to exit right away - - _run_trap_internal: setjmp_nosigs: call instead of setjmp when saving - return_catch; don't need to manipulate signal mask - -builtins/evalfile.c - - _evalfile: setjmp_nosigs: call instead of setjmp when saving - return_catch; don't need to manipulate signal mask - -builtins/evalstring.c - - evalstring: setjmp_nosigs: call instead of setjmp when saving - return_catch; don't need to manipulate signal mask - -shell.c - - main: setjmp_nosigs: call instead of setjmp where appropriate when - saving top_level; don't need to manipulate signal mask if we're - going to exit right away - - run_one_command: setjmp_nosigs: call instead of setjmp where - appropriate when saving top_level; don't need to manipulate signal - mask if we're going to exit right away - - run_wordexp: setjmp_nosigs: call instead of setjmp where - appropriate when saving top_level; don't need to manipulate signal - mask if we're going to exit right away - -eval.c - - reader_loop: save and restore the signal mask if we get a longjmp - that doesn't cause us to return or exit (case DISCARD) - - 12/26 - ----- -parse.y - - shell_input_line_{index,size,len}: now of type size_t; in some cases - the unsigned property makes a difference - - STRING_SAVER: saved_line_{size,index} now of type size_t - - shell_getc: don't allow shell_input_line to grow larger than SIZE_MAX; - lines longer than that are truncated until read sees a newline; - addresses theoretical buffer overflow described by Paul Eggert - - - set_line_mbstate: size_t changes like shell_getc - - shell_getc: if shell_input_line is larger than 32K, free it and - start over to avoid large memory allocations sticking around - -variables.c - - bind_global_variable: new function, binds value to a variable in - the global shell_variables table - -variables.h - - bind_global_variable: new extern declaration - -builtins/declare.def - - declare_internal: if -g given with name=value, but variable is not - found in the global variable table, make sure to call - bind_global_variable so the variable is created and modified at - global scope. Fixes a bug where declare -g x=y could modify `x' - at a previous function scope - -command.h - - W_ASSIGNARRAY: new word flag, compound indexed array assignment - -subst.h - - ASS_MKGLOBAL: new assignment flag, forcing global assignment even in - a function context, used by declare -g - -execute_cmd.c - - fix_assignment_words: set W_ASSIGNARRAY flag if -a option given to - declaration builtin - -subst.c - - do_assignment_internal: explicitly handle case where we are - executing in a function and we want to create a global array or - assoc variable - - shell_expand_word_list: call make_internal_declare if -a option - given to declaration builtin (W_ASSIGNARRAY); handle -g option with - it (W_ASSNGLOBAL). Fixes inconsistency noticed by Vicente Couce - Diaz , where declare -ag foo=(bar) could modify - array variable foo at previous function scope, not global scope - - 12/27 - ----- -bashline.c - - Minix needs the third argument to tputs to be a void funtion taking - an int argument, not an int-returning function. Fix from - John E. Malmberg as part of VMS bash port - - 12/29 - ----- -configure.ac,version.c,patchlevel.h - - bash-4.3-devel: new version, new shell compatibility level (43) - -subst.c - - parameter_brace_patsub: put the bash-4.2 code back in from the - change of 3/3 that runs the replacement string through quote - removal, make it dependent on shell_compatibility_level <= 42 - -builtins/shopt.def - - compat42: new shopt option - - set_compatibility_level: change logic to set and unset various - compat variables and shell_compatibility_level - -COMPAT - - new documentation for bash-4.3 compatibility changes - -doc/{bash.1,bashref.texi} - - compat42: document new shopt option - -builtins/shopt.def - - set_compatibility_opts: new function, sets the various shopt - compat variables based on the value of shell_compatibility_level - -builtins/common.h - - set_compatibility_opts: new extern declaration - -variables.c - - BASH_COMPAT: new special variable; sets the shell compatibility - level. Accepts values in decimal (4.2) or integer (42) form; - Unsetting variable, setting it to empty string, or setting it to - out-of-range value sets the shell's compatibility level to the - default for the current version. Valid values are 3.1/31 through - the current version - - sv_shcompat: new function implementing logic for BASH_COMPAT - -variables.h - - sv_shcompat: new extern declaration - -doc/{bash.1,bashref.texi} - - BASH_COMPAT: description of new variable - -lib/readline/complete.c - - _rl_colored_stats: default back to 0 for 4.3 release branch - - 1/5/2013 - -------- -quit.h - - remove spurious call to itrace in CHECK_WAIT_INTR - -bashline.c - - bash_event_hook: if we're going to jump to top_level, make sure we - clean up after readline() by calling rl_cleanup_after_signal(). - Fixes bug reported against devel branch by Raphaël Droz - - - bash_event_hook: reset the event hook before checking for signals - or traps in case we longjmp - -doc/{bash.1,bashref.texi} - - small additions to the set -e section to make it more clear that - contexts where -e is ignored extend to compound commands as well - as shell functions - -lib/readline/readline.h - - rl_signal_event_hook: new extern declaration - -lib/readline/input.c - - rl_signal_event_hook: new variable, hook function to call when a - function (currently just read(2)) is interrupted by a signal and - not restarted - - rl_getc: call rl_signal_event_hook instead of rl_event_hook - -lib/readline/doc/rltech.texi - - rl_signal_event_hook: document new function - -bashline.c - - changes to set rl_signal_event_hook instead of rl_event_hook - -lib/readline/readline.h - - change readline version numbers to 6.3 - - 1/6 - --- -doc/{bash.1,bashref.texi} - - a couple of changes to the descriptions of the ERR trap and its - effects based on a message from Rob Nagler - - 1/9 - --- -expr.c - - expassign: invalidate curlval before freeing and NULLing tokstr to - avoid aliasing issues. Fixes bug reported by Eduardo A. Bustamante - López and Dan Douglas - -braces.c - - array_concat: don't be so aggressive in trying to short-circuit. We - can only short-circuit if we have a single-element array where the - element is an empty string (array[0] == "" array[1] = 0x0). Existing - practice requires us to replicate arrays and prefix or append empty - strings. Fixes bug reported by Eduardo A. Bustamante López - - - 1/11 - ---- -execute_cmd.c - - execute_builtin: since mapfile uses evalstring() to run its callbacks - internally, just like eval, so it needs to handle the case where the - temp environment given to mapfile persists throughout the entire - set of callback commands. This might be a problem with trap also, but - trap isn't run in the same way. Fixes bug reported by Dan Douglas - - - 1/13 - ---- -redir.c - - redirection_error: before expanding the redirection word (if - expandable_redirection_filename returns true), disable command - substitution during expansion. Fixes bug reported by Dan Douglas - - -subst.c - - expand_word_internal: case '\\': if the next character is an IFS - character, and the expansion occurs within double quotes, and the - character is not one for which backslash retains its meaning, add - the (escaped) '\' and the (escaped) character. Fixes bug reported - by Dan Douglas - - 1/15 - ---- -builtins/cd.def - - cd_builtin: make sure call to internal_getopt handles -e option. - Fixes bug reported by - - 1/17 - ---- -subst.c - - expand_word_list_internal: make sure tempenv_assign_error is - initialized to 0 - -execute_cmd.c - - execute_simple_command: make sure tempenv_assign_error is reset to 0 - after it's tested to see if an error should force the shell to exit. - Fixes problem where a the failure of a tempenv assignment preceding - a non-special builtin `sticks' and causes the next special builtin - to exit the shell. From a discussion on bug-bash started by - douxin - - 1/20 - ---- -subst.c - - parameter_brace_expand_rhs: call stupidly_hack_special_variables - after assigning with ${param[:]=word} even if IFS is changing. - Suggested by Dan Douglas [TENTATIVE, needs work - on IFS side effects] - -command.h - - W_GLOBEXP (which was unused) is now W_SPLITSPACE (which isn't used - yet) - -{execute_cmd,subst,variables}.c - - removed all code that mentioned W_GLOBEXP - - removed mention of gnu_argv_flags and code that set it - - 1/22 - ---- -subst.c - - param_expand: set W_SPLITSPACE if we expand (unquoted) $* and - IFS is unset or null so we can be sure to split this on spaces - no matter what happens with IFS later - - expand_word_internal: note that param_expand returns W_SPLITSPACE - in the returned word flags and keep track of that state with - `split_on_spaces' - - 1/23 - ---- -subst.c - - expand_word_internal: if split_on_spaces is non-zero, make sure - we split `istring' on spaces and return the resultant word. The - previous expansions should have quoted spaces in the positional - parameters where necessary. Suggested by Dan Douglas - - -execute_cmd.c - - execute_command_internal: make sure any subshell forked to run a - group command or user subshell at the end of a pipeline runs any - EXIT trap it sets. Fixes debian bash bug 698411 - http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=698411 - -subst.c - - shell_expand_word_list: fix code that creates args for and calls - make_internal_declare to avoid calling it twice (missing `else' - in 12/26 change) - - do_assignment_internal: fix code from 12/26 change to fix problem - where an existing assoc variable could be converted to an array - without checking `mkassoc' - - 1/24 - ---- -builtins/evalfile.c - - _evalfile: add missing `close (fd)' calls before returning to - avoid fd leaks. Bug and fix from Roman Rakus - - 1/25 - ---- -builtins/read.def - - read_builtin: don't try to play tricks with the top of the unwind- - protect stack after read gets a SIGALRM; save input_string to new - memory, run the stack, then restore input_string and assign the - variables. Part of fix for bug reported by konsolebox - ; the rest of the fix is with the changes in - trap and signal handling and doing away with interrupt_immediately - - 1/26 - ---- -redir.c - - redirection_expand, write_here_string, write_here_document: before - calling any of the word expansion functions, after setting - expanding_redir to 1 (which bypasses the temp environment in the - variable lookup functions), call sv_ifs to reset the cached IFS- - related variables set by subst.c:setifs(). This ensures that - redirections will not get any IFS values that are set in the - temporary environment, as Posix specifies. Then, after the word - expansions, after resetting expanding_redir to 0, call sv_ifs - again to make sure the cached IFS values are set from any - assignments in the temporary environment. We force executing_builtin - to 1 to `fool' the variable lookup functions into using any temp - environment, then reset it to its old value after sv_ifs returns. - This is what allows read() to use the (cached) IFS variables set - in the temp environment. Fixes inconsistency reported by Dan Douglas - - - 1/29 - ---- -lib/readline/display.c - - update_line: fix off-by-one error when updating vis_lbreaks array - in a multibyte locale that occurs when moving multibyte chars from - one line down to another. Bug report and fix from Egmont - Koblinger - - 1/30 - ---- -configure.ac - - changed version to 4.3-alpha - -redir.c - - redir_open: handle open returning -1/EINTR, which seems to happen - a lot with FIFOs and SIGCHLD, and call QUIT to handle other - signals that can interrupt open(2). Bug report and initial fix - from Mike Frysinger - - 1/31 - ---- -subst.c - - parameter_brace_expand: make sure to propagate the PF_ASSIGNRHS flag - to parameter_brace_expand_word - - parameter_brace_expand_word: make sure that if the PF_ASSIGNRHS flag - is set and we are expanding ${a[@]} or ${a[*]} we set quoted to - include Q_DOUBLE_QUOTES before calling array_value_internal, mirroring - what we do for $@ and $*. Fixes inconsistency reported by Dan - Douglas - -configure.ac - - use AC_CHECK_TOOL instead of AC_CHECK_PROG to check for ar, since it - will find $host-prefixed versions of utilities. Report and fix from - Mike Frysinger - -builtins/setattr.def - - set_var_attribute: check whether bind_variable (called when the - variable whose attributes are being modified is found in the temp - environment) just modified a read-only global variable, and don't - bother marking the temporary variable for propagation if so. The - propagation is superfluous and will result in a strange error - message - - 2/2 - --- -variables.c - - initialize_shell_variables: don't try to import function definitions - with invalid names from the environment if already in posix mode, - but create them as (invisible) exported variables so they pass - through the environment. Print an error message so user knows - what's wrong. Fixes bug reported by Tomas Trnka - - 2/9 - --- - -builtins/read.def - - sigalrm_seen, alrmbuf: now global so the rest of the shell (trap.c) - can use them - - sigalrm: just sets flag, no longer longjmps to alrmbuf; problem was - longjmp without manipulating signal mask, leaving SIGALRM blocked - -quit.h - - move CHECK_ALRM macro here from builtins/read.def so trap.c: - check_signals() can call it - -trap.c - - check_signals: add call to CHECK_ALRM before QUIT - - check_signals_and_traps: call check_signals() instead of including - CHECK_ALRM and QUIT inline. Integrating check for read builtin's - SIGALRM (where zread call to check_signals_and_traps can see it) - fixes problem reported by Mike Frysinger - - 2/12 - ---- -lib/glob/xmbsrtowcs.c - - xdupmbstowcs2: fixed but where end of string was not handled - correctly, causing loop to go past end of string in a bunch of cases. - Fixes bug reported by "Dashing" - - - 2/13 - ---- -builtins/pushd.def - - popd_builtin: treat any argument that isn't -n or of the form - [-+][[:digit:]]* as an error. Fixes problem reported by Bruce - Korb - - 2/14 - ---- -configure.ac - - add check for sig_atomic_t; already a placeholder for it in - config.h.in - - 2/15 - ---- -subst.c - - do_compound_assignment: don't call assign_compound_array_list with - a NULL variable in case make_local_xxx_variable returns NULL - (it will if you try to shadow a readonly or noassign variable). - Fixes bug reported by Richard Tollerton - - 2/16 - ---- -variables.c - - make_local_variable: print error messager if an attempt is made to - create a local variable shadowing a `noassign' variable. Previously - we just silently refused to do it - -trap.[ch] - - get_original_signal: now global so rest of the shell can use it - -sig.c - - initialize_shell_signals: install a signal handler for SIGTERM - that does nothing except set a sigterm_received flag instead of - ignoring it with SIG_IGN, as long as SIGTERM is not ignored when - the shell is started. Use get_original_signal early to get the - original handler, since we will do that later anyway - - set_signal_handler: if installing sigterm_sighandler as the SIGTERM - handler, make sure to add SA_RESTART flag to make it as close to - SIG_IGN as possible - -sig.h - - sigterm_sighandler: new extern declaration - -quit.h - - RESET_SIGTERM: set sigterm_receved to 0 - - CHECK_SIGTERM: check sigterm_received; if it's non-zero, treat it - as a fatal signal and call termsig_handler to exit the shell - -jobs.c - - make_child: call RESET_SIGTERM just before fork() so we can detect - if the child process received a SIGTERM before it's able to change - the signal handler back to what it was when the shell started - (presumably SIG_DFL). Only has effect if the shell installed - sigterm_sighandler for SIGTERM, interactive shells that were not - started with SIG_IGN as the SIGTERM handler - - make_child: call RESET_SIGTERM in the parent after fork() so the - rest of the shell won't react to it - -execute_cmd.c - - execute_simple_command: call CHECK_SIGTERM after make_child in child - to catch SIGTERM received after fork() and before restoring old - signal handlers - - execute_disk_command: call CHECK_SIGTERM after make_child in child - process after restoring old signal handlers and again just before - calling shell_execve. Fixes race condition observed by - Padraig Brady when testing with his `timeout' - program - -lib/readline/display.c - - open_some_spaces: new function, subset of insert_some_chars that just - opens up a specified number of spaces to be overwritten - - insert_some_spaces: now just calls to open_some_spaces followed by - _rl_output_some_chars - - update_line: use col_temp instead of recalculating it using - _rl_col_width in the case where we use more columns with fewer bytes - - update_line: use open_some_spaces and then output the right number - of chars instead of trying to print new characters then overwrite - existing characters in two separate calls. This includes removing - some dodgy code and making things simpler. Fix from Egmont - Koblinger - - use new variable `bytes_to_insert' instead of overloading temp in - some code blocks (nls - nfd, bytes that comprise the characters - different in the new line from the old) - - 2/18 - ---- -redir.c - - do_redirection_internal: add undoable redirection for the implicit - close performed by the <&n- and >&n- redirections. Fixes bug - reported by Stephane Chazelas - - 2/19 - ---- -sig.c - - termsig_handler: an interactive shell killed by SIGHUP and keeping - command history will try to save the shell history before exiting. - This is an attempt to preserve the save-history-when-the-terminal- - window-is-closed behavior - - 2/21 - ---- -braces.c - - brace_expand: if a sequence expansion fails (e.g. because the - integers overflow), treat that expansion as a simple string, including - the braces, and try to process any remainder of the string. The - remainder may include brace expansions. Derived from SuSE bug - 804551 example (https://bugzilla.novell.com/show_bug.cgi?id=804551) - - 2/23 - ---- -{quit,sig}.h,sig.c - - sigterm_received declaration now in sig.h; type is sig_atomic_t - - sigwinch_received type now sig_atomic_t - - sig.h includes bashtypes.h and if SIG_DFL not defined - (same logic as trap.h) to pick up sig_atomic_t - -unwind_prot.c - - include sig.h before quit.h (reverse order) - - 2/27 - ---- -builtins/shopt.def - - reset_shopt_options: make sure check_window_size is reset to the - default from config.h, not unconditionally to 0 - -jobs.[ch] - - last_made_pid, last_asynchronous_pid: now volatile. Change from SuSE - -jobs.c - - wait_for: if we're using sigaction to install a handler for SIGCHLD, - make sure we specify SA_RESTART - -lib/{tilde,readline}/shell.c - - get_home_dir: instead of looking in the password file every time, - look once and cache the result - -sig.[ch] - - sigwinch_received, sigterm_received: now `volatile' qualified - -sig.c,quit.h - - interrupt_state,terminating_signal: now sig_atomic_t - - 3/1 - --- -MANIFEST,examples/* - - removed around 120 files without FSF copyrights; requested by - Karl Berry in early January - - 3/2 - --- -lib/malloc/malloc.c - - morecore: only check whether SIGCHLD is trapped if SIGCHLD is defined - -doc/bashref.texi - - Fixed most of the examples in the GNU Parallel section to use better - shell idioms following complaints on bug-bash; added a couple of - examples and smoothed out the text - -quit.h - - include "sig.h" for sig_atomic_t - -lib/readline/display.c - - update_line: when inserting one or more characters at the end of - the display line in a non-multibyte environment, just write from the - first difference to the end of the line and return. We don't have - to adjust _rl_last_c_pos. This is needed to adjust from the old - two-part copy to a single call to _rl_output_some_chars (change of - 2/16) - - 3/4 - --- -Makefile.in,doc/Makefile.in - - PACKAGE_TARNAME, docdir: new variables substituted by autoconf - - OTHER_DOCS,OTHER_INSTALLED_DOCS: new variables with auxiliary - documentation files to be installed into $(docdir) - - install: add new rule to install $(OTHER_DOCS) - - uninstall: add new rule to uninstall $(docdir)/$(OTHER_INSTALLED_DOCS) - -doc/bash.1 - - add URL to `POSIX' file in `SEE ALSO' section; put pointer to that - section in --posix and set -o posix descriptions - -examples/ - - removed around 110 examples at the request of the FSF due to copyright - issues - - 3/5 - --- -builtins/setattr.def - - readonly: modified help text slightly to make it clearer that - functions aren't changed or displayed unless the -f option is given. - Report from - - 3/9 - --- -include/typemax.h - - SIZE_MAX: define to 65535 (Posix minimum maximum) if not defined - -parse.y - - include "typemax.h" for possible SIZE_MAX definition, make sure we - include it after shell.h - -{braces,expr}.c - - include "typemax.h" for possible INTMAX_MIN and INTMAX_MAX definitions - - 3/10 - ---- -bashline.c - - bash_default_completion: make sure completion type of `!' (same as - TAB but with show-all-if-ambiguous set) and glob-word-completion - sets rl_filename_completion_desired to 0 so extra backslashes don't - get inserted by `quoting' the completion. We can't kill all the - matches because show-all-if-ambiguous needs them. Bug report from - Marcel (Felix) Giannelia - -[bash-4.3-alpha frozen] - - 3/14 - ---- -general.c - - trim_pathname: use memmove instead of memcpy since the source and - destination pathnames may overlap. Report and fix from Matthew - Riley - - 3/18 - ---- -configure.ac - - socklen_t is defined as `unsigned int' if configure can't find it - - 3/20 - ---- -lib/readline/complete.c - - S_ISVTX: since it's not defined on all platforms (Minix), make sure - its use is protected with #ifdef - - 3/21 - ---- -doc/{bash.1,bashref.texi} - - Added mention of ${!name[@]} and ${!name[*]} expansions to get all - indices of an array. Suggested by Jonathan Leffler - - - 3/24 - ---- -subst.h - - SD_IGNOREQUOTE: new define for skip_to_delim; if set, means that - single quotes (for now) will be treated as ordinary characters - -subst.c - - skip_to_delim: handle SD_IGNOREQUOTE. no callers use it for now - - 3/25 - ---- -support/config.{guess,sub} - - updated to versions from autoconf-2.69 - - 3/31 - ---- -lib/sh/shquote.c - - sh_single_quote: short-circuit quoting a single "'" instead of - creating a long string with empty single-quoted strings - -parser.h - - DOLBRACE_QUOTE2: new define, like DOLBRACE_QUOTE, but need to single- - quote results of $'...' expansion because quote removal will be - done later. Right now this is only done for ${word/pat/rep} - -parse.y - - parse_matched_pair: set state to DOLBRACE_QUOTE2 for pattern - substitution word expansion so we don't treat single quote specially - in the pattern or replacement string - - parse_matched_pair: if we're parsing a dollar-brace word expansion - (${...}) and we're not treating single quote specially within - double quotes, single-quote the translation of $'...' ansi-c - escaped strings. Original report and fix from Eduardo A. - Bustamante López - -subst.c - - extract_dollar_brace_string: ${word/pat/rep} scanning now sets the - DOLBRACE_QUOTE2 flag instead of DOLBRACE_QUOTE so we don't treat - single quotes specially within a double-quoted string - -execute_cmd.c - - fix_assignment_words: skip over assignment statements preceding a - command word before trying to figure out whether or not assignment - statements following a possible declaration command should be - treated specially. Fixes bug reported by Dan Douglas - - - 4/4 - --- -lib/readline/readline.c - - _rl_dispatch_subseq: only call _rl_vi_set_last (and check whether - the key is a text modification command) if the key sequence length - is 1. That keeps the arrow keys from setting the last command - when called in vi command mode. Fixes bug reported by Ian A. - Watson - - 4/6 - --- -lib/readline/bind.c - - rl_parse_and_bind: when parsing a double-quoted string as the value - of a variable, make sure we skip past the leading double quote. - Fix from Andreas Schwab - -variables.c - - hash_lookup: set new local variable last_table_searched to the table - a successful lookup appears in; tested in make_local_variable to - solve the problem below - - make_local_variable: if we find a variable with the tempenv flag - set at the same `level' as variable_context', but not found in the - temporary_env (temp environment preceding the builtin), return it. - The temp environment preceding the function call has already been - merged (in execute_function) into the list of variable contexts the - function sees as shell_variables by the time this is called. Fixes - inconsistency pointed out by Dan Douglas - -subst.c - - expand_arith_string: expanded out contents of expand_string, - expand_string_internal, expand_string_if_necessary to create a - WORD_DESC and call call_expand_word_internal() on it directly. - We don't want process substitution to be performed ( 1<(2) ) should - mean something different in an arithmetic expression context. - It doesn't work to just turn on the DQUOTE flag, since that means - that things like ${x["expression"]} are not expanded correctly. - Fixes problem pointed out by Dan Douglas - - 4/13 - ---- -subst.c - - process_substitute: run the EXIT trap before exiting, as other - shells seem to. Fixes problem pointed out by Dan Douglas - - -lib/readline/readline.c - - readline_internal_setup: call rl_vi_insertion_mode to enter vi - mode instead of rl_vi_insert_mode to avoid resetting the saved last - command information. Posix says that `.' can repeat a command - that was entered on a previous line so we need to save the info. - Fixes bug reported by Ian A. Watson - - 4/14 - ---- -lib/readline/complete.c - - rl_completion_matches: make sure xrealloc returns something non-null - (can happen when interrupted by a signal) before trying to add - matches to match_list - -subst.c - - array_remove_pattern: return NULL right away if array_variable_part - returns an invisible variable - - array_length_reference: handle array_variable_part returning an - invisible variable - - get_var_and_type: handle array_variable_part returning an invisible - variable - - 4/15 - ---- -execute_cmd.c - - execute_command_internal: make sure to run the EXIT trap for group - commands anywhere in pipelines, not just at the end. From a point - raised by Andreas Schwab - -variables.c - - bind_int_variable: make sure invisible flag is unset. Fixes problems - like "declare -ai a; : $(( a[4]=4 ));" - -arrayfunc.c - - array_variable_part: return variable even if invisible flag set, - callers must handle invisible vars - - 4/18 - ---- -builtins/set.def - - unset_builtin: if -n flag given, call unset_nameref instead of - unset_variable - -variables.c - - find_variable_nameref: print warning message if nameref circular - reference detected, return NULL and let caller deal with it - -builtins/declare.def - - declare_builtin: only disallow global references at this point if - we are at the global scope - - 5/16 - ---- -configure.ac - - update release status to beta - - 5/23 - ---- -trap.c - - run_pending_traps: save and restore pipeline around calls to - evalstring() in case we get a trap while running a trap. Have to - figure out the recursive running traps issue elsewhere. Fixes - bug reported by Roman Rakus - - run_pending_traps: make sure to set running_trap to the appropriate - signal value when running a trap command - - run_pending_traps: short-circuit immediately if running_trap set - when invoked. Could change this later to only skip if it would - run the same trap as currently being run (running_trap == sig + 1) - -configure.ac - - add warning if bison not found - -lib/readline/doc/rltech.texi - - new section with an example program illustrating the callback - interface. Suggested by Peng Yu - -examples/loadables/Makefile.in - - remove references to `cut' and `getconf', which were removed in - early March - - 5/28 - ---- -lib/sh/pathphys.c - - sh_realpath: correct inverted two arguments to call to sh_makepath. - Report and fix from Julien Thomas - - 6/7 - --- -execute_cmd.c - - executing_line_number: the else clauses that are conditional on - various options being defined can simply be if clauses -- they are - mutually exclusive and all have `return' in the body. Fixes bug - reported by Flavio Medeiros - - 6/25 - ---- -lib/readline/readline.c - - readline_internal_setup: only sent the meta-key enable string to the - terminal if we've been told to use one and the terminal has been - successfully initialized (RL_ISSTATE (RL_STATE_TERMPREPPED) != 0). - Suggested by Dan Mick - -lib/readline/signals.c - - _rl_signal_handler: call any defined signal hook after calling - rl_resize_terminal when handling a SIGWINCH. We already have called - the original SIGWINCH handler but will not be resending the signal - to ourselves - - 6/27 - ---- -lib/readline/doc/history.3, doc/bash.1 - - fix description of the `$' modifier to note that it expands to the - last *word*, which is not always the last argument. Report from - ariyetz@gmail.com via gnu.org RT - - 6/29 - ---- -lib/glob/smatch.c - - glob_asciiranges: initialize to value of GLOBASCII_DEFAULT instead - of 0 (0 if not defined) - -configure.ac,config.h.in - - --enable-glob-asciiranges-default: new option, controls the value of - GLOBASCII_DEFAULT; use it to turn globasciiranges shopt option on - by default - -doc/bashref.texi - - document new --enable-glob-asciiranges-default configure option - -variables.c - - assign_in_env: implement += value appending semantics for assignments - preceding command names - - 7/4 - --- -expr.c - - set lasttok = NUM in all of the functions that result in a number, - even if it's a boolean, to avoid errors with constructs like - 1 * x = 1, which should be an asignment error. Fixes problem - pointed out by Dan Douglas - -parse.y - - decode_prompt_string: don't bother to call strcpy if - polite_directory_format returns its argument unchanged. It's not - necessary and Mac OS X 10.9 aborts because of a supposed overlapping - string copy. Bug and fix from simon@hitzemann.org - -subst.c - - parameter_brace_find_indir: new function, code from - parameter_brace_expand_indir that looks up the indirectly-referenced - variable, but does not expand it - - parameter_brace_expand_indir: call parameter_brace_find_indir to - look up indirected variable reference - - get_var_and_type: call parameter_brace_find_indir if it looks like we - are trying to manipulate an indirect variable reference like - ${!b%%foo}. This makes a difference if !b references an array - variable. Bug report from Dan Douglas - - 7/6 - --- -lib/sh/casemod.c - - sh_modcase: make sure argument passed to is_basic is <= UCHAR_MAX, - since cval can convert something to a wchar_t greater than UCHAR_MAX. - Fixes bug reported by Tomasz Tomasik - - 7/8 - --- -lib/readline/history.c - - add_history_time: if history_length == 0, referencing history_length - - 1 will result in an array bounds error, so make history_length be - at least 1 before going on. Fixes bug reported by Geng Sheng Liu - - -builtins/setattr.def - - show_func_attributes: display definition (if NODEFS argument is 0) and - attributes for a particular function; used by `declare -fp name' - -builtins/declare.def - - declare_internal: call show_func_attributes if -f supplied with -p. - Fixes inconsistency observed by Linda Walsh - -builtins/common.h - - new extern declaration for show_func_attributes - -builtins/read.def - - read_builtin: check the first supplied variable name for validity - before attempting to read any input, since we know we will have to - at least use that one. Don't check any other names yet. Suggested - by jidanni@jidanni.org - - 7/10 - ---- -redir.c - - do_redirection_internal: when closing a file descriptor with - r_close_this ([n]<&-) count close errors as redirection errors if - errno ends up as EIO or ENOSPC. Originally reported back in April - 2012 by Andrey Zaitsev - - 7/11 - ---- -redir.c - - do_redirection_internal: before calling check_bash_input, make sure - that we don't call check_bash_input for an asynchronous process that - is replacing stdin with something else. The seek backwards affects - the parent process as well, since parents and children share the - file pointer. Fixes problem originally reported in March 2013 by - Martin Jackson - - 7/13 - ---- -doc/{bash.1,bashref.texi} - - slight change to add a description of `shopt -o' suggested by Bruce - Korb - - 7/19 - ---- -lib/readline/histfile.c - - history_do_write: if close returns < 0, make sure we restore the - backup history file and return a non-zero value - - history_truncate_file: if write or close return < 0, make sure we - return a non-zero value - -[bash-4.3-beta frozen] - - 7/21 - ---- -lib/readline/isearch.c - - rl_display_search: now takes an entire search context flags word as - the second argument, instead of just reverse flag; changed callers - - rl_display_search: if the search has failed, add `failed ' to the - beginning of the search prompt - - _rl_isearch_dispatch: if the search has failed, display the entire - search string with an indication that the search failed but with the - last matching line. Suggested by jidanni@jidanni.org - -command.h - - W_ASSIGNINT: new word flag; used internally for make_internal_declare - and set by fix_assignment_words - -execute_cmd.c - - fix_assignment_words: set W_ASSIGNINT if compound assignment and -i - given as option. We don't do anything with the value yet - -subst.c - - shell_expand_word_list: rework the way the option list that is - passed to make_internal_declare is created - - 8/1 - --- -doc/{bash.1,bashref.texi} - - minor changes to description of $! based on a report from Chris - Down - -arrayfunc.c - - assign_array_element_internal: before trying to get an array's max - index to process a negative subscript, make sure the array exists. - Bug report from Geir Hauge - - 8/2 - --- -arrayfunc.c - - assign_array_element_internal: before using array_max_index() when - processing a negative subscript, make sure the variable is an array. - if it's not, use 0 as array_max_index assuming it's a string. - Fixes bug report from Geir Hauge - - 8/3 - --- -Makefile.in - - pcomplete.o: add dependency on $(DEFDIR)/builtext.h. Suggested by - Curtis Doty - - 8/5 - --- -lib/glob/sm_loop.c - - strcompare: short-circuit and return FNM_NOMATCH if the lengths of the - pattern and string (pe - p and se - s, respectively) are not equal - - strcompare: don't bother trying to set *pe or *se to '\0' if that's - what they already are. Fixes bug reported by Geir Hauge - - - 8/6 - --- -doc/{bash.1,bashref.texi},builtins/hash.def,lib/readline/doc/rluser.texi - - minor typo changes from Geir Hauge - -bultins/help.def - - show_longdoc: avoid trying to translate the empty string because it - often translates to some boilerplate about the project and - translation. Report and fix from Geir Hauge - - 8/8 - --- -builtins/help.def - - help_builtin: try two passes through the list of help topics for each - argument: one doing exact string matching and one, if the first pass - fails to find a match, doing string prefix matching like previous - versions. This prevents `help read' from matching both `read' and - `readonly', but allows `help r' to match everything beginning with - `r'. Inspired by report from Geir Hauge - - 8/13 - ---- -builtins/fc.def - - fc_builtin,fc_gethnum: calculate `real' end of the history list and - use it if -0 is specified as the beginning or end of the history - range to list. Doesn't work for fc -e or fc -s by design. Feature - requested by Mike Fied - - 8/16 - ---- -trap.c - - _run_trap_internal: use {save,restore}_parser_state instead of - {save,restore}_token_state. It's more comprehensive - - 8/23 - ---- -doc/bash.1 - - disown: remove repeated text. Report and fix from Thomas Hood - - - 8/25 - ---- -lib/readline/rltty.c - - set_special_char: fix prototype (last arg is rl_command_func_t *) - -sig.c - - set_signal_handler: return oact.sa_handler only if sigaction - succeeds; if it doesn't, return SIG_DFL (reasonable default). From - https://bugzilla.redhat.com/show_bug.cgi?id=911404 - -bashline.c - - attempt_shell_completion: fix to skip assignment statements preceding - command name even if there are no programmable completions defined. - From https://bugzilla.redhat.com/show_bug.cgi?id=994659 - - attempt_shell_completion: if still completing command word following - assignment statements, do command completion even if programmable - completion defined for partial command name entered so far - - 8/26 - ---- -pcomplete.c - - pcomp_filename_completion_function: make sure rl_filename_dequoting_function - is non-NULL before trying to call it. Bug and fix from - Andreas Schwab - -bashline.c - - bash_command_name_stat_hook: if *name is not something we're going - to look up in $PATH (absolute_program(*name) != 0), just call the - usual bash_filename_stat_hook and return those results. This makes - completions like $PWD/exam[TAB] add a trailing slash - - 9/2 - --- -builtins/read.def - - read_builtin: before comparing what we read to the delim, make sure - we are not supposed to be ignoring the delimiter (read -N). We - set the delim to -1, but it's possible to read a character whose - int value ends up being between -1 and -128. Fixes bug - reported by Stephane Chazelas - -doc/{bash.1,bashref.texi} - - word splitting: crib some language from Posix to make it clear that - characters in IFS are treated as field *terminators*, not field - *separators*. Addresses issue raised by DJ Mills - - -lib/readline/{util.c,rldefs.h} - - _rl_stricmp,_rl_strnicmp: now take const char * string arguments; - changed prototype declarations - - 9/5 - --- -doc/{bash.1,bashref.texi} - - [[: modify description of pattern matching to make it clear that the - match is performed as if the extglob option were enabled. From Red - Hat bug https://bugzilla.redhat.com/show_bug.cgi?id=1002078 - - 9/12 - ---- -lib/readline/isearch.c - - _rl_isearch_dispatch: if we read an ESC and it's supposed to - terminate the search, make sure we check for typeahead with - _rl_pushed_input_available, since installing a hook function causes - typeahead to be collected in `ibuffer' (input.c). If there is any, - make sure we still use the ESC as a prefix character. Bug and fix - from Mike Miller - - 9/16 - ---- -builtins/{caller,cd,kill,pushd,wait}.def - - builtin_usage(): make sure call to this sets return status to - EX_USAGE - - 9/18 - ---- -terminal.c - - rl_change_environment: new application-settable variable; if non- - zero (the default), readline will modify LINES and COLUMNS in the - environment when it handles SIGWINCH - - _rl_get_screen_size: if rl_change_environment is non-zero, use setenv - to modify LINES and COLUMNS environment variables - -readline.h - - rl_change_environment: new extern declaration for applications - - 9/22 - ---- -configure.ac - - relstatus: bumped version to bash-4.3-beta2 - - 9/24 - ---- - -lib/readline/readline.c - - bind_arrow_keys_internal: added more key bindings for the numeric key - pad arrow keys on mingw32. Patch from Pierre Muller - - - 10/19 - ----- - -bashline.c - - maybe_restore_tilde: version of restore_tilde that honors `direxpand'; - calls restore_tilde after saving directory expansion hook if - necessary. Report from Andreas Schwab - -builtins/cd.def - - -@: new option, allows cd to use `extended attributes' present in - NFSv4, ZFS; idea taken from ksh93. Attributes associated with a - file are presented as a directory containing the attributes as - individual files. Original patch contributed by Cedric Blancher - - - 10/20 - ----- -aclocal.m4 - - BASH_CHECK_MULTIBYTE: check for wcwidth being broken with unicode - combining characters needs a value to use when cross-compiling. - Bug report from Bert Sutherland - -doc/{bash.1,bashref.texi} - - document new -@ option to cd builtin - - 10/28 - ----- -lib/glob/{{gmisc,glob}.c,glob.h} - - extglob_pattern renamed to extglob_pattern_p, declared in glob.h - -subst.c - - expand_word_internal: typo fix: case to fix " $@\ " bug in bash-4.2 - had a typo (& isexp instead of &&) - - 10/29 - ----- -input.c - - getc_with_restart: make sure local_index and local_bufused are - reset to 0 before returning EOF, in case we are running an interactive - shell without line editing and ignoreeof is set. Report and fix - from Yong Zhang - -lib/readline/search.c - - _rl_nsearch_init: take out extra third argument to rl_message; it - only matches prototype (and maybe format) in cases where - PREFER_STDARG and USE_VARARGS are both undefined, which is rare - - 10/31 - ----- -subst.c - - process_substitute: when opening the named pipe in the child, open - without O_NONBLOCK to avoid race conditions. Happens often on AIX. - Bug report and fix from Michael Haubenwallner - - -builtins/ulimit.def - - RLIMIT_NTHR: if RLIMIT_PTHREAD is not defined, but RLIMIT_NTHR is, - use RLIMIT_NTHR (NetBSD) - - 11/5 - ---- -locale.c - - set_default_locale_vars,set_locale_var: if TEXTDOMAINDIR has been - set, and default_dir has a non-null value, call bindtextdomain(3) - when TEXTDOMAIN is assigned a value. Fixes problem reported by - Michael Arlt - - 11/6 - ---- -builtins/cd.def - - cdxattr: only create synthetic pathname in `buf' if NDIRP argument - is non-null - - change_to_directory: if we have specified -@ and cdxattr returns - failure, fail immediately. Fixes bug reported by Joshuah Hurst - - - 11/12 - ----- -redir.c - - print_redirection: change r_err_and_out (&>) and its append form, - r_append_err_and_out (&>>) cases to separate redirection operator - from filename by a space, in case we have a process substitution. - Fixes bug reported by admn ombres - - 11/15 - ----- -execute_cmd.c - - execute_simple_command: don't close process substitution fds until - we are finished executing any current shell function. Partial fix - for bug reported by John Dawson - -support/shobj-conf - - add support for Darwin 13 (Mac OS X 10.9, Mavericks). Based on a - report by Ludwig Schwardt - - 11/20 - ----- -[bash-4.3-rc1 frozen] - - 11/24 - ----- -builtins/printf.def - - bind_printf_variable: make sure that the variable assigned to is - no longer marked as invisible. Fixes bug reported by NBaH - - - 11/28 - ----- -jobs.c - - delete_old_job: fix off-by-one error in job index in call to - internal_warning. Bug report from Peter Cordes - - 11/30 - ----- -doc/bashref.texi - - add string to description of special parameters with name of - special parameter prefixed by a $, so you can search for $#, - for instance - - 12/2 - ---- -lib/readline/{histexpand.c - - get_history_event: account for current_history() possibly returning - NULL. Report and fix from Pankaj Sharma - - - 12/11 - ----- - -lib/readline/parse-colors.c - - get_funky_string: don't call abort if we see something we can't - parse; just return an error - - _rl_parse_colors: if we encounter an error while parsing $LS_COLORS - we need to leave _rl_color_ext_list as NULL after freeing its - elements, then turn off _rl_colored_stats. Report and fix from Martin - Wesdorp - - 12/13 - ----- - -lib/readline/parse-colors.c - - _rl_parse_colors: if we encounter an unrecognized prefix, throw an - error but try to recover and go on to the next specification - -variables.c - - make_local_variable: for new variables this function creates, set - the att_invisible attribute. All callers from declare_internal. - Indirectly, this is a fix for bug with `declare -n var; var=foo;' - reported by Pierre Gaston - - bind_variable: if assigning to nameref variable that doesn't have - a value yet (e.g., with `declare -n var; var=foo'), don't try to - use the unset name. Fixes a segfault reported by Pierre Gaston - - -execute_cmd.c - - execute_command_internal: make sure last_command_exit_value is set - to 0 after any command executed in the background. Fixes bug - reported by Martin Kealey - - 12/17 - ----- -support/config.{guess,sub} - - updated to latest versions from git - - 12/19 - ----- -parse.y - - struct STRING_SAVER: now has a new `flags' element, to identify the - caller: alias expansion, double-paren parsing, or parse_and_execute - - push_string: now sets flags to PSH_ALIAS if `ap' argument is non-NULL - - push_string: now doesn't attempt to call strlen on a NULL string to - set shell_input_line_size - - parser_expanding_alias, parser_save_alias, parser_restore_alias: new - functions to provide an external interface to push_string and - pop_string; parser_save_alias sets flags element to PSH_SOURCE (could - be renamed PSH_EXTERN someday) - - shell_getc: when yy_getc returns '\0', instead of just testing - whether the pushed_string_list is not-empty before popping it, don't - pop if if the saved string has flags PSH_SOURCE, indicating that - parse_and_execute set it before setting bash_input to the string. - We should continue reading to the end of that string before popping - back to a potential alias. Partial solution for the problem of aliases - with embedded newlines containing `.' commands being executed out of - order reported by Andrew Martin - - shell_getc: when yy_getc returns '\0' and there is a saved string of - type PSH_SOURCE, restart the read without popping the string stack - if we have not read to the end of bash_input.location.string. Rest - of fix for out-of-order execution problem - -externs.h - - parser_expanding_alias, parser_save_alias, parser_restore_alias: new - extern function declarations - -builtins/evalstring.c - - pe_prologue: if the parser is expanding an alias, make sure to add - an unwind-protect to restore the alias; undoes the work that will be - performed by parse_and_execute/parse_string - - parse_and_execute,parse_string: after calling push_stream to save - bash_input, check whether or not the parser is currently expanding - an alias (parser_expanding_alias() != 0). If it is, we want to save - that string in the pushed_string_list, which we do with - parser_save_alias. - - 12/23 - ----- -execute_cmd.c - - execute_for_command: make sure to set line_number before expanding - the word list, so expansion errors have the right line number. - From a report from Ben Okopnik - -expr.c - - exp2: save token pointer before calling readtok(), arrange to use - saved token pointer when printing error token on a division by 0 - error - - 12/27 - ----- -lib/readline/display.c - - rl_redisplay: when calculating effects of invisible characters in a - prompt that is split across physical screen lines to set the indices - of linebreaks, don't bother testing local_prompt_prefix (line 751). - That prefix doesn't matter when calculating prompt visible and - invisible characters. Fixes problem reported by Jinesh Choksi - - -Makefile.in - - install: make sure to use $(DESTDIR) when installing OTHER_DOCS. - Report and fix from Matthias Klose - -doc/texinfo.tex - - updated to version of 2013-09-11 - - 12/28 - ----- -lib/readline/undo.c - - rl_do_undo: if we are undoing from a history entry (rl_undo_list == - current_history()->data), make sure the change to rl_line_buffer is - reflected in the history entry. We use the guts of - rl_maybe_replace_line to do the work. Fixes problem reported by - gregrwm - - 12/30 - ----- -sig.c - - sigint_sighandler: if we get a SIGINT (and this signal handler is - installed) while the wait builtin is running, note that we received - it in the same way as jobs.c:wait_sigint_handler and return. The - various wait_for functions will look for that with CHECK_WAIT_INTR. - This fixes the wait builtin not being interruptible in an interactive - job control shell - - 12/31 - ----- -trap.c - - set_signal_hard_ignored: rename set_signal_ignored to this, since it - both sets original_signals[sig] and sets the HARD_IGNORE flag - - set_signal_ignored: new function, now just sets original_signals[sig] - -trap.h - - set_signal_hard_ignored: new external declaration - -sig.c - - initialize_terminating_signals: call set_signal_hard_ignored instead - of set_signal_ignored for signals with disposition SIG_IGN when the - shell starts - -execute_cmd.c - - setup_async_signals: make sure we get the original dispositions for - SIGINT and SIGQUIT before starting the subshell, and don't call - set_signal_ignored because that sets original_signals[sig]. If we - don't, subsequent attempts to reset handling using trap will fail - because it thinks the original dispositions were SIG_IGN. Posix - interpretation 751 (http://austingroupbugs.net/view.php?id=751) - - 1/2/2014 - -------- -lib/sh/stringvec.c - - strvec_mcreate, strvec_mresize: versions of create and resize that - use malloc and realloc, respectively, instead of xmalloc/xrealloc - -braces.c - - expand_amble,mkseq: use strvec_mcreate/strvec_mresize so we can - catch and handle memory allocation failures instead of aborting - with the xmalloc/xrealloc interface - -lib/sh/strdup.c - - strdup replacement function for ancient systems that don't have it - -lib/sh/itos.c - - mitos: new function, itos that uses strdup instead of savestring - -externs.h - - strvec_mcreate/strvec_mresize: new extern declarations - - mitos: new extern declaration - -configure.ac - - bash version moved to 4.3-rc2 - - 1/6 - --- -doc/bash.1,lib/readline/doc/{rluser.texi,readline.3} - - separate the description of what happens when readline reads the - tty EOF character from the description of delete-char, leaving a - note in the delete-char description about common binding for ^D. - From suggestion by Parke - -lib/readline/doc/{version.texi,history.3,*.texi} - - updated email addresses and copyright dates - - 1/7 - --- -variables.c - - delete_var: new function, just removes a variable from a hash table - and frees it, without doing anything else - - make_variable_value: if we are trying to assign to a nameref variable, - return NULL if the value is null or the empty string or not a valid - identifier - -variables.h - - delete_var: new extern declaration - -subst.h - - ASS_NAMEREF: new define for assignments, means assigning to a nameref - variable - -builtins/declare.def - - declare_internal: if we are creating and assigning to a nameref - variable, make sure the value is a valid variable name (checks done - by make_variable_value via bind_variable_value) and display an - error message, deleting the variable we just created, if it is not. - Fixes bug reported by Peggy Russell - - 1/9 - --- -builtins/declare.def - - declare_internal: turning on nameref attribute for an existing - variable turns off -i/-l/-u/-c attributes (essentially the ones - that cause evaluation at assignment time) for ksh93 compat - -builtins/setattr.def - - show_name_attributes: if asked to display attributes and values for - a nameref variable, don't follow the nameref chain to the end. More - ksh93 compat - - 1/10 - ---- -trap.c - - _run_trap_internal: use {save,restore}_parser_state instead of - {save,restore}_token_state, like in run_pending_traps(); don't - need to save and restore last_command_exit_value as a result - - _run_trap_internal: call {save,restore}_pipeline like in - run_pending_traps() - - run_pending_traps: since we no longer run traps in a signal handler - context, do not block and unblock the trapped signal while the - trap is executing - - run_pending_traps: allow recursive invocations (basically, running - traps from a trap handler) with only a warning if the shell is - compiled in debug mode. If a caller doesn't want this to happen, - it should test running_trap > 0. signal_in_progress (sig) only works - for the signals the shell handles specially - -bashline.c - - bash_event_hook: make sure we clean up readline if interrupt_state - is set, not only when SIGINT is not trapped. check_signals_and_traps - will call check_signals, which calls QUIT, which will longjmp back - to top_level, running the interrupt trap along the way. Fixes the - problem of signal handlers being reset out from under readline, and - not being set properly the next time readline is called, because - signals_set_flag is still set to 1. XXX - might need to do this - for other signals too? - - 1/11 - ---- -subst.h - - SD_GLOB: new define for skip_to_delim; means we are scanning a - glob pattern. - -subst.c - - skip_to_delim: if flags include SD_GLOB, assume we are scanning a - glob pattern. Currently only used to skip bracket expressions - which may contain one of the delimiters - - 1/12 - ---- -subst.c - - parameter_brace_expand: when expanding $@ as part of substring - expansion, pattern substitution, or case modification, don't turn - on the QUOTED_NULL flag. The code that constructs the word to be - returned from expand_word_internal expects a different code path - when $@ is being expanded. Fixes bug reported by Theodoros - V. Kalamatianos - - 1/19 - ---- -subst.c - - list_dequote_escapes: new function; analogue of list_quote_escapes - -pathexp.c - - quote_string_for_globbing: fix case where unescaped ^A is last char - in string; need to pass it through unaltered instead of turning it - into a bare backslash - - quote_string_for_globbing: when quoting for regexp matching in [[, - don't treat backslash as a quote character; quote the backslash as - any other character. Part of investigation into reports from - Eduardo A. Bustamante López - - 1/25 - ---- -builtins/gen-helpfiles.c - - write_helpfiles: add prototype - - make sure to #undef xmalloc/xfree/xrealloc/free if USING_BASH_MALLOC - is defined. the code does not use them, and we don't link against - xmalloc.o. Report from Linda Walsh - -Makefile.in - - variables.o: add dependency on builtins/builtext.h; helps with - parallel builds. Report from Linda Walsh - -support/shobj-conf - - darwin: combine the stanzas into one that will not require them to - be updated on each Mac OS X release. Report and fix from Max Horn - - - 1/27 - ---- -support/shobj-conf - - darwin: changed the install_name embedded into the shared library - to contain only the major version number, not the minor one. The - idea is that the minor versions should all be API/ABI compatible, - and it is better to link automatically with the latest one. Idea - from Max Horn - - 1/29 - ---- -[bash-4.3-rc2 released] - - 1/30 - ---- -lib/readline/readline.h - - rl_clear_history, rl_free_keymap: add extern declarations. Report - from Hiroo Hayashi - -general.c - - include trap.h for any_signals_trapped() prototype - -lib/sh/unicode.c - - include for sprintf prototype - - 1/31 - ---- -execute_cmd.c - - execute_simple_command: only posix-mode shells should exit on an - assignment failure in the temporary environment preceding a special - builtin. This is what the documentation and code comments have - always said - - execute_simple_command: make sure redirection errors, word expansion - errors, and assignment errors to Posix special builtins cause a - non-interactive posix mode shell to exit. Previously the shell - would not exit if the failed special builtin was on the LHS of || - or && - -pathexp.c - - quote_string_for_globbing: when quoting a regular expression - (QGLOB_REGEXP), allow an unquoted backslash to pass through - unaltered. Don't use it as a quote character or quote it. More - investigation from 1/24 and report by Mike Frysinger - - - quote_string_for_globbing: when quoting a regular expression - (QGLOB_REGEXP), turn CTLESC CTLESC into CTLESC without adding a - backslash to quote it. We should not have to quote it because it is - not a character special to EREs. More investigation from 1/24 - -lib/glob/glob.c - - glob_testdir: now takes a second flags argument (currently unused); - changed prototype and callers - - 2/1 - --- -lib/glob/glob.c - - glob_testdir: if flags argument includes GX_ALLDIRS (globstar), use - lstat so we skip symlinks when traversing the directory tree. - Originally reported by Chris Down - - 2/2 - --- -lib/readline/undo.c - - rl_do_undo: make sure CUR is non-zero before dereferencing it to - check cur->data against rl_undo_list. Report and fix from - Andreas Schwab - -doc/{bash.1,bashref.texi} - - added slight clarifying language to the description of $*, - describing what happens when the expansion is not within double - quotes - - 2/4 - --- -test.c - - unary_test: add code to -v case so that it interprets `bare' array - references (foo[1]) and returns true if that index has a value - - 2/5 - --- -trap.c - - restore_default_signal: fix SIGCHLD special case for SIG_TRAPPED flag - off but SIG_INPROGRESS mode set and handler IMPOSSIBLE_TRAP_HANDLER; - continue with resetting handler in this case. maybe_set_sigchld_trap - will check these things before resetting sigchld trap from - run_sigchld_trap. Fixes (apparently long-standing?) problem reported - by Alexandru Damian - - 2/6 - --- -lib/sh/strtrans.c - - ansic_quote: fixed a bug when copying a printable character that - consumes more than one byte; byte counter was not being incremented. - Bug report from jidanni@jidanni.org - - 2/7 - --- -input.c - - getc_with_restart: if read(2) returns -1/EINTR and interrupt_state or - terminating_signal is set (which means QUIT; will longjmp out of this - function), make sure the local buffer variables are zeroed out to - avoid reading past the end of the buffer on the next call. Bug report - from Dan Jacobson - - 2/9 - --- -bashline.c - - command_word_completion_function: if a directory in $PATH contains - quote characters, we need to quote them before passing the candidate - path to rl_filename_completion_function, which performs dequoting on - the pathname it's passed. Fixes bug reported by Ilyushkin Nikita - - - 2/11 - ---- -parse.y - - xparse_dolparen: save and restore shell_eof_token around call to - parse_string, intead of just leaving it set to ')' - - shell_getc: when -v is set, only print the command line when - shell_eof_token is 0, so we don't print it multiple times when - recursively entering the parser to parse $(...) commands. Fixes - bug reported by Greg Wooledge - -[changed release status to 4.3-release] - - 2/13 - ---- -lib/sh/strtrans.c - - ansic_quote: handle case where mbrtowc reports that the multibyte - sequence is incomplete or invalid. Fixes bug reported by - Eduardo A. Bustamante López - - 2/14 - ---- -variables.c - - find_variable_nameref_context: fix a problem that caused the loop - to go one context too close to the global context. In some cases, - simple variable assignment would set a variable in the global - context instead of a local context. Bug report from - Geir Hauge - - 2/26 - ---- -[bash-4.3 released] - - 2/27 - ---- -aclocal.m4 - - broken wcwidth check: fix typo reported by David Michael - - - 2/28 - ---- -support/bashbug.sh - - add ${BUGADDR} to error message printed if sending mail fails - -trap.c - - _run_trap_internal: don't call {save,restore}_pipeline if running - DEBUG trap; run_debug_trap calls them itself. Fixes bug reported - by Moe Tunes - -test.c - - unary_test: fix 'R' case by using find_variable_noref instead of - find_variable - - test_unop: add back missing 'R' case. Fixes bug reported by - NBaH - - 3/2 - --- -jobs.c - - end_job_control: if job control is active, we changed the terminal's - process group, so make sure we restore it. Fixes bug reported by - Eduardo A. Bustamante López - - 3/7 - --- -pcomplete.c - - pcomp_curtxt: new variable, holds the original text to be completed - as passed to the programmable completion code - - pcomp_filename_completion_function: if we are running compgen - (presumably in a shell function completion) and performing readline - completion, check the word being completed. If it's not empty, but - the original word passed to the programmable completion code is an - empty string (""), call a dequoting function if one is available. - This compensates for an assumption in bash-completion. Reported by - Albert Shih - -lib/readline/readline.c - - _rl_dispatch_subseq: when deciding whether or not to set vi mode's - idea of the last command, use whether or not the dispatching keymap - is vi_movement_keymap instead of the key sequence length. The `c', - `d', and `y' commands all take motion commands as `arguments' and - will produce key sequences longer than 1 character. The arrow keys - will end up dispatching out of a different keymap, so the test will - prevent arrow keys from setting the last command (the problem in - bash-4.2). Bug report from Daan van Rossum - -lib/readline/vi_mode.c - - _rl_vi_motion_command: convenience function to test whether a key is - a vi-mode motion command - -lib/readline/rlprivate.h - - _rl_vi_motion_command: extern declaration - -parse.y - - parse_matched_pair: we should not skip processing single quotes in - posix mode if dolbrace_state == DOLBRACE_QUOTE2 (pattern - substitution). Fixes bug reported by David Sines - - - 3/10 - ---- -lib/readline/readline.c - - _rl_dispatch_callback: treat a return value of -1 as the end of - a command dispatch sequence if the current context doesn't - indicate that we're reading a multi-key sequence - ((cxt->flags & KSEQ_SUBSEQ) == 0). Turn off the multikey flag - and free the context chain in this case. Fixes one bug reported - by Felix Yan to bug-readline list - - _rl_dispatch_callback: treat a return value of > 0 the same as 0 - and return from the function, since only values < 0 cause us to - simulate recursion. Rest of fix for bug tracked down by - Anatol Pomozov - - 3/11 - ---- - -execute_cmd.c - - execute_in_subshell: if a longjmp occurs, set result to - EXECUTION_FAILURE only if last_command_exit_value == EXECUTION_SUCCESS; - use value of last_command_exit_value otherwise. Fixes cosmetic - issue reported by Dennis Lambe Jr. - -doc/bash.1 - - shell-kill-word and shell-backward-kill-word should be documented - as unbound by default. Report from Oliver Hartley - - -trap.c - - run_pending_traps: save value of $? before running trap commands in - trap_saved_exit_value, like run_exit_trap - - _run_trap_internal: save value of $? before running trap commands in - trap_saved_exit_value, like run_exit_trap - -builtins/common.c - - get_exitstat: when running `return' in a trap action, and it is not - supplied an argument, use the saved exit status in - trap_saved_exit_value. Fixes Posix problem reported by - Eduardo A. Bustamante López - - 3/13 - ---- -lib/sh/shquote.c - - sh_contains_quotes: new function, returns true if a given string - contains any of the shell quote characters (single quote, double - quote, or backslash) - -externs.h - - sh_contains_quotes: new extern declaration - -pcomplete.c - - pcomp_filename_completion_function: more changes for the benefit of - bash-completion: if the argument is not the same as the original - argument passed to the programmable completion code (pcomp_curtxt), - and we are being run by compgen as part of a completion, dequote the - argument as bash-completion expects. Fix for the complete-word- - with-quoted-special-chars problem with bash-completion - - 3/17 - ---- -execute_cmd.c - - execute_intern_function: when in posix mode, make defining a function - with the same name as a special builtin a fatal error only when the - shell is not interactive. Interactive shells display an error - message and go on. From a discussion with Doug McIlroy - - - 3/18 - ---- -arrayfunc.c - - assign_compound_array_list: when using expand_assignment_string_to_string - to expand the value in a ( [x]=y ) compound assignment, make sure - that we convert 0x0 to "" when expanding [x]= so it doesn't appear as - if the index is unset. Fixes bug reported by Geir Hauge - - -builtins/common.c - - get_exitstat: update fix of 3/11 to allow the DEBUG trap to use the - current value of $? instead of the value it had before the trap - action was run. This is one reason the DEBUG trap exists, and - extended debug mode uses it. Might want to do this only in Posix - mode - -doc/{bash.1,bashref.texi} - - return: add language cribbed from Posix saying what happens when - return is run without an argument from a trap, including the DEBUG - trap exception - - 3/19 - ---- -lib/glob/gmisc.c - - extglob_pattern_p: make sure ?(patlist) is flagged as an extglob - pattern - -lib/glob/glob.c - - extglob_skipname: rewrite to handle patterns that begin but do not - end with an extglob pattern; change test for easy case and loop - through patterns accordingly. Fixes problem with matching filenames - with a leading dot reported by Stephane Chazelas - - - wextglob_skipname: make analogous changes - - 3/20 - ---- -Makefile.in - - pass -DDEBUG down to builds in readline and history directories - -lib/readline/util.c - - _rl_trace and related functions are now only compiled in if DEBUG - is defined - -lib/readline/Makefile.in - - substitute @DEBUG@ and pass -DDEBUG, if necessary, to compilation - in LOCAL_CFLAGS - - 3/21 - ---- -parse.y - - shell_getc: when checking whether or not to reallocate - shell_input_line to add trailing newline, don't try to subtract from - shell_input_line_size. size_t is unsigned, so if its value is less - than 3 (like, say, 2), size-3 is a very large number and the string - will not be reallocated. Use len+3 > size instead of len > size-3. - Fixes bug reported in - https://bugs.launchpad.net/ubuntu/+source/bash/+bug/1295467 - - 3/27 - ---- -lib/readline/display.c - - _rl_clean_up_for_exit: don't bother to call _rl_move_vert to whatever - readline thinks the last displayed line is if it's 0. Two reasons: a - minor optimization, and it protects against unwanted moving if this - function is called twice, as it is when ^C is pressed. Fixes bug - reported by Egmont Koblinger - - 3/28 - ---- -bashline.c - - invalid_completion: new function, used to identify attempts to - complete words that are syntax errors - - attempt_shell_completion: if invalid_completion returns true for a - word in a command position, punt on all completions. Fixes cosmetic - issue reported by Uwe Storbeck - - attempt_shell_completion: add clause so that in_command_position - remains set to 1 for an empty word following a command separator like - (, &, or | - -lib/readline/kill.c - - rl_yank, rl_yank_nth_arg_internal: don't return -1 from bindable - functions, return 1 instead - -lib/readline/text.c - - rl_rubout, _rl_rubout_char, rl_delete, rl_change_case, - rl_transpose_chars, rl_transpose_words, _rl_set_mark_at_pos, - rl_exchange_point_and_mark, _rl_insert_next, _rl_char_search, - _rl_char_search_internal: - don't return -1 from bindable functions, return 1 instead - -lib/readline/vi_mode.c - - rl_vi_end_word, rl_vi_rubout, rl_vi_delete, rl_vi_char_search, - rl_vi_match, _rl_vi_set_mark, _rl_vi_goto_mark: - don't return -1 from bindable functions, return 1 instead - -lib/readline/macro.c - - rl_start_kbd_macro, rl_end_kbd_macro: - don't return -1 from bindable functions, return 1 instead - -builtins/setattr.def - - set_var_attribute: honor setting of no_invisible_vars when setting - att_invisible on a variable - - include "../flags.h" for no_invisible_vars - -builtins/declare.def - - declare_internal: honor setting of no_invisible_vars when setting - att_invisible on a variable - - include "../flags.h" for no_invisible_vars - -Makefile.in,builtins/Makefile.in - - make sure declare.o and setattr.o depend on flags.h - -execute_cmd.c - - decpoint: new function, returns locale's decimal point or `.' default - - mkfmt: use decpoint() to get decimal point instead of unconditionally - using `.'. Fixes bug reported by Andrey Tataranovich - in debian bug 741669 - - 4/10 - ---- -lib/readline/rltypedefs.h - - add back old Function/VFunction/etc typedefs, since other packages - (python, samba) use them. Mark as deprecated using gcc and clang - attributes. Report and fix from Max Horn - - 4/14 - ---- -jobs.c - - run_sigchld_trap: unwind-protect value of this_shell_builtin, since - it matters in some cases whether or not we are running `wait' or - `eval'. Fixes bug reported by Eduardo A. Bustamante López - - - 4/18 - ---- -shell.h - - sh_parser_state_t: add `need_here_doc' flags member, since - xparse_dolparen (via parse_command) sets it to 0 - -parse.y - - gather_here_documents: make sure need_here_doc is > 0, since we - don't want to just decrement it forever if it ends up < 0. Partial - fix for bug reported by Jared Yanovich - - {save,restore}_parser_state: save and restore need_here_doc flag. - Rest of fix for bug reported by Jared Yanovich - - 4/19 - ---- -subst.c - - cond_expand_word: since we are not supposed to be performing word - splitting here, set expand_no_split_dollar_star to 1 in addition to - setting W_NOSPLIT2 - - expand_word_internal: if we have a case where we have an unquoted - $@ but we are in a case where we don't want to split (W_NOSPLIT2), - make sure we return a list consisting of a single word with the - arguments separated by spaces and don't do word splitting. Fixes - bug reported by Greg Wooledge from an IRC - discussion - -builtins/hash.def - - print_portable_hash_info: single-quote pathnames and hashed filenames - that contain shell metacharacters. Fixes bug reported by - in debian bash bug #739853 - - 4/20 - ---- -lib/readline/display.c - - When using horizontal scrolling, the redisplay code erases too much - of the line containing successful results, so make sure we only - erase to the end of the line after making sure we move the cursor - to the end. Fixes bug reported by - - 4/23 - ---- -{bashhist,bashline}.c -builtins{bind,help,type}.def -lib/glob/glob.c, lib/intl/{loadmsgcat,localealias}.c,lib/sh/mktime.c - - fixes to memory leaks uncovered by coverity scan - - 4/24 - ---- -{bashhist,subst,redir,assoc,jobs,array,trap}.c -lib/intl/l10flist.c -builtins/complete.def - - fixes to memory leaks and other resource usage problems uncovered by - coverity scan - -redir.c - - do_redirection_internal: if dup2 fails (presumably because of a - resource limit), close the file descriptor we opened before returning - error - - 4/25 - ---- -config-top.h - - DEFAULT_BASHRC: new define with the name of the default shell - startup file - -bashline.c - - bash_directory_completion_matches: don't dequote the directory name. - If rl_completion_found_quote is non-zero, readline will dequote the - filename itself. Fixes bug reported by Clark Wang - - - 4/27 - ---- -subst.c - - parameter_brace_expand_rhs: if parameter_brace_find_indir returns - NULL or "", or if it returns something that is not a valid identifier, - report an error and return &expand_wdesc_error so the error can - propagate up. Fixes bug reported by Andre Holzhey - - - 4/29 - ---- -subst.c - - parameter_brace_substring: don't short-circuit right away if the - value is NULL but we are looking at the positional parameters. Part - of fix for bug reported by Pierre Gaston - - pos_params: if there are no positional parameters, only short-circuit - if we are looking for $1 and above. Rest of fix for bug reported - by Pierre Gaston - -subst.h - - SD_NOPROCSUB: new flag for skip_to_delim, means to not allow any - process subsitutions (should not have overloaded SD_NOSKIPCMD) - -subst.c - - skip_to_delim: honor SD_NOPROCSUB flag - -make_cmd.c - - make_arith_for_expr: set W_NOPROCSUB flag in the created word - - make_arith_for_command: set SD_NOPROCSUB in the flags argument to - skip_to_delim so we don't treat <( or >( as a process substitution - (we won't evaluate them in eval_arith_for_expr anyway). Fixes - bug reported by Pierre Gaston - - 5/1 - --- -lib/glob/gmisc.c - - glob_dirscan: new function, takes a pattern and a directory separator - argument and advances the pattern to the last occurrence of the - separator. Like strrchr, but understands extended glob patterns and - uses glob_patscan to skip over them - -lib/glob/glob.c - - extglob_skipname: if the extended globbing pattern is invalid, don't - skip the name - - glob_filename: if there is a slash in the pattern to be matched, and - extglob is enabled, use glob_dirscan to find the real last occurrence - of `/' to avoid being confused by slashes in extglob patterns. Fix - for bug reported by Pierre Gaston - - 5/6 - --- -variables.c - - make_local_variable: only set the att_invisible attribute if - no_invisible_vars isn't set - - find_variable_for_assignment: new function, intended to be called by - code that eventually wants to assign a value to the variable; will not - skip invisible variables; currently identical to find_variable - - find_variable_no_invisible: new function, finds the first visible - instance of variable with a given name in the variable context chain; - eventually will be used to replace find_variable; separate right now - for testing - -variables.h - - find_variable_for_assignment: extern declaration - - find_variable_no_invisible: extern declaration - - 5/7 - --- -variables.c - - make_local_variable: don't clear `invisible' attribute if we are - returning an existing local variable at the right context. Let the - upper layers do that. Fixes bug reported by Dan Douglas - - - 5/8 - --- -lib/readline/input.c - - rl_getc: call RL_CHECK_SIGNALS if a read(2) is interrupted (-1/EINTR) - by SIGALRM or SIGVTALRM (placeholder for non-keyboard-generated - signals of interest) - -builtins/read.def - - edit_line: call bashline_set_event_hook and - bashline_reset_event_hook around call to readline(), so the right - signal handling happens - - read_builtin: make sure we add an unwind_protect call to - bashline_reset_event_hook. These changes fix bug reported in - https://bugs.launchpad.net/ubuntu/+source/bash/+bug/1317476 - -bashline.c - - bash_event_hook: make sure we clean up the readline state by calling - rl_cleanup_after_signal if sigalrm_seen is non-zero. The read builtin - sets this when it times out - - 5/12 - ---- -doc/{bash.1,bashref.texi} - - clarify language to make it clear that changing attributes of a - nameref variable (e.g., export), actually changes the attributes of - the referenced variable. Fixes omission noted by Jeff Haemer - - -arrayfunc.c - - bind_array_var_internal: make sure ENTRY no longer has invisible - attribute before returning. Fixes bug reported by Geir Hauge - - - 5/22 - ---- -execute_cmd.c - - shell_execve: if execve fails and we return 127 or 126, make sure to - set last_command_exit_value if a call to file_error or report_error - causes the shell to exit. This ensures that the shell exits with - the right value. - - 6/6 - --- -shell.c - - drop_priv_mode: print an error message on setuid() failure, optionally - exit if errno == EAGAIN, as it can be on Linux when RLIMIT_NPROC for - the target user is exceeded. - -config-top.h - - EXIT_ON_SETUID_FAILURE: new settable define, will cause the shell to - exit if setuid fails with errno == EAGAIN - - 6/10 - ---- -parse.y - - time_command_acceptable: fix so time is accepted everywhere the - grammar is looking for a `compound_list'. Fixes bug reported by - Dale Worley - - 6/12 - ---- -subst.c - - clear_fifo_list: new function, clears FDs associated with open pipes - in current FIFO list without closing the file descriptors. Can - possibly be used when shell_execve fails and the shell jumps back - to top_level and we don't want the shell to close the open FIFOs - each time through the read-execute loop. Bug reported by Harald - Koenig - - - 6/16 - ---- -builtins/shopt.def - - compat42: make sure the `compat42' option sets the correct variable - for compatibility level. Fixes bug reported by Ondrej Oprala - - -support/bashbug.sh - - fix typo when echoing $USAGE. Report from Shantanu Kulkarni - - -execute_cmd.c - - shell_execve: before longjmp back to subshell_top_level, clear out the - FIFO fd list by calling clear_fifo_list so the FDs (which we inherited - from our parent) aren't closed every time through the read-eval loop. - Fix for bug reported by Harald Koenig - - 6/18 - ---- -subst.c - - extract_process_subst: add additional argument: xflags, allow callers to - pass flags like extract_command_subst - - extract_process_subst: call xparse_dolparen like command substitution - to avoid problems when parsing commands constructs with embedded open - parens. Fixes bug reported by Tim Friske - -subst.h - - extract_process_subst: modified prototype for extern declaration - - 6/19 - ---- -execute_cmd.c - - execute_pipeline: if running with lastpipe enabled, make sure that we - check whether or not the job id is valid using INVALID_JOB before - calling job_exit_status. the jobs list can get frozen and unfrozen in - the presence of nested pipelines and loops and wait_for can clear a - job table entry. Fixes bug reported by - -jobs.c - - freeze_jobs_list: now returns old value of jobs_list_frozen; unused at - current time - -jobs.h - - freeze_jobs_list: change return value - - 6/20 - ---- -lib/glob/smatch.c - - MEMCHR: single-byte and wide character defines (memchr/wmemchr) - -lib/glob/sm_loop.c - - GMATCH: when the wildcards are the last element of the pattern, make - sure they do not match a string containing a `/' if FNM_PATHNAME is - set in FLAGS - - GMATCH: when recursively calling GMATCH after we see a `*', don't - try to consume the rest of the pattern with `*' if FNM_PATHNAME is - set in FLAGS, just consume up to the next slash and then see whether - or not the rest of the pattern matches. Fixes bug reported by Ian - Kelling - - GMATCH: when processing `*' in the pattern, after skipping consecutive - wildcards, if we hit a literal `/' in the pattern and we're looking - for a pathname, skip characters in the string until we find a `/' - (no slash means the match fails), and try to match the rest of the - pattern against the portion of the string after the next `/'. Picked - up from gnulib/glibc - -pathexp.c - - split_ignorespec: since split_ignorespec gets globbing patterns, - make sure we call skip_to_delim with the SD_GLOB flag so delimiters - that occur within bracket expressions don't delimit the pattern. - Fixes problem with [[:digit:]] in GLOBIGNORE reported by Ian Kelling - - -unwind_prot.c - - unwind_protect_tag_on_stack: new function, returns 1 if unwind-protect - frame corresponding to `tag' argument is on unwind-protect stack - -unwind_prot.h - - unwind_protect_tag_on_stack: extern declaration - - 6/30 - ---- -lib/readline/misc.c - - _rl_revert_all_lines: set entry->data to 0 after assigning it to - rl_undo_list to avoid pointer aliasing problems that would result - in entry->line being freed by an undo. The subsequent free would - be a double free. Report and fix from Jared Yanovich - - -subst.c - - command_substitute: other shells do not appear to inherit the -v - option when reading and executing command substitutions. Reported - by Ondrej Oprala - - 7/1 - --- -config-top.h - - CHECKHASH_DEFAULT: new define that supplies the default value for - check_hashed_filenames (`checkhash' shopt option); still 0 by default - -findcmd.c - - check_hashed_filenames: initialize using CHECKHASH_DEFAULT - -lib/readline/histexpand.c - - history_expand: double quotes can inhibit recognition of the history - comment character if history_quotes_inhibit_expansion is non-zero - -lib/readline/doc/{history.3,hstech.texi} - - history_quotes_inhibit_expansion: expand definition to note that it - inhibits scanning for the history comment character as well; correct - typo to make it clear that it only works on double-quoted strings - -lib/sh/zgetline.c - - add new fourth argument: DELIM, allows delimiter to be something - other than newline (if DELIM != '\n', UNBUFFERED_READ should be - non-zero) - - UNBUFFERED_READ is now fifth argument - - check character against DELIM rather than strictly newline - -externs.h - - zgetline: change function prototype for extern declaration - -builtins/mapfile.def - - mapfile: change calling sequence for zgetline calls - - mapfile_builtin: new -d option: DELIM, like in read builtin - - mapfile_builtin: pass `delim' to mapfile() as new argument; default - to '\n' unless -d option supplied - - mapfile: take new DELIM argument, pass to zgetline - - mapfile: if DELIM != '\n', set unbuffered_read to 1 - -doc/{bash.1,bashref.texi} - - mapfile: document new `-d DELIM' option - - 7/5 - --- -lib/readline/histfile.c - - history_truncate_file: if there is an error writing the truncated - history list back to the history file, use the same strategy as - history_do_write: create a backup file, rename the history file to - the backup file, and restore the original history file from the - backup file name if the write or the close fails. Suggestion from - Chen Gang to bug-readline - -execute_cmd.c - - evalnest, evalnest_max: new variables establishing maximum number of - recursive `eval' calls; current max is 4096 - - execute_builtin: unwind-protect value of evalnest around calls to - eval builtin. Suggested by Oliver Morais - - {initialize_subshell,execute_subshell_builtin_or_function}: reset - evalnest to 0 in a subshell - -builtins/setattr.def - - show_name_attributes: show a variable's attributes even if it's - invisible (don't show any value since it has none). This means that - declare -p var will display VAR's attributes even when var marked - as invisible. Feature request from Peggy Russell - - - show_var_attributes: don't print assignment if array or assoc - attribute is set but variable marked as invisible - -tests/array.right - - special note: changed all declare -a output tests because the shell - will no longer print out values for invisible array variables. This - is a change, but one for correctness: - - declare -a foo='()' - and - declare -a foo - are not equivalent - - 7/22 - ---- -subst.c - - parameter_brace_expand: after calling parameter_brace_expand_indir, - turn off the W_ARRAYIND flag in the word it returns, because there - is no way for it to return the index that should be used, and the - rest of the function assumes that IND is valid if W_ARRAYIND is set. - Fixes bug reported by Corentin Peuvrel - - 8/2 - --- -parse.y - - read_token_word: if we read a character that will end a command - substitution, don't skip over quoted newlines when we read an - additional character to figure out whether it's a two-character - token. This lets the higher layers deal with quoted newlines after - the command substitution. Fixes bug reported by EmanueL Czirai - - - 8/11 - ---- -execute_cmd.c - - execute_pipeline: check whether lastpipe_jid corresponds to a valid - job before calling append_process, for the same reason as fix from - 6/19. Fixes bug reported by - - 8/12 - ---- -lib/sh/unicode.c - - stub_charset: use strncpy instead of strcpy because we are copying - into a local fixed-length buffer. Fixes vulnerability reported by - - -execute_cmd.c - - execute_pipeline: if we don't call append_process, call - wait_for_single_pid to get the status of `lastpid', since that will - check the status of already-reaped processes. Fixes spurious error - message about non-existent process from fix of 8/11 - - 8/15 - ---- -jobs.c - - running_in_background: new variable, keeps track of whether or not we - are running in the background (not perfect yet) - - initialize_job_control: even if we are not turning on job control, - get the terminal pgrp so we can use it later - - {set_job_control,initialize_job_control}: set running_in_background - to 1 if terminal pgrp != shell pgrp - - {stop_pipeline,make_child,wait_for}: if we are running in the - background, don't mess with the terminal's process group; assume that - the parent shell will do that. Fixes bug reprted by Greg Wooledge - - -shell.c - - shell_reinitialize: reset running_in_background back to 0 - - 8/24 - ---- -execute_cmd.c - - {execute_connection,execute_command_internal}: make sure that - asynchronous commands always set $? to 0 and are not affected by the - command's exit status being inverted using `!'. Fixes bug reported - by Vincent Lefevre - -lib/readline/display.c - - rl_message: call vsnprintf with full msg_bufsiz, since it counts - one fewer than the buffer length passed as an argument. Bug report - and fix from Dylan Cali - - 8/26 - ---- -builtins/evalstring.c - - evalstring: if CURRENT_TOKEN == yacc_EOF, reset it to newline. This - is instead of calling reset_parser(); that might still be needed. - Fixes bug with eval and a subsequent statement ending with EOF - reported by - -pcomplete.c - - filter_stringlist: when extglob is on, a leading ! in the filter - pattern should be left alone when it introduces a !(pat) pattern; - otherwise it messes up the pattern. Fixes bug reported by David - Korn - - 8/27 - ---- -doc/{bash.1,bashref.texi} - - clarify the behavior of bash when given the -c option, since $0 is - technically not a positional parameter. Bug reported by Stephane - Chazelas - - 8/28 - ---- -lib/readline/history.c - - add_history: use history_max_entries (if history is stifled) or - DEFAULT_HISTORY_INITIAL_SIZE if not (new define, defaults to 502) - to size the initial allocation of the history array. Assumption - is that this will reduce the number of allocations - - 8/29 - ---- -execute_command.c: - - sourcenest, sourcenest_max: new variables used to track level of - sourced files and (maybe) one day catch infinite source recursion - - execute_builtin: if current source level exceeds sourcenest_max, - trigger an error and jump back to the top level - - {initialize_subshell,execute_subshell_builtin_or_function}: reset - sourcenest to 0 in a subshell - - 9/2 - --- -variables.c - - bind_variable: if a nameref expands to an array reference, make - sure that assign_array_element gets called (maybe even - recursively) instead of bind_variable_internal, so invalid variable - names (like arr[0]) don't get created. Fixes bug reported by - - - 9/3 - --- -execute_cmd.c - - evalnest_max,sourcenest_max: initialize from EVALNEST_MAX and - SOURCENEST_MAX, respectively. Feature suggested by - - -config-top.h - - define EVALNEST_MAX and SOURCENEST_MAX to 0 - - 9/6 - --- -bashline.c - - find_cmd_start: fix to (crudely) deal with >| token; even though - skip_to_delim finds `|' as a delimiter, we call it again and use - what the second call finds. Fixes bug reported by Dan Jacobson - - -findcmd.c - - find_in_path_element: if in posix mode, do not expand a literal - tilde in a $PATH element - -doc/bashref.texi - - add change to tilde expansion in $PATH elements to posix mode - description - -builtins/common.h - - ISHELP: new define for builtins that do their own option parsing - and don't use internal_getopt(); checks whether argument is --help - - CHECK_HELPOPT: convenience define to help builtins that do their - own option parsing to check for --help with one line of code - - CASE_HELPOPT: convenience define to help builtins that use - internal_getopt() check for --help with one line of code - -builtins/help.def - - builtin_help: new function, prints out --help output for current - builtin - -builtins/{kill,let,pushd}.def - - add CHECK_HELPOPT to builtins that use ISOPTION; call builtin_help - and return EX_USAGE (kill/let/pushd/popd/dirs) - -builtins/{caller,fg_bg}.def - - use CHECK_HELPOPT to recognize --help, since these builtins perform - checks that can cause them to return before calling no_options - (caller/fg/bg) - -builtins/{exit,return}.def - - use CHECK_HELPOPT to recognize --help before calling get_exitstat() - (return/exit/logout) - -builtins/{break,shift}.def - - use CHECK_HELPOPT to recognize --help before any other checks - (break/continue/shift) - -builtins/bashgetopt.h - - GETOPT_EOF: convenience define - - GETOPT_HELP: new define, to indicate internal_getopt saw --help - -builtins/bashgetopt.c - - internal_getopt: return GETOPT_HELP for --help - -builtins/common.c - - no_options: recognize --help, call builtin_help and return 2 - (builtin/eval/source/./times) - -builtins/command.def - - use CASE_HELPOPT() to handle --help after calling internal_getopt() - (command) - -builtins/{colon,echo,test}.def - - do not recognize --help (:/true/false/echo/test) - - 9/8 - --- -sig.c - - termsig_sighandler: if readline is active now, set the bashline event - hook. Old code just set it for interactive shells. Part of fix for - bug reported by - -bashline.c - - bash_event_hook: call rl_cleanup_after_signal if terminating_signal - is non-zero, since check_signals_and_traps() will cause the shell to - exit if it is and we want to clean up the readline state first. Rest - of fix for bug reported by - - 9/9 - --- -jobs.c - - waitchld: when running the wait builtin in posix mode, with a trap set - on SIGCHLD, use queue_sigchld_trap instead of trap_handler (SIGCHLD), - otherwise you will lose SIGCHLDs when children_exited > 1. Fixes bug - reported by - -builtins/read.def - - read_builtin: if we are changing the tty settings, call - initialize_terminating_signals so we have a chance to catch all - terminating signals and potentially clean up the terminal before - exiting - - read_builtin: tty_modified: new variable, set to 1 if we change the - terminal attributes and have to call ttyrestore() to restore them - - if one of the `reads' returns -1/EINTR due to a terminating signal, - and we have modified the terminal, call ttyrestore before calling - CHECK_TERMSIG - - ttyrestore: set tty_modified to 0 when called - - 9/10 - ---- -builtins/read.def - - termsave: now global to file so other functions can use it - - read_tty_cleanup: if tty_modified is non-zero, call ttycleanup to restore - old terminal settings and turn off tty_modified - -sig.c - - termsig_handler: call read_tty_cleanup if currently executing read - builtin; it does the right thing. Final piece of fix for bug reported - by Jan Rome - - 9/11 - ---- -general.c - - printable_filename: general function to return a printable representation - of a string (presumed to be a filename) - -general.h - - extern declaration for printable_filename - -execute_cmd.c - - execute_disk_command: use printable_filename - -builtins/{bind,cd,enable,hash,source}.def - - use printable_filename as appropriate when printing error messages. - From a suggestion by Vincent Lefevre - -builtins/bind.def - - use CASE_HELPOPT() to handle --help after calling internal_getopt() - (bind) - - 9/12 - ---- -builtins/common.h - - SEVAL_FUNCDEF: new flag for parse_and_execute; it means that we only - accept a single function definition command, as when we are importing - functions from the environment - - SEVAL_ONECMD: new flag for parse_and_execute; for future use - -builtins/evalstring.c - - parse_and_execute: if the SEVAL_FUNCDEF flag is set, disallow anything - but a function definition command - -variables.c - - initialize_shell_variables: don't allow functions with invalid names - to be imported from the environment, even though we still allow them - to be defined - - initialize_shell_variables: when importing function definitions from - the environment, call parse_and_execute with the SEVAL_FUNCDEF flag - to force the command to be just a function definition - -subst.c - - param_expand: when expanding a $name variable expansion, make sure that - the variable is visible and set before following the nameref chain - - param_expand: when expanding a $name variable expansion and following the - nameref chain, make sure the resulting variable is visible and set - before using it - - 9/13 - ---- -variables.c - - initialize_shell_variables: when importing function definitions from - environment, use SEVAL_ONECMD flag for parse_and_execute. Part of - CVE-2014-6271 - -builtins/evalstring.c - - parse_and_execute: if SEVAL_ONECMD flag set, return immediately after - calling execute_command_internal. Final piece for fix for bug - reported by Stephane Chazelas . Part of - CVE-2014-6271 - - 9/24 - ---- -parse.y - - reset_parser: reset eol_ungetc_lookahead to 0 here, since we don't want - shell_getc returning it on the next call. Fixes problem reported by - Tavis Ormandy and Michal Zalewski - . Potentially part of CVE-2014-6271; fix for - CVE-2014-7169 - - 9/25 - ---- -parse.y - - push_heredoc: new function, pushes a here-doc redirection onto - redir_stack handling overflow of redir_stack. Exits on overflow. - Original fix from Florian Weimer . Fix for - CVE-2014-7186 - - change straight assignments to redir_stack to call push_redir - - add one to size of word_lineno stack to avoid off-by-one error - below in read_token_word. Overflow just results in line numbers - being wrong. Fix for CVE-2014-7187 - - 9/27 - ---- -{execute_cmd,trap}.c - - changes to make minimal-config builds work again, mostly missing - #ifdefs for optional features - -builtins/common.c - - builtin_help: dummy version to be included if HELP_BUILTIN not - defined, for minimal-config builds - -variables.c - - initialize_shell_variables: incorporated patches from Florian - Weimer to change the strings bash looks - for when importing shell functions from the environment. It - adds a prefix (BASH_FUNC_) and a suffix (%%) to the name to - mark it as having been created by bash as an exported function. - Fix for remote attacks part of CVE-2014-6271 and CVE-2014-7169 - - mk_env_string: takes new argument, indicating whether we are - constructing a function - - mk_env_string: encodes function names as described above, so - initialize_shell_variables can find them - - 9/28 - ---- -copy_cmd.c - - copy_redirects: before calling savestring on here_doc_eof, make - sure it's not NULL (it could have been the result of a here - document delimited by EOF or EOS). Fixes bug reported by - Michal Zalewski . Fix for CVE-2014-6277 - -make_cmd.c - - make_redirection: initialize here_doc_eof member to NULL. Rest of - fix for CVE-2014-6277 - - 9/29 - ---- -parse.y - - current_input_line_state: return a sh_input_line_state_t containing - the current shell_input_line and its index and size variables - -shell.h - - current_input_line_state: extern declaration - -builtins/evalstring.c - - parse_and_execute: call reset_parser() before returning if - SEVAL_ONECMD set. Fixes bug reported by Michal Zalewski - and designated CVE-2014-6278 - - parse_and_execute: if we parse a function definition when - SEVAL_FUNCDEF is set, but don't consume the entire passed string, - throw an error, reset the parser, and return. Part of fix for - CVE-2014-6278 - - parse_and_execute: if parsing the shell function definition when - SEVAL_FUNCDEF is set transforms the function name (e.g., if it - begins with a newline or begins or ends with whitespace), throw - an error, reset the parser, and return. Fixes bug reported by - Eric Kobrin - - 10/2 - ---- -jobs.c - - bgp_prune: don't do anything if bgpids.npid == 0 or bgpids.list == NULL. - This can happen if something gets run before the job control framework - is initialized. Bug report from - - 10/3 - ---- -parse.y - - xparse_dolparen: don't set token_to_read to newline after calling - parse_string() and cleaning up when the shell is not interactive. This - makes the parser thing it's ok to read new commands even if it's not in - a state where that should be possible. Underlying fix for bug reported - by Michal Zalewski and designated CVE-6278 - - parser_remaining_input: new function, returns the portion of - shell_input_line that hasn't yet been read - - current_input_line_state: removed - -shell.h - - parser_remaining_input: extern declaration - - current_input_line_state: removed - -builtins/evalstring.c - - parse_and_execute: change code that checks whether parse_command has - consumed the entire passed string when SEVAL_FUNCDEF is used to use - parser_remaining_input instead of messing around with (new) - current_input_line_state. Part of fix for CVE-2014-6278 - -variables.c - - initialize_shell_variables: if we don't call parse_and_execute, free the - temporary string, since parse_and_execute won't. Report and fix from - Eric Kobrin - - 10/4 - ---- -print_cmd.c - - print_function_def: when in posix mode, print shell function - definitions as posix specifies them, without the leading - `function' keyword - -general.c - - exportable_function_name: return 1 if the passed string can be - added to the environment as an exported function name. Currently - prohibits function names containing `/' and `=' from being - exported - -general.h - - exportable_function_name: extern declaration - -builtins/setattr.def - - set_or_show_attributes: if exporting a function with export -f, - call exportable_function_name to determine whether the function - should be exported; don't export function if it returns 0 - - 10/7 - ---- -builtins/setattr.def - - set_or_show_attributes: don't show identifiers that are invisible - and imported from the environment, since that combination of - attributes means that the imported variable is not a valid shell - identifier. Report from Stephane Chazelas - - 10/8 - ---- -shell.c - - shell_initialize: set new variable should_be_restricted, which - says whether or not the shell will be a restricted one based on the - shell name; use in calls to initialize_shell_variables (to inhibit - importing shell functions) and initialize_shell_options (to inhibit - parsing $SHELLOPTS) and initialize_bashopts (to inhibit parsing - $BASHOPTS). Report from - - 10/12 - ----- -execute_cmd.c - - execute_function: unwind-protect loop_level, set loop_level to 0 - when entering a function so break and continue in functions don't - break loops running outside of the function. Fix picked up from - dash via Herbert Xu - - 10/13 - ----- -doc/Makefile.in - - bashref.pdf: create using texi2dvi --pdf rather than postprocessing the - dvi file, so we have PDF bookmarks and links. Fix from - Siep Kroonenberg - - 10/14 - ----- -subst.h - - Q_ARITH: new quoting flag. Semantics are per Posix's spec for arithmetic - expansion: act as if string is quoted, but don't treat double quotes - specially (in this case, they will be removed by quote removal) - - Q_ARRAYSUB: new quoting flag, indicates we are expanding an indexed array - subscript - -subst.c - - expand_arith_string: if we are not expanding the string, but we saw a quote - with Q_ARITH specified as one of quoting flags, perform quote removal even - if Q_DOUBLE_QUOTES is specified - - param_expand: change calls to expand_arith_string for $[ and $(( cases to - specify Q_ARITH. Now $(( "$x" )) and $(( "x" )) work if x has a value that - evaluates to a valid number, as Posix specifies - - expand_word_internal: add test for quoted&Q_ARITH to the tilde case, so we - continue to perform tilde expansion in arithmetic contexts - - expand_word_internal: if quoted&Q_ARITH, continue processing when we see a - `"', acting as if the double quote isn't present (already Q_DOUBLE_QUOTED) - -arrayfunc.c - - array_expand_index: pass Q_DOUBLE_QUOTED|Q_ARITH|Q_ARRAYSUB as quoted argument - in call to expand_arith_string. This inhibits word splitting - (Q_DOUBLE_QUOTED) while discarding double quotes (Q_ARITH), identical to the - quote flags passed while expanding $(( )) and $[ ]. Q_ARRAYSUB reserved for - future use. Fixes problem reported by Stephane Chazelas - - - 10/16 - ----- -subst.c - - parameter_brace_expand_word: if the PF_ASSIGNRHS flag is set and we - are expanding what looks like an array subscripted with @ or *, - make sure the variable we're expanding is actually an array before - we add Q_DOUBLE_QUOTES to the flags. If we don't, things like - scalar[@] will remain quoted. Fixes ubuntu bug 1381567 - https://bugs.launchpad.net/ubuntu/+source/bash/+bug/1381567 - - 10/17 - ----- -{jobs,nojobs}.c - - get_original_tty_job_signals: get original signal dispostions for - SIGTSTP, SIGTTIN, SIGTTOU before we start manipulating them in - make_child - - default_tty_job_signals: make sure we set SIGTSTP, SIGTTIN, or - SIGTTOU to SIG_IGN if they were ignored at shell startup instead of - unconditionally setting them to SIG_DFL. Fixes bug reported by - idallen@idallen.ca - -jobs.h - - get_original_tty_job_signals: extern declaration - -trap.c - - initialize_traps: add call to get_original_tty_job_signals - - 10/22 - ----- -subst.c - - expand_string_for_rhs: when expanding in this context (rhs of a word - expansion or pattern removal), we don't perform word splitting, so - we don't want to split $* if IFS is empty. Fixes bug reported by - Stephane Chazelas - - 10/23 - ----- -subst.c - - param_expand: when expanding $* in a pattern context where the - expansion is quoted (Q_PATQUOTE), don't quote the expansion -- - the outer quotes don't make the characters in the expansion of - $* special. Posix interp 221. Reported by Stephane Chazelas - - - 10/28 - ----- -lib/readline/bind.c - - enable-bracketed-paste: new bindable variable, enables support for - a terminal's `bracketed paste mode'. Code contributed by - Daniel Colascione - -doc/bash.1,lib/readline/doc/{readline.3,rluser.texi} - - enable-bracketed-paste: add description - -lib/readline/{readline.c,rlprivate.h} - - _rl_enable_bracketed_paste: declarations - - #defines for use by bracketed paste implementation - -lib/readline/rltty.c - - rl_prep_terminal: send BRACK_PASTE_INIT string to terminal if we - are supposed to enable bracketed-paste mode; change terminal_prepped - to indicate we sent that string and need to clean up - - rl_deprep_terminal: if terminal_prepped indicates we sent the - bracketed-paste mode init string to the terminal, send the cleanup - string before restoring the terminal modes - -lib/readline/kill.c - - rl_bracketed_paste_begin: function to read bracketed paste until - BRACK_PASTE_SUFF; discard the suffix, and insert the rest of the - paste as a single (undoable) object. Bound to BRACK_PASTE_PREF - -lib/readline/funmap.c - - bracketed-paste-begin: new bindable command, executes - rl_bracketed_paste_begin - -lib/readline/readline.c - - bind_bracketed_paste_prefix: new function, sets up to recognize - the bracketed paste prefix sequence (BRACK_PASTE_PREF) in emacs - keymap and vi insertion keymap - - readline_initialize_everything: call bind_bracketed_paste_prefix - - 11/1 - ---- -builtins/ulimit.def - - RLIMIT_POSIXLOCKS: now synonym for RLIMIT_LOCKS - - -k: new option: RLIMIT_KQUEUES, max kqueues allocated for this - process - - -P: new option: RLIMIT_NPTS, max number of pseudoterminals available - to this process - -doc/{bash.1,bashref.texi} - - document `ulimit -k' option - - document `ulimit -P' option - -parse.y - - `timespec list_terminator' production: if the list terminator is `;' - set last_read_token to `;' to allow things like `time ; command' to - time null commands and not throw a syntax error. Patch from - Piotr Grzybowski - - `BANG list_terminator' production: do the same thing - -variables.c - - sv_optind: use find_shell_variable and get_variable_value so we can - have the variable's context in the case we need to do something - when we are restoring a previous variable context's value - -builtins/getopt.h - - sh_getopt_state_t: struct to save sh_getopt's internal state so we - can restore it around function calls in the event that we have a - local copy of OPTIND - -builtins/getopt.[ch] - - sh_getopt_{save,restore}_istate: new functions to save and restore - getopt's internal state - - sh_getopt_{alloc,dispose}_istate: new functions to allocate and - deallocate sh_getopt_istate_t objects - -execute_cmd.c - - maybe_restore_getopt_state: restore sh_getopt state after executing - function body iff the funtion declared a local copy of OPTIND - - execute_function: save sh_getopt state before executing function body - - execute_function: note in getopt_state->flags whether or not the - function declared a local copy of OPTIND; used by maybe_restore_getopt_state - - execute_function: maybe restore sh_getopt state before returning via - call to maybe_restore_getopt_state. Fixes bugs with getopts and - state between calls reported in 2011 by Bernd Eggink - and in 2014 by Oyvind Hvidsten - -configure.ac - - enable-function-import: new option, controls whether function imports - are included. Enabled by default. Patch from David Galos - - -config.h.in - - FUNCTION_IMPORT: define controlled by enable-function-import above - -variables.c - - initialize_shell_variables: include code to import function definitions - from the environment if FUNCTION_IMPORT is defined - -doc/bashref.texi - - --enable_function-import: document new configuration option - - 11/5 - ---- -lib/readline/history.c - - history_lines_read_from_file: new variable, set by read_history and - read_history_range to the actual number of lines read from the - history file. The value is valid immediately after a call to one - of those functions - - history_lines_written_to_file: new variable, set by write_history, - history_do_write, and history_truncate_file to the actual number of - lines written to the history file. The value is valid immediately - after a call to one of those functions - -variables.c - - sv_histsize: set history_lines_in_file after history_truncate_file() - only if hmax < history_lines_in_file (lines we've already read); a - cosmetic change only - -bashhist.c - - load_history: set history_lines_in_file after read_history() from - history_lines_read_from_file, since read_history reads all of the - lines from the history file even if it's more than $HISTSIZE - - maybe_save_shell_history: after calling write_history(), set - history_lines_in_file to history_lines_written_to_file, since we - can assume that we read everyhing we just wrote - -builtins/history.def - - history_builtin: after calling read_history (history -r), set the - new value of history_lines_in_file, for the same reason as above - - history_builtin: after calling read_history_range (history -n), set - history_lines_in_file from history_lines_read_from_file - - 11/6 - ---- -lib/readline/histfile.c - - history_truncate_file: since we move the old file to a backup copy - before truncating, make sure the new file is owned by the same uid - as the old - - history_do_write: use chown in the same way as history_truncate_file - - 11/12 - ----- -lib/readline/display.c - - expand_prompt: takes a new `flags' argument; only one flag defined - so far: PMT_MULTILINE - - expand_prompt: changed all callers to add new flags argument - - rl_expand_prompt, redraw_prompt: make sure to set PMT_MULTILINE in - FLAGS argument to expand_prompt if expanding parts of a prompt - containing embedded newlines - - expand_prompt: only add mode char to last line of a prompt with - embedded newlines, so mode indicator doesn't get lost and gets - updated properly. Fixes problem reported by Renlin Li - - - 11/13 - ----- - -lib/readline/display.c - - prompt_modestr: changed prompt_modechar to return a string denoting - the editing mode; default strings for emacs and both vi modes are - #defines in this file. prompt_modestr takes an argument in which - it returns the length of the mode string - - expand_prompt: if expanding mode strings in the prompt, get the - mode string to use and add it at the beginning of the prompt string, - before expanding it. This will allow future work allowing the mode - string to contain invisible characters - - 11/15 - ----- -lib/readline/rlprivate.h - - _rl_{emacs,vi_cmd,vi_ins}_mode_str: extern declarations for - variables to hold current values of user-settable mode strings; - variables to hold lengths - -lib/readline/rlconf.h - - defines for default values of the mode strings for each editing mode - and keymap - -lib/readline/display.c - - _rl_{emacs,vi_cmd,vi_ins}_mode_str: new variables to hold values of - user-settable mode strings - - _rl_{emacs,vi_cmd,vi_ins}_modestr_len: new variables to hold lengths - of corresponding mode string variables - - prompt_modestr: return appropriate user-settable mode string - variables - -lib/readline/bind.c - - {emacs,vi-ins,vi-cmd}-mode-string: new user-settable mode string - variables - - sv_{emacs,viins,vicmd}_modestr: variable handling functions for user- - settable mode string variables. Non-null values are run through - rl_translate_keyseq so users can include invisible character - sequences in the mode strings; null values restore the default - - _rl_get_string_variable_value: handle values for new user-settable - mode string variables. Original code contributed by Dylan Cali - - -lib/readline/doc/rluser.texi - - {emacs,vi-ins,vi-cmd}-mode-string: document, including the fact that - you can use \1 and \2 to bracket sequences of non-printing - characters - - 11/16 - ----- -lib/readline/history.c - - add_history: replace loop that copies history list down one item - with call to memmove to take advantage of whatever efficiencies - libc can offer. Won't be any slower than current loop - -lib/readline/display.c - - rl_redraw_prompt_last_line: new function, calls redraw_prompt if - the prompt contains multiple lines; calls rl_forced_update_display - if not - -lib/readline/readline.h - - rl_redraw_prompt_last_line: extern declaration, undocumented in - texinfo manual until I get it a little more work - -bashline.c - - bash_execute_unix_command: instead of unconditionally calling - rl_forced_update_display, call rl_redraw_prompt_last_line if we - cleared the last line before executing the command. This keeps - commands that don't display any other output but just manipulate - the contents of the line buffer from redisplaying the prompt lines - before the last newline multiple times. Fixes bug reported by - Jesper Nygards and Rob Foehl - . This means that commands that display output - will *only* display the final line of the prompt - - bash_execute_unix_command: if the command returns 124, we redraw - the line unconditionally, including all lines of the prompt - - 11/18 - ----- -builtins/mapfile.def - - mapfile_builtin: don't allow a valid array reference through to - mapfile(), since it will just create a shell variable with that name. - Bug and fix from Eduardo A. Bustamante López - - 11/19 - ----- -lib/readline/complete.c - - _rl_colored_completion_prefix: new variable, if non-zero, and color - support is compiled in, and the $LS_COLORS variable exists and - contains color definitions, display any common prefix of a set of - completions in blue when displaying all the possible completions. - Doesn't work with menu-complete, which inserts possible completions - inline - - colored_prefix_start(), colored_prefix_end(): new functions, used to - bracket colored completion prefixes - - fnprint: if prefix_bytes is non-zero, and _rl_colored_completion_prefix - is > 0, display the first PREFIX_BYTES bytes of the word bracketed - by calls to colored_prefix_start and colored_prefix_end - - print_filename: if _rl_colored_completion_prefix is > 0, compute the - length in bytes of the common prefix and pass that to fnprint - -lib/readline/readline.c - - readline_initialize_everything: initialize the colors from $LS_COLORS - if _rl_colored_completion_prefix is non-zero - -lib/readline/colors.c - - _rl_print_prefix_color: new function, changes text color to that - defined for the common prefix of a set of possible completions - (currently cyan, same as directories); currently uses C_PREFIX, - defined in colors.h as C_DIR - -lib/readline/colors.h - - _rl_print_prefix_color: new extern declaration - -lib/readline/bind.c - - colored-completion-prefix: new bindable variable, if set, common - prefix of a set of possible completions is displayed in color. - Feature requested by several, most recently by Richard Neill - (in a slightly different form) and - Duy Nguyen - - 11/20 - ----- -builtins/printf.def - - printf_builtin: allow null (empty) format strings supplied with - -v var to set `var' to the empty string. That is, printf -v var "" - is now the same as var="". Change suggested by Mike Frysinger - - -pathexp.h - - FNMATCH_NOCASEGLOB: macro to decide whether or not to pass - FNM_CASEFOLD flag to strmatch depending on whether glob_ignore_case - is set; analogout to FNMATCH_IGNCASE - -pathexp.c - - glob_name_is_acceptable: use FNMATCH_NOCASEMATCH to determine flags - passed to strmatch; if nocaseglob is used to generate glob matches, - it should be used to generate ignored matches - - 11/21 - ----- -pcomplete.c - - filter_stringlist: the call to strmatch now honors the setting of - nocasematch. Feature request from Ville Skytta - back in 2010 - -doc/bash.1,lib/readline/doc/rluser.texi - - complete -X: document that filtering the list of possible completions - honors the nocasematch option when performing matching - -lib/glob/gmisc.c - - include chartypes.h and strmatch.h for new defines - - match_pattern_{wchar,char}: now take new third FLAGS argument, flags - have same meanings as strmatch(); intent is to handle case - insensitive comparisons under same conditions as strmatch - - FOLD: imported case-folding define from sm_loop.c; wide and single- - byte character versions - - match_pattern_{wchar,char}: use FOLD when comparing characters to - honor FNM_CASEFOLD if set in FLAGS argument - -externs.h - - match_pattern_{wchar,char}: updated extern declarations - -subst.c - - match_{upattern,wpattern}: update strmatch/wcsmatch calls to include - FNMATCH_IGNCASE in flags argument - - match_{upattern,wpattern}: update match_pattern_{char,wchar} calls - to include FNMATCH_IGNCASE in flags argument (consistent with calls - to strmatch). This makes pattern substitution word expansion honor - nocasematch shell option. Feature requested by Davide Baldini - - - match_wpattern: make sure to fold case if necessary when doing simple - matching - -doc/{bash.1,bashref.texi} - - pattern substitution: updated description to include honoring setting - of nocasematch when performing matching - -subst.c - - expand_word_internal: optimize handling of "$@" idiom by calling - list_rest_of_args() and quote_list() directly at the top of the - function instead of going through normal code path - - cached_quoted_dollar_at: WORD_LIST of quoted positional parameters, - used by same code above that optimizes "$@"; if non-null we just - return a copy of the list; if null, we save a copy of the list we - create - - invalidate_cached_quoted_dollar_at: convenience function to allow - other parts of the shell (e.g., remember_args()) to destroy the - cached list of quoted positional parameter when the positional - parameters change - -builtins/common.c - - remember_args: call invalidate_cached_quoted_dollar_at() - -builtins/shift.def - - shift_builtin: call invalidate_cached_quoted_dollar_at after modifying - dollar_vars[] - -builtins/source.def - - maybe_pop_dollar_vars: call invalidate_cached_quoted_dollar_at just - to be safe - - 11/23 - ----- -builtins/evalfile.c - - _evalfile: return -1 if errno == ENOENT and the flags don't include - FEVAL_ENOENTOK. If we print an error message we should return an - error - - force_execute_file: new function, reads and executes commands from - a file but returns an error if file doesn't exist - -builtins/common.h - - force_execute_file: new extern declaration - -shell.c - - main: call start_debugger even if dollar_vars[1] == 0 if the shell - isn't interactive (interactive_shell == 0) - - start_debugger: call force_execute_file instead of maybe_execute_file; - turn off debugging mode if it returns value < 0 - - 11/24 - ----- -hashlib.h - - DEFAULT_HASH_BUCKETS: doubled to 128, cost in memory use is small but - changes traversal order when not sorting results - - 11/25 - ----- -doc/{bash.1,bashref.texi} - - make it clearer, by breaking it out into a separate paragraph, that - referencing an array without a subscript is equivalent to referencing - it with subscript 0 - - add text saying that referencing any variable using a valid subscript - is OK - - 11/28 - ----- - -arrayfunc.c - - bind_array_variable, bind_assoc_variable: allow binding value to a - readonly variable if the ASS_FORCE flag is set in the FLAGS - argument - -subst.h - - ASS_FORCE: new assignment flag; means to allow assignment even if - variable is marked readonly - -builtins/declare.def - - when assigning a value to an array or assoc variable using - something like `declare -r foo=bar' where foo is an existing array - variable, pass the ASS_FORCE to assign_array_var_from_string so - the assignment is allowed. Fixes debian bug 765759 - http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=765759 - -builtins/setattr.def - - var_attribute_string: new function to return (as argument) a char - array with attribute flag values for a given variable; returns the - length of the array - -lib/sh/shquote.c - - sh_quote_reusable: function returning a version of its string - argument that is quoted for reuse - -externs.h - - sh_quote_reusable: extern declaration - -builtins/common.h - - MAX_ATTRIBUTES: define used to size arrays for attribute flag - characters - - var_attribute_string: new extern function declaration - -subst.c - - array_remove_pattern: fixed a bug where `var' instead of `v' was - tested for invisible attribute - - get_var_and_type: fill in a valid *VARP if returning VT_VARIABLE - because callers may need to use it - - parameter_brace_transform: family of functions to implement the new - mksh-inspired ${param@spec} transformation word expansions. Some - of the operators transform the (expanded) value of the parameter, - the rest expand to information about the parameter itself - (array_transform, parameter_list_transform, list_transform, - string_transform, pos_params_assignment, array_var_assignment, - string_var_assignment) - - parameter_brace_expand: changes to parse the new `@' word expansion - operator and call parameter_brace_transform appropriately - - parameter_brace_expand: make sure we handle ${#@} as we have before - even in the presence of the new `@' operator - -variables.c - - push_temp_var: make sure to call bind_variable_internal with the - ASS_FORCE flag so we override readonly variables created with - something like `tempvar=foo declare -r foo'. - - bind_variable_internal: honor ASS_FORCE flag to allow binding even - if a variable is readonly - -execute_cmd.c - - struct func_array_state: new state to save state of BASH_LINENO, - BASH_SOURCE, and FUNCNAME during function execution so it can be - restored on a jump to top level - - restore_funcarray_state: new function to restore func_array_state - - execute_function: fill in func_array_state variable, add unwind- - protect to restore it on jump to top level, call explicitly at - end of function if subshell != 0 (may not be necessary, but safe - for now). Fixes bug with local assignments to FUNCNAME reported - by Arfrever Frehtes Taifersar Arahesis - - 11/29 - ----- -arrayfunc.c - - assign_compound_array_list: turn off ASS_APPEND flag when processing - each individual assignment inside the parens in var+=(...). The - outer += should not affect assignments to existing subscripts; - those should be treated like usual assignments unless += supplied - inside the parens. Bug report from Maarten Billemont - , fix from Eduardo A. Bustamante López - - -config.h.in - - HAVE_PSELECT: define if pselect(2) available - -configure.ac - - check for pselect(2), define HAVE_PSELECT if found - -lib/readline/input.c - - rl_getc: use pselect(2) to wait for input ready on readline's - input fd or for a signal to arrive, will handle SIGWINCH (which - does not interrupt read(2)) and thus allow resize to happen without - having to wait to read more input. Only works if pselect available - and returns -1/EINTR on a signal even if the signal was installed - with SA_RESTART. From a suggestion from Egmont Koblinger - - - 12/3 - ---- -variables.c - - flush_temporary_env: new function, disposes all temp variables in - temporary_env hash table - - bind_variable: only try to update a temporary variable's value in the - temporary env if the value argument is not null. Fixes bug reported - by - -variables.h - - flush_temporary_env: new extern declaration - -subst.c - - command_substitute: if running command substitution as part of - expanding a redirection (expanding_redir == 1), flush any temporary - environment we've inherited as part of this command, since we are not - supposed to have access to the temporary environment. Since - expanding_redir only controls access to the temporary environment for - variable lookup and binding, we can turn it off in the subshell - - 12/4 - ---- -builtins/printf.def - - printstr: make sure a missing precision specifier after a `.' is - treated as 0, as printf(3) specifies. Fixes ubuntu bash bug - 1399087 (https://bugs.launchpad.net/ubuntu/+source/bash/+bug/1399087) - - 12/5 - ---- -subst.c - - skip_to_delim: if scanning past process substitution (skipcmd == 1, - noprocsub == 0), use extract_delimited_string instead of - extract_process_subst, which was changed a while back (bash-4.3.23) - to use xparse_dolparen. xparse_dolparen complains if the command - or process substitution is unterminated, since it runs the parser, - which is not what we want here. Command substitution does the same - thing. Fixes bug reported by Daniel Kahn Gillmor - as Debian bash bug 771968 - (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=771968) - - 12/6 - ---- -subst.c - - command_substitute: short-circuit without forking on a command string - that consists entirely of s and newlines - -jobs.c - - make_child: changes to allow interrupts through if fork fails and - we are sleeping for `forksleep' seconds - - waitchld: make things a little more resilient if CHILD ends up NULL - - 12/12 - ----- -lib/readline/complete.c - - rl_display_match_list: when calculating common prefix to display in - color, make sure we correctly handle a common prefix with a trailing - `/' as we do when checking whether or not to add an ellipis. - printable_part() doesn't return the whole pathname if it ends in a - slash, to avoid printing null strings, so we have to make sure we - have the entire prefix - -lib/readline/complete.c - - _rl_complete_display_matches_interrupt: new variable, set to 1 by - _rl_complete_sigcleanup to let rl_display_match_list know it has - freed the match list - - display_matches: check for signals during the printing loops with - RL_SIG_RECEIVED(), return immediately if there is a pending signal - (might not want to do this if it's SIGWINCH -- CHECK) - - rl_complete_internal: if _rl_complete_display_matches_interrupt - set after calling display_matches, just null out `matches' since - it's already been freed and call any application-set signal hook - - 12/14 - ----- -parse.y - - time_command_acceptable: if the token before a newline is `|', - return 0, since it's not really valid to time inside a pipeline. - Only handles a single newline but allows things like - echo a | - time cat - to invoke /usr/bin/time, which is probably enough to catch the - stray carriage return. Fixes bug reported by Andre Majorel - - -builtins/declare.def - - declare_internal: don't try to perform compound assignments unless - the WORD_DESC has flags including W_COMPASSIGN (maybe should check - W_ASSIGNMENT as well), avoiding unexpected evaluation if a word - is of the form (word) and is assigned to an array variable like so: - declare -x var=$value. Bug reported by Stephane Chazelas - . Will eventually be contingent on - compatibility level > 43, but not there yet. TENTATIVE - - 12/15 - ----- -lib/sh/Makefile.in - - add missing dependencies for shmatch.o. Pointed out by Sergey - Mikhailov - - 12/16 - ----- -{execute_cmd,subst}.c - - W_ASSIGNINT: remove, not used any more - -execute_cmd.c - - fix_assignment_words: don't look for `-i' option and set W_ASSIGNINT - flag any more; doing things a different way - - shell_expand_word_list: instead of using W_ASSIGNINT flag, since it - doesn't take into account all options that can transform values on - assignment (-l/-u/-c can also), go through option arguments looking - for options that need special handling and add them to the `opts' - array for make_internal_declare to use. Fixes bug with constructs - like `declare -al foo=(UPONE UPTWO UPTHREE)' not being lowercased on - assignment reported by Linda Walsh - - - - 12/18 - ----- -lib/readline/readline.c - - rl_internal_char: when we read EOF on a non-empty line, check for - signals and invoke any readline signal handling and any application- - installed signal hook - - 12/20 - ----- -lib/readline/readline.c - - rl_internal_char: if we read EOF on a non-empty line, set c to - _rl_eof_char the first time through. If we read EOF the next time, - return EOF from readline(). If callbacks are defined, this returns - EOF immediately, since lastc isn't available. Fix for problem - most recently identified by Jiri Kukacka , - it has come up in the past - - 12/21 - ----- -builtins/declare.def - - declare_internal: keep track of whether or not an assignment statement - argument to declare is an array subscript assignment; need to - differentiate assignments from straight declarations (declare a[4]) - which are accepted for backwards compatibility - - assignment statements like declare a[2]=foo are now treated as - straight subscript assignment statements if a already exists as an - array variable - - declare foo='(1 2 3)' is treated as an assignment to foo[0] if foo - exists and is an array, just as it would be if it were an assignment - statement and `declare' was not present. All this from a proposal - by Stephane Chazelas - - 12/22 - ----- -builtins/read.def - - read_tty_modified: function to tell the rest of the shell if the - read builtin has modified the tty - - read_builtin: make sure to initialize terminating signals before - installing a SIGALRM signal handler in case we modify the tty as - well as ask for a timeout; the subsequent call to - initialize_terminating_signals would overwrite the read-builtin- - local SIGALRM handler - -builtins/common.h - - read_tty_modified: new extern declaration - -shell.c - - exit_shell: if read_tty_modified() returns true, call read_tty_cleanup - to undo the terminal modifications. Extension of previous fixes; - fixes bug with read -s reported by Richard W. Marsden - - - - 12/23 - ----- -builtins/setattr.def - - show_var_attributes: call print_array_assignment and print_assoc_assignment - with a `not quoted' flag so the assignment statements are not - surrounded by single quotes. Caused changes to a lot of test output - - 12/29 - ----- -lib/readline/complete.c - - stat_char: Windows doesn't handle X_OK flag to access(2); use file - extensions to determine whether or not a file is executable. Bug - report and fix from Eli Zaretskii - -configure.ac - - changed version to bash-4.4-devel - -lib/readline/readline.h - - changed version to readline-6.4 - - 12/30 - ----- -readline.h - - struct readline_state: fix types of `ignorefunc' and `attemptfunc' - members - -lib/sh/shquote.c,externs.h - - sh_contains_shell_metas, sh_contains_quotes: now take `const char *' - as parameter - -stringlib.c,externs.h - - strcreplace: `text' argument now `const char *' - -pathexp.[ch] - - quote_globbing_chars: `string' argument now `const char *', accompanying - changes to function local variables - -pcomplete.c - - preproc_filterpat: `text' argument now `const char *' - - filter_stringlist: `text' argument now `const char *' - - 12/31 - ----- -builtins/evalstring.c - - should_suppress_fork: new function, broke code that decides whether - to turn on CMD_NO_FORK flag out of parse_and_execute into a separate - function - -execute_cmd.c - - execute_command_internal: AND_AND, OR_OR: call should_suppress_fork - for the RHS of && and ||, make `make' invocations marginally more - efficient - -flags.c - - get_current_flags: returns a bitmap of all single-letter shell - options with a non-zero value meaning option is enabled - - set_current_flags: set current single-letter options from a passed - bitmap, which has presumably been initialized with get_current_flags - -flags.h - - {get,set}_current_flags: new extern declarations - -builtins/declare.def - - declare_internal: if invoked as `local', interpret name argument of - `-' to mean to save (and restore at shell return) single-letter - shell options - -variables.c - - push_func_var: if we encounter `-' as the name of a local variable, - take the value and call set_current_flags on it to restore old - flag settings - -builtins/set.def - - get_current_options: returns a bitmap of all shell options settable - with `set', with a non-zero value meaning option is enabled - - set_current_options: set current shell options from a passed - bitmap, which has presumably been initialized with get_current_options - - - 1/1/2015 - -------- -lib/readline/parens.c - - _rl_blink_matching_paren: initialize to 0 whether or not select(2) is - available. Inconsistency reported by Mark Karpov - - -builtins/declare.def - - declare_internal: use get_current_options instead of get_current_flags, - so `local -' can be generalized - -variables.c - - push_func_var: use set_current_options instead of set_current_flags - so `local -' can be generalized - -doc/{bash.1,bashref.texi} - - document new `local -' feature; originally inspired by Robert Elz - describing feature in NetBSD sh - - 1/3 - --- -lib/readline/{complete,funmap,kill,histfile,util} -lib/readline/readline.h -lib/tilde/tilde.c - - fixes for filename- and evironment-related issues on Windows. Fixes - from Eli Zaretskii - - Windows can paste to the console from the clipboard like Cygwin - - Windows uses $APPDATA as a pseudo-$HOME - -lib/readline/input.c - - rl_getc: use _getch on Windows to avoid being overridden by a getch - ncurses function - - win32_isatty: replace Windows isatty(3) with a function that does - additional checks, sinces Windows isatty returns non-zero for - every character device. From Eli Zaretskii - -lib/readline/display.c - - delete_chars: if compiled with ncurses on Windows, this code can - work, so build it in if NCURSES_VERSION defined - - open_some_spaces: ditto - - 1/6 - --- -doc/{bash.1,bashref.texi} - - minor grammar and typo corrections from TonyMc - - 1/8 - --- -sig.c - - throw_to_top_level: only attempt to run the interrupt trap if SIGINT - is trapped -- minor optimization - - throw_to_top_level: if we are running a trap, call run_trap_cleanup - to turn off the sigmodes flags - -trap.c - - _run_trap_internal: temporarily suppress pending SIGINTs while running - one of the traps the shell handles internally (e.g., ERR). Fixes bug - reported by Keith Thompson diff --git a/CWRU/POSIX.NOTES.old b/CWRU/POSIX.NOTES.old deleted file mode 100644 index 1707ab10c..000000000 --- a/CWRU/POSIX.NOTES.old +++ /dev/null @@ -1,82 +0,0 @@ -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 deleted file mode 100644 index 87b78d7cc..000000000 --- a/CWRU/old/set.def.save +++ /dev/null @@ -1,544 +0,0 @@ -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 deleted file mode 100644 index 998fd72b6..000000000 --- a/CWRU/save/unwind_prot.h.save +++ /dev/null @@ -1,50 +0,0 @@ -/* 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/bashhist.c~ b/bashhist.c~ deleted file mode 100644 index c68dcd3b5..000000000 --- a/bashhist.c~ +++ /dev/null @@ -1,945 +0,0 @@ -/* bashhist.c -- bash interface to the GNU history library. */ - -/* Copyright (C) 1993-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" - -#if defined (HISTORY) - -#if defined (HAVE_UNISTD_H) -# ifdef _MINIX - # include -# endif -# include -#endif - -#include "bashtypes.h" -#include -#include -#include "bashansi.h" -#include "posixstat.h" -#include "filecntl.h" - -#include "bashintl.h" - -#if defined (SYSLOG_HISTORY) -# include -#endif - -#include "shell.h" -#include "flags.h" -#include "input.h" -#include "parser.h" /* for the struct dstack stuff. */ -#include "pathexp.h" /* for the struct ignorevar stuff */ -#include "bashhist.h" /* matching prototypes and declarations */ -#include "builtins/common.h" - -#include -#include -#include - -#if defined (READLINE) -# include "bashline.h" -extern int rl_done, rl_dispatching; /* should really include readline.h */ -#endif - -#if !defined (errno) -extern int errno; -#endif - -static int histignore_item_func __P((struct ign *)); -static int check_history_control __P((char *)); -static void hc_erasedups __P((char *)); -static void really_add_history __P((char *)); - -static struct ignorevar histignore = -{ - "HISTIGNORE", - (struct ign *)0, - 0, - (char *)0, - (sh_iv_item_func_t *)histignore_item_func, -}; - -#define HIGN_EXPAND 0x01 - -/* Declarations of bash history variables. */ -/* Non-zero means to remember lines typed to the shell on the history - list. This is different than the user-controlled behaviour; this - becomes zero when we read lines from a file, for example. */ -int remember_on_history = 1; -int enable_history_list = 1; /* value for `set -o history' */ - -/* The number of lines that Bash has added to this history session. The - difference between the number of the top element in the history list - (offset from history_base) and the number of lines in the history file. - Appending this session's history to the history file resets this to 0. */ -int history_lines_this_session; - -/* The number of lines that Bash has read from the history file. */ -int history_lines_in_file; - -#if defined (BANG_HISTORY) -/* Non-zero means do no history expansion on this line, regardless - of what history_expansion says. */ -int history_expansion_inhibited; -#endif - -/* With the old default, every line was saved in the history individually. - I.e., if the user enters: - bash$ for i in a b c - > do - > echo $i - > done - Each line will be individually saved in the history. - bash$ history - 10 for i in a b c - 11 do - 12 echo $i - 13 done - 14 history - If the variable command_oriented_history is set, multiple lines - which form one command will be saved as one history entry. - bash$ for i in a b c - > do - > echo $i - > done - bash$ history - 10 for i in a b c - do - echo $i - done - 11 history - The user can then recall the whole command all at once instead - of just being able to recall one line at a time. - - This is now enabled by default. - */ -int command_oriented_history = 1; - -/* Set to 1 if the first line of a possibly-multi-line command was saved - in the history list. Managed by maybe_add_history(), but global so - the history-manipluating builtins can see it. */ -int current_command_first_line_saved = 0; - -/* Non-zero means to store newlines in the history list when using - command_oriented_history rather than trying to use semicolons. */ -int literal_history; - -/* Non-zero means to append the history to the history file at shell - exit, even if the history has been stifled. */ -int force_append_history; - -/* A nit for picking at history saving. Flags have the following values: - - Value == 0 means save all lines parsed by the shell on the history. - Value & HC_IGNSPACE means save all lines that do not start with a space. - Value & HC_IGNDUPS means save all lines that do not match the last - line saved. - Value & HC_ERASEDUPS means to remove all other matching lines from the - history list before saving the latest line. */ -int history_control; - -/* Set to 1 if the last command was added to the history list successfully - as a separate history entry; set to 0 if the line was ignored or added - to a previous entry as part of command-oriented-history processing. */ -int hist_last_line_added; - -/* Set to 1 if builtins/history.def:push_history added the last history - entry. */ -int hist_last_line_pushed; - -#if defined (READLINE) -/* If non-zero, and readline is being used, the user is offered the - chance to re-edit a failed history expansion. */ -int history_reediting; - -/* If non-zero, and readline is being used, don't directly execute a - line with history substitution. Reload it into the editing buffer - instead and let the user further edit and confirm with a newline. */ -int hist_verify; - -#endif /* READLINE */ - -/* Non-zero means to not save function definitions in the history list. */ -int dont_save_function_defs; - -/* Variables declared in other files used here. */ -extern int current_command_line_count; - -extern struct dstack dstack; -extern int parser_state; - -static int bash_history_inhibit_expansion __P((char *, int)); -#if defined (READLINE) -static void re_edit __P((char *)); -#endif -static int history_expansion_p __P((char *)); -static int shell_comment __P((char *)); -static int should_expand __P((char *)); -static HIST_ENTRY *last_history_entry __P((void)); -static char *expand_histignore_pattern __P((char *)); -static int history_should_ignore __P((char *)); - -/* Is the history expansion starting at string[i] one that should not - be expanded? */ -static int -bash_history_inhibit_expansion (string, i) - char *string; - int i; -{ - int t; - char hx[2]; - - hx[0] = history_expansion_char; - hx[1] = '\0'; - - /* The shell uses ! as a pattern negation character in globbing [...] - expressions, so let those pass without expansion. */ - if (i > 0 && (string[i - 1] == '[') && member (']', string + i + 1)) - return (1); - /* The shell uses ! as the indirect expansion character, so let those - expansions pass as well. */ - else if (i > 1 && string[i - 1] == '{' && string[i - 2] == '$' && - member ('}', string + i + 1)) - return (1); - /* The shell uses $! as a defined parameter expansion. */ - else if (i > 1 && string[i - 1] == '$' && string[i] == '!') - return (1); -#if defined (EXTENDED_GLOB) - else if (extended_glob && i > 1 && string[i+1] == '(' && member (')', string + i + 2)) - return (1); -#endif - /* Make sure the history expansion should not be skipped by quoting or - command/process substitution. */ - else if (te = skip_to_delim (string, 0, hx, SD_NOJMP) > 0 && te > i) - return (1); - else - return (0); -} - -void -bash_initialize_history () -{ - history_quotes_inhibit_expansion = 1; - history_search_delimiter_chars = ";&()|<>"; - history_inhibit_expansion_function = bash_history_inhibit_expansion; -#if defined (BANG_HISTORY) - sv_histchars ("histchars"); -#endif -} - -void -bash_history_reinit (interact) - int interact; -{ -#if defined (BANG_HISTORY) - history_expansion = interact != 0; - history_expansion_inhibited = 1; -#endif - remember_on_history = enable_history_list = interact != 0; - history_inhibit_expansion_function = bash_history_inhibit_expansion; -} - -void -bash_history_disable () -{ - remember_on_history = 0; -#if defined (BANG_HISTORY) - history_expansion_inhibited = 1; -#endif -} - -void -bash_history_enable () -{ - remember_on_history = 1; -#if defined (BANG_HISTORY) - history_expansion_inhibited = 0; -#endif - history_inhibit_expansion_function = bash_history_inhibit_expansion; - sv_history_control ("HISTCONTROL"); - sv_histignore ("HISTIGNORE"); -} - -/* Load the history list from the history file. */ -void -load_history () -{ - char *hf; - - /* Truncate history file for interactive shells which desire it. - Note that the history file is automatically truncated to the - size of HISTSIZE if the user does not explicitly set the size - differently. */ - set_if_not ("HISTSIZE", "500"); - sv_histsize ("HISTSIZE"); - - set_if_not ("HISTFILESIZE", get_string_value ("HISTSIZE")); - sv_histsize ("HISTFILESIZE"); - - /* Read the history in HISTFILE into the history list. */ - hf = get_string_value ("HISTFILE"); - - if (hf && *hf && file_exists (hf)) - { - read_history (hf); - /* We have read all of the lines from the history file, even if we - read more lines than $HISTSIZE. Remember the total number of lines - we read so we don't count the last N lines as new over and over - again. */ - history_lines_in_file = history_lines_read_from_file; - using_history (); - /* history_lines_in_file = where_history () + history_base - 1; */ - } -} - -void -bash_clear_history () -{ - clear_history (); - history_lines_this_session = 0; -} - -/* Delete and free the history list entry at offset I. */ -int -bash_delete_histent (i) - int i; -{ - HIST_ENTRY *discard; - - discard = remove_history (i); - if (discard) - free_history_entry (discard); - history_lines_this_session--; - - return 1; -} - -int -bash_delete_last_history () -{ - register int i; - HIST_ENTRY **hlist, *histent; - int r; - - hlist = history_list (); - if (hlist == NULL) - return 0; - - for (i = 0; hlist[i]; i++) - ; - i--; - - /* History_get () takes a parameter that must be offset by history_base. */ - histent = history_get (history_base + i); /* Don't free this */ - if (histent == NULL) - return 0; - - r = bash_delete_histent (i); - - if (where_history () > history_length) - history_set_pos (history_length); - - return r; -} - -#ifdef INCLUDE_UNUSED -/* Write the existing history out to the history file. */ -void -save_history () -{ - char *hf; - int r; - - hf = get_string_value ("HISTFILE"); - if (hf && *hf && file_exists (hf)) - { - /* Append only the lines that occurred this session to - the history file. */ - using_history (); - - if (history_lines_this_session <= where_history () || force_append_history) - r = append_history (history_lines_this_session, hf); - else - r = write_history (hf); - sv_histsize ("HISTFILESIZE"); - } -} -#endif - -int -maybe_append_history (filename) - char *filename; -{ - int fd, result; - struct stat buf; - - result = EXECUTION_SUCCESS; - if (history_lines_this_session > 0 && (history_lines_this_session <= where_history ())) - { - /* If the filename was supplied, then create it if necessary. */ - if (stat (filename, &buf) == -1 && errno == ENOENT) - { - fd = open (filename, O_WRONLY|O_CREAT, 0600); - if (fd < 0) - { - builtin_error (_("%s: cannot create: %s"), filename, strerror (errno)); - return (EXECUTION_FAILURE); - } - close (fd); - } - result = append_history (history_lines_this_session, filename); - /* Pretend we already read these lines from the file because we just - added them */ - history_lines_in_file += history_lines_this_session; - history_lines_this_session = 0; - } - else - history_lines_this_session = 0; /* reset if > where_history() */ - - return (result); -} - -/* If this is an interactive shell, then append the lines executed - this session to the history file. */ -int -maybe_save_shell_history () -{ - int result; - char *hf; - - result = 0; - if (history_lines_this_session > 0) - { - hf = get_string_value ("HISTFILE"); - - if (hf && *hf) - { - /* If the file doesn't exist, then create it. */ - if (file_exists (hf) == 0) - { - int file; - file = open (hf, O_CREAT | O_TRUNC | O_WRONLY, 0600); - if (file != -1) - close (file); - } - - /* Now actually append the lines if the history hasn't been - stifled. If the history has been stifled, rewrite the - history file. */ - using_history (); - if (history_lines_this_session <= where_history () || force_append_history) - { - result = append_history (history_lines_this_session, hf); - history_lines_in_file += history_lines_this_session; - } - else - { - result = write_history (hf); - history_lines_in_file = history_lines_written_to_file; - /* history_lines_in_file = where_history () + history_base - 1; */ - } - history_lines_this_session = 0; - - sv_histsize ("HISTFILESIZE"); - } - } - return (result); -} - -#if defined (READLINE) -/* Tell readline () that we have some text for it to edit. */ -static void -re_edit (text) - char *text; -{ - if (bash_input.type == st_stdin) - bash_re_edit (text); -} -#endif /* READLINE */ - -/* Return 1 if this line needs history expansion. */ -static int -history_expansion_p (line) - char *line; -{ - register char *s; - - for (s = line; *s; s++) - if (*s == history_expansion_char || *s == history_subst_char) - return 1; - return 0; -} - -/* Do pre-processing on LINE. If PRINT_CHANGES is non-zero, then - print the results of expanding the line if there were any changes. - If there is an error, return NULL, otherwise the expanded line is - returned. If ADDIT is non-zero the line is added to the history - list after history expansion. ADDIT is just a suggestion; - REMEMBER_ON_HISTORY can veto, and does. - Right now this does history expansion. */ -char * -pre_process_line (line, print_changes, addit) - char *line; - int print_changes, addit; -{ - char *history_value; - char *return_value; - int expanded; - - return_value = line; - expanded = 0; - -# if defined (BANG_HISTORY) - /* History expand the line. If this results in no errors, then - add that line to the history if ADDIT is non-zero. */ - if (!history_expansion_inhibited && history_expansion && history_expansion_p (line)) - { - expanded = history_expand (line, &history_value); - - if (expanded) - { - if (print_changes) - { - if (expanded < 0) - internal_error ("%s", history_value); -#if defined (READLINE) - else if (hist_verify == 0 || expanded == 2) -#else - else -#endif - fprintf (stderr, "%s\n", history_value); - } - - /* If there was an error, return NULL. */ - if (expanded < 0 || expanded == 2) /* 2 == print only */ - { -# if defined (READLINE) - if (expanded == 2 && rl_dispatching == 0 && *history_value) -# else - if (expanded == 2 && *history_value) -# endif /* !READLINE */ - maybe_add_history (history_value); - - free (history_value); - -# if defined (READLINE) - /* New hack. We can allow the user to edit the - failed history expansion. */ - if (history_reediting && expanded < 0 && rl_done) - re_edit (line); -# endif /* READLINE */ - return ((char *)NULL); - } - -# if defined (READLINE) - if (hist_verify && expanded == 1) - { - re_edit (history_value); - free (history_value); - return ((char *)NULL); - } -# endif - } - - /* Let other expansions know that return_value can be free'ed, - and that a line has been added to the history list. Note - that we only add lines that have something in them. */ - expanded = 1; - return_value = history_value; - } -# endif /* BANG_HISTORY */ - - if (addit && remember_on_history && *return_value) - maybe_add_history (return_value); - -#if 0 - if (expanded == 0) - return_value = savestring (line); -#endif - - return (return_value); -} - -/* Return 1 if the first non-whitespace character in LINE is a `#', indicating - * that the line is a shell comment. */ -static int -shell_comment (line) - char *line; -{ - char *p; - - for (p = line; p && *p && whitespace (*p); p++) - ; - return (p && *p == '#'); -} - -#ifdef INCLUDE_UNUSED -/* Remove shell comments from LINE. A `#' and anything after it is a comment. - This isn't really useful yet, since it doesn't handle quoting. */ -static char * -filter_comments (line) - char *line; -{ - char *p; - - for (p = line; p && *p && *p != '#'; p++) - ; - if (p && *p == '#') - *p = '\0'; - return (line); -} -#endif - -/* Check LINE against what HISTCONTROL says to do. Returns 1 if the line - should be saved; 0 if it should be discarded. */ -static int -check_history_control (line) - char *line; -{ - HIST_ENTRY *temp; - int r; - - if (history_control == 0) - return 1; - - /* ignorespace or ignoreboth */ - if ((history_control & HC_IGNSPACE) && *line == ' ') - return 0; - - /* ignoredups or ignoreboth */ - if (history_control & HC_IGNDUPS) - { - using_history (); - temp = previous_history (); - - r = (temp == 0 || STREQ (temp->line, line) == 0); - - using_history (); - - if (r == 0) - return r; - } - - return 1; -} - -/* Remove all entries matching LINE from the history list. Triggered when - HISTCONTROL includes `erasedups'. */ -static void -hc_erasedups (line) - char *line; -{ - HIST_ENTRY *temp; - int r; - - using_history (); - while (temp = previous_history ()) - { - if (STREQ (temp->line, line)) - { - r = where_history (); - remove_history (r); - } - } - using_history (); -} - -/* Add LINE to the history list, handling possibly multi-line compound - commands. We note whether or not we save the first line of each command - (which is usually the entire command and history entry), and don't add - the second and subsequent lines of a multi-line compound command if we - didn't save the first line. We don't usually save shell comment lines in - compound commands in the history, because they could have the effect of - commenting out the rest of the command when the entire command is saved as - a single history entry (when COMMAND_ORIENTED_HISTORY is enabled). If - LITERAL_HISTORY is set, we're saving lines in the history with embedded - newlines, so it's OK to save comment lines. If we're collecting the body - of a here-document, we should act as if literal_history is enabled, because - we want to save the entire contents of the here-document as it was - entered. We also make sure to save multiple-line quoted strings or other - constructs. */ -void -maybe_add_history (line) - char *line; -{ - hist_last_line_added = 0; - - /* Don't use the value of history_control to affect the second - and subsequent lines of a multi-line command (old code did - this only when command_oriented_history is enabled). */ - if (current_command_line_count > 1) - { - if (current_command_first_line_saved && - ((parser_state & PST_HEREDOC) || literal_history || dstack.delimiter_depth != 0 || shell_comment (line) == 0)) - bash_add_history (line); - return; - } - - /* This is the first line of a (possible multi-line) command. Note whether - or not we should save the first line and remember it. */ - current_command_first_line_saved = check_add_history (line, 0); -} - -/* Just check LINE against HISTCONTROL and HISTIGNORE and add it to the - history if it's OK. Used by `history -s' as well as maybe_add_history(). - Returns 1 if the line was saved in the history, 0 otherwise. */ -int -check_add_history (line, force) - char *line; - int force; -{ - if (check_history_control (line) && history_should_ignore (line) == 0) - { - /* We're committed to saving the line. If the user has requested it, - remove other matching lines from the history. */ - if (history_control & HC_ERASEDUPS) - hc_erasedups (line); - - if (force) - { - really_add_history (line); - using_history (); - } - else - bash_add_history (line); - return 1; - } - return 0; -} - -#if defined (SYSLOG_HISTORY) -#define SYSLOG_MAXLEN 600 - -void -bash_syslog_history (line) - const char *line; -{ - char trunc[SYSLOG_MAXLEN]; - - if (strlen(line) < SYSLOG_MAXLEN) - syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d UID=%d %s", getpid(), current_user.uid, line); - else - { - strncpy (trunc, line, SYSLOG_MAXLEN); - trunc[SYSLOG_MAXLEN - 1] = '\0'; - syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d UID=%d %s", getpid(), current_user.uid, trunc); - } -} -#endif - -/* Add a line to the history list. - The variable COMMAND_ORIENTED_HISTORY controls the style of history - remembering; when non-zero, and LINE is not the first line of a - complete parser construct, append LINE to the last history line instead - of adding it as a new line. */ -void -bash_add_history (line) - char *line; -{ - int add_it, offset, curlen; - HIST_ENTRY *current, *old; - char *chars_to_add, *new_line; - - add_it = 1; - if (command_oriented_history && current_command_line_count > 1) - { - /* The second and subsequent lines of a here document have the trailing - newline preserved. We don't want to add extra newlines here, but we - do want to add one after the first line (which is the command that - contains the here-doc specifier). parse.y:history_delimiting_chars() - does the right thing to take care of this for us. We don't want to - add extra newlines if the user chooses to enable literal_history, - so we have to duplicate some of what that function does here. */ - if ((parser_state & PST_HEREDOC) && literal_history && current_command_line_count > 2 && line[strlen (line) - 1] == '\n') - chars_to_add = ""; - else - chars_to_add = literal_history ? "\n" : history_delimiting_chars (line); - - using_history (); - current = previous_history (); - - if (current) - { - /* If the previous line ended with an escaped newline (escaped - with backslash, but otherwise unquoted), then remove the quoted - newline, since that is what happens when the line is parsed. */ - curlen = strlen (current->line); - - if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\\' && - current->line[curlen - 2] != '\\') - { - current->line[curlen - 1] = '\0'; - curlen--; - chars_to_add = ""; - } - - /* If we're not in some kind of quoted construct, the current history - entry ends with a newline, and we're going to add a semicolon, - don't. In some cases, it results in a syntax error (e.g., before - a close brace), and it should not be needed. */ - if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\n' && *chars_to_add == ';') - chars_to_add++; - - new_line = (char *)xmalloc (1 - + curlen - + strlen (line) - + strlen (chars_to_add)); - sprintf (new_line, "%s%s%s", current->line, chars_to_add, line); - offset = where_history (); - old = replace_history_entry (offset, new_line, current->data); - free (new_line); - - if (old) - free_history_entry (old); - - add_it = 0; - } - } - - if (add_it) - really_add_history (line); - -#if defined (SYSLOG_HISTORY) - bash_syslog_history (line); -#endif - - using_history (); -} - -static void -really_add_history (line) - char *line; -{ - hist_last_line_added = 1; - hist_last_line_pushed = 0; - add_history (line); - history_lines_this_session++; -} - -int -history_number () -{ - using_history (); - return (remember_on_history ? history_base + where_history () : 1); -} - -static int -should_expand (s) - char *s; -{ - char *p; - - for (p = s; p && *p; p++) - { - if (*p == '\\') - p++; - else if (*p == '&') - return 1; - } - return 0; -} - -static int -histignore_item_func (ign) - struct ign *ign; -{ - if (should_expand (ign->val)) - ign->flags |= HIGN_EXPAND; - return (0); -} - -void -setup_history_ignore (varname) - char *varname; -{ - setup_ignore_patterns (&histignore); -} - -static HIST_ENTRY * -last_history_entry () -{ - HIST_ENTRY *he; - - using_history (); - he = previous_history (); - using_history (); - return he; -} - -char * -last_history_line () -{ - HIST_ENTRY *he; - - he = last_history_entry (); - if (he == 0) - return ((char *)NULL); - return he->line; -} - -static char * -expand_histignore_pattern (pat) - char *pat; -{ - HIST_ENTRY *phe; - char *ret; - - phe = last_history_entry (); - - if (phe == (HIST_ENTRY *)0) - return (savestring (pat)); - - ret = strcreplace (pat, '&', phe->line, 1); - - return ret; -} - -/* Return 1 if we should not put LINE into the history according to the - patterns in HISTIGNORE. */ -static int -history_should_ignore (line) - char *line; -{ - register int i, match; - char *npat; - - if (histignore.num_ignores == 0) - return 0; - - for (i = match = 0; i < histignore.num_ignores; i++) - { - if (histignore.ignores[i].flags & HIGN_EXPAND) - npat = expand_histignore_pattern (histignore.ignores[i].val); - else - npat = histignore.ignores[i].val; - - match = strmatch (npat, line, FNMATCH_EXTFLAG) != FNM_NOMATCH; - - if (histignore.ignores[i].flags & HIGN_EXPAND) - free (npat); - - if (match) - break; - } - - return match; -} -#endif /* HISTORY */ diff --git a/builtins/declare.def~ b/builtins/declare.def~ deleted file mode 100644 index 2fde562f8..000000000 --- a/builtins/declare.def~ +++ /dev/null @@ -1,726 +0,0 @@ -This file is declare.def, from which is created declare.c. -It implements the builtins "declare" and "local" in Bash. - -Copyright (C) 1987-2015 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 . - -$PRODUCES declare.c - -$BUILTIN declare -$FUNCTION declare_builtin -$SHORT_DOC declare [-aAfFgilnrtux] [-p] [name[=value] ...] -Set variable values and attributes. - -Declare variables and give them attributes. If no NAMEs are given, -display the attributes and values of all variables. - -Options: - -f restrict action or display to function names and definitions - -F restrict display to function names only (plus line number and - source file when debugging) - -g create global variables when used in a shell function; otherwise - ignored - -p display the attributes and value of each NAME - -Options which set attributes: - -a to make NAMEs indexed arrays (if supported) - -A to make NAMEs associative arrays (if supported) - -i to make NAMEs have the `integer' attribute - -l to convert NAMEs to lower case on assignment - -n make NAME a reference to the variable named by its value - -r to make NAMEs readonly - -t to make NAMEs have the `trace' attribute - -u to convert NAMEs to upper case on assignment - -x to make NAMEs export - -Using `+' instead of `-' turns off the given attribute. - -Variables with the integer attribute have arithmetic evaluation (see -the `let' command) performed when the variable is assigned a value. - -When used in a function, `declare' makes NAMEs local, as with the `local' -command. The `-g' option suppresses this behavior. - -Exit Status: -Returns success unless an invalid option is supplied or a variable -assignment error occurs. -$END - -$BUILTIN typeset -$FUNCTION declare_builtin -$SHORT_DOC typeset [-aAfFgilrtux] [-p] name[=value] ... -Set variable values and attributes. - -Obsolete. See `help declare'. -$END - -#include - -#if defined (HAVE_UNISTD_H) -# ifdef _MINIX -# include -# endif -# include -#endif - -#include - -#include "../bashansi.h" -#include "../bashintl.h" - -#include "../shell.h" -#include "../flags.h" -#include "common.h" -#include "builtext.h" -#include "bashgetopt.h" - -extern int array_needs_making; -extern int posixly_correct; - -static int declare_internal __P((register WORD_LIST *, int)); - -/* Declare or change variable attributes. */ -int -declare_builtin (list) - register WORD_LIST *list; -{ - return (declare_internal (list, 0)); -} - -$BUILTIN local -$FUNCTION local_builtin -$SHORT_DOC local [option] name[=value] ... -Define local variables. - -Create a local variable called NAME, and give it VALUE. OPTION can -be any option accepted by `declare'. - -Local variables can only be used within a function; they are visible -only to the function where they are defined and its children. - -Exit Status: -Returns success unless an invalid option is supplied, a variable -assignment error occurs, or the shell is not executing a function. -$END -int -local_builtin (list) - register WORD_LIST *list; -{ - if (variable_context) - return (declare_internal (list, 1)); - else - { - builtin_error (_("can only be used in a function")); - return (EXECUTION_FAILURE); - } -} - -#if defined (ARRAY_VARS) -# define DECLARE_OPTS "+acfgilnprtuxAF" -#else -# define DECLARE_OPTS "+cfgilnprtuxF" -#endif - -/* The workhorse function. */ -static int -declare_internal (list, local_var) - register WORD_LIST *list; - int local_var; -{ - int flags_on, flags_off, *flags; - int any_failed, assign_error, pflag, nodefs, opt, mkglobal, onref, offref; - char *t, *subscript_start; - SHELL_VAR *var, *refvar, *v; - FUNCTION_DEF *shell_fn; - - flags_on = flags_off = any_failed = assign_error = pflag = nodefs = mkglobal = 0; - refvar = (SHELL_VAR *)NULL; - reset_internal_getopt (); - while ((opt = internal_getopt (list, DECLARE_OPTS)) != -1) - { - flags = list_opttype == '+' ? &flags_off : &flags_on; - - /* If you add options here, see whether or not they need to be added to - the loop in subst.c:shell_expand_word_list() */ - switch (opt) - { - case 'a': -#if defined (ARRAY_VARS) - *flags |= att_array; - break; -#else - builtin_usage (); - return (EX_USAGE); -#endif - case 'A': -#if defined (ARRAY_VARS) - *flags |= att_assoc; - break; -#else - builtin_usage (); - return (EX_USAGE); -#endif - case 'p': - if (local_var == 0) - pflag++; - break; - case 'F': - nodefs++; - *flags |= att_function; - break; - case 'f': - *flags |= att_function; - break; - case 'g': - if (flags == &flags_on) - mkglobal = 1; - break; - case 'i': - *flags |= att_integer; - break; - case 'n': - *flags |= att_nameref; - break; - case 'r': - *flags |= att_readonly; - break; - case 't': - *flags |= att_trace; - break; - case 'x': - *flags |= att_exported; - array_needs_making = 1; - break; -#if defined (CASEMOD_ATTRS) -# if defined (CASEMOD_CAPCASE) - case 'c': - *flags |= att_capcase; - if (flags == &flags_on) - flags_off |= att_uppercase|att_lowercase; - break; -# endif - case 'l': - *flags |= att_lowercase; - if (flags == &flags_on) - flags_off |= att_capcase|att_uppercase; - break; - case 'u': - *flags |= att_uppercase; - if (flags == &flags_on) - flags_off |= att_capcase|att_lowercase; - break; -#endif /* CASEMOD_ATTRS */ - default: - builtin_usage (); - return (EX_USAGE); - } - } - - list = loptend; - - /* If there are no more arguments left, then we just want to show - some variables. */ - if (list == 0) /* declare -[aAfFirtx] */ - { - /* Show local variables defined at this context level if this is - the `local' builtin. */ - if (local_var) - { - register SHELL_VAR **vlist; - register int i; - - vlist = all_local_variables (); - - if (vlist) - { - for (i = 0; vlist[i]; i++) - print_assignment (vlist[i]); - - free (vlist); - } - } - else if (pflag && (flags_on == 0 || flags_on == att_function)) - show_all_var_attributes (flags_on == 0, nodefs); - else if (flags_on == 0) - return (set_builtin ((WORD_LIST *)NULL)); - else - set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs); - - return (sh_chkwrite (EXECUTION_SUCCESS)); - } - - if (pflag) /* declare -p [-aAfFirtx] name [name...] */ - { - for (any_failed = 0; list; list = list->next) - { - if (flags_on & att_function) - pflag = show_func_attributes (list->word->word, nodefs); - else - pflag = show_name_attributes (list->word->word, nodefs); - if (pflag) - { - sh_notfound (list->word->word); - any_failed++; - } - } - return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS)); - } - -#define NEXT_VARIABLE() free (name); list = list->next; continue - - /* There are arguments left, so we are making variables. */ - while (list) /* declare [-aAfFirx] name [name ...] */ - { - char *value, *name; - int offset, aflags, wflags; -#if defined (ARRAY_VARS) - int making_array_special, compound_array_assign, simple_array_assign; - int var_exists, array_exists, array_subscript_assignment; -#endif - - name = savestring (list->word->word); - wflags = list->word->flags; - offset = assignment (name, 0); - aflags = 0; - - if (local_var && variable_context && STREQ (name, "-")) - { - var = make_local_variable ("-"); - FREE (value_cell (var)); /* just in case */ - value = get_current_options (); - var_setvalue (var, value); - VSETATTR (var, att_invisible); - NEXT_VARIABLE (); - } - - if (offset) /* declare [-aAfFirx] name=value */ - { - name[offset] = '\0'; - value = name + offset + 1; - if (name[offset - 1] == '+') - { - aflags |= ASS_APPEND; - name[offset - 1] = '\0'; - } - } - else - value = ""; - - /* Do some lexical error checking on the LHS and RHS of the assignment - that is specific to nameref variables. */ - if (flags_on & att_nameref) - { -#if defined (ARRAY_VARIABLES) - if (valid_array_reference (name)) - { - builtin_error (_("%s: reference variable cannot be an array"), name); - assign_error++; - NEXT_VARIABLE (); - } - else -#endif - /* disallow self references at global scope */ - if (STREQ (name, value) && variable_context == 0) - { - builtin_error (_("%s: nameref variable self references not allowed"), name); - assign_error++; - NEXT_VARIABLE (); - } - } - -#if defined (ARRAY_VARS) - var_exists = array_exists = 0; - compound_array_assign = simple_array_assign = 0; - array_subscript_assignment = 0; - subscript_start = (char *)NULL; - if (t = strchr (name, '[')) /* ] */ - { - /* If offset != 0 we have already validated any array reference */ - if (offset == 0 && valid_array_reference (name) == 0) - { - sh_invalidid (name); - assign_error++; - NEXT_VARIABLE (); - } - subscript_start = t; - *t = '\0'; - making_array_special = 1; /* XXX - should this check offset? */ - array_subscript_assignment = offset != 0; - } - else - making_array_special = 0; -#endif - - /* If we're in posix mode or not looking for a shell function (since - shell function names don't have to be valid identifiers when the - shell's not in posix mode), check whether or not the argument is a - valid, well-formed shell identifier. */ - if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0) - { - sh_invalidid (name); - assign_error++; - NEXT_VARIABLE (); - } - - /* If VARIABLE_CONTEXT has a non-zero value, then we are executing - inside of a function. This means we should make local variables, - not global ones. */ - - /* XXX - this has consequences when we're making a local copy of a - variable that was in the temporary environment. Watch out - for this. */ - refvar = (SHELL_VAR *)NULL; - if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0)) - { -#if defined (ARRAY_VARS) - if (flags_on & att_assoc) - var = make_local_assoc_variable (name); - else if ((flags_on & att_array) || making_array_special) - var = make_local_array_variable (name, making_array_special); - else -#endif - var = make_local_variable (name); /* sets att_invisible for new vars */ - if (var == 0) - { - any_failed++; - NEXT_VARIABLE (); - } - } - else - var = (SHELL_VAR *)NULL; - - /* If we are declaring a function, then complain about it in some way. - We don't let people make functions by saying `typeset -f foo=bar'. */ - - /* There should be a way, however, to let people look at a particular - function definition by saying `typeset -f foo'. */ - - if (flags_on & att_function) - { - if (offset) /* declare -f [-rix] foo=bar */ - { - builtin_error (_("cannot use `-f' to make functions")); - free (name); - return (EXECUTION_FAILURE); - } - else /* declare -f [-rx] name [name...] */ - { - var = find_function (name); - - if (var) - { - if (readonly_p (var) && (flags_off & att_readonly)) - { - builtin_error (_("%s: readonly function"), name); - any_failed++; - NEXT_VARIABLE (); - } - - /* declare -[Ff] name [name...] */ - if (flags_on == att_function && flags_off == 0) - { -#if defined (DEBUGGER) - if (nodefs && debugging_mode) - { - shell_fn = find_function_def (var->name); - if (shell_fn) - printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file); - else - printf ("%s\n", var->name); - } - else -#endif /* DEBUGGER */ - { - t = nodefs ? var->name - : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL); - printf ("%s\n", t); - any_failed = sh_chkwrite (any_failed); - } - } - else /* declare -[fF] -[rx] name [name...] */ - { - VSETATTR (var, flags_on); - VUNSETATTR (var, flags_off); - } - } - else - any_failed++; - NEXT_VARIABLE (); - } - } - else /* declare -[aAirx] name [name...] */ - { - /* Non-null if we just created or fetched a local variable. */ - /* Here's what ksh93 seems to do. If we are modifying an existing - nameref variable, we don't follow the nameref chain past the last - nameref, and we set the nameref variable's value so future - references to that variable will return the value of the variable - we're assigning right now. */ - if (var == 0 && (flags_on & att_nameref)) - { - /* See if we are trying to modify an existing nameref variable */ - var = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name); - if (var && nameref_p (var) == 0) - var = 0; - } - /* However, if we're turning off the nameref attribute on an existing - nameref variable, we first follow the nameref chain to the end, - modify the value of the variable this nameref variable references, - *CHANGING ITS VALUE AS A SIDE EFFECT* then turn off the nameref - flag *LEAVING THE NAMEREF VARIABLE'S VALUE UNCHANGED* */ - else if (var == 0 && (flags_off & att_nameref)) - { - /* See if we are trying to modify an existing nameref variable */ - refvar = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name); - if (refvar && nameref_p (refvar) == 0) - refvar = 0; - if (refvar) - var = mkglobal ? find_global_variable (nameref_cell (refvar)) : find_variable (nameref_cell (refvar)); - } - - if (var == 0) - var = mkglobal ? find_global_variable (name) : find_variable (name); - - var_exists = var != 0; - array_exists = var && (array_p (var) || assoc_p (var)); - - if (var == 0) - { -#if defined (ARRAY_VARS) - if (flags_on & att_assoc) - { - var = make_new_assoc_variable (name); - if (offset == 0 && no_invisible_vars == 0) - VSETATTR (var, att_invisible); - } - else if ((flags_on & att_array) || making_array_special) - { - var = make_new_array_variable (name); - if (offset == 0 && no_invisible_vars == 0) - VSETATTR (var, att_invisible); - } - else -#endif - if (offset) - var = mkglobal ? bind_global_variable (name, "", 0) : bind_variable (name, "", 0); - else - { - var = mkglobal ? bind_global_variable (name, (char *)NULL, 0) : bind_variable (name, (char *)NULL, 0); - if (no_invisible_vars == 0) - VSETATTR (var, att_invisible); - } - } - /* Can't take an existing array variable and make it a nameref */ - else if ((array_p (var) || assoc_p (var)) && (flags_on & att_nameref)) - { - builtin_error (_("%s: reference variable cannot be an array"), name); - assign_error++; - NEXT_VARIABLE (); - } - else if (flags_on & att_nameref) - { - /* ksh93 compat: turning on nameref attribute turns off -ilu */ - VUNSETATTR (var, att_integer|att_uppercase|att_lowercase|att_capcase); - } - - /* Cannot use declare +r to turn off readonly attribute. */ - if (readonly_p (var) && (flags_off & att_readonly)) - { - sh_readonly (name); - any_failed++; - NEXT_VARIABLE (); - } - - /* Cannot use declare to assign value to readonly or noassign - variable. */ - if ((readonly_p (var) || noassign_p (var)) && offset) - { - if (readonly_p (var)) - sh_readonly (name); - assign_error++; - NEXT_VARIABLE (); - } - -#if defined (ARRAY_VARS) - /* make declare a[2]=foo as similar to a[2]=foo as possible if - a is already an array or assoc variable. */ - if (array_subscript_assignment && array_exists && (flags_on & (att_array|att_assoc)) == 0) - simple_array_assign = 1; - else if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset) - { - int vlen; - vlen = STRLEN (value); -/*itrace("declare_builtin: name = %s value = %s flags = %d", name, value, wflags);*/ -#if 0 /* bash-4.4 */ - if (value[0] == '(' && value[vlen-1] == ')' && (shell_compatibility_level <= 43 || (wflags & W_COMPASSIGN))) -#else - if (array_exists == 0 && value[0] == '(' && value[vlen-1] == ')') -#endif - compound_array_assign = 1; - else - simple_array_assign = 1; - } - - /* Cannot use declare +a name or declare +A name to remove an - array variable. */ - if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var))) - { - builtin_error (_("%s: cannot destroy array variables in this way"), name); - any_failed++; - NEXT_VARIABLE (); - } - - if ((flags_on & att_array) && assoc_p (var)) - { - builtin_error (_("%s: cannot convert associative to indexed array"), name); - any_failed++; - NEXT_VARIABLE (); - } - if ((flags_on & att_assoc) && array_p (var)) - { - builtin_error (_("%s: cannot convert indexed to associative array"), name); - any_failed++; - NEXT_VARIABLE (); - } - - /* declare -A name[[n]] makes name an associative array variable. */ - if (flags_on & att_assoc) - { - if (assoc_p (var) == 0) - var = convert_var_to_assoc (var); - } - /* declare -a name[[n]] or declare name[n] makes name an indexed - array variable. */ - else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0) - var = convert_var_to_array (var); -#endif /* ARRAY_VARS */ - - /* XXX - we note that we are turning on nameref attribute and defer - setting it until the assignment has been made so we don't do an - inadvertent nameref lookup. Might have to do the same thing for - flags_off&att_nameref. */ - /* XXX - ksh93 makes it an error to set a readonly nameref variable - using a single typeset command. */ - onref = (flags_on & att_nameref); - flags_on &= ~att_nameref; -#if defined (ARRAY_VARS) - if (array_p (var) || assoc_p (var) - || (offset && compound_array_assign) - || simple_array_assign) - onref = 0; /* array variables may not be namerefs */ -#endif - - /* ksh93 seems to do this */ - offref = (flags_off & att_nameref); - flags_off &= ~att_nameref; - - VSETATTR (var, flags_on); - VUNSETATTR (var, flags_off); - -#if defined (ARRAY_VARS) - aflags |= ASS_FORCE; - if (offset && compound_array_assign) - assign_array_var_from_string (var, value, aflags); - else if (simple_array_assign && subscript_start) - { - /* declare [-aA] name[N]=value */ - *subscript_start = '['; /* ] */ - var = assign_array_element (name, value, 0); /* XXX - not aflags */ - *subscript_start = '\0'; - if (var == 0) /* some kind of assignment error */ - { - assign_error++; - flags_on |= onref; - flags_off |= offref; - NEXT_VARIABLE (); - } - } - else if (simple_array_assign) - { - /* let bind_{array,assoc}_variable take care of this. */ - if (assoc_p (var)) - bind_assoc_variable (var, name, savestring ("0"), value, aflags); - else - bind_array_variable (name, 0, value, aflags); - } - else -#endif - /* bind_variable_value duplicates the essential internals of - bind_variable() */ - if (offset) - { - if (onref) - aflags |= ASS_NAMEREF; - v = bind_variable_value (var, value, aflags); - if (v == 0 && onref) - { - sh_invalidid (value); - assign_error++; - /* XXX - unset this variable? or leave it as normal var? */ - delete_var (var->name, mkglobal ? global_variables : shell_variables); - NEXT_VARIABLE (); - } - } - - /* If we found this variable in the temporary environment, as with - `var=value declare -x var', make sure it is treated identically - to `var=value export var'. Do the same for `declare -r' and - `readonly'. Preserve the attributes, except for att_tempvar. */ - /* XXX -- should this create a variable in the global scope, or - modify the local variable flags? ksh93 has it modify the - global scope. - Need to handle case like in set_var_attribute where a temporary - variable is in the same table as the function local vars. */ - if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var)) - { - SHELL_VAR *tv; - char *tvalue; - - tv = find_tempenv_variable (var->name); - if (tv) - { - tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring (""); - tv = bind_variable (var->name, tvalue, 0); - tv->attributes |= var->attributes & ~att_tempvar; - if (tv->context > 0) - VSETATTR (tv, att_propagate); - free (tvalue); - } - VSETATTR (var, att_propagate); - } - } - - /* Turn on nameref attribute we deferred above. */ - /* XXX - should we turn on the noassign attribute for consistency with - ksh93 when we turn on the nameref attribute? */ - VSETATTR (var, onref); - flags_on |= onref; - VUNSETATTR (var, offref); - flags_off |= offref; - /* Yuck. ksh93 compatibility */ - if (refvar) - VUNSETATTR (refvar, flags_off); - - stupidly_hack_special_variables (name); - - NEXT_VARIABLE (); - } - - return (assign_error ? EX_BADASSIGN - : ((any_failed == 0) ? EXECUTION_SUCCESS - : EXECUTION_FAILURE)); -} diff --git a/cross-build/cygwin32.cache.old b/cross-build/cygwin32.cache.old deleted file mode 100644 index 640390fbf..000000000 --- a/cross-build/cygwin32.cache.old +++ /dev/null @@ -1,42 +0,0 @@ -# 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.orig b/doc/FAQ.orig deleted file mode 100644 index 1cff3c8ef..000000000 --- a/doc/FAQ.orig +++ /dev/null @@ -1,1745 +0,0 @@ -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/doc/aosa-bash.pdf.old b/doc/aosa-bash.pdf.old deleted file mode 100644 index 006a76776..000000000 Binary files a/doc/aosa-bash.pdf.old and /dev/null differ diff --git a/examples/loadables/Makefile.in.save b/examples/loadables/Makefile.in.save deleted file mode 100644 index f6208f5cc..000000000 --- a/examples/loadables/Makefile.in.save +++ /dev/null @@ -1,238 +0,0 @@ -# -# 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/execute_cmd.c~ b/execute_cmd.c~ deleted file mode 100644 index 05ddc8458..000000000 --- a/execute_cmd.c~ +++ /dev/null @@ -1,5610 +0,0 @@ -/* execute_cmd.c -- Execute a COMMAND structure. */ - -/* Copyright (C) 1987-2013 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" - -#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX) - #pragma alloca -#endif /* _AIX && RISC6000 && !__GNUC__ */ - -#include -#include "chartypes.h" -#include "bashtypes.h" -#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H) -# include -#endif -#include "filecntl.h" -#include "posixstat.h" -#include -#if defined (HAVE_SYS_PARAM_H) -# include -#endif - -#if defined (HAVE_UNISTD_H) -# include -#endif - -#include "posixtime.h" - -#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE) -# include -#endif - -#if defined (HAVE_SYS_TIMES_H) && defined (HAVE_TIMES) -# include -#endif - -#include - -#if !defined (errno) -extern int errno; -#endif - -#define NEED_FPURGE_DECL - -#include "bashansi.h" -#include "bashintl.h" - -#include "memalloc.h" -#include "shell.h" -#include /* use <...> so we pick it up from the build directory */ -#include "flags.h" -#include "builtins.h" -#include "hashlib.h" -#include "jobs.h" -#include "execute_cmd.h" -#include "findcmd.h" -#include "redir.h" -#include "trap.h" -#include "pathexp.h" -#include "hashcmd.h" - -#if defined (COND_COMMAND) -# include "test.h" -#endif - -#include "builtins/common.h" -#include "builtins/builtext.h" /* list of builtins */ - -#include "builtins/getopt.h" - -#include -#include - -#if defined (BUFFERED_INPUT) -# include "input.h" -#endif - -#if defined (ALIAS) -# include "alias.h" -#endif - -#if defined (HISTORY) -# include "bashhist.h" -#endif - -#if defined (ARRAY_VARS) -struct func_array_state - { - ARRAY *funcname_a; - SHELL_VAR *funcname_v; - ARRAY *source_a; - SHELL_VAR *source_v; - ARRAY *lineno_a; - SHELL_VAR *lineno_v; - }; -#endif - -extern int dollar_dollar_pid; -extern int posixly_correct; -extern int expand_aliases; -extern int autocd; -extern int breaking, continuing, loop_level; -extern int parse_and_execute_level, running_trap, sourcelevel; -extern int command_string_index, line_number; -extern int dot_found_in_search; -extern int already_making_children; -extern int tempenv_assign_error; -extern char *the_printed_command, *shell_name; -extern pid_t last_command_subst_pid; -extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin; -extern char **subshell_argv, **subshell_envp; -extern int subshell_argc; -extern time_t shell_start_time; -#if 0 -extern char *glob_argv_flags; -#endif - -extern int job_control; /* XXX */ - -extern int close __P((int)); - -/* Static functions defined and used in this file. */ -static void close_pipes __P((int, int)); -static void do_piping __P((int, int)); -static void bind_lastarg __P((char *)); -static int shell_control_structure __P((enum command_type)); -static void cleanup_redirects __P((REDIRECT *)); - -#if defined (JOB_CONTROL) -static int restore_signal_mask __P((sigset_t *)); -#endif - -static void async_redirect_stdin __P((void)); - -static int builtin_status __P((int)); - -static int execute_for_command __P((FOR_COM *)); -#if defined (SELECT_COMMAND) -static int displen __P((const char *)); -static int print_index_and_element __P((int, int, WORD_LIST *)); -static void indent __P((int, int)); -static void print_select_list __P((WORD_LIST *, int, int, int)); -static char *select_query __P((WORD_LIST *, int, char *, int)); -static int execute_select_command __P((SELECT_COM *)); -#endif -#if defined (DPAREN_ARITHMETIC) -static int execute_arith_command __P((ARITH_COM *)); -#endif -#if defined (COND_COMMAND) -static int execute_cond_node __P((COND_COM *)); -static int execute_cond_command __P((COND_COM *)); -#endif -#if defined (COMMAND_TIMING) -static int mkfmt __P((char *, int, int, time_t, int)); -static void print_formatted_time __P((FILE *, char *, - time_t, int, time_t, int, - time_t, int, int)); -static int time_command __P((COMMAND *, int, int, int, struct fd_bitmap *)); -#endif -#if defined (ARITH_FOR_COMMAND) -static intmax_t eval_arith_for_expr __P((WORD_LIST *, int *)); -static int execute_arith_for_command __P((ARITH_FOR_COM *)); -#endif -static int execute_case_command __P((CASE_COM *)); -static int execute_while_command __P((WHILE_COM *)); -static int execute_until_command __P((WHILE_COM *)); -static int execute_while_or_until __P((WHILE_COM *, int)); -static int execute_if_command __P((IF_COM *)); -static int execute_null_command __P((REDIRECT *, int, int, int)); -static void fix_assignment_words __P((WORD_LIST *)); -static int execute_simple_command __P((SIMPLE_COM *, int, int, int, struct fd_bitmap *)); -static int execute_builtin __P((sh_builtin_func_t *, WORD_LIST *, int, int)); -static int execute_function __P((SHELL_VAR *, WORD_LIST *, int, struct fd_bitmap *, int, int)); -static int execute_builtin_or_function __P((WORD_LIST *, sh_builtin_func_t *, - SHELL_VAR *, - REDIRECT *, struct fd_bitmap *, int)); -static void execute_subshell_builtin_or_function __P((WORD_LIST *, REDIRECT *, - sh_builtin_func_t *, - SHELL_VAR *, - int, int, int, - struct fd_bitmap *, - int)); -static int execute_disk_command __P((WORD_LIST *, REDIRECT *, char *, - int, int, int, struct fd_bitmap *, int)); - -static char *getinterp __P((char *, int, int *)); -static void initialize_subshell __P((void)); -static int execute_in_subshell __P((COMMAND *, int, int, int, struct fd_bitmap *)); -#if defined (COPROCESS_SUPPORT) -static int execute_coproc __P((COMMAND *, int, int, struct fd_bitmap *)); -#endif - -static int execute_pipeline __P((COMMAND *, int, int, int, struct fd_bitmap *)); - -static int execute_connection __P((COMMAND *, int, int, int, struct fd_bitmap *)); - -static int execute_intern_function __P((WORD_DESC *, FUNCTION_DEF *)); - -/* Set to 1 if fd 0 was the subject of redirection to a subshell. Global - so that reader_loop can set it to zero before executing a command. */ -int stdin_redir; - -/* The name of the command that is currently being executed. - `test' needs this, for example. */ -char *this_command_name; - -/* The printed representation of the currently-executing command (same as - the_printed_command), except when a trap is being executed. Useful for - a debugger to know where exactly the program is currently executing. */ -char *the_printed_command_except_trap; - -/* For catching RETURN in a function. */ -int return_catch_flag; -int return_catch_value; -procenv_t return_catch; - -/* The value returned by the last synchronous command. */ -volatile int last_command_exit_value; - -/* Whether or not the last command (corresponding to last_command_exit_value) - was terminated by a signal, and, if so, which one. */ -int last_command_exit_signal; - -/* Are we currently ignoring the -e option for the duration of a builtin's - execution? */ -int builtin_ignoring_errexit = 0; - -/* The list of redirections to perform which will undo the redirections - that I made in the shell. */ -REDIRECT *redirection_undo_list = (REDIRECT *)NULL; - -/* The list of redirections to perform which will undo the internal - redirections performed by the `exec' builtin. These are redirections - that must be undone even when exec discards redirection_undo_list. */ -REDIRECT *exec_redirection_undo_list = (REDIRECT *)NULL; - -/* When greater than zero, value is the `level' of builtins we are - currently executing (e.g. `eval echo a' would have it set to 2). */ -int executing_builtin = 0; - -/* Non-zero if we are executing a command list (a;b;c, etc.) */ -int executing_list = 0; - -/* Non-zero if failing commands in a command substitution should not exit the - shell even if -e is set. Used to pass the CMD_IGNORE_RETURN flag down to - commands run in command substitutions by parse_and_execute. */ -int comsub_ignore_return = 0; - -/* Non-zero if we have just forked and are currently running in a subshell - environment. */ -int subshell_environment; - -/* Count of nested subshells, like SHLVL. Available via $BASH_SUBSHELL */ -int subshell_level = 0; - -/* Currently-executing shell function. */ -SHELL_VAR *this_shell_function; - -/* If non-zero, matches in case and [[ ... ]] are case-insensitive */ -int match_ignore_case = 0; - -int executing_command_builtin = 0; - -struct stat SB; /* used for debugging */ - -static int special_builtin_failed; - -static COMMAND *currently_executing_command; - -/* The line number that the currently executing function starts on. */ -static int function_line_number; - -/* XXX - set to 1 if we're running the DEBUG trap and we want to show the line - number containing the function name. Used by executing_line_number to - report the correct line number. Kind of a hack. */ -static int showing_function_line; - -/* $LINENO ($BASH_LINENO) for use by an ERR trap. Global so parse_and_execute - can save and restore it. */ -int line_number_for_err_trap; - -/* A sort of function nesting level counter */ -int funcnest = 0; -int funcnest_max = 0; - -int evalnest = 0; /* bash-4.4/bash-5.0 */ -int evalnest_max = EVALNEST_MAX; - -int sourcenest = 0; -int sourcenest_max = SOURCENEST_MAX; - -volatile int from_return_trap = 0; - -int lastpipe_opt = 0; - -struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL; - -#define FD_BITMAP_DEFAULT_SIZE 32 - -/* Functions to allocate and deallocate the structures used to pass - information from the shell to its children about file descriptors - to close. */ -struct fd_bitmap * -new_fd_bitmap (size) - int size; -{ - struct fd_bitmap *ret; - - ret = (struct fd_bitmap *)xmalloc (sizeof (struct fd_bitmap)); - - ret->size = size; - - if (size) - { - ret->bitmap = (char *)xmalloc (size); - memset (ret->bitmap, '\0', size); - } - else - ret->bitmap = (char *)NULL; - return (ret); -} - -void -dispose_fd_bitmap (fdbp) - struct fd_bitmap *fdbp; -{ - FREE (fdbp->bitmap); - free (fdbp); -} - -void -close_fd_bitmap (fdbp) - struct fd_bitmap *fdbp; -{ - register int i; - - if (fdbp) - { - for (i = 0; i < fdbp->size; i++) - if (fdbp->bitmap[i]) - { - close (i); - fdbp->bitmap[i] = 0; - } - } -} - -/* Return the line number of the currently executing command. */ -int -executing_line_number () -{ - if (executing && showing_function_line == 0 && - (variable_context == 0 || interactive_shell == 0) && - currently_executing_command) - { -#if defined (COND_COMMAND) - if (currently_executing_command->type == cm_cond) - return currently_executing_command->value.Cond->line; -#endif -#if defined (DPAREN_ARITHMETIC) - if (currently_executing_command->type == cm_arith) - return currently_executing_command->value.Arith->line; -#endif -#if defined (ARITH_FOR_COMMAND) - if (currently_executing_command->type == cm_arith_for) - return currently_executing_command->value.ArithFor->line; -#endif - - return line_number; - } - else - return line_number; -} - -/* Execute the command passed in COMMAND. COMMAND is exactly what - read_command () places into GLOBAL_COMMAND. See "command.h" for the - details of the command structure. - - EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible - return values. Executing a command with nothing in it returns - EXECUTION_SUCCESS. */ -int -execute_command (command) - COMMAND *command; -{ - struct fd_bitmap *bitmap; - int result; - - current_fds_to_close = (struct fd_bitmap *)NULL; - bitmap = new_fd_bitmap (FD_BITMAP_DEFAULT_SIZE); - begin_unwind_frame ("execute-command"); - add_unwind_protect (dispose_fd_bitmap, (char *)bitmap); - - /* Just do the command, but not asynchronously. */ - result = execute_command_internal (command, 0, NO_PIPE, NO_PIPE, bitmap); - - dispose_fd_bitmap (bitmap); - discard_unwind_frame ("execute-command"); - -#if defined (PROCESS_SUBSTITUTION) - /* don't unlink fifos if we're in a shell function; wait until the function - returns. */ - if (variable_context == 0) - unlink_fifo_list (); -#endif /* PROCESS_SUBSTITUTION */ - - QUIT; - return (result); -} - -/* Return 1 if TYPE is a shell control structure type. */ -static int -shell_control_structure (type) - enum command_type type; -{ - switch (type) - { -#if defined (ARITH_FOR_COMMAND) - case cm_arith_for: -#endif -#if defined (SELECT_COMMAND) - case cm_select: -#endif -#if defined (DPAREN_ARITHMETIC) - case cm_arith: -#endif -#if defined (COND_COMMAND) - case cm_cond: -#endif - case cm_case: - case cm_while: - case cm_until: - case cm_if: - case cm_for: - case cm_group: - case cm_function_def: - return (1); - - default: - return (0); - } -} - -/* A function to use to unwind_protect the redirection undo list - for loops. */ -static void -cleanup_redirects (list) - REDIRECT *list; -{ - do_redirections (list, RX_ACTIVE); - dispose_redirects (list); -} - -#if 0 -/* Function to unwind_protect the redirections for functions and builtins. */ -static void -cleanup_func_redirects (list) - REDIRECT *list; -{ - do_redirections (list, RX_ACTIVE); -} -#endif - -void -dispose_exec_redirects () -{ - if (exec_redirection_undo_list) - { - dispose_redirects (exec_redirection_undo_list); - exec_redirection_undo_list = (REDIRECT *)NULL; - } -} - -#if defined (JOB_CONTROL) -/* A function to restore the signal mask to its proper value when the shell - is interrupted or errors occur while creating a pipeline. */ -static int -restore_signal_mask (set) - sigset_t *set; -{ - return (sigprocmask (SIG_SETMASK, set, (sigset_t *)NULL)); -} -#endif /* JOB_CONTROL */ - -#ifdef DEBUG -/* A debugging function that can be called from gdb, for instance. */ -void -open_files () -{ - register int i; - int f, fd_table_size; - - fd_table_size = getdtablesize (); - - fprintf (stderr, "pid %ld open files:", (long)getpid ()); - for (i = 3; i < fd_table_size; i++) - { - if ((f = fcntl (i, F_GETFD, 0)) != -1) - fprintf (stderr, " %d (%s)", i, f ? "close" : "open"); - } - fprintf (stderr, "\n"); -} -#endif - -static void -async_redirect_stdin () -{ - int fd; - - fd = open ("/dev/null", O_RDONLY); - if (fd > 0) - { - dup2 (fd, 0); - close (fd); - } - else if (fd < 0) - internal_error (_("cannot redirect standard input from /dev/null: %s"), strerror (errno)); -} - -#define DESCRIBE_PID(pid) do { if (interactive) describe_pid (pid); } while (0) - -/* Execute the command passed in COMMAND, perhaps doing it asynchronously. - COMMAND is exactly what read_command () places into GLOBAL_COMMAND. - ASYNCHROUNOUS, if non-zero, says to do this command in the background. - PIPE_IN and PIPE_OUT are file descriptors saying where input comes - from and where it goes. They can have the value of NO_PIPE, which means - I/O is stdin/stdout. - FDS_TO_CLOSE is a list of file descriptors to close once the child has - been forked. This list often contains the unusable sides of pipes, etc. - - EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible - return values. Executing a command with nothing in it returns - EXECUTION_SUCCESS. */ -int -execute_command_internal (command, asynchronous, pipe_in, pipe_out, - fds_to_close) - COMMAND *command; - int asynchronous; - int pipe_in, pipe_out; - struct fd_bitmap *fds_to_close; -{ - int exec_result, user_subshell, invert, ignore_return, was_error_trap; - REDIRECT *my_undo_list, *exec_undo_list; - char *tcmd; - volatile int last_pid; - volatile int save_line_number; -#if defined (PROCESS_SUBSTITUTION) - volatile int ofifo, nfifo, osize, saved_fifo; - volatile char *ofifo_list; -#endif - - if (breaking || continuing) - return (last_command_exit_value); - if (command == 0 || read_but_dont_execute) - return (EXECUTION_SUCCESS); - - QUIT; - run_pending_traps (); - -#if 0 - if (running_trap == 0) -#endif - currently_executing_command = command; - - invert = (command->flags & CMD_INVERT_RETURN) != 0; - - /* If we're inverting the return value and `set -e' has been executed, - we don't want a failing command to inadvertently cause the shell - to exit. */ - if (exit_immediately_on_error && invert) /* XXX */ - command->flags |= CMD_IGNORE_RETURN; /* XXX */ - - exec_result = EXECUTION_SUCCESS; - - /* If a command was being explicitly run in a subshell, or if it is - a shell control-structure, and it has a pipe, then we do the command - in a subshell. */ - if (command->type == cm_subshell && (command->flags & CMD_NO_FORK)) - return (execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)); - -#if defined (COPROCESS_SUPPORT) - if (command->type == cm_coproc) - return (execute_coproc (command, pipe_in, pipe_out, fds_to_close)); -#endif - - user_subshell = command->type == cm_subshell || ((command->flags & CMD_WANT_SUBSHELL) != 0); - - if (command->type == cm_subshell || - (command->flags & (CMD_WANT_SUBSHELL|CMD_FORCE_SUBSHELL)) || - (shell_control_structure (command->type) && - (pipe_out != NO_PIPE || pipe_in != NO_PIPE || asynchronous))) - { - pid_t paren_pid; - int s; - - /* Fork a subshell, turn off the subshell bit, turn off job - control and call execute_command () on the command again. */ - line_number_for_err_trap = line_number; - tcmd = make_command_string (command); - paren_pid = make_child (savestring (tcmd), asynchronous); - - if (user_subshell && signal_is_trapped (ERROR_TRAP) && - signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0) - { - FREE (the_printed_command_except_trap); - the_printed_command_except_trap = savestring (the_printed_command); - } - - if (paren_pid == 0) - { - /* We want to run the exit trap for forced {} subshells, and we - want to note this before execute_in_subshell modifies the - COMMAND struct. Need to keep in mind that execute_in_subshell - runs the exit trap for () subshells itself. */ - /* This handles { command; } & */ - s = user_subshell == 0 && command->type == cm_group && pipe_in == NO_PIPE && pipe_out == NO_PIPE && asynchronous; - /* run exit trap for : | { ...; } and { ...; } | : */ - /* run exit trap for : | ( ...; ) and ( ...; ) | : */ - s += user_subshell == 0 && command->type == cm_group && (pipe_in != NO_PIPE || pipe_out != NO_PIPE) && asynchronous == 0; - - last_command_exit_value = execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close); - if (s) - subshell_exit (last_command_exit_value); - else - exit (last_command_exit_value); - /* NOTREACHED */ - } - else - { - close_pipes (pipe_in, pipe_out); - -#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD) - if (variable_context == 0) /* wait until shell function completes */ - unlink_fifo_list (); -#endif - /* If we are part of a pipeline, and not the end of the pipeline, - then we should simply return and let the last command in the - pipe be waited for. If we are not in a pipeline, or are the - last command in the pipeline, then we wait for the subshell - and return its exit status as usual. */ - if (pipe_out != NO_PIPE) - return (EXECUTION_SUCCESS); - - stop_pipeline (asynchronous, (COMMAND *)NULL); - - if (asynchronous == 0) - { - was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0; - invert = (command->flags & CMD_INVERT_RETURN) != 0; - ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; - - exec_result = wait_for (paren_pid); - - /* If we have to, invert the return value. */ - if (invert) - exec_result = ((exec_result == EXECUTION_SUCCESS) - ? EXECUTION_FAILURE - : EXECUTION_SUCCESS); - - last_command_exit_value = exec_result; - if (user_subshell && was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS) - { - save_line_number = line_number; - line_number = line_number_for_err_trap; - run_error_trap (); - line_number = save_line_number; - } - - if (user_subshell && ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS) - { - run_pending_traps (); - jump_to_top_level (ERREXIT); - } - - return (last_command_exit_value); - } - else - { - DESCRIBE_PID (paren_pid); - - run_pending_traps (); - - /* Posix 2013 2.9.3.1: "the exit status of an asynchronous list - shall be zero." */ - last_command_exit_value = 0; - return (EXECUTION_SUCCESS); - } - } - } - -#if defined (COMMAND_TIMING) - if (command->flags & CMD_TIME_PIPELINE) - { - if (asynchronous) - { - command->flags |= CMD_FORCE_SUBSHELL; - exec_result = execute_command_internal (command, 1, pipe_in, pipe_out, fds_to_close); - } - else - { - exec_result = time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close); -#if 0 - if (running_trap == 0) -#endif - currently_executing_command = (COMMAND *)NULL; - } - return (exec_result); - } -#endif /* COMMAND_TIMING */ - - if (shell_control_structure (command->type) && command->redirects) - stdin_redir = stdin_redirects (command->redirects); - -#if defined (PROCESS_SUBSTITUTION) - if (variable_context != 0) - { - ofifo = num_fifos (); - ofifo_list = copy_fifo_list ((int *)&osize); - saved_fifo = 1; - } - else - saved_fifo = 0; -#endif - - /* Handle WHILE FOR CASE etc. with redirections. (Also '&' input - redirection.) */ - if (do_redirections (command->redirects, RX_ACTIVE|RX_UNDOABLE) != 0) - { - cleanup_redirects (redirection_undo_list); - redirection_undo_list = (REDIRECT *)NULL; - dispose_exec_redirects (); -#if defined (PROCESS_SUBSTITUTION) - if (saved_fifo) - free ((void *)ofifo_list); -#endif - return (last_command_exit_value = EXECUTION_FAILURE); - } - - if (redirection_undo_list) - { - /* XXX - why copy here? */ - my_undo_list = (REDIRECT *)copy_redirects (redirection_undo_list); - dispose_redirects (redirection_undo_list); - redirection_undo_list = (REDIRECT *)NULL; - } - else - my_undo_list = (REDIRECT *)NULL; - - if (exec_redirection_undo_list) - { - /* XXX - why copy here? */ - exec_undo_list = (REDIRECT *)copy_redirects (exec_redirection_undo_list); - dispose_redirects (exec_redirection_undo_list); - exec_redirection_undo_list = (REDIRECT *)NULL; - } - else - exec_undo_list = (REDIRECT *)NULL; - - if (my_undo_list || exec_undo_list) - begin_unwind_frame ("loop_redirections"); - - if (my_undo_list) - add_unwind_protect ((Function *)cleanup_redirects, my_undo_list); - - if (exec_undo_list) - add_unwind_protect ((Function *)dispose_redirects, exec_undo_list); - - ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; - - QUIT; - - switch (command->type) - { - case cm_simple: - { - save_line_number = line_number; - /* We can't rely on variables retaining their values across a - call to execute_simple_command if a longjmp occurs as the - result of a `return' builtin. This is true for sure with gcc. */ -#if defined (RECYCLES_PIDS) - last_made_pid = NO_PID; -#endif - last_pid = last_made_pid; - was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0; - - if (ignore_return && command->value.Simple) - command->value.Simple->flags |= CMD_IGNORE_RETURN; - if (command->flags & CMD_STDIN_REDIR) - command->value.Simple->flags |= CMD_STDIN_REDIR; - - line_number_for_err_trap = line_number = command->value.Simple->line; - exec_result = - execute_simple_command (command->value.Simple, pipe_in, pipe_out, - asynchronous, fds_to_close); - line_number = save_line_number; - - /* The temporary environment should be used for only the simple - command immediately following its definition. */ - dispose_used_env_vars (); - -#if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA) - /* Reclaim memory allocated with alloca () on machines which - may be using the alloca emulation code. */ - (void) alloca (0); -#endif /* (ultrix && mips) || C_ALLOCA */ - - /* If we forked to do the command, then we must wait_for () - the child. */ - - /* XXX - this is something to watch out for if there are problems - when the shell is compiled without job control. Don't worry about - whether or not last_made_pid == last_pid; already_making_children - tells us whether or not there are unwaited-for children to wait - for and reap. */ - if (already_making_children && pipe_out == NO_PIPE) - { - stop_pipeline (asynchronous, (COMMAND *)NULL); - - if (asynchronous) - { - DESCRIBE_PID (last_made_pid); - exec_result = EXECUTION_SUCCESS; - invert = 0; /* async commands always succeed */ - } - else -#if !defined (JOB_CONTROL) - /* Do not wait for asynchronous processes started from - startup files. */ - if (last_made_pid != last_asynchronous_pid) -#endif - /* When executing a shell function that executes other - commands, this causes the last simple command in - the function to be waited for twice. This also causes - subshells forked to execute builtin commands (e.g., in - pipelines) to be waited for twice. */ - exec_result = wait_for (last_made_pid); - } - } - - /* 2009/02/13 -- pipeline failure is processed elsewhere. This handles - only the failure of a simple command. */ - if (was_error_trap && ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS) - { - last_command_exit_value = exec_result; - line_number = line_number_for_err_trap; - run_error_trap (); - line_number = save_line_number; - } - - if (ignore_return == 0 && invert == 0 && - ((posixly_correct && interactive == 0 && special_builtin_failed) || - (exit_immediately_on_error && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS))) - { - last_command_exit_value = exec_result; - run_pending_traps (); - -#if 0 /* XXX - bash-4.4 or bash-5.0 */ - /* Undo redirections before running exit trap on the way out of - set -e. Report by Mark Farrell 5/19/2014 */ - if (exit_immediately_on_error && signal_is_trapped (0) && - unwind_protect_tag_on_stack ("saved-redirects")) - run_unwind_frame ("saved-redirects"); -#endif - - jump_to_top_level (ERREXIT); - } - - break; - - case cm_for: - if (ignore_return) - command->value.For->flags |= CMD_IGNORE_RETURN; - exec_result = execute_for_command (command->value.For); - break; - -#if defined (ARITH_FOR_COMMAND) - case cm_arith_for: - if (ignore_return) - command->value.ArithFor->flags |= CMD_IGNORE_RETURN; - exec_result = execute_arith_for_command (command->value.ArithFor); - break; -#endif - -#if defined (SELECT_COMMAND) - case cm_select: - if (ignore_return) - command->value.Select->flags |= CMD_IGNORE_RETURN; - exec_result = execute_select_command (command->value.Select); - break; -#endif - - case cm_case: - if (ignore_return) - command->value.Case->flags |= CMD_IGNORE_RETURN; - exec_result = execute_case_command (command->value.Case); - break; - - case cm_while: - if (ignore_return) - command->value.While->flags |= CMD_IGNORE_RETURN; - exec_result = execute_while_command (command->value.While); - break; - - case cm_until: - if (ignore_return) - command->value.While->flags |= CMD_IGNORE_RETURN; - exec_result = execute_until_command (command->value.While); - break; - - case cm_if: - if (ignore_return) - command->value.If->flags |= CMD_IGNORE_RETURN; - exec_result = execute_if_command (command->value.If); - break; - - case cm_group: - - /* This code can be executed from either of two paths: an explicit - '{}' command, or via a function call. If we are executed via a - function call, we have already taken care of the function being - executed in the background (down there in execute_simple_command ()), - and this command should *not* be marked as asynchronous. If we - are executing a regular '{}' group command, and asynchronous == 1, - we must want to execute the whole command in the background, so we - need a subshell, and we want the stuff executed in that subshell - (this group command) to be executed in the foreground of that - subshell (i.e. there will not be *another* subshell forked). - - What we do is to force a subshell if asynchronous, and then call - execute_command_internal again with asynchronous still set to 1, - but with the original group command, so the printed command will - look right. - - The code above that handles forking off subshells will note that - both subshell and async are on, and turn off async in the child - after forking the subshell (but leave async set in the parent, so - the normal call to describe_pid is made). This turning off - async is *crucial*; if it is not done, this will fall into an - infinite loop of executions through this spot in subshell after - subshell until the process limit is exhausted. */ - - if (asynchronous) - { - command->flags |= CMD_FORCE_SUBSHELL; - exec_result = - execute_command_internal (command, 1, pipe_in, pipe_out, - fds_to_close); - } - else - { - if (ignore_return && command->value.Group->command) - command->value.Group->command->flags |= CMD_IGNORE_RETURN; - exec_result = - execute_command_internal (command->value.Group->command, - asynchronous, pipe_in, pipe_out, - fds_to_close); - } - break; - - case cm_connection: - exec_result = execute_connection (command, asynchronous, - pipe_in, pipe_out, fds_to_close); - if (asynchronous) - invert = 0; /* XXX */ - - break; - -#if defined (DPAREN_ARITHMETIC) - case cm_arith: - was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0; - if (ignore_return) - command->value.Arith->flags |= CMD_IGNORE_RETURN; - line_number_for_err_trap = save_line_number = line_number; - exec_result = execute_arith_command (command->value.Arith); - line_number = save_line_number; - - if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS) - { - last_command_exit_value = exec_result; - save_line_number = line_number; - line_number = line_number_for_err_trap; - run_error_trap (); - line_number = save_line_number; - } - - if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS) - { - last_command_exit_value = exec_result; - run_pending_traps (); - jump_to_top_level (ERREXIT); - } - - break; -#endif - -#if defined (COND_COMMAND) - case cm_cond: - was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0; - if (ignore_return) - command->value.Cond->flags |= CMD_IGNORE_RETURN; - - line_number_for_err_trap = save_line_number = line_number; - exec_result = execute_cond_command (command->value.Cond); - line_number = save_line_number; - - if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS) - { - last_command_exit_value = exec_result; - save_line_number = line_number; - line_number = line_number_for_err_trap; - run_error_trap (); - line_number = save_line_number; - } - - if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS) - { - last_command_exit_value = exec_result; - run_pending_traps (); - jump_to_top_level (ERREXIT); - } - - break; -#endif - - case cm_function_def: - exec_result = execute_intern_function (command->value.Function_def->name, - command->value.Function_def); - break; - - default: - command_error ("execute_command", CMDERR_BADTYPE, command->type, 0); - } - - if (my_undo_list) - { - do_redirections (my_undo_list, RX_ACTIVE); - dispose_redirects (my_undo_list); - } - - if (exec_undo_list) - dispose_redirects (exec_undo_list); - - if (my_undo_list || exec_undo_list) - discard_unwind_frame ("loop_redirections"); - -#if defined (PROCESS_SUBSTITUTION) - if (saved_fifo) - { - nfifo = num_fifos (); - if (nfifo > ofifo) - close_new_fifos ((char *)ofifo_list, osize); - free ((void *)ofifo_list); - } -#endif - - /* Invert the return value if we have to */ - if (invert) - exec_result = (exec_result == EXECUTION_SUCCESS) - ? EXECUTION_FAILURE - : EXECUTION_SUCCESS; - -#if defined (DPAREN_ARITHMETIC) || defined (COND_COMMAND) - /* This is where we set PIPESTATUS from the exit status of the appropriate - compound commands (the ones that look enough like simple commands to - cause confusion). We might be able to optimize by not doing this if - subshell_environment != 0. */ - switch (command->type) - { -# if defined (DPAREN_ARITHMETIC) - case cm_arith: -# endif -# if defined (COND_COMMAND) - case cm_cond: -# endif - set_pipestatus_from_exit (exec_result); - break; - } -#endif - - last_command_exit_value = exec_result; - run_pending_traps (); -#if 0 - if (running_trap == 0) -#endif - currently_executing_command = (COMMAND *)NULL; - - return (last_command_exit_value); -} - -#if defined (COMMAND_TIMING) - -#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY) -extern struct timeval *difftimeval __P((struct timeval *, struct timeval *, struct timeval *)); -extern struct timeval *addtimeval __P((struct timeval *, struct timeval *, struct timeval *)); -extern int timeval_to_cpu __P((struct timeval *, struct timeval *, struct timeval *)); -#endif - -#define POSIX_TIMEFORMAT "real %2R\nuser %2U\nsys %2S" -#define BASH_TIMEFORMAT "\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS" - -static const int precs[] = { 0, 100, 10, 1 }; - -#if defined (HAVE_LOCALE_H) && defined (HAVE_LOCALECONV) -static int -decpoint () -{ - struct lconv *lv; - - lv = localeconv (); - return (lv && lv->decimal_point && lv->decimal_point[0]) ? lv->decimal_point[0] : '.'; -} -#else -# define decpoint() '.' -#endif - -/* Expand one `%'-prefixed escape sequence from a time format string. */ -static int -mkfmt (buf, prec, lng, sec, sec_fraction) - char *buf; - int prec, lng; - time_t sec; - int sec_fraction; -{ - time_t min; - char abuf[INT_STRLEN_BOUND(time_t) + 1]; - int ind, aind; - - ind = 0; - abuf[sizeof(abuf) - 1] = '\0'; - - /* If LNG is non-zero, we want to decompose SEC into minutes and seconds. */ - if (lng) - { - min = sec / 60; - sec %= 60; - aind = sizeof(abuf) - 2; - do - abuf[aind--] = (min % 10) + '0'; - while (min /= 10); - aind++; - while (abuf[aind]) - buf[ind++] = abuf[aind++]; - buf[ind++] = 'm'; - } - - /* Now add the seconds. */ - aind = sizeof (abuf) - 2; - do - abuf[aind--] = (sec % 10) + '0'; - while (sec /= 10); - aind++; - while (abuf[aind]) - buf[ind++] = abuf[aind++]; - - /* We want to add a decimal point and PREC places after it if PREC is - nonzero. PREC is not greater than 3. SEC_FRACTION is between 0 - and 999. */ - if (prec != 0) - { - buf[ind++] = decpoint (); - for (aind = 1; aind <= prec; aind++) - { - buf[ind++] = (sec_fraction / precs[aind]) + '0'; - sec_fraction %= precs[aind]; - } - } - - if (lng) - buf[ind++] = 's'; - buf[ind] = '\0'; - - return (ind); -} - -/* Interpret the format string FORMAT, interpolating the following escape - sequences: - %[prec][l][RUS] - - where the optional `prec' is a precision, meaning the number of - characters after the decimal point, the optional `l' means to format - using minutes and seconds (MMmNN[.FF]s), like the `times' builtin', - and the last character is one of - - R number of seconds of `real' time - U number of seconds of `user' time - S number of seconds of `system' time - - An occurrence of `%%' in the format string is translated to a `%'. The - result is printed to FP, a pointer to a FILE. The other variables are - the seconds and thousandths of a second of real, user, and system time, - resectively. */ -static void -print_formatted_time (fp, format, rs, rsf, us, usf, ss, ssf, cpu) - FILE *fp; - char *format; - time_t rs; - int rsf; - time_t us; - int usf; - time_t ss; - int ssf, cpu; -{ - int prec, lng, len; - char *str, *s, ts[INT_STRLEN_BOUND (time_t) + sizeof ("mSS.FFFF")]; - time_t sum; - int sum_frac; - int sindex, ssize; - - len = strlen (format); - ssize = (len + 64) - (len % 64); - str = (char *)xmalloc (ssize); - sindex = 0; - - for (s = format; *s; s++) - { - if (*s != '%' || s[1] == '\0') - { - RESIZE_MALLOCED_BUFFER (str, sindex, 1, ssize, 64); - str[sindex++] = *s; - } - else if (s[1] == '%') - { - s++; - RESIZE_MALLOCED_BUFFER (str, sindex, 1, ssize, 64); - str[sindex++] = *s; - } - else if (s[1] == 'P') - { - s++; -#if 0 - /* clamp CPU usage at 100% */ - if (cpu > 10000) - cpu = 10000; -#endif - sum = cpu / 100; - sum_frac = (cpu % 100) * 10; - len = mkfmt (ts, 2, 0, sum, sum_frac); - RESIZE_MALLOCED_BUFFER (str, sindex, len, ssize, 64); - strcpy (str + sindex, ts); - sindex += len; - } - else - { - prec = 3; /* default is three places past the decimal point. */ - lng = 0; /* default is to not use minutes or append `s' */ - s++; - if (DIGIT (*s)) /* `precision' */ - { - prec = *s++ - '0'; - if (prec > 3) prec = 3; - } - if (*s == 'l') /* `length extender' */ - { - lng = 1; - s++; - } - if (*s == 'R' || *s == 'E') - len = mkfmt (ts, prec, lng, rs, rsf); - else if (*s == 'U') - len = mkfmt (ts, prec, lng, us, usf); - else if (*s == 'S') - len = mkfmt (ts, prec, lng, ss, ssf); - else - { - internal_error (_("TIMEFORMAT: `%c': invalid format character"), *s); - free (str); - return; - } - RESIZE_MALLOCED_BUFFER (str, sindex, len, ssize, 64); - strcpy (str + sindex, ts); - sindex += len; - } - } - - str[sindex] = '\0'; - fprintf (fp, "%s\n", str); - fflush (fp); - - free (str); -} - -static int -time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close) - COMMAND *command; - int asynchronous, pipe_in, pipe_out; - struct fd_bitmap *fds_to_close; -{ - int rv, posix_time, old_flags, nullcmd; - time_t rs, us, ss; - int rsf, usf, ssf; - int cpu; - char *time_format; - -#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY) - struct timeval real, user, sys; - struct timeval before, after; -# if defined (HAVE_STRUCT_TIMEZONE) - struct timezone dtz; /* posix doesn't define this */ -# endif - struct rusage selfb, selfa, kidsb, kidsa; /* a = after, b = before */ -#else -# if defined (HAVE_TIMES) - clock_t tbefore, tafter, real, user, sys; - struct tms before, after; -# endif -#endif - -#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY) -# if defined (HAVE_STRUCT_TIMEZONE) - gettimeofday (&before, &dtz); -# else - gettimeofday (&before, (void *)NULL); -# endif /* !HAVE_STRUCT_TIMEZONE */ - getrusage (RUSAGE_SELF, &selfb); - getrusage (RUSAGE_CHILDREN, &kidsb); -#else -# if defined (HAVE_TIMES) - tbefore = times (&before); -# endif -#endif - - posix_time = command && (command->flags & CMD_TIME_POSIX); - - nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0); - if (posixly_correct && nullcmd) - { -#if defined (HAVE_GETRUSAGE) - selfb.ru_utime.tv_sec = kidsb.ru_utime.tv_sec = selfb.ru_stime.tv_sec = kidsb.ru_stime.tv_sec = 0; - selfb.ru_utime.tv_usec = kidsb.ru_utime.tv_usec = selfb.ru_stime.tv_usec = kidsb.ru_stime.tv_usec = 0; - before.tv_sec = shell_start_time; - before.tv_usec = 0; -#else - before.tms_utime = before.tms_stime = before.tms_cutime = before.tms_cstime = 0; - tbefore = shell_start_time; -#endif - } - - old_flags = command->flags; - command->flags &= ~(CMD_TIME_PIPELINE|CMD_TIME_POSIX); - rv = execute_command_internal (command, asynchronous, pipe_in, pipe_out, fds_to_close); - command->flags = old_flags; - - rs = us = ss = 0; - rsf = usf = ssf = cpu = 0; - -#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY) -# if defined (HAVE_STRUCT_TIMEZONE) - gettimeofday (&after, &dtz); -# else - gettimeofday (&after, (void *)NULL); -# endif /* !HAVE_STRUCT_TIMEZONE */ - getrusage (RUSAGE_SELF, &selfa); - getrusage (RUSAGE_CHILDREN, &kidsa); - - difftimeval (&real, &before, &after); - timeval_to_secs (&real, &rs, &rsf); - - addtimeval (&user, difftimeval(&after, &selfb.ru_utime, &selfa.ru_utime), - difftimeval(&before, &kidsb.ru_utime, &kidsa.ru_utime)); - timeval_to_secs (&user, &us, &usf); - - addtimeval (&sys, difftimeval(&after, &selfb.ru_stime, &selfa.ru_stime), - difftimeval(&before, &kidsb.ru_stime, &kidsa.ru_stime)); - timeval_to_secs (&sys, &ss, &ssf); - - cpu = timeval_to_cpu (&real, &user, &sys); -#else -# if defined (HAVE_TIMES) - tafter = times (&after); - - real = tafter - tbefore; - clock_t_to_secs (real, &rs, &rsf); - - user = (after.tms_utime - before.tms_utime) + (after.tms_cutime - before.tms_cutime); - clock_t_to_secs (user, &us, &usf); - - sys = (after.tms_stime - before.tms_stime) + (after.tms_cstime - before.tms_cstime); - clock_t_to_secs (sys, &ss, &ssf); - - cpu = (real == 0) ? 0 : ((user + sys) * 10000) / real; - -# else - rs = us = ss = 0; - rsf = usf = ssf = cpu = 0; -# endif -#endif - - if (posix_time) - time_format = POSIX_TIMEFORMAT; - else if ((time_format = get_string_value ("TIMEFORMAT")) == 0) - { - if (posixly_correct && nullcmd) - time_format = "user\t%2lU\nsys\t%2lS"; - else - time_format = BASH_TIMEFORMAT; - } - if (time_format && *time_format) - print_formatted_time (stderr, time_format, rs, rsf, us, usf, ss, ssf, cpu); - - return rv; -} -#endif /* COMMAND_TIMING */ - -/* Execute a command that's supposed to be in a subshell. This must be - called after make_child and we must be running in the child process. - The caller will return or exit() immediately with the value this returns. */ -static int -execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) - COMMAND *command; - int asynchronous; - int pipe_in, pipe_out; - struct fd_bitmap *fds_to_close; -{ - int user_subshell, return_code, function_value, should_redir_stdin, invert; - int ois, user_coproc; - int result; - volatile COMMAND *tcom; - - USE_VAR(user_subshell); - USE_VAR(user_coproc); - USE_VAR(invert); - USE_VAR(tcom); - USE_VAR(asynchronous); - - subshell_level++; - should_redir_stdin = (asynchronous && (command->flags & CMD_STDIN_REDIR) && - pipe_in == NO_PIPE && - stdin_redirects (command->redirects) == 0); - - invert = (command->flags & CMD_INVERT_RETURN) != 0; - user_subshell = command->type == cm_subshell || ((command->flags & CMD_WANT_SUBSHELL) != 0); - user_coproc = command->type == cm_coproc; - - command->flags &= ~(CMD_FORCE_SUBSHELL | CMD_WANT_SUBSHELL | CMD_INVERT_RETURN); - - /* If a command is asynchronous in a subshell (like ( foo ) & or - the special case of an asynchronous GROUP command where the - the subshell bit is turned on down in case cm_group: below), - turn off `asynchronous', so that two subshells aren't spawned. - XXX - asynchronous used to be set to 0 in this block, but that - means that setup_async_signals was never run. Now it's set to - 0 after subshell_environment is set appropriately and setup_async_signals - is run. - - This seems semantically correct to me. For example, - ( foo ) & seems to say ``do the command `foo' in a subshell - environment, but don't wait for that subshell to finish'', - and "{ foo ; bar ; } &" seems to me to be like functions or - builtins in the background, which executed in a subshell - environment. I just don't see the need to fork two subshells. */ - - /* Don't fork again, we are already in a subshell. A `doubly - async' shell is not interactive, however. */ - if (asynchronous) - { -#if defined (JOB_CONTROL) - /* If a construct like ( exec xxx yyy ) & is given while job - control is active, we want to prevent exec from putting the - subshell back into the original process group, carefully - undoing all the work we just did in make_child. */ - original_pgrp = -1; -#endif /* JOB_CONTROL */ - ois = interactive_shell; - interactive_shell = 0; - /* This test is to prevent alias expansion by interactive shells that - run `(command) &' but to allow scripts that have enabled alias - expansion with `shopt -s expand_alias' to continue to expand - aliases. */ - if (ois != interactive_shell) - expand_aliases = 0; - } - - /* Subshells are neither login nor interactive. */ - login_shell = interactive = 0; - - if (user_subshell) - subshell_environment = SUBSHELL_PAREN; /* XXX */ - else - { - subshell_environment = 0; /* XXX */ - if (asynchronous) - subshell_environment |= SUBSHELL_ASYNC; - if (pipe_in != NO_PIPE || pipe_out != NO_PIPE) - subshell_environment |= SUBSHELL_PIPE; - if (user_coproc) - subshell_environment |= SUBSHELL_COPROC; - } - - reset_terminating_signals (); /* in sig.c */ - /* Cancel traps, in trap.c. */ - /* 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; - - /* Make sure restore_original_signals doesn't undo the work done by - make_child to ensure that asynchronous children are immune to SIGINT - and SIGQUIT. Turn off asynchronous to make sure more subshells are - not spawned. */ - if (asynchronous) - { - setup_async_signals (); - asynchronous = 0; - } - -#if defined (JOB_CONTROL) - set_sigchld_handler (); -#endif /* JOB_CONTROL */ - - set_sigint_handler (); - -#if defined (JOB_CONTROL) - /* Delete all traces that there were any jobs running. This is - only for subshells. */ - without_job_control (); -#endif /* JOB_CONTROL */ - - if (fds_to_close) - close_fd_bitmap (fds_to_close); - - do_piping (pipe_in, pipe_out); - -#if defined (COPROCESS_SUPPORT) - coproc_closeall (); -#endif - - /* If this is a user subshell, set a flag if stdin was redirected. - This is used later to decide whether to redirect fd 0 to - /dev/null for async commands in the subshell. This adds more - sh compatibility, but I'm not sure it's the right thing to do. */ - if (user_subshell) - { - stdin_redir = stdin_redirects (command->redirects); - restore_default_signal (EXIT_TRAP); - } - - /* If this is an asynchronous command (command &), we want to - redirect the standard input from /dev/null in the absence of - any specific redirection involving stdin. */ - if (should_redir_stdin && stdin_redir == 0) - async_redirect_stdin (); - - /* Do redirections, then dispose of them before recursive call. */ - if (command->redirects) - { - if (do_redirections (command->redirects, RX_ACTIVE) != 0) - exit (invert ? EXECUTION_SUCCESS : EXECUTION_FAILURE); - - dispose_redirects (command->redirects); - command->redirects = (REDIRECT *)NULL; - } - - if (command->type == cm_subshell) - tcom = command->value.Subshell->command; - else if (user_coproc) - tcom = command->value.Coproc->command; - else - tcom = command; - - if (command->flags & CMD_TIME_PIPELINE) - tcom->flags |= CMD_TIME_PIPELINE; - if (command->flags & CMD_TIME_POSIX) - tcom->flags |= CMD_TIME_POSIX; - - /* Make sure the subshell inherits any CMD_IGNORE_RETURN flag. */ - if ((command->flags & CMD_IGNORE_RETURN) && tcom != command) - tcom->flags |= CMD_IGNORE_RETURN; - - /* If this is a simple command, tell execute_disk_command that it - might be able to get away without forking and simply exec. - This means things like ( sleep 10 ) will only cause one fork. - If we're timing the command or inverting its return value, however, - we cannot do this optimization. */ - if ((user_subshell || user_coproc) && (tcom->type == cm_simple || tcom->type == cm_subshell) && - ((tcom->flags & CMD_TIME_PIPELINE) == 0) && - ((tcom->flags & CMD_INVERT_RETURN) == 0)) - { - tcom->flags |= CMD_NO_FORK; - if (tcom->type == cm_simple) - tcom->value.Simple->flags |= CMD_NO_FORK; - } - - invert = (tcom->flags & CMD_INVERT_RETURN) != 0; - tcom->flags &= ~CMD_INVERT_RETURN; - - result = setjmp_nosigs (top_level); - - /* If we're inside a function while executing this subshell, we - need to handle a possible `return'. */ - function_value = 0; - if (return_catch_flag) - function_value = setjmp_nosigs (return_catch); - - /* If we're going to exit the shell, we don't want to invert the return - status. */ - if (result == EXITPROG) - invert = 0, return_code = last_command_exit_value; - else if (result) - return_code = (last_command_exit_value == EXECUTION_SUCCESS) ? EXECUTION_FAILURE : last_command_exit_value; - else if (function_value) - return_code = return_catch_value; - else - return_code = execute_command_internal ((COMMAND *)tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close); - - /* If we are asked to, invert the return value. */ - if (invert) - return_code = (return_code == EXECUTION_SUCCESS) ? EXECUTION_FAILURE - : EXECUTION_SUCCESS; - - /* If we were explicitly placed in a subshell with (), we need - to do the `shell cleanup' things, such as running traps[0]. */ - if (user_subshell && signal_is_trapped (0)) - { - last_command_exit_value = return_code; - return_code = run_exit_trap (); - } - - subshell_level--; - return (return_code); - /* NOTREACHED */ -} - -#if defined (COPROCESS_SUPPORT) -#define COPROC_MAX 16 - -typedef struct cpelement - { - struct cpelement *next; - struct coproc *coproc; - } -cpelement_t; - -typedef struct cplist - { - struct cpelement *head; - struct cpelement *tail; - int ncoproc; - int lock; - } -cplist_t; - -static struct cpelement *cpe_alloc __P((struct coproc *)); -static void cpe_dispose __P((struct cpelement *)); -static struct cpelement *cpl_add __P((struct coproc *)); -static struct cpelement *cpl_delete __P((pid_t)); -static void cpl_reap __P((void)); -static void cpl_flush __P((void)); -static void cpl_closeall __P((void)); -static struct cpelement *cpl_search __P((pid_t)); -static struct cpelement *cpl_searchbyname __P((const char *)); -static void cpl_prune __P((void)); - -static void coproc_free __P((struct coproc *)); - -/* Will go away when there is fully-implemented support for multiple coprocs. */ -Coproc sh_coproc = { 0, NO_PID, -1, -1, 0, 0, 0, 0, 0 }; - -cplist_t coproc_list = {0, 0, 0}; - -/* Functions to manage the list of coprocs */ - -static struct cpelement * -cpe_alloc (cp) - Coproc *cp; -{ - struct cpelement *cpe; - - cpe = (struct cpelement *)xmalloc (sizeof (struct cpelement)); - cpe->coproc = cp; - cpe->next = (struct cpelement *)0; - return cpe; -} - -static void -cpe_dispose (cpe) - struct cpelement *cpe; -{ - free (cpe); -} - -static struct cpelement * -cpl_add (cp) - Coproc *cp; -{ - struct cpelement *cpe; - - cpe = cpe_alloc (cp); - - if (coproc_list.head == 0) - { - coproc_list.head = coproc_list.tail = cpe; - coproc_list.ncoproc = 0; /* just to make sure */ - } - else - { - coproc_list.tail->next = cpe; - coproc_list.tail = cpe; - } - coproc_list.ncoproc++; - - return cpe; -} - -static struct cpelement * -cpl_delete (pid) - pid_t pid; -{ - struct cpelement *prev, *p; - - for (prev = p = coproc_list.head; p; prev = p, p = p->next) - if (p->coproc->c_pid == pid) - { - prev->next = p->next; /* remove from list */ - break; - } - - if (p == 0) - return 0; /* not found */ - -#if defined (DEBUG) - itrace("cpl_delete: deleting %d", pid); -#endif - - /* Housekeeping in the border cases. */ - if (p == coproc_list.head) - coproc_list.head = coproc_list.head->next; - else if (p == coproc_list.tail) - coproc_list.tail = prev; - - coproc_list.ncoproc--; - if (coproc_list.ncoproc == 0) - coproc_list.head = coproc_list.tail = 0; - else if (coproc_list.ncoproc == 1) - coproc_list.tail = coproc_list.head; /* just to make sure */ - - return (p); -} - -static void -cpl_reap () -{ - struct cpelement *p, *next, *nh, *nt; - - /* Build a new list by removing dead coprocs and fix up the coproc_list - pointers when done. */ - nh = nt = next = (struct cpelement *)0; - for (p = coproc_list.head; p; p = next) - { - next = p->next; - if (p->coproc->c_flags & COPROC_DEAD) - { - coproc_list.ncoproc--; /* keep running count, fix up pointers later */ - -#if defined (DEBUG) - itrace("cpl_reap: deleting %d", p->coproc->c_pid); -#endif - - coproc_dispose (p->coproc); - cpe_dispose (p); - } - else if (nh == 0) - nh = nt = p; - else - { - nt->next = p; - nt = nt->next; - } - } - - if (coproc_list.ncoproc == 0) - coproc_list.head = coproc_list.tail = 0; - else - { - if (nt) - nt->next = 0; - coproc_list.head = nh; - coproc_list.tail = nt; - if (coproc_list.ncoproc == 1) - coproc_list.tail = coproc_list.head; /* just to make sure */ - } -} - -/* Clear out the list of saved statuses */ -static void -cpl_flush () -{ - struct cpelement *cpe, *p; - - for (cpe = coproc_list.head; cpe; ) - { - p = cpe; - cpe = cpe->next; - - coproc_dispose (p->coproc); - cpe_dispose (p); - } - - coproc_list.head = coproc_list.tail = 0; - coproc_list.ncoproc = 0; -} - -static void -cpl_closeall () -{ - struct cpelement *cpe; - - for (cpe = coproc_list.head; cpe; cpe = cpe->next) - coproc_close (cpe->coproc); -} - -static void -cpl_fdchk (fd) - int fd; -{ - struct cpelement *cpe; - - for (cpe = coproc_list.head; cpe; cpe = cpe->next) - coproc_checkfd (cpe->coproc, fd); -} - -/* Search for PID in the list of coprocs; return the cpelement struct if - found. If not found, return NULL. */ -static struct cpelement * -cpl_search (pid) - pid_t pid; -{ - struct cpelement *cpe; - - for (cpe = coproc_list.head ; cpe; cpe = cpe->next) - if (cpe->coproc->c_pid == pid) - return cpe; - return (struct cpelement *)NULL; -} - -/* Search for the coproc named NAME in the list of coprocs; return the - cpelement struct if found. If not found, return NULL. */ -static struct cpelement * -cpl_searchbyname (name) - const char *name; -{ - struct cpelement *cp; - - for (cp = coproc_list.head ; cp; cp = cp->next) - if (STREQ (cp->coproc->c_name, name)) - return cp; - return (struct cpelement *)NULL; -} - -#if 0 -static void -cpl_prune () -{ - struct cpelement *cp; - - while (coproc_list.head && coproc_list.ncoproc > COPROC_MAX) - { - cp = coproc_list.head; - coproc_list.head = coproc_list.head->next; - coproc_dispose (cp->coproc); - cpe_dispose (cp); - coproc_list.ncoproc--; - } -} -#endif - -/* These currently use a single global "shell coproc" but are written in a - way to not preclude additional coprocs later (using the list management - package above). */ - -struct coproc * -getcoprocbypid (pid) - pid_t pid; -{ -#if MULTIPLE_COPROCS - struct cpelement *p; - - p = cpl_search (pid); - return (p ? p->coproc : 0); -#else - return (pid == sh_coproc.c_pid ? &sh_coproc : 0); -#endif -} - -struct coproc * -getcoprocbyname (name) - const char *name; -{ -#if MULTIPLE_COPROCS - struct cpelement *p; - - p = cpl_searchbyname (name); - return (p ? p->coproc : 0); -#else - return ((sh_coproc.c_name && STREQ (sh_coproc.c_name, name)) ? &sh_coproc : 0); -#endif -} - -void -coproc_init (cp) - struct coproc *cp; -{ - cp->c_name = 0; - cp->c_pid = NO_PID; - cp->c_rfd = cp->c_wfd = -1; - cp->c_rsave = cp->c_wsave = -1; - cp->c_flags = cp->c_status = cp->c_lock = 0; -} - -struct coproc * -coproc_alloc (name, pid) - char *name; - pid_t pid; -{ - struct coproc *cp; - -#if MULTIPLE_COPROCS - cp = (struct coproc *)xmalloc (sizeof (struct coproc)); -#else - cp = &sh_coproc; -#endif - coproc_init (cp); - cp->c_lock = 2; - - cp->c_pid = pid; - cp->c_name = savestring (name); -#if MULTIPLE_COPROCS - cpl_add (cp); -#endif - cp->c_lock = 0; - return (cp); -} - -static void -coproc_free (cp) - struct coproc *cp; -{ - free (cp); -} - -void -coproc_dispose (cp) - struct coproc *cp; -{ - sigset_t set, oset; - - if (cp == 0) - return; - - BLOCK_SIGNAL (SIGCHLD, set, oset); - cp->c_lock = 3; - coproc_unsetvars (cp); - FREE (cp->c_name); - coproc_close (cp); -#if MULTIPLE_COPROCS - coproc_free (cp); -#else - coproc_init (cp); - cp->c_lock = 0; -#endif - UNBLOCK_SIGNAL (oset); -} - -/* Placeholder for now. Will require changes for multiple coprocs */ -void -coproc_flush () -{ -#if MULTIPLE_COPROCS - cpl_flush (); -#else - coproc_dispose (&sh_coproc); -#endif -} - -void -coproc_close (cp) - struct coproc *cp; -{ - if (cp->c_rfd >= 0) - { - close (cp->c_rfd); - cp->c_rfd = -1; - } - if (cp->c_wfd >= 0) - { - close (cp->c_wfd); - cp->c_wfd = -1; - } - cp->c_rsave = cp->c_wsave = -1; -} - -void -coproc_closeall () -{ -#if MULTIPLE_COPROCS - cpl_closeall (); -#else - coproc_close (&sh_coproc); /* XXX - will require changes for multiple coprocs */ -#endif -} - -void -coproc_reap () -{ -#if MULTIPLE_COPROCS - cpl_reap (); -#else - struct coproc *cp; - - cp = &sh_coproc; /* XXX - will require changes for multiple coprocs */ - if (cp && (cp->c_flags & COPROC_DEAD)) - coproc_dispose (cp); -#endif -} - -void -coproc_rclose (cp, fd) - struct coproc *cp; - int fd; -{ - if (cp->c_rfd >= 0 && cp->c_rfd == fd) - { - close (cp->c_rfd); - cp->c_rfd = -1; - } -} - -void -coproc_wclose (cp, fd) - struct coproc *cp; - int fd; -{ - if (cp->c_wfd >= 0 && cp->c_wfd == fd) - { - close (cp->c_wfd); - cp->c_wfd = -1; - } -} - -void -coproc_checkfd (cp, fd) - struct coproc *cp; - int fd; -{ - int update; - - update = 0; - if (cp->c_rfd >= 0 && cp->c_rfd == fd) - update = cp->c_rfd = -1; - if (cp->c_wfd >= 0 && cp->c_wfd == fd) - update = cp->c_wfd = -1; - if (update) - coproc_setvars (cp); -} - -void -coproc_fdchk (fd) - int fd; -{ -#if MULTIPLE_COPROCS - cpl_fdchk (fd); -#else - coproc_checkfd (&sh_coproc, fd); -#endif -} - -void -coproc_fdclose (cp, fd) - struct coproc *cp; - int fd; -{ - coproc_rclose (cp, fd); - coproc_wclose (cp, fd); - coproc_setvars (cp); -} - -void -coproc_fdsave (cp) - struct coproc *cp; -{ - cp->c_rsave = cp->c_rfd; - cp->c_wsave = cp->c_wfd; -} - -void -coproc_fdrestore (cp) - struct coproc *cp; -{ - cp->c_rfd = cp->c_rsave; - cp->c_wfd = cp->c_wsave; -} - -void -coproc_pidchk (pid, status) - pid_t pid; -{ - struct coproc *cp; - -#if MULTIPLE_COPROCS - struct cpelement *cpe; - - cpe = cpl_delete (pid); - cp = cpe ? cpe->coproc : 0; -#else - cp = getcoprocbypid (pid); -#endif - if (cp) - { - cp->c_lock = 4; - cp->c_status = status; - cp->c_flags |= COPROC_DEAD; - cp->c_flags &= ~COPROC_RUNNING; - /* Don't dispose the coproc or unset the COPROC_XXX variables because - this is executed in a signal handler context. Wait until coproc_reap - takes care of it. */ - cp->c_lock = 0; - } -} - -void -coproc_setvars (cp) - struct coproc *cp; -{ - SHELL_VAR *v; - char *namevar, *t; - int l; -#if defined (ARRAY_VARS) - arrayind_t ind; -#endif - - if (cp->c_name == 0) - return; - - l = strlen (cp->c_name); - namevar = xmalloc (l + 16); - -#if defined (ARRAY_VARS) - v = find_variable (cp->c_name); - if (v == 0) - v = make_new_array_variable (cp->c_name); - if (array_p (v) == 0) - v = convert_var_to_array (v); - - t = itos (cp->c_rfd); - ind = 0; - v = bind_array_variable (cp->c_name, ind, t, 0); - free (t); - - t = itos (cp->c_wfd); - ind = 1; - bind_array_variable (cp->c_name, ind, t, 0); - free (t); -#else - sprintf (namevar, "%s_READ", cp->c_name); - t = itos (cp->c_rfd); - bind_variable (namevar, t, 0); - free (t); - sprintf (namevar, "%s_WRITE", cp->c_name); - t = itos (cp->c_wfd); - bind_variable (namevar, t, 0); - free (t); -#endif - - sprintf (namevar, "%s_PID", cp->c_name); - t = itos (cp->c_pid); - bind_variable (namevar, t, 0); - free (t); - - free (namevar); -} - -void -coproc_unsetvars (cp) - struct coproc *cp; -{ - int l; - char *namevar; - - if (cp->c_name == 0) - return; - - l = strlen (cp->c_name); - namevar = xmalloc (l + 16); - - sprintf (namevar, "%s_PID", cp->c_name); - unbind_variable (namevar); - -#if defined (ARRAY_VARS) - unbind_variable (cp->c_name); -#else - sprintf (namevar, "%s_READ", cp->c_name); - unbind_variable (namevar); - sprintf (namevar, "%s_WRITE", cp->c_name); - unbind_variable (namevar); -#endif - - free (namevar); -} - -static int -execute_coproc (command, pipe_in, pipe_out, fds_to_close) - COMMAND *command; - int pipe_in, pipe_out; - struct fd_bitmap *fds_to_close; -{ - int rpipe[2], wpipe[2], estat, invert; - pid_t coproc_pid; - Coproc *cp; - char *tcmd; - sigset_t set, oset; - - /* XXX -- can be removed after changes to handle multiple coprocs */ -#if !MULTIPLE_COPROCS - if (sh_coproc.c_pid != NO_PID) - internal_warning ("execute_coproc: coproc [%d:%s] still exists", sh_coproc.c_pid, sh_coproc.c_name); - coproc_init (&sh_coproc); -#endif - - invert = (command->flags & CMD_INVERT_RETURN) != 0; - command_string_index = 0; - tcmd = make_command_string (command); - - sh_openpipe ((int *)&rpipe); /* 0 = parent read, 1 = child write */ - sh_openpipe ((int *)&wpipe); /* 0 = child read, 1 = parent write */ - - BLOCK_SIGNAL (SIGCHLD, set, oset); - - coproc_pid = make_child (savestring (tcmd), 1); - - if (coproc_pid == 0) - { - close (rpipe[0]); - close (wpipe[1]); - - UNBLOCK_SIGNAL (oset); - estat = execute_in_subshell (command, 1, wpipe[0], rpipe[1], fds_to_close); - - fflush (stdout); - fflush (stderr); - - exit (estat); - } - - close (rpipe[1]); - close (wpipe[0]); - - /* XXX - possibly run Coproc->name through word expansion? */ - cp = coproc_alloc (command->value.Coproc->name, coproc_pid); - cp->c_rfd = rpipe[0]; - cp->c_wfd = wpipe[1]; - - SET_CLOSE_ON_EXEC (cp->c_rfd); - SET_CLOSE_ON_EXEC (cp->c_wfd); - - coproc_setvars (cp); - - UNBLOCK_SIGNAL (oset); - -#if 0 - itrace ("execute_coproc: [%d] %s", coproc_pid, the_printed_command); -#endif - - close_pipes (pipe_in, pipe_out); -#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD) - unlink_fifo_list (); -#endif - stop_pipeline (1, (COMMAND *)NULL); - DESCRIBE_PID (coproc_pid); - run_pending_traps (); - - return (invert ? EXECUTION_FAILURE : EXECUTION_SUCCESS); -} -#endif - -static void -restore_stdin (s) - int s; -{ - dup2 (s, 0); - close (s); -} - -/* Catch-all cleanup function for lastpipe code for unwind-protects */ -static void -lastpipe_cleanup (s) - int s; -{ - unfreeze_jobs_list (); -} - -static int -execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close) - COMMAND *command; - int asynchronous, pipe_in, pipe_out; - struct fd_bitmap *fds_to_close; -{ - int prev, fildes[2], new_bitmap_size, dummyfd, ignore_return, exec_result; - int lstdin, lastpipe_flag, lastpipe_jid; - COMMAND *cmd; - struct fd_bitmap *fd_bitmap; - pid_t lastpid; - -#if defined (JOB_CONTROL) - sigset_t set, oset; - BLOCK_CHILD (set, oset); -#endif /* JOB_CONTROL */ - - ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; - - prev = pipe_in; - cmd = command; - - while (cmd && cmd->type == cm_connection && - cmd->value.Connection && cmd->value.Connection->connector == '|') - { - /* Make a pipeline between the two commands. */ - if (pipe (fildes) < 0) - { - sys_error (_("pipe error")); -#if defined (JOB_CONTROL) - terminate_current_pipeline (); - kill_current_pipeline (); - UNBLOCK_CHILD (oset); -#endif /* JOB_CONTROL */ - last_command_exit_value = EXECUTION_FAILURE; - /* The unwind-protects installed below will take care - of closing all of the open file descriptors. */ - throw_to_top_level (); - return (EXECUTION_FAILURE); /* XXX */ - } - - /* Here is a problem: with the new file close-on-exec - code, the read end of the pipe (fildes[0]) stays open - in the first process, so that process will never get a - SIGPIPE. There is no way to signal the first process - that it should close fildes[0] after forking, so it - remains open. No SIGPIPE is ever sent because there - is still a file descriptor open for reading connected - to the pipe. We take care of that here. This passes - around a bitmap of file descriptors that must be - closed after making a child process in execute_simple_command. */ - - /* We need fd_bitmap to be at least as big as fildes[0]. - If fildes[0] is less than fds_to_close->size, then - use fds_to_close->size. */ - new_bitmap_size = (fildes[0] < fds_to_close->size) - ? fds_to_close->size - : fildes[0] + 8; - - fd_bitmap = new_fd_bitmap (new_bitmap_size); - - /* Now copy the old information into the new bitmap. */ - xbcopy ((char *)fds_to_close->bitmap, (char *)fd_bitmap->bitmap, fds_to_close->size); - - /* And mark the pipe file descriptors to be closed. */ - fd_bitmap->bitmap[fildes[0]] = 1; - - /* In case there are pipe or out-of-processes errors, we - want all these file descriptors to be closed when - unwind-protects are run, and the storage used for the - bitmaps freed up. */ - begin_unwind_frame ("pipe-file-descriptors"); - add_unwind_protect (dispose_fd_bitmap, fd_bitmap); - add_unwind_protect (close_fd_bitmap, fd_bitmap); - if (prev >= 0) - add_unwind_protect (close, prev); - dummyfd = fildes[1]; - add_unwind_protect (close, dummyfd); - -#if defined (JOB_CONTROL) - add_unwind_protect (restore_signal_mask, &oset); -#endif /* JOB_CONTROL */ - - if (ignore_return && cmd->value.Connection->first) - cmd->value.Connection->first->flags |= CMD_IGNORE_RETURN; - execute_command_internal (cmd->value.Connection->first, asynchronous, - prev, fildes[1], fd_bitmap); - - if (prev >= 0) - close (prev); - - prev = fildes[0]; - close (fildes[1]); - - dispose_fd_bitmap (fd_bitmap); - discard_unwind_frame ("pipe-file-descriptors"); - - cmd = cmd->value.Connection->second; - } - - lastpid = last_made_pid; - - /* Now execute the rightmost command in the pipeline. */ - if (ignore_return && cmd) - cmd->flags |= CMD_IGNORE_RETURN; - - lastpipe_flag = 0; - - begin_unwind_frame ("lastpipe-exec"); - lstdin = -1; - /* If the `lastpipe' option is set with shopt, and job control is not - enabled, execute the last element of non-async pipelines in the - current shell environment. */ - if (lastpipe_opt && job_control == 0 && asynchronous == 0 && pipe_out == NO_PIPE && prev > 0) - { - lstdin = move_to_high_fd (0, 1, -1); - if (lstdin > 0) - { - do_piping (prev, pipe_out); - prev = NO_PIPE; - add_unwind_protect (restore_stdin, lstdin); - lastpipe_flag = 1; - freeze_jobs_list (); - lastpipe_jid = stop_pipeline (0, (COMMAND *)NULL); /* XXX */ - add_unwind_protect (lastpipe_cleanup, lastpipe_jid); - } - if (cmd) - cmd->flags |= CMD_LASTPIPE; - } - if (prev >= 0) - add_unwind_protect (close, prev); - - exec_result = execute_command_internal (cmd, asynchronous, prev, pipe_out, fds_to_close); - - if (lstdin > 0) - restore_stdin (lstdin); - - if (prev >= 0) - close (prev); - -#if defined (JOB_CONTROL) - UNBLOCK_CHILD (oset); -#endif - - QUIT; - - if (lastpipe_flag) - { -#if defined (JOB_CONTROL) - if (INVALID_JOB (lastpipe_jid) == 0) - { - append_process (savestring (the_printed_command_except_trap), dollar_dollar_pid, exec_result, lastpipe_jid); - lstdin = wait_for (lastpid); - } - else - lstdin = wait_for_single_pid (lastpid); /* checks bgpids list */ -#else - lstdin = wait_for (lastpid); -#endif - -#if defined (JOB_CONTROL) - /* If wait_for removes the job from the jobs table, use result of last - command as pipeline's exit status as usual. The jobs list can get - frozen and unfrozen at inconvenient times if there are multiple pipelines - running simultaneously. */ - if (INVALID_JOB (lastpipe_jid) == 0) - exec_result = job_exit_status (lastpipe_jid); - else if (pipefail_opt) - exec_result = exec_result | lstdin; /* XXX */ - /* otherwise we use exec_result */ - -#endif - unfreeze_jobs_list (); - } - - discard_unwind_frame ("lastpipe-exec"); - - return (exec_result); -} - -static int -execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close) - COMMAND *command; - int asynchronous, pipe_in, pipe_out; - struct fd_bitmap *fds_to_close; -{ - COMMAND *tc, *second; - int ignore_return, exec_result, was_error_trap, invert; - volatile int save_line_number; - - ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; - - switch (command->value.Connection->connector) - { - /* Do the first command asynchronously. */ - case '&': - tc = command->value.Connection->first; - if (tc == 0) - return (EXECUTION_SUCCESS); - - if (ignore_return) - tc->flags |= CMD_IGNORE_RETURN; - tc->flags |= CMD_AMPERSAND; - - /* If this shell was compiled without job control support, - if we are currently in a subshell via `( xxx )', or if job - control is not active then the standard input for an - asynchronous command is forced to /dev/null. */ -#if defined (JOB_CONTROL) - if ((subshell_environment || !job_control) && !stdin_redir) -#else - if (!stdin_redir) -#endif /* JOB_CONTROL */ - tc->flags |= CMD_STDIN_REDIR; - - exec_result = execute_command_internal (tc, 1, pipe_in, pipe_out, fds_to_close); - QUIT; - - if (tc->flags & CMD_STDIN_REDIR) - tc->flags &= ~CMD_STDIN_REDIR; - - second = command->value.Connection->second; - if (second) - { - if (ignore_return) - second->flags |= CMD_IGNORE_RETURN; - - exec_result = execute_command_internal (second, asynchronous, pipe_in, pipe_out, fds_to_close); - } - - break; - - /* Just call execute command on both sides. */ - case ';': - if (ignore_return) - { - if (command->value.Connection->first) - command->value.Connection->first->flags |= CMD_IGNORE_RETURN; - if (command->value.Connection->second) - command->value.Connection->second->flags |= CMD_IGNORE_RETURN; - } - executing_list++; - QUIT; - execute_command (command->value.Connection->first); - QUIT; - exec_result = execute_command_internal (command->value.Connection->second, - asynchronous, pipe_in, pipe_out, - fds_to_close); - executing_list--; - break; - - case '|': - was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0; - invert = (command->flags & CMD_INVERT_RETURN) != 0; - ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; - - line_number_for_err_trap = line_number; - exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close); - - if (asynchronous) - { - exec_result = EXECUTION_SUCCESS; - invert = 0; - } - - if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS) - { - last_command_exit_value = exec_result; - save_line_number = line_number; - line_number = line_number_for_err_trap; - run_error_trap (); - line_number = save_line_number; - } - - if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS) - { - last_command_exit_value = exec_result; - run_pending_traps (); - jump_to_top_level (ERREXIT); - } - - break; - - case AND_AND: - case OR_OR: - if (asynchronous) - { - /* If we have something like `a && b &' or `a || b &', run the - && or || stuff in a subshell. Force a subshell and just call - execute_command_internal again. Leave asynchronous on - so that we get a report from the parent shell about the - background job. */ - command->flags |= CMD_FORCE_SUBSHELL; - exec_result = execute_command_internal (command, 1, pipe_in, pipe_out, fds_to_close); - break; - } - - /* Execute the first command. If the result of that is successful - and the connector is AND_AND, or the result is not successful - and the connector is OR_OR, then execute the second command, - otherwise return. */ - - executing_list++; - if (command->value.Connection->first) - command->value.Connection->first->flags |= CMD_IGNORE_RETURN; - - exec_result = execute_command (command->value.Connection->first); - QUIT; - if (((command->value.Connection->connector == AND_AND) && - (exec_result == EXECUTION_SUCCESS)) || - ((command->value.Connection->connector == OR_OR) && - (exec_result != EXECUTION_SUCCESS))) - { - second = command->value.Connection->second; - if (ignore_return && second) - second->flags |= CMD_IGNORE_RETURN; - if (should_suppress_fork (second)) - { -itrace ("execute_command_internal: should_suppress_fork returns TRUE"); - second->flags |= CMD_NO_FORK; - second->value.Simple->flags |= CMD_NO_FORK; - } - - exec_result = execute_command (second); - } - executing_list--; - break; - - default: - command_error ("execute_connection", CMDERR_BADCONN, command->value.Connection->connector, 0); - jump_to_top_level (DISCARD); - exec_result = EXECUTION_FAILURE; - } - - return exec_result; -} - -#define REAP() \ - do \ - { \ - if (!interactive_shell) \ - reap_dead_jobs (); \ - } \ - while (0) - -/* Execute a FOR command. The syntax is: FOR word_desc IN word_list; - DO command; DONE */ -static int -execute_for_command (for_command) - FOR_COM *for_command; -{ - register WORD_LIST *releaser, *list; - SHELL_VAR *v; - char *identifier; - int retval, save_line_number; -#if 0 - SHELL_VAR *old_value = (SHELL_VAR *)NULL; /* Remember the old value of x. */ -#endif - - save_line_number = line_number; - if (check_identifier (for_command->name, 1) == 0) - { - if (posixly_correct && interactive_shell == 0) - { - last_command_exit_value = EX_BADUSAGE; - jump_to_top_level (ERREXIT); - } - return (EXECUTION_FAILURE); - } - - loop_level++; - identifier = for_command->name->word; - - line_number = for_command->line; /* for expansion error messages */ - list = releaser = expand_words_no_vars (for_command->map_list); - - begin_unwind_frame ("for"); - add_unwind_protect (dispose_words, releaser); - -#if 0 - if (lexical_scoping) - { - old_value = copy_variable (find_variable (identifier)); - if (old_value) - add_unwind_protect (dispose_variable, old_value); - } -#endif - - if (for_command->flags & CMD_IGNORE_RETURN) - for_command->action->flags |= CMD_IGNORE_RETURN; - - for (retval = EXECUTION_SUCCESS; list; list = list->next) - { - QUIT; - - line_number = for_command->line; - - /* Remember what this command looks like, for debugger. */ - command_string_index = 0; - print_for_command_head (for_command); - - if (echo_command_at_execute) - xtrace_print_for_command_head (for_command); - - /* Save this command unless it's a trap command and we're not running - a debug trap. */ - if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0) - { - FREE (the_printed_command_except_trap); - the_printed_command_except_trap = savestring (the_printed_command); - } - - retval = run_debug_trap (); -#if defined (DEBUGGER) - /* In debugging mode, if the DEBUG trap returns a non-zero status, we - skip the command. */ - if (debugging_mode && retval != EXECUTION_SUCCESS) - continue; -#endif - - this_command_name = (char *)NULL; - /* XXX - special ksh93 for command index variable handling */ - v = find_variable_last_nameref (identifier); - if (v && nameref_p (v)) - { - v = bind_variable_value (v, list->word->word, 0); - } - else - v = bind_variable (identifier, list->word->word, 0); - if (readonly_p (v) || noassign_p (v)) - { - line_number = save_line_number; - if (readonly_p (v) && interactive_shell == 0 && posixly_correct) - { - last_command_exit_value = EXECUTION_FAILURE; - jump_to_top_level (FORCE_EOF); - } - else - { - dispose_words (releaser); - discard_unwind_frame ("for"); - loop_level--; - return (EXECUTION_FAILURE); - } - } - retval = execute_command (for_command->action); - REAP (); - QUIT; - - if (breaking) - { - breaking--; - break; - } - - if (continuing) - { - continuing--; - if (continuing) - break; - } - } - - loop_level--; - line_number = save_line_number; - -#if 0 - if (lexical_scoping) - { - if (!old_value) - unbind_variable (identifier); - else - { - SHELL_VAR *new_value; - - new_value = bind_variable (identifier, value_cell(old_value), 0); - new_value->attributes = old_value->attributes; - dispose_variable (old_value); - } - } -#endif - - dispose_words (releaser); - discard_unwind_frame ("for"); - return (retval); -} - -#if defined (ARITH_FOR_COMMAND) -/* Execute an arithmetic for command. The syntax is - - for (( init ; step ; test )) - do - body - done - - The execution should be exactly equivalent to - - eval \(\( init \)\) - while eval \(\( test \)\) ; do - body; - eval \(\( step \)\) - done -*/ -static intmax_t -eval_arith_for_expr (l, okp) - WORD_LIST *l; - int *okp; -{ - WORD_LIST *new; - intmax_t expresult; - int r; - - new = expand_words_no_vars (l); - if (new) - { - if (echo_command_at_execute) - xtrace_print_arith_cmd (new); - this_command_name = "(("; /* )) for expression error messages */ - - command_string_index = 0; - print_arith_command (new); - if (signal_in_progress (DEBUG_TRAP) == 0) - { - FREE (the_printed_command_except_trap); - the_printed_command_except_trap = savestring (the_printed_command); - } - - r = run_debug_trap (); - /* In debugging mode, if the DEBUG trap returns a non-zero status, we - skip the command. */ -#if defined (DEBUGGER) - if (debugging_mode == 0 || r == EXECUTION_SUCCESS) - expresult = evalexp (new->word->word, okp); - else - { - expresult = 0; - if (okp) - *okp = 1; - } -#else - expresult = evalexp (new->word->word, okp); -#endif - dispose_words (new); - } - else - { - expresult = 0; - if (okp) - *okp = 1; - } - return (expresult); -} - -static int -execute_arith_for_command (arith_for_command) - ARITH_FOR_COM *arith_for_command; -{ - intmax_t expresult; - int expok, body_status, arith_lineno, save_lineno; - - body_status = EXECUTION_SUCCESS; - loop_level++; - save_lineno = line_number; - - if (arith_for_command->flags & CMD_IGNORE_RETURN) - arith_for_command->action->flags |= CMD_IGNORE_RETURN; - - this_command_name = "(("; /* )) for expression error messages */ - - /* save the starting line number of the command so we can reset - line_number before executing each expression -- for $LINENO - and the DEBUG trap. */ - line_number = arith_lineno = arith_for_command->line; - if (variable_context && interactive_shell) - line_number -= function_line_number; - - /* Evaluate the initialization expression. */ - expresult = eval_arith_for_expr (arith_for_command->init, &expok); - if (expok == 0) - { - line_number = save_lineno; - return (EXECUTION_FAILURE); - } - - while (1) - { - /* Evaluate the test expression. */ - line_number = arith_lineno; - expresult = eval_arith_for_expr (arith_for_command->test, &expok); - line_number = save_lineno; - - if (expok == 0) - { - body_status = EXECUTION_FAILURE; - break; - } - REAP (); - if (expresult == 0) - break; - - /* Execute the body of the arithmetic for command. */ - QUIT; - body_status = execute_command (arith_for_command->action); - QUIT; - - /* Handle any `break' or `continue' commands executed by the body. */ - if (breaking) - { - breaking--; - break; - } - - if (continuing) - { - continuing--; - if (continuing) - break; - } - - /* Evaluate the step expression. */ - line_number = arith_lineno; - expresult = eval_arith_for_expr (arith_for_command->step, &expok); - line_number = save_lineno; - - if (expok == 0) - { - body_status = EXECUTION_FAILURE; - break; - } - } - - loop_level--; - line_number = save_lineno; - - return (body_status); -} -#endif - -#if defined (SELECT_COMMAND) -static int LINES, COLS, tabsize; - -#define RP_SPACE ") " -#define RP_SPACE_LEN 2 - -/* XXX - does not handle numbers > 1000000 at all. */ -#define NUMBER_LEN(s) \ -((s < 10) ? 1 \ - : ((s < 100) ? 2 \ - : ((s < 1000) ? 3 \ - : ((s < 10000) ? 4 \ - : ((s < 100000) ? 5 \ - : 6))))) - -static int -displen (s) - const char *s; -{ -#if defined (HANDLE_MULTIBYTE) - wchar_t *wcstr; - size_t slen; - int wclen; - - wcstr = 0; - slen = mbstowcs (wcstr, s, 0); - if (slen == -1) - slen = 0; - wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (slen + 1)); - mbstowcs (wcstr, s, slen + 1); - wclen = wcswidth (wcstr, slen); - free (wcstr); - return (wclen < 0 ? STRLEN(s) : wclen); -#else - return (STRLEN (s)); -#endif -} - -static int -print_index_and_element (len, ind, list) - int len, ind; - WORD_LIST *list; -{ - register WORD_LIST *l; - register int i; - - if (list == 0) - return (0); - for (i = ind, l = list; l && --i; l = l->next) - ; - if (l == 0) /* don't think this can happen */ - return (0); - fprintf (stderr, "%*d%s%s", len, ind, RP_SPACE, l->word->word); - return (displen (l->word->word)); -} - -static void -indent (from, to) - int from, to; -{ - while (from < to) - { - if ((to / tabsize) > (from / tabsize)) - { - putc ('\t', stderr); - from += tabsize - from % tabsize; - } - else - { - putc (' ', stderr); - from++; - } - } -} - -static void -print_select_list (list, list_len, max_elem_len, indices_len) - WORD_LIST *list; - int list_len, max_elem_len, indices_len; -{ - int ind, row, elem_len, pos, cols, rows; - int first_column_indices_len, other_indices_len; - - if (list == 0) - { - putc ('\n', stderr); - return; - } - - cols = max_elem_len ? COLS / max_elem_len : 1; - if (cols == 0) - cols = 1; - rows = list_len ? list_len / cols + (list_len % cols != 0) : 1; - cols = list_len ? list_len / rows + (list_len % rows != 0) : 1; - - if (rows == 1) - { - rows = cols; - cols = 1; - } - - first_column_indices_len = NUMBER_LEN (rows); - other_indices_len = indices_len; - - for (row = 0; row < rows; row++) - { - ind = row; - pos = 0; - while (1) - { - indices_len = (pos == 0) ? first_column_indices_len : other_indices_len; - elem_len = print_index_and_element (indices_len, ind + 1, list); - elem_len += indices_len + RP_SPACE_LEN; - ind += rows; - if (ind >= list_len) - break; - indent (pos + elem_len, pos + max_elem_len); - pos += max_elem_len; - } - putc ('\n', stderr); - } -} - -/* Print the elements of LIST, one per line, preceded by an index from 1 to - LIST_LEN. Then display PROMPT and wait for the user to enter a number. - If the number is between 1 and LIST_LEN, return that selection. If EOF - is read, return a null string. If a blank line is entered, or an invalid - number is entered, the loop is executed again. */ -static char * -select_query (list, list_len, prompt, print_menu) - WORD_LIST *list; - int list_len; - char *prompt; - int print_menu; -{ - int max_elem_len, indices_len, len; - intmax_t reply; - WORD_LIST *l; - char *repl_string, *t; - -#if 0 - t = get_string_value ("LINES"); - LINES = (t && *t) ? atoi (t) : 24; -#endif - t = get_string_value ("COLUMNS"); - COLS = (t && *t) ? atoi (t) : 80; - -#if 0 - t = get_string_value ("TABSIZE"); - tabsize = (t && *t) ? atoi (t) : 8; - if (tabsize <= 0) - tabsize = 8; -#else - tabsize = 8; -#endif - - max_elem_len = 0; - for (l = list; l; l = l->next) - { - len = displen (l->word->word); - if (len > max_elem_len) - max_elem_len = len; - } - indices_len = NUMBER_LEN (list_len); - max_elem_len += indices_len + RP_SPACE_LEN + 2; - - while (1) - { - if (print_menu) - print_select_list (list, list_len, max_elem_len, indices_len); - fprintf (stderr, "%s", prompt); - fflush (stderr); - QUIT; - - if (read_builtin ((WORD_LIST *)NULL) != EXECUTION_SUCCESS) - { - putchar ('\n'); - return ((char *)NULL); - } - repl_string = get_string_value ("REPLY"); - if (*repl_string == 0) - { - print_menu = 1; - continue; - } - if (legal_number (repl_string, &reply) == 0) - return ""; - if (reply < 1 || reply > list_len) - return ""; - - for (l = list; l && --reply; l = l->next) - ; - return (l->word->word); /* XXX - can't be null? */ - } -} - -/* Execute a SELECT command. The syntax is: - SELECT word IN list DO command_list DONE - Only `break' or `return' in command_list will terminate - the command. */ -static int -execute_select_command (select_command) - SELECT_COM *select_command; -{ - WORD_LIST *releaser, *list; - SHELL_VAR *v; - char *identifier, *ps3_prompt, *selection; - int retval, list_len, show_menu, save_line_number; - - if (check_identifier (select_command->name, 1) == 0) - return (EXECUTION_FAILURE); - - save_line_number = line_number; - line_number = select_command->line; - - command_string_index = 0; - print_select_command_head (select_command); - - if (echo_command_at_execute) - xtrace_print_select_command_head (select_command); - -#if 0 - if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0))) -#else - if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0) -#endif - { - FREE (the_printed_command_except_trap); - the_printed_command_except_trap = savestring (the_printed_command); - } - - retval = run_debug_trap (); -#if defined (DEBUGGER) - /* In debugging mode, if the DEBUG trap returns a non-zero status, we - skip the command. */ - if (debugging_mode && retval != EXECUTION_SUCCESS) - return (EXECUTION_SUCCESS); -#endif - - loop_level++; - identifier = select_command->name->word; - - /* command and arithmetic substitution, parameter and variable expansion, - word splitting, pathname expansion, and quote removal. */ - list = releaser = expand_words_no_vars (select_command->map_list); - list_len = list_length (list); - if (list == 0 || list_len == 0) - { - if (list) - dispose_words (list); - line_number = save_line_number; - return (EXECUTION_SUCCESS); - } - - begin_unwind_frame ("select"); - add_unwind_protect (dispose_words, releaser); - - if (select_command->flags & CMD_IGNORE_RETURN) - select_command->action->flags |= CMD_IGNORE_RETURN; - - retval = EXECUTION_SUCCESS; - show_menu = 1; - - while (1) - { - line_number = select_command->line; - ps3_prompt = get_string_value ("PS3"); - if (ps3_prompt == 0) - ps3_prompt = "#? "; - - QUIT; - selection = select_query (list, list_len, ps3_prompt, show_menu); - QUIT; - if (selection == 0) - { - /* select_query returns EXECUTION_FAILURE if the read builtin - fails, so we want to return failure in this case. */ - retval = EXECUTION_FAILURE; - break; - } - - v = bind_variable (identifier, selection, 0); - if (readonly_p (v) || noassign_p (v)) - { - if (readonly_p (v) && interactive_shell == 0 && posixly_correct) - { - last_command_exit_value = EXECUTION_FAILURE; - jump_to_top_level (FORCE_EOF); - } - else - { - dispose_words (releaser); - discard_unwind_frame ("select"); - loop_level--; - line_number = save_line_number; - return (EXECUTION_FAILURE); - } - } - - retval = execute_command (select_command->action); - - REAP (); - QUIT; - - if (breaking) - { - breaking--; - break; - } - - if (continuing) - { - continuing--; - if (continuing) - break; - } - -#if defined (KSH_COMPATIBLE_SELECT) - show_menu = 0; - selection = get_string_value ("REPLY"); - if (selection && *selection == '\0') - show_menu = 1; -#endif - } - - loop_level--; - line_number = save_line_number; - - dispose_words (releaser); - discard_unwind_frame ("select"); - return (retval); -} -#endif /* SELECT_COMMAND */ - -/* Execute a CASE command. The syntax is: CASE word_desc IN pattern_list ESAC. - The pattern_list is a linked list of pattern clauses; each clause contains - some patterns to compare word_desc against, and an associated command to - execute. */ -static int -execute_case_command (case_command) - CASE_COM *case_command; -{ - register WORD_LIST *list; - WORD_LIST *wlist, *es; - PATTERN_LIST *clauses; - char *word, *pattern; - int retval, match, ignore_return, save_line_number; - - save_line_number = line_number; - line_number = case_command->line; - - command_string_index = 0; - print_case_command_head (case_command); - - if (echo_command_at_execute) - xtrace_print_case_command_head (case_command); - -#if 0 - if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0))) -#else - if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0) -#endif - { - FREE (the_printed_command_except_trap); - the_printed_command_except_trap = savestring (the_printed_command); - } - - retval = run_debug_trap(); -#if defined (DEBUGGER) - /* In debugging mode, if the DEBUG trap returns a non-zero status, we - skip the command. */ - if (debugging_mode && retval != EXECUTION_SUCCESS) - { - line_number = save_line_number; - return (EXECUTION_SUCCESS); - } -#endif - - wlist = expand_word_unsplit (case_command->word, 0); - word = wlist ? string_list (wlist) : savestring (""); - dispose_words (wlist); - - retval = EXECUTION_SUCCESS; - ignore_return = case_command->flags & CMD_IGNORE_RETURN; - - begin_unwind_frame ("case"); - add_unwind_protect (xfree, word); - -#define EXIT_CASE() goto exit_case_command - - for (clauses = case_command->clauses; clauses; clauses = clauses->next) - { - QUIT; - for (list = clauses->patterns; list; list = list->next) - { - es = expand_word_leave_quoted (list->word, 0); - - if (es && es->word && es->word->word && *(es->word->word)) - pattern = quote_string_for_globbing (es->word->word, QGLOB_CVTNULL); - else - { - pattern = (char *)xmalloc (1); - pattern[0] = '\0'; - } - - /* Since the pattern does not undergo quote removal (as per - Posix.2, section 3.9.4.3), the strmatch () call must be able - to recognize backslashes as escape characters. */ - match = strmatch (pattern, word, FNMATCH_EXTFLAG|FNMATCH_IGNCASE) != FNM_NOMATCH; - free (pattern); - - dispose_words (es); - - if (match) - { - do - { - if (clauses->action && ignore_return) - clauses->action->flags |= CMD_IGNORE_RETURN; - retval = execute_command (clauses->action); - } - while ((clauses->flags & CASEPAT_FALLTHROUGH) && (clauses = clauses->next)); - if (clauses == 0 || (clauses->flags & CASEPAT_TESTNEXT) == 0) - EXIT_CASE (); - else - break; - } - - QUIT; - } - } - -exit_case_command: - free (word); - discard_unwind_frame ("case"); - line_number = save_line_number; - return (retval); -} - -#define CMD_WHILE 0 -#define CMD_UNTIL 1 - -/* The WHILE command. Syntax: WHILE test DO action; DONE. - Repeatedly execute action while executing test produces - EXECUTION_SUCCESS. */ -static int -execute_while_command (while_command) - WHILE_COM *while_command; -{ - return (execute_while_or_until (while_command, CMD_WHILE)); -} - -/* UNTIL is just like WHILE except that the test result is negated. */ -static int -execute_until_command (while_command) - WHILE_COM *while_command; -{ - return (execute_while_or_until (while_command, CMD_UNTIL)); -} - -/* The body for both while and until. The only difference between the - two is that the test value is treated differently. TYPE is - CMD_WHILE or CMD_UNTIL. The return value for both commands should - be EXECUTION_SUCCESS if no commands in the body are executed, and - the status of the last command executed in the body otherwise. */ -static int -execute_while_or_until (while_command, type) - WHILE_COM *while_command; - int type; -{ - int return_value, body_status; - - body_status = EXECUTION_SUCCESS; - loop_level++; - - while_command->test->flags |= CMD_IGNORE_RETURN; - if (while_command->flags & CMD_IGNORE_RETURN) - while_command->action->flags |= CMD_IGNORE_RETURN; - - while (1) - { - return_value = execute_command (while_command->test); - REAP (); - - /* Need to handle `break' in the test when we would break out of the - loop. The job control code will set `breaking' to loop_level - when a job in a loop is stopped with SIGTSTP. If the stopped job - is in the loop test, `breaking' will not be reset unless we do - this, and the shell will cease to execute commands. */ - if (type == CMD_WHILE && return_value != EXECUTION_SUCCESS) - { - if (breaking) - breaking--; - break; - } - if (type == CMD_UNTIL && return_value == EXECUTION_SUCCESS) - { - if (breaking) - breaking--; - break; - } - - QUIT; - body_status = execute_command (while_command->action); - QUIT; - - if (breaking) - { - breaking--; - break; - } - - if (continuing) - { - continuing--; - if (continuing) - break; - } - } - loop_level--; - - return (body_status); -} - -/* IF test THEN command [ELSE command]. - IF also allows ELIF in the place of ELSE IF, but - the parser makes *that* stupidity transparent. */ -static int -execute_if_command (if_command) - IF_COM *if_command; -{ - int return_value, save_line_number; - - save_line_number = line_number; - if_command->test->flags |= CMD_IGNORE_RETURN; - return_value = execute_command (if_command->test); - line_number = save_line_number; - - if (return_value == EXECUTION_SUCCESS) - { - QUIT; - - if (if_command->true_case && (if_command->flags & CMD_IGNORE_RETURN)) - if_command->true_case->flags |= CMD_IGNORE_RETURN; - - return (execute_command (if_command->true_case)); - } - else - { - QUIT; - - if (if_command->false_case && (if_command->flags & CMD_IGNORE_RETURN)) - if_command->false_case->flags |= CMD_IGNORE_RETURN; - - return (execute_command (if_command->false_case)); - } -} - -#if defined (DPAREN_ARITHMETIC) -static int -execute_arith_command (arith_command) - ARITH_COM *arith_command; -{ - int expok, save_line_number, retval; - intmax_t expresult; - WORD_LIST *new; - char *exp; - - expresult = 0; - - save_line_number = line_number; - this_command_name = "(("; /* )) */ - line_number = arith_command->line; - /* If we're in a function, update the line number information. */ - if (variable_context && interactive_shell) - line_number -= function_line_number; - - command_string_index = 0; - print_arith_command (arith_command->exp); - - if (signal_in_progress (DEBUG_TRAP) == 0) - { - FREE (the_printed_command_except_trap); - the_printed_command_except_trap = savestring (the_printed_command); - } - - /* Run the debug trap before each arithmetic command, but do it after we - update the line number information and before we expand the various - words in the expression. */ - retval = run_debug_trap (); -#if defined (DEBUGGER) - /* In debugging mode, if the DEBUG trap returns a non-zero status, we - skip the command. */ - if (debugging_mode && retval != EXECUTION_SUCCESS) - { - line_number = save_line_number; - return (EXECUTION_SUCCESS); - } -#endif - - new = expand_words_no_vars (arith_command->exp); - - /* If we're tracing, make a new word list with `((' at the front and `))' - at the back and print it. */ - if (echo_command_at_execute) - xtrace_print_arith_cmd (new); - - if (new) - { - exp = new->next ? string_list (new) : new->word->word; - expresult = evalexp (exp, &expok); - line_number = save_line_number; - if (exp != new->word->word) - free (exp); - dispose_words (new); - } - else - { - expresult = 0; - expok = 1; - } - - if (expok == 0) - return (EXECUTION_FAILURE); - - return (expresult == 0 ? EXECUTION_FAILURE : EXECUTION_SUCCESS); -} -#endif /* DPAREN_ARITHMETIC */ - -#if defined (COND_COMMAND) - -static char * const nullstr = ""; - -/* XXX - can COND ever be NULL when this is called? */ -static int -execute_cond_node (cond) - COND_COM *cond; -{ - int result, invert, patmatch, rmatch, mflags, ignore; - char *arg1, *arg2; -#if 0 - char *t1, *t2; -#endif - - invert = (cond->flags & CMD_INVERT_RETURN); - ignore = (cond->flags & CMD_IGNORE_RETURN); - if (ignore) - { - if (cond->left) - cond->left->flags |= CMD_IGNORE_RETURN; - if (cond->right) - cond->right->flags |= CMD_IGNORE_RETURN; - } - - if (cond->type == COND_EXPR) - result = execute_cond_node (cond->left); - else if (cond->type == COND_OR) - { - result = execute_cond_node (cond->left); - if (result != EXECUTION_SUCCESS) - result = execute_cond_node (cond->right); - } - else if (cond->type == COND_AND) - { - result = execute_cond_node (cond->left); - if (result == EXECUTION_SUCCESS) - result = execute_cond_node (cond->right); - } - else if (cond->type == COND_UNARY) - { - if (ignore) - comsub_ignore_return++; - arg1 = cond_expand_word (cond->left->op, 0); - if (ignore) - comsub_ignore_return--; - if (arg1 == 0) - arg1 = nullstr; - if (echo_command_at_execute) - xtrace_print_cond_term (cond->type, invert, cond->op, arg1, (char *)NULL); - result = unary_test (cond->op->word, arg1) ? EXECUTION_SUCCESS : EXECUTION_FAILURE; - if (arg1 != nullstr) - free (arg1); - } - else if (cond->type == COND_BINARY) - { - rmatch = 0; - patmatch = (((cond->op->word[1] == '=') && (cond->op->word[2] == '\0') && - (cond->op->word[0] == '!' || cond->op->word[0] == '=')) || - (cond->op->word[0] == '=' && cond->op->word[1] == '\0')); -#if defined (COND_REGEXP) - rmatch = (cond->op->word[0] == '=' && cond->op->word[1] == '~' && - cond->op->word[2] == '\0'); -#endif - - if (ignore) - comsub_ignore_return++; - arg1 = cond_expand_word (cond->left->op, 0); - if (ignore) - comsub_ignore_return--; - if (arg1 == 0) - arg1 = nullstr; - if (ignore) - comsub_ignore_return++; - arg2 = cond_expand_word (cond->right->op, - (rmatch && shell_compatibility_level > 31) ? 2 : (patmatch ? 1 : 0)); - if (ignore) - comsub_ignore_return--; - if (arg2 == 0) - arg2 = nullstr; - - if (echo_command_at_execute) - xtrace_print_cond_term (cond->type, invert, cond->op, arg1, arg2); - -#if defined (COND_REGEXP) - if (rmatch) - { - mflags = SHMAT_PWARN; -#if defined (ARRAY_VARS) - mflags |= SHMAT_SUBEXP; -#endif - -#if 0 - t1 = strescape(arg1); - t2 = strescape(arg2); - itrace("execute_cond_node: sh_regmatch on `%s' and `%s'", t1, t2); - free(t1); - free(t2); -#endif - - result = sh_regmatch (arg1, arg2, mflags); - } - else -#endif /* COND_REGEXP */ - { - int oe; - oe = extended_glob; - extended_glob = 1; - result = binary_test (cond->op->word, arg1, arg2, TEST_PATMATCH|TEST_ARITHEXP|TEST_LOCALE) - ? EXECUTION_SUCCESS - : EXECUTION_FAILURE; - extended_glob = oe; - } - if (arg1 != nullstr) - free (arg1); - if (arg2 != nullstr) - free (arg2); - } - else - { - command_error ("execute_cond_node", CMDERR_BADTYPE, cond->type, 0); - jump_to_top_level (DISCARD); - result = EXECUTION_FAILURE; - } - - if (invert) - result = (result == EXECUTION_SUCCESS) ? EXECUTION_FAILURE : EXECUTION_SUCCESS; - - return result; -} - -static int -execute_cond_command (cond_command) - COND_COM *cond_command; -{ - int retval, save_line_number; - - retval = EXECUTION_SUCCESS; - save_line_number = line_number; - - this_command_name = "[["; - line_number = cond_command->line; - /* If we're in a function, update the line number information. */ - if (variable_context && interactive_shell) - line_number -= function_line_number; - command_string_index = 0; - print_cond_command (cond_command); - - if (signal_in_progress (DEBUG_TRAP) == 0) - { - FREE (the_printed_command_except_trap); - the_printed_command_except_trap = savestring (the_printed_command); - } - - /* Run the debug trap before each conditional command, but do it after we - update the line number information. */ - retval = run_debug_trap (); -#if defined (DEBUGGER) - /* In debugging mode, if the DEBUG trap returns a non-zero status, we - skip the command. */ - if (debugging_mode && retval != EXECUTION_SUCCESS) - { - line_number = save_line_number; - return (EXECUTION_SUCCESS); - } -#endif - -#if 0 - debug_print_cond_command (cond_command); -#endif - - last_command_exit_value = retval = execute_cond_node (cond_command); - line_number = save_line_number; - return (retval); -} -#endif /* COND_COMMAND */ - -static void -bind_lastarg (arg) - char *arg; -{ - SHELL_VAR *var; - - if (arg == 0) - arg = ""; - var = bind_variable ("_", arg, 0); - VUNSETATTR (var, att_exported); -} - -/* Execute a null command. Fork a subshell if the command uses pipes or is - to be run asynchronously. This handles all the side effects that are - supposed to take place. */ -static int -execute_null_command (redirects, pipe_in, pipe_out, async) - REDIRECT *redirects; - int pipe_in, pipe_out, async; -{ - int r; - int forcefork; - REDIRECT *rd; - - for (forcefork = 0, rd = redirects; rd; rd = rd->next) - forcefork += rd->rflags & REDIR_VARASSIGN; - - if (forcefork || pipe_in != NO_PIPE || pipe_out != NO_PIPE || async) - { - /* We have a null command, but we really want a subshell to take - care of it. Just fork, do piping and redirections, and exit. */ - if (make_child ((char *)NULL, async) == 0) - { - /* Cancel traps, in trap.c. */ - restore_original_signals (); /* XXX */ - - do_piping (pipe_in, pipe_out); - -#if defined (COPROCESS_SUPPORT) - coproc_closeall (); -#endif - - subshell_environment = 0; - if (async) - subshell_environment |= SUBSHELL_ASYNC; - if (pipe_in != NO_PIPE || pipe_out != NO_PIPE) - subshell_environment |= SUBSHELL_PIPE; - - if (do_redirections (redirects, RX_ACTIVE) == 0) - exit (EXECUTION_SUCCESS); - else - exit (EXECUTION_FAILURE); - } - else - { - close_pipes (pipe_in, pipe_out); -#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD) - if (pipe_out == NO_PIPE) - unlink_fifo_list (); -#endif - return (EXECUTION_SUCCESS); - } - } - else - { - /* Even if there aren't any command names, pretend to do the - redirections that are specified. The user expects the side - effects to take place. If the redirections fail, then return - failure. Otherwise, if a command substitution took place while - expanding the command or a redirection, return the value of that - substitution. Otherwise, return EXECUTION_SUCCESS. */ - - r = do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE); - cleanup_redirects (redirection_undo_list); - redirection_undo_list = (REDIRECT *)NULL; - - if (r != 0) - return (EXECUTION_FAILURE); - else if (last_command_subst_pid != NO_PID) - return (last_command_exit_value); - else - return (EXECUTION_SUCCESS); - } -} - -/* This is a hack to suppress word splitting for assignment statements - given as arguments to builtins with the ASSIGNMENT_BUILTIN flag set. */ -static void -fix_assignment_words (words) - WORD_LIST *words; -{ - WORD_LIST *w, *wcmd; - struct builtin *b; - int assoc, global, array, integer; - - if (words == 0) - return; - - b = 0; - assoc = global = array = integer = 0; - - /* Skip over assignment statements preceding a command name */ - wcmd = words; - for (wcmd = words; wcmd; wcmd = wcmd->next) - if ((wcmd->word->flags & W_ASSIGNMENT) == 0) - break; - - for (w = wcmd; w; w = w->next) - if (w->word->flags & W_ASSIGNMENT) - { - if (b == 0) - { - /* Posix (post-2008) says that `command' doesn't change whether - or not the builtin it shadows is a `declaration command', even - though it removes other special builtin properties. In Posix - mode, we skip over one or more instances of `command' and - deal with the next word as the assignment builtin. */ - while (posixly_correct && wcmd && wcmd->word && wcmd->word->word && STREQ (wcmd->word->word, "command")) - wcmd = wcmd->next; - b = builtin_address_internal (wcmd->word->word, 0); - if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0) - return; - else if (b && (b->flags & ASSIGNMENT_BUILTIN)) - wcmd->word->flags |= W_ASSNBLTIN; - } - w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP|W_ASSIGNARG); -#if defined (ARRAY_VARS) - if (assoc) - w->word->flags |= W_ASSIGNASSOC; - if (array) - w->word->flags |= W_ASSIGNARRAY; -#endif - if (global) - w->word->flags |= W_ASSNGLOBAL; - } -#if defined (ARRAY_VARS) - /* Note that we saw an associative array option to a builtin that takes - assignment statements. This is a bit of a kludge. */ - else if (w->word->word[0] == '-' && (strpbrk (w->word->word+1, "Aag") != 0)) -#else - else if (w->word->word[0] == '-' && strchr (w->word->word+1, 'g')) -#endif - { - if (b == 0) - { - while (posixly_correct && wcmd && wcmd->word && wcmd->word->word && STREQ (wcmd->word->word, "command")) - wcmd = wcmd->next; - b = builtin_address_internal (wcmd->word->word, 0); - if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0) - return; - else if (b && (b->flags & ASSIGNMENT_BUILTIN)) - wcmd->word->flags |= W_ASSNBLTIN; - } - if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'A')) - assoc = 1; - else if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'a')) - array = 1; - if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'g')) - global = 1; - } -} - -/* Return 1 if the file found by searching $PATH for PATHNAME, defaulting - to PATHNAME, is a directory. Used by the autocd code below. */ -static int -is_dirname (pathname) - char *pathname; -{ - char *temp; - int ret; - - temp = search_for_command (pathname, 0); - ret = (temp ? file_isdir (temp) : file_isdir (pathname)); - free (temp); - return ret; -} - -/* The meaty part of all the executions. We have to start hacking the - real execution of commands here. Fork a process, set things up, - execute the command. */ -static int -execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close) - SIMPLE_COM *simple_command; - int pipe_in, pipe_out, async; - struct fd_bitmap *fds_to_close; -{ - WORD_LIST *words, *lastword; - char *command_line, *lastarg, *temp; - int first_word_quoted, result, builtin_is_special, already_forked, dofork; - pid_t old_last_async_pid; - sh_builtin_func_t *builtin; - SHELL_VAR *func; - volatile int old_builtin, old_command_builtin; - - result = EXECUTION_SUCCESS; - special_builtin_failed = builtin_is_special = 0; - command_line = (char *)0; - - QUIT; - - /* If we're in a function, update the line number information. */ - if (variable_context && interactive_shell && sourcelevel == 0) - line_number -= function_line_number; - - /* Remember what this command line looks like at invocation. */ - command_string_index = 0; - print_simple_command (simple_command); - -#if 0 - if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0))) -#else - if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0) -#endif - { - FREE (the_printed_command_except_trap); - the_printed_command_except_trap = the_printed_command ? savestring (the_printed_command) : (char *)0; - } - - /* Run the debug trap before each simple command, but do it after we - update the line number information. */ - result = run_debug_trap (); -#if defined (DEBUGGER) - /* In debugging mode, if the DEBUG trap returns a non-zero status, we - skip the command. */ - if (debugging_mode && result != EXECUTION_SUCCESS) - return (EXECUTION_SUCCESS); -#endif - - first_word_quoted = - simple_command->words ? (simple_command->words->word->flags & W_QUOTED) : 0; - - last_command_subst_pid = NO_PID; - old_last_async_pid = last_asynchronous_pid; - - already_forked = dofork = 0; - - /* If we're in a pipeline or run in the background, set DOFORK so we - make the child early, before word expansion. This keeps assignment - statements from affecting the parent shell's environment when they - should not. */ - dofork = pipe_in != NO_PIPE || pipe_out != NO_PIPE || async; - - /* Something like `%2 &' should restart job 2 in the background, not cause - the shell to fork here. */ - if (dofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE && - simple_command->words && simple_command->words->word && - simple_command->words->word->word && - (simple_command->words->word->word[0] == '%')) - dofork = 0; - - if (dofork) - { - /* Do this now, because execute_disk_command will do it anyway in the - vast majority of cases. */ - maybe_make_export_env (); - - /* Don't let a DEBUG trap overwrite the command string to be saved with - the process/job associated with this child. */ - if (make_child (savestring (the_printed_command_except_trap), async) == 0) - { - already_forked = 1; - simple_command->flags |= CMD_NO_FORK; - - subshell_environment = SUBSHELL_FORK; /* XXX */ - if (pipe_in != NO_PIPE || pipe_out != NO_PIPE) - subshell_environment |= SUBSHELL_PIPE; - if (async) - subshell_environment |= SUBSHELL_ASYNC; - - /* We need to do this before piping to handle some really - pathological cases where one of the pipe file descriptors - is < 2. */ - if (fds_to_close) - close_fd_bitmap (fds_to_close); - - do_piping (pipe_in, pipe_out); - pipe_in = pipe_out = NO_PIPE; -#if defined (COPROCESS_SUPPORT) - coproc_closeall (); -#endif - - last_asynchronous_pid = old_last_async_pid; - - CHECK_SIGTERM; - } - else - { - /* Don't let simple commands that aren't the last command in a - pipeline change $? for the rest of the pipeline (or at all). */ - if (pipe_out != NO_PIPE) - result = last_command_exit_value; - close_pipes (pipe_in, pipe_out); -#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD) - /* Close /dev/fd file descriptors in the parent after forking the - last child in a (possibly one-element) pipeline. Defer this - until any running shell function completes. */ - if (pipe_out == NO_PIPE && variable_context == 0) /* XXX */ - unlink_fifo_list (); /* XXX */ -#endif - command_line = (char *)NULL; /* don't free this. */ - bind_lastarg ((char *)NULL); - return (result); - } - } - - /* If we are re-running this as the result of executing the `command' - builtin, do not expand the command words a second time. */ - if ((simple_command->flags & CMD_INHIBIT_EXPANSION) == 0) - { - current_fds_to_close = fds_to_close; - fix_assignment_words (simple_command->words); - /* Pass the ignore return flag down to command substitutions */ - if (simple_command->flags & CMD_IGNORE_RETURN) /* XXX */ - comsub_ignore_return++; - words = expand_words (simple_command->words); - if (simple_command->flags & CMD_IGNORE_RETURN) - comsub_ignore_return--; - current_fds_to_close = (struct fd_bitmap *)NULL; - } - else - words = copy_word_list (simple_command->words); - - /* It is possible for WORDS not to have anything left in it. - Perhaps all the words consisted of `$foo', and there was - no variable `$foo'. */ - if (words == 0) - { - this_command_name = 0; - result = execute_null_command (simple_command->redirects, - pipe_in, pipe_out, - already_forked ? 0 : async); - if (already_forked) - exit (result); - else - { - bind_lastarg ((char *)NULL); - set_pipestatus_from_exit (result); - return (result); - } - } - - lastarg = (char *)NULL; - - begin_unwind_frame ("simple-command"); - - if (echo_command_at_execute) - xtrace_print_word_list (words, 1); - - builtin = (sh_builtin_func_t *)NULL; - func = (SHELL_VAR *)NULL; - if ((simple_command->flags & CMD_NO_FUNCTIONS) == 0) - { - /* Posix.2 says special builtins are found before functions. We - don't set builtin_is_special anywhere other than here, because - this path is followed only when the `command' builtin is *not* - being used, and we don't want to exit the shell if a special - builtin executed with `command builtin' fails. `command' is not - a special builtin. */ - if (posixly_correct) - { - builtin = find_special_builtin (words->word->word); - if (builtin) - builtin_is_special = 1; - } - if (builtin == 0) - func = find_function (words->word->word); - } - - /* In POSIX mode, assignment errors in the temporary environment cause a - non-interactive shell to exit. */ - if (posixly_correct && builtin_is_special && interactive_shell == 0 && tempenv_assign_error) - { - last_command_exit_value = EXECUTION_FAILURE; - jump_to_top_level (ERREXIT); - } - tempenv_assign_error = 0; /* don't care about this any more */ - - add_unwind_protect (dispose_words, words); - QUIT; - - /* Bind the last word in this command to "$_" after execution. */ - for (lastword = words; lastword->next; lastword = lastword->next) - ; - lastarg = lastword->word->word; - -#if defined (JOB_CONTROL) - /* Is this command a job control related thing? */ - if (words->word->word[0] == '%' && already_forked == 0) - { - this_command_name = async ? "bg" : "fg"; - last_shell_builtin = this_shell_builtin; - this_shell_builtin = builtin_address (this_command_name); - result = (*this_shell_builtin) (words); - goto return_result; - } - - /* One other possibililty. The user may want to resume an existing job. - If they do, find out whether this word is a candidate for a running - job. */ - if (job_control && already_forked == 0 && async == 0 && - !first_word_quoted && - !words->next && - words->word->word[0] && - !simple_command->redirects && - pipe_in == NO_PIPE && - pipe_out == NO_PIPE && - (temp = get_string_value ("auto_resume"))) - { - int job, jflags, started_status; - - jflags = JM_STOPPED|JM_FIRSTMATCH; - if (STREQ (temp, "exact")) - jflags |= JM_EXACT; - else if (STREQ (temp, "substring")) - jflags |= JM_SUBSTRING; - else - jflags |= JM_PREFIX; - job = get_job_by_name (words->word->word, jflags); - if (job != NO_JOB) - { - run_unwind_frame ("simple-command"); - this_command_name = "fg"; - last_shell_builtin = this_shell_builtin; - this_shell_builtin = builtin_address ("fg"); - - started_status = start_job (job, 1); - return ((started_status < 0) ? EXECUTION_FAILURE : started_status); - } - } -#endif /* JOB_CONTROL */ - -run_builtin: - /* Remember the name of this command globally. */ - this_command_name = words->word->word; - - QUIT; - - /* This command could be a shell builtin or a user-defined function. - We have already found special builtins by this time, so we do not - set builtin_is_special. If this is a function or builtin, and we - have pipes, then fork a subshell in here. Otherwise, just execute - the command directly. */ - if (func == 0 && builtin == 0) - builtin = find_shell_builtin (this_command_name); - - last_shell_builtin = this_shell_builtin; - this_shell_builtin = builtin; - - if (builtin || func) - { - if (builtin) - { - old_builtin = executing_builtin; - old_command_builtin = executing_command_builtin; - unwind_protect_int (executing_builtin); /* modified in execute_builtin */ - unwind_protect_int (executing_command_builtin); /* ditto */ - } - if (already_forked) - { - /* reset_terminating_signals (); */ /* XXX */ - /* 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 (async) - { - if ((simple_command->flags & CMD_STDIN_REDIR) && - pipe_in == NO_PIPE && - (stdin_redirects (simple_command->redirects) == 0)) - async_redirect_stdin (); - setup_async_signals (); - } - - subshell_level++; - execute_subshell_builtin_or_function - (words, simple_command->redirects, builtin, func, - pipe_in, pipe_out, async, fds_to_close, - simple_command->flags); - subshell_level--; - } - else - { - result = execute_builtin_or_function - (words, builtin, func, simple_command->redirects, fds_to_close, - simple_command->flags); - if (builtin) - { - if (result > EX_SHERRBASE) - { - switch (result) - { - case EX_REDIRFAIL: - case EX_BADASSIGN: - case EX_EXPFAIL: - /* These errors cause non-interactive posix mode shells to exit */ - if (posixly_correct && builtin_is_special && interactive_shell == 0) - { - last_command_exit_value = EXECUTION_FAILURE; - jump_to_top_level (ERREXIT); - } - } - result = builtin_status (result); - if (builtin_is_special) - special_builtin_failed = 1; - } - /* In POSIX mode, if there are assignment statements preceding - a special builtin, they persist after the builtin - completes. */ - if (posixly_correct && builtin_is_special && temporary_env) - merge_temporary_env (); - } - else /* function */ - { - if (result == EX_USAGE) - result = EX_BADUSAGE; - else if (result > EX_SHERRBASE) - result = EXECUTION_FAILURE; - } - - set_pipestatus_from_exit (result); - - goto return_result; - } - } - - if (autocd && interactive && words->word && is_dirname (words->word->word)) - { - words = make_word_list (make_word ("cd"), words); - xtrace_print_word_list (words, 0); - goto run_builtin; - } - - if (command_line == 0) - command_line = savestring (the_printed_command_except_trap ? the_printed_command_except_trap : ""); - -#if defined (PROCESS_SUBSTITUTION) - if ((subshell_environment & SUBSHELL_COMSUB) && (simple_command->flags & CMD_NO_FORK) && fifos_pending() > 0) - simple_command->flags &= ~CMD_NO_FORK; -#endif - - result = execute_disk_command (words, simple_command->redirects, command_line, - pipe_in, pipe_out, async, fds_to_close, - simple_command->flags); - - return_result: - bind_lastarg (lastarg); - FREE (command_line); - dispose_words (words); - if (builtin) - { - executing_builtin = old_builtin; - executing_command_builtin = old_command_builtin; - } - discard_unwind_frame ("simple-command"); - this_command_name = (char *)NULL; /* points to freed memory now */ - return (result); -} - -/* Translate the special builtin exit statuses. We don't really need a - function for this; it's a placeholder for future work. */ -static int -builtin_status (result) - int result; -{ - int r; - - switch (result) - { - case EX_USAGE: - r = EX_BADUSAGE; - break; - case EX_REDIRFAIL: - case EX_BADSYNTAX: - case EX_BADASSIGN: - case EX_EXPFAIL: - r = EXECUTION_FAILURE; - break; - default: - r = EXECUTION_SUCCESS; - break; - } - return (r); -} - -static int -execute_builtin (builtin, words, flags, subshell) - sh_builtin_func_t *builtin; - WORD_LIST *words; - int flags, subshell; -{ - int old_e_flag, result, eval_unwind; - int isbltinenv; - char *error_trap; - - error_trap = 0; - old_e_flag = exit_immediately_on_error; - - /* The eval builtin calls parse_and_execute, which does not know about - the setting of flags, and always calls the execution functions with - flags that will exit the shell on an error if -e is set. If the - eval builtin is being called, and we're supposed to ignore the exit - value of the command, we turn the -e flag off ourselves and disable - the ERR trap, then restore them when the command completes. This is - also a problem (as below) for the command and source/. builtins. */ - if (subshell == 0 && (flags & CMD_IGNORE_RETURN) && - (builtin == eval_builtin || builtin == command_builtin || builtin == source_builtin)) - { - begin_unwind_frame ("eval_builtin"); - unwind_protect_int (exit_immediately_on_error); - unwind_protect_int (builtin_ignoring_errexit); - error_trap = TRAP_STRING (ERROR_TRAP); - if (error_trap) - { - error_trap = savestring (error_trap); - add_unwind_protect (xfree, error_trap); - add_unwind_protect (set_error_trap, error_trap); - restore_default_signal (ERROR_TRAP); - } - exit_immediately_on_error = 0; - builtin_ignoring_errexit = 1; - eval_unwind = 1; - } - else - eval_unwind = 0; - - /* The temporary environment for a builtin is supposed to apply to - all commands executed by that builtin. Currently, this is a - problem only with the `unset', `source' and `eval' builtins. - `mapfile' is a special case because it uses evalstring (same as - eval or source) to run its callbacks. */ - isbltinenv = (builtin == source_builtin || builtin == eval_builtin || builtin == unset_builtin || builtin == mapfile_builtin); - - if (isbltinenv) - { - if (subshell == 0) - begin_unwind_frame ("builtin_env"); - - if (temporary_env) - { - push_scope (VC_BLTNENV, temporary_env); - if (subshell == 0) - add_unwind_protect (pop_scope, (flags & CMD_COMMAND_BUILTIN) ? 0 : "1"); - temporary_env = (HASH_TABLE *)NULL; - } - } - - if (subshell == 0 && builtin == eval_builtin) - { - if (evalnest_max > 0 && evalnest >= evalnest_max) - { - internal_error (_("eval: maximum eval nesting level exceeded (%d)"), evalnest); - evalnest = 0; - jump_to_top_level (DISCARD); - } - unwind_protect_int (evalnest); - /* The test for subshell == 0 above doesn't make a difference */ - evalnest++; /* execute_subshell_builtin_or_function sets this to 0 */ - } - else if (subshell == 0 && builtin == source_builtin) - { - if (sourcenest_max > 0 && sourcenest >= sourcenest_max) - { - internal_error (_("%s: maximum source nesting level exceeded (%d)"), this_command_name, sourcenest); - sourcenest = 0; - jump_to_top_level (DISCARD); - } - unwind_protect_int (sourcenest); - /* The test for subshell == 0 above doesn't make a difference */ - sourcenest++; /* execute_subshell_builtin_or_function sets this to 0 */ - } - - - /* `return' does a longjmp() back to a saved environment in execute_function. - If a variable assignment list preceded the command, and the shell is - running in POSIX mode, we need to merge that into the shell_variables - table, since `return' is a POSIX special builtin. */ - if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env) - { - begin_unwind_frame ("return_temp_env"); - add_unwind_protect (merge_temporary_env, (char *)NULL); - } - - executing_builtin++; - executing_command_builtin |= builtin == command_builtin; - result = ((*builtin) (words->next)); - - /* This shouldn't happen, but in case `return' comes back instead of - longjmp'ing, we need to unwind. */ - if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env) - discard_unwind_frame ("return_temp_env"); - - if (subshell == 0 && isbltinenv) - run_unwind_frame ("builtin_env"); - - if (eval_unwind) - { - exit_immediately_on_error = errexit_flag; - builtin_ignoring_errexit = 0; - if (error_trap) - { - set_error_trap (error_trap); - xfree (error_trap); - } - discard_unwind_frame ("eval_builtin"); - } - - return (result); -} - -static void -maybe_restore_getopt_state (gs) - sh_getopt_state_t *gs; -{ - SHELL_VAR *v; - - /* If we have a local copy of OPTIND and it's at the right (current) - context, then we restore getopt's internal state. If not, we just - let it go. We know there is a local OPTIND if gs->gs_flags & 1. - This is set below in execute_function() before the context is run. */ - if (gs->gs_flags & 1) - sh_getopt_restore_istate (gs); - else - free (gs); -} - -#if defined (ARRAY_VARS) -static void -restore_funcarray_state (fa) - struct func_array_state *fa; -{ - SHELL_VAR *nfv; - ARRAY *funcname_a; - - array_pop (fa->source_a); - array_pop (fa->lineno_a); - - GET_ARRAY_FROM_VAR ("FUNCNAME", nfv, funcname_a); - if (nfv == fa->funcname_v) - array_pop (funcname_a); - - free (fa); -} -#endif - -static int -execute_function (var, words, flags, fds_to_close, async, subshell) - SHELL_VAR *var; - WORD_LIST *words; - int flags; - struct fd_bitmap *fds_to_close; - int async, subshell; -{ - int return_val, result; - COMMAND *tc, *fc, *save_current; - char *debug_trap, *error_trap, *return_trap; -#if defined (ARRAY_VARS) - SHELL_VAR *funcname_v, *bash_source_v, *bash_lineno_v; - ARRAY *funcname_a; - volatile ARRAY *bash_source_a; - volatile ARRAY *bash_lineno_a; - struct func_array_state *fa; -#endif - FUNCTION_DEF *shell_fn; - char *sfile, *t; - sh_getopt_state_t *gs; - SHELL_VAR *gv; - - USE_VAR(fc); - - if (funcnest_max > 0 && funcnest >= funcnest_max) - { - internal_error (_("%s: maximum function nesting level exceeded (%d)"), var->name, funcnest); - funcnest = 0; /* XXX - should we reset it somewhere else? */ - jump_to_top_level (DISCARD); - } - -#if defined (ARRAY_VARS) - GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a); - GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a); - GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a); -#endif - - tc = (COMMAND *)copy_command (function_cell (var)); - if (tc && (flags & CMD_IGNORE_RETURN)) - tc->flags |= CMD_IGNORE_RETURN; - - gs = sh_getopt_save_istate (); - if (subshell == 0) - { - begin_unwind_frame ("function_calling"); - push_context (var->name, subshell, temporary_env); - /* This has to be before the pop_context(), because the unwinding of - local variables may cause the restore of a local declaration of - OPTIND to force a getopts state reset. */ - add_unwind_protect (maybe_restore_getopt_state, gs); - add_unwind_protect (pop_context, (char *)NULL); - unwind_protect_int (line_number); - unwind_protect_int (return_catch_flag); - unwind_protect_jmp_buf (return_catch); - add_unwind_protect (dispose_command, (char *)tc); - unwind_protect_pointer (this_shell_function); - unwind_protect_int (funcnest); - unwind_protect_int (loop_level); - } - else - push_context (var->name, subshell, temporary_env); /* don't unwind-protect for subshells */ - - temporary_env = (HASH_TABLE *)NULL; - - this_shell_function = var; - make_funcname_visible (1); - - debug_trap = TRAP_STRING(DEBUG_TRAP); - error_trap = TRAP_STRING(ERROR_TRAP); - return_trap = TRAP_STRING(RETURN_TRAP); - - /* The order of the unwind protects for debug_trap, error_trap and - return_trap is important here! unwind-protect commands are run - in reverse order of registration. If this causes problems, take - out the xfree unwind-protect calls and live with the small memory leak. */ - - /* function_trace_mode != 0 means that all functions inherit the DEBUG trap. - if the function has the trace attribute set, it inherits the DEBUG trap */ - if (debug_trap && ((trace_p (var) == 0) && function_trace_mode == 0)) - { - if (subshell == 0) - { - debug_trap = savestring (debug_trap); - add_unwind_protect (xfree, debug_trap); - add_unwind_protect (set_debug_trap, debug_trap); - } - restore_default_signal (DEBUG_TRAP); - } - - /* error_trace_mode != 0 means that functions inherit the ERR trap. */ - if (error_trap && error_trace_mode == 0) - { - if (subshell == 0) - { - error_trap = savestring (error_trap); - add_unwind_protect (xfree, error_trap); - add_unwind_protect (set_error_trap, error_trap); - } - restore_default_signal (ERROR_TRAP); - } - - /* Shell functions inherit the RETURN trap if function tracing is on - globally or on individually for this function. */ -#if 0 - if (return_trap && ((trace_p (var) == 0) && function_trace_mode == 0)) -#else - if (return_trap && (signal_in_progress (DEBUG_TRAP) || ((trace_p (var) == 0) && function_trace_mode == 0))) -#endif - { - if (subshell == 0) - { - return_trap = savestring (return_trap); - add_unwind_protect (xfree, return_trap); - add_unwind_protect (set_return_trap, return_trap); - } - restore_default_signal (RETURN_TRAP); - } - - funcnest++; -#if defined (ARRAY_VARS) - /* This is quite similar to the code in shell.c and elsewhere. */ - shell_fn = find_function_def (this_shell_function->name); - sfile = shell_fn ? shell_fn->source_file : ""; - array_push ((ARRAY *)funcname_a, this_shell_function->name); - - array_push ((ARRAY *)bash_source_a, sfile); - t = itos (executing_line_number ()); - array_push ((ARRAY *)bash_lineno_a, t); - free (t); -#endif - -#if defined (ARRAY_VARS) - fa = (struct func_array_state *)xmalloc (sizeof (struct func_array_state)); - fa->source_a = bash_source_a; - fa->source_v = bash_source_v; - fa->lineno_a = bash_lineno_a; - fa->lineno_v = bash_lineno_v; - fa->funcname_a = funcname_a; - fa->funcname_v = funcname_v; - if (subshell == 0) - add_unwind_protect (restore_funcarray_state, fa); -#endif - - /* The temporary environment for a function is supposed to apply to - all commands executed within the function body. */ - - remember_args (words->next, 1); - - /* Update BASH_ARGV and BASH_ARGC */ - if (debugging_mode) - push_args (words->next); - - /* Number of the line on which the function body starts. */ - line_number = function_line_number = tc->line; - -#if defined (JOB_CONTROL) - if (subshell) - stop_pipeline (async, (COMMAND *)NULL); -#endif - - loop_level = 0; - - fc = tc; - - from_return_trap = 0; - - return_catch_flag++; - return_val = setjmp_nosigs (return_catch); - - if (return_val) - { - result = return_catch_value; - /* Run the RETURN trap in the function's context. */ - save_current = currently_executing_command; - if (from_return_trap == 0) - run_return_trap (); - currently_executing_command = save_current; - } - else - { - /* Run the debug trap here so we can trap at the start of a function's - execution rather than the execution of the body's first command. */ - showing_function_line = 1; - save_current = currently_executing_command; - result = run_debug_trap (); -#if defined (DEBUGGER) - /* In debugging mode, if the DEBUG trap returns a non-zero status, we - skip the command. */ - if (debugging_mode == 0 || result == EXECUTION_SUCCESS) - { - showing_function_line = 0; - currently_executing_command = save_current; - result = execute_command_internal (fc, 0, NO_PIPE, NO_PIPE, fds_to_close); - - /* Run the RETURN trap in the function's context */ - save_current = currently_executing_command; - run_return_trap (); - currently_executing_command = save_current; - } -#else - result = execute_command_internal (fc, 0, NO_PIPE, NO_PIPE, fds_to_close); - - save_current = currently_executing_command; - run_return_trap (); - currently_executing_command = save_current; -#endif - showing_function_line = 0; - } - - /* Restore BASH_ARGC and BASH_ARGV */ - if (debugging_mode) - pop_args (); - - /* If we have a local copy of OPTIND, note it in the saved getopts state. */ - gv = find_variable ("OPTIND"); - if (gv && gv->context == variable_context) - gs->gs_flags |= 1; - - if (subshell == 0) - run_unwind_frame ("function_calling"); -#if defined (ARRAY_VARS) - else - restore_funcarray_state (fa); -#endif - - if (variable_context == 0 || this_shell_function == 0) - { - make_funcname_visible (0); -#if defined (PROCESS_SUBSTITUTION) - unlink_fifo_list (); -#endif - } - - return (result); -} - -/* A convenience routine for use by other parts of the shell to execute - a particular shell function. */ -int -execute_shell_function (var, words) - SHELL_VAR *var; - WORD_LIST *words; -{ - int ret; - struct fd_bitmap *bitmap; - - bitmap = new_fd_bitmap (FD_BITMAP_DEFAULT_SIZE); - begin_unwind_frame ("execute-shell-function"); - add_unwind_protect (dispose_fd_bitmap, (char *)bitmap); - - ret = execute_function (var, words, 0, bitmap, 0, 0); - - dispose_fd_bitmap (bitmap); - discard_unwind_frame ("execute-shell-function"); - - return ret; -} - -/* Execute a shell builtin or function in a subshell environment. This - routine does not return; it only calls exit(). If BUILTIN is non-null, - it points to a function to call to execute a shell builtin; otherwise - VAR points at the body of a function to execute. WORDS is the arguments - to the command, REDIRECTS specifies redirections to perform before the - command is executed. */ -static void -execute_subshell_builtin_or_function (words, redirects, builtin, var, - pipe_in, pipe_out, async, fds_to_close, - flags) - WORD_LIST *words; - REDIRECT *redirects; - sh_builtin_func_t *builtin; - SHELL_VAR *var; - int pipe_in, pipe_out, async; - struct fd_bitmap *fds_to_close; - int flags; -{ - int result, r, funcvalue; -#if defined (JOB_CONTROL) - int jobs_hack; - - jobs_hack = (builtin == jobs_builtin) && - ((subshell_environment & SUBSHELL_ASYNC) == 0 || pipe_out != NO_PIPE); -#endif - - /* A subshell is neither a login shell nor interactive. */ - login_shell = interactive = 0; - if (builtin == eval_builtin) - evalnest = 0; - else if (builtin == source_builtin) - sourcenest = 0; - - if (async) - subshell_environment |= SUBSHELL_ASYNC; - if (pipe_in != NO_PIPE || pipe_out != NO_PIPE) - subshell_environment |= SUBSHELL_PIPE; - - maybe_make_export_env (); /* XXX - is this needed? */ - -#if defined (JOB_CONTROL) - /* Eradicate all traces of job control after we fork the subshell, so - all jobs begun by this subshell are in the same process group as - the shell itself. */ - - /* Allow the output of `jobs' to be piped. */ - if (jobs_hack) - kill_current_pipeline (); - else - without_job_control (); - - set_sigchld_handler (); -#endif /* JOB_CONTROL */ - - set_sigint_handler (); - - if (fds_to_close) - close_fd_bitmap (fds_to_close); - - do_piping (pipe_in, pipe_out); - - if (do_redirections (redirects, RX_ACTIVE) != 0) - exit (EXECUTION_FAILURE); - - if (builtin) - { - /* Give builtins a place to jump back to on failure, - so we don't go back up to main(). */ - result = setjmp_nosigs (top_level); - - /* Give the return builtin a place to jump to when executed in a subshell - or pipeline */ - funcvalue = 0; - if (return_catch_flag && builtin == return_builtin) - funcvalue = setjmp_nosigs (return_catch); - - if (result == EXITPROG) - exit (last_command_exit_value); - else if (result) - exit (EXECUTION_FAILURE); - else if (funcvalue) - exit (return_catch_value); - else - { - r = execute_builtin (builtin, words, flags, 1); - fflush (stdout); - if (r == EX_USAGE) - r = EX_BADUSAGE; - exit (r); - } - } - else - { - r = execute_function (var, words, flags, fds_to_close, async, 1); - fflush (stdout); - exit (r); - } -} - -/* Execute a builtin or function in the current shell context. If BUILTIN - is non-null, it is the builtin command to execute, otherwise VAR points - to the body of a function. WORDS are the command's arguments, REDIRECTS - are the redirections to perform. FDS_TO_CLOSE is the usual bitmap of - file descriptors to close. - - If BUILTIN is exec_builtin, the redirections specified in REDIRECTS are - not undone before this function returns. */ -static int -execute_builtin_or_function (words, builtin, var, redirects, - fds_to_close, flags) - WORD_LIST *words; - sh_builtin_func_t *builtin; - SHELL_VAR *var; - REDIRECT *redirects; - struct fd_bitmap *fds_to_close; - int flags; -{ - int result; - REDIRECT *saved_undo_list; -#if defined (PROCESS_SUBSTITUTION) - int ofifo, nfifo, osize; - char *ofifo_list; -#endif - -#if defined (PROCESS_SUBSTITUTION) - ofifo = num_fifos (); - ofifo_list = copy_fifo_list (&osize); -#endif - - if (do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE) != 0) - { - cleanup_redirects (redirection_undo_list); - redirection_undo_list = (REDIRECT *)NULL; - dispose_exec_redirects (); -#if defined (PROCESS_SUBSTITUTION) - free (ofifo_list); -#endif - return (EX_REDIRFAIL); /* was EXECUTION_FAILURE */ - } - - saved_undo_list = redirection_undo_list; - - /* Calling the "exec" builtin changes redirections forever. */ - if (builtin == exec_builtin) - { - dispose_redirects (saved_undo_list); - saved_undo_list = exec_redirection_undo_list; - exec_redirection_undo_list = (REDIRECT *)NULL; - } - else - dispose_exec_redirects (); - - if (saved_undo_list) - { - begin_unwind_frame ("saved-redirects"); - add_unwind_protect (cleanup_redirects, (char *)saved_undo_list); - } - - redirection_undo_list = (REDIRECT *)NULL; - - if (builtin) - result = execute_builtin (builtin, words, flags, 0); - else - result = execute_function (var, words, flags, fds_to_close, 0, 0); - - /* We do this before undoing the effects of any redirections. */ - fflush (stdout); - fpurge (stdout); - if (ferror (stdout)) - clearerr (stdout); - - /* If we are executing the `command' builtin, but this_shell_builtin is - set to `exec_builtin', we know that we have something like - `command exec [redirection]', since otherwise `exec' would have - overwritten the shell and we wouldn't get here. In this case, we - want to behave as if the `command' builtin had not been specified - and preserve the redirections. */ - if (builtin == command_builtin && this_shell_builtin == exec_builtin) - { - int discard; - - discard = 0; - if (saved_undo_list) - { - dispose_redirects (saved_undo_list); - discard = 1; - } - redirection_undo_list = exec_redirection_undo_list; - saved_undo_list = exec_redirection_undo_list = (REDIRECT *)NULL; - if (discard) - discard_unwind_frame ("saved-redirects"); - } - - if (saved_undo_list) - { - redirection_undo_list = saved_undo_list; - discard_unwind_frame ("saved-redirects"); - } - - if (redirection_undo_list) - { - cleanup_redirects (redirection_undo_list); - redirection_undo_list = (REDIRECT *)NULL; - } - -#if defined (PROCESS_SUBSTITUTION) - /* Close any FIFOs created by this builtin or function. */ - nfifo = num_fifos (); - if (nfifo > ofifo) - close_new_fifos (ofifo_list, osize); - free (ofifo_list); -#endif - - return (result); -} - -void -setup_async_signals () -{ -#if defined (__BEOS__) - set_signal_handler (SIGHUP, SIG_IGN); /* they want csh-like behavior */ -#endif - -#if defined (JOB_CONTROL) - if (job_control == 0) -#endif - { - /* Make sure we get the original signal dispositions now so we don't - confuse the trap builtin later if the subshell tries to use it to - reset SIGINT/SIGQUIT. Don't call set_signal_ignored; that sets - the value of original_signals to SIG_IGN. Posix interpretation 751. */ - get_original_signal (SIGINT); - set_signal_handler (SIGINT, SIG_IGN); - - get_original_signal (SIGQUIT); - set_signal_handler (SIGQUIT, SIG_IGN); - } -} - -/* Execute a simple command that is hopefully defined in a disk file - somewhere. - - 1) fork () - 2) connect pipes - 3) look up the command - 4) do redirections - 5) execve () - 6) If the execve failed, see if the file has executable mode set. - If so, and it isn't a directory, then execute its contents as - a shell script. - - Note that the filename hashing stuff has to take place up here, - in the parent. This is probably why the Bourne style shells - don't handle it, since that would require them to go through - this gnarly hair, for no good reason. - - NOTE: callers expect this to fork or exit(). */ - -/* Name of a shell function to call when a command name is not found. */ -#ifndef NOTFOUND_HOOK -# define NOTFOUND_HOOK "command_not_found_handle" -#endif - -static int -execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, - async, fds_to_close, cmdflags) - WORD_LIST *words; - REDIRECT *redirects; - char *command_line; - int pipe_in, pipe_out, async; - struct fd_bitmap *fds_to_close; - int cmdflags; -{ - char *pathname, *command, **args; - int nofork, result; - pid_t pid; - SHELL_VAR *hookf; - WORD_LIST *wl; - - nofork = (cmdflags & CMD_NO_FORK); /* Don't fork, just exec, if no pipes */ - pathname = words->word->word; - - result = EXECUTION_SUCCESS; -#if defined (RESTRICTED_SHELL) - command = (char *)NULL; - if (restricted && mbschr (pathname, '/')) - { - internal_error (_("%s: restricted: cannot specify `/' in command names"), - pathname); - result = last_command_exit_value = EXECUTION_FAILURE; - - /* If we're not going to fork below, we must already be in a child - process or a context in which it's safe to call exit(2). */ - if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE) - exit (last_command_exit_value); - else - goto parent_return; - } -#endif /* RESTRICTED_SHELL */ - - command = search_for_command (pathname, 1); - - if (command) - { - maybe_make_export_env (); - put_command_name_into_env (command); - } - - /* We have to make the child before we check for the non-existence - of COMMAND, since we want the error messages to be redirected. */ - /* If we can get away without forking and there are no pipes to deal with, - don't bother to fork, just directly exec the command. */ - if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE) - pid = 0; - else - pid = make_child (savestring (command_line), async); - - if (pid == 0) - { - int old_interactive; - - reset_terminating_signals (); /* XXX */ - /* Cancel traps, in trap.c. */ - restore_original_signals (); - - CHECK_SIGTERM; - - /* restore_original_signals may have undone the work done - by make_child to ensure that SIGINT and SIGQUIT are ignored - in asynchronous children. */ - if (async) - { - if ((cmdflags & CMD_STDIN_REDIR) && - pipe_in == NO_PIPE && - (stdin_redirects (redirects) == 0)) - async_redirect_stdin (); - setup_async_signals (); - } - - /* This functionality is now provided by close-on-exec of the - file descriptors manipulated by redirection and piping. - Some file descriptors still need to be closed in all children - because of the way bash does pipes; fds_to_close is a - bitmap of all such file descriptors. */ - if (fds_to_close) - close_fd_bitmap (fds_to_close); - - do_piping (pipe_in, pipe_out); - - old_interactive = interactive; - if (async) - interactive = 0; - - subshell_environment = SUBSHELL_FORK; /* XXX */ - - if (redirects && (do_redirections (redirects, RX_ACTIVE) != 0)) - { -#if defined (PROCESS_SUBSTITUTION) - /* Try to remove named pipes that may have been created as the - result of redirections. */ - unlink_fifo_list (); -#endif /* PROCESS_SUBSTITUTION */ - exit (EXECUTION_FAILURE); - } - - if (async) - interactive = old_interactive; - - if (command == 0) - { - hookf = find_function (NOTFOUND_HOOK); - if (hookf == 0) - { - /* Make sure filenames are displayed using printable characters */ - pathname = printable_filename (pathname, 0); - internal_error (_("%s: command not found"), pathname); - exit (EX_NOTFOUND); /* Posix.2 says the exit status is 127 */ - } - -#if defined (JOB_CONTROL) - /* May need to reinitialize more of the job control state here. */ - kill_current_pipeline (); -#endif - - wl = make_word_list (make_word (NOTFOUND_HOOK), words); - exit (execute_shell_function (hookf, wl)); - } - - CHECK_SIGTERM; - - /* Execve expects the command name to be in args[0]. So we - leave it there, in the same format that the user used to - type it in. */ - args = strvec_from_word_list (words, 0, 0, (int *)NULL); - exit (shell_execve (command, args, export_env)); - } - else - { -parent_return: - QUIT; - - /* Make sure that the pipes are closed in the parent. */ - close_pipes (pipe_in, pipe_out); -#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD) - if (variable_context == 0) - unlink_fifo_list (); -#endif - FREE (command); - return (result); - } -} - -/* CPP defines to decide whether a particular index into the #! line - corresponds to a valid interpreter name or argument character, or - whitespace. The MSDOS define is to allow \r to be treated the same - as \n. */ - -#if !defined (MSDOS) -# define STRINGCHAR(ind) \ - (ind < sample_len && !whitespace (sample[ind]) && sample[ind] != '\n') -# define WHITECHAR(ind) \ - (ind < sample_len && whitespace (sample[ind])) -#else /* MSDOS */ -# define STRINGCHAR(ind) \ - (ind < sample_len && !whitespace (sample[ind]) && sample[ind] != '\n' && sample[ind] != '\r') -# define WHITECHAR(ind) \ - (ind < sample_len && whitespace (sample[ind])) -#endif /* MSDOS */ - -static char * -getinterp (sample, sample_len, endp) - char *sample; - int sample_len, *endp; -{ - register int i; - char *execname; - int start; - - /* Find the name of the interpreter to exec. */ - for (i = 2; i < sample_len && whitespace (sample[i]); i++) - ; - - for (start = i; STRINGCHAR(i); i++) - ; - - execname = substring (sample, start, i); - - if (endp) - *endp = i; - return execname; -} - -#if !defined (HAVE_HASH_BANG_EXEC) -/* If the operating system on which we're running does not handle - the #! executable format, then help out. SAMPLE is the text read - from the file, SAMPLE_LEN characters. COMMAND is the name of - the script; it and ARGS, the arguments given by the user, will - become arguments to the specified interpreter. ENV is the environment - to pass to the interpreter. - - The word immediately following the #! is the interpreter to execute. - A single argument to the interpreter is allowed. */ - -static int -execute_shell_script (sample, sample_len, command, args, env) - char *sample; - int sample_len; - char *command; - char **args, **env; -{ - char *execname, *firstarg; - int i, start, size_increment, larry; - - /* Find the name of the interpreter to exec. */ - execname = getinterp (sample, sample_len, &i); - size_increment = 1; - - /* Now the argument, if any. */ - for (firstarg = (char *)NULL, start = i; WHITECHAR(i); i++) - ; - - /* If there is more text on the line, then it is an argument for the - interpreter. */ - - if (STRINGCHAR(i)) - { - for (start = i; STRINGCHAR(i); i++) - ; - firstarg = substring ((char *)sample, start, i); - size_increment = 2; - } - - larry = strvec_len (args) + size_increment; - args = strvec_resize (args, larry + 1); - - for (i = larry - 1; i; i--) - args[i] = args[i - size_increment]; - - args[0] = execname; - if (firstarg) - { - args[1] = firstarg; - args[2] = command; - } - else - args[1] = command; - - args[larry] = (char *)NULL; - - return (shell_execve (execname, args, env)); -} -#undef STRINGCHAR -#undef WHITECHAR - -#endif /* !HAVE_HASH_BANG_EXEC */ - -static void -initialize_subshell () -{ -#if defined (ALIAS) - /* Forget about any aliases that we knew of. We are in a subshell. */ - delete_all_aliases (); -#endif /* ALIAS */ - -#if defined (HISTORY) - /* Forget about the history lines we have read. This is a non-interactive - subshell. */ - history_lines_this_session = 0; -#endif - -#if defined (JOB_CONTROL) - /* Forget about the way job control was working. We are in a subshell. */ - without_job_control (); - set_sigchld_handler (); - init_job_stats (); -#endif /* JOB_CONTROL */ - - /* Reset the values of the shell flags and options. */ - reset_shell_flags (); - reset_shell_options (); - reset_shopt_options (); - - /* Zero out builtin_env, since this could be a shell script run from a - sourced file with a temporary environment supplied to the `source/.' - builtin. Such variables are not supposed to be exported (empirical - testing with sh and ksh). Just throw it away; don't worry about a - memory leak. */ - if (vc_isbltnenv (shell_variables)) - shell_variables = shell_variables->down; - - clear_unwind_protect_list (0); - /* XXX -- are there other things we should be resetting here? */ - parse_and_execute_level = 0; /* nothing left to restore it */ - - /* We're no longer inside a shell function. */ - variable_context = return_catch_flag = funcnest = evalnest = sourcenest = 0; - - executing_list = 0; /* XXX */ - - /* If we're not interactive, close the file descriptor from which we're - reading the current shell script. */ - if (interactive_shell == 0) - unset_bash_input (0); -} - -#if defined (HAVE_SETOSTYPE) && defined (_POSIX_SOURCE) -# define SETOSTYPE(x) __setostype(x) -#else -# define SETOSTYPE(x) -#endif - -#define READ_SAMPLE_BUF(file, buf, len) \ - do \ - { \ - fd = open(file, O_RDONLY); \ - if (fd >= 0) \ - { \ - len = read (fd, buf, 80); \ - close (fd); \ - } \ - else \ - len = -1; \ - } \ - while (0) - -/* Call execve (), handling interpreting shell scripts, and handling - exec failures. */ -int -shell_execve (command, args, env) - char *command; - char **args, **env; -{ - int larray, i, fd; - char sample[80]; - int sample_len; - - SETOSTYPE (0); /* Some systems use for USG/POSIX semantics */ - execve (command, args, env); - i = errno; /* error from execve() */ - CHECK_TERMSIG; - SETOSTYPE (1); - - /* If we get to this point, then start checking out the file. - Maybe it is something we can hack ourselves. */ - if (i != ENOEXEC) - { - /* make sure this is set correctly for file_error/report_error */ - last_command_exit_value = (i == ENOENT) ? EX_NOTFOUND : EX_NOEXEC; /* XXX Posix.2 says that exit status is 126 */ - if (file_isdir (command)) -#if defined (EISDIR) - internal_error (_("%s: %s"), command, strerror (EISDIR)); -#else - internal_error (_("%s: is a directory"), command); -#endif - else if (executable_file (command) == 0) - { - errno = i; - file_error (command); - } - /* errors not involving the path argument to execve. */ - else if (i == E2BIG || i == ENOMEM) - { - errno = i; - file_error (command); - } - else - { - /* The file has the execute bits set, but the kernel refuses to - run it for some reason. See why. */ -#if defined (HAVE_HASH_BANG_EXEC) - READ_SAMPLE_BUF (command, sample, sample_len); - sample[sample_len - 1] = '\0'; - if (sample_len > 2 && sample[0] == '#' && sample[1] == '!') - { - char *interp; - int ilen; - - interp = getinterp (sample, sample_len, (int *)NULL); - ilen = strlen (interp); - errno = i; - if (interp[ilen - 1] == '\r') - { - interp = xrealloc (interp, ilen + 2); - interp[ilen - 1] = '^'; - interp[ilen] = 'M'; - interp[ilen + 1] = '\0'; - } - sys_error (_("%s: %s: bad interpreter"), command, interp ? interp : ""); - FREE (interp); - return (EX_NOEXEC); - } -#endif - errno = i; - file_error (command); - } - return (last_command_exit_value); - } - - /* This file is executable. - If it begins with #!, then help out people with losing operating - systems. Otherwise, check to see if it is a binary file by seeing - if the contents of the first line (or up to 80 characters) are in the - ASCII set. If it's a text file, execute the contents as shell commands, - otherwise return 126 (EX_BINARY_FILE). */ - READ_SAMPLE_BUF (command, sample, sample_len); - - if (sample_len == 0) - return (EXECUTION_SUCCESS); - - /* Is this supposed to be an executable script? - If so, the format of the line is "#! interpreter [argument]". - A single argument is allowed. The BSD kernel restricts - the length of the entire line to 32 characters (32 bytes - being the size of the BSD exec header), but we allow 80 - characters. */ - if (sample_len > 0) - { -#if !defined (HAVE_HASH_BANG_EXEC) - if (sample_len > 2 && sample[0] == '#' && sample[1] == '!') - return (execute_shell_script (sample, sample_len, command, args, env)); - else -#endif - if (check_binary_file (sample, sample_len)) - { - internal_error (_("%s: cannot execute binary file: %s"), command, strerror (i)); - return (EX_BINARY_FILE); - } - } - - /* We have committed to attempting to execute the contents of this file - as shell commands. */ - - initialize_subshell (); - - set_sigint_handler (); - - /* Insert the name of this shell into the argument list. */ - larray = strvec_len (args) + 1; - args = strvec_resize (args, larray + 1); - - for (i = larray - 1; i; i--) - args[i] = args[i - 1]; - - args[0] = shell_name; - args[1] = command; - args[larray] = (char *)NULL; - - if (args[0][0] == '-') - args[0]++; - -#if defined (RESTRICTED_SHELL) - if (restricted) - change_flag ('r', FLAG_OFF); -#endif - - if (subshell_argv) - { - /* Can't free subshell_argv[0]; that is shell_name. */ - for (i = 1; i < subshell_argc; i++) - free (subshell_argv[i]); - free (subshell_argv); - } - - dispose_command (currently_executing_command); /* XXX */ - currently_executing_command = (COMMAND *)NULL; - - subshell_argc = larray; - subshell_argv = args; - subshell_envp = env; - - unbind_args (); /* remove the positional parameters */ - -#if defined (PROCESS_SUBSTITUTION) - clear_fifo_list (); /* pipe fds are what they are now */ -#endif - - longjmp (subshell_top_level, 1); - /*NOTREACHED*/ -} - -static int -execute_intern_function (name, funcdef) - WORD_DESC *name; - FUNCTION_DEF *funcdef; -{ - SHELL_VAR *var; - - if (check_identifier (name, posixly_correct) == 0) - { - if (posixly_correct && interactive_shell == 0) - { - last_command_exit_value = EX_BADUSAGE; - jump_to_top_level (ERREXIT); - } - return (EXECUTION_FAILURE); - } - - /* Posix interpretation 383 */ - if (posixly_correct && find_special_builtin (name->word)) - { - internal_error (_("`%s': is a special builtin"), name->word); - last_command_exit_value = EX_BADUSAGE; - jump_to_top_level (interactive_shell ? DISCARD : ERREXIT); - } - - var = find_function (name->word); - if (var && (readonly_p (var) || noassign_p (var))) - { - if (readonly_p (var)) - internal_error (_("%s: readonly function"), var->name); - return (EXECUTION_FAILURE); - } - -#if defined (DEBUGGER) - bind_function_def (name->word, funcdef); -#endif - - bind_function (name->word, funcdef->command); - return (EXECUTION_SUCCESS); -} - -#if defined (INCLUDE_UNUSED) -#if defined (PROCESS_SUBSTITUTION) -void -close_all_files () -{ - register int i, fd_table_size; - - fd_table_size = getdtablesize (); - if (fd_table_size > 256) /* clamp to a reasonable value */ - fd_table_size = 256; - - for (i = 3; i < fd_table_size; i++) - close (i); -} -#endif /* PROCESS_SUBSTITUTION */ -#endif - -static void -close_pipes (in, out) - int in, out; -{ - if (in >= 0) - close (in); - if (out >= 0) - close (out); -} - -static void -dup_error (oldd, newd) - int oldd, newd; -{ - sys_error (_("cannot duplicate fd %d to fd %d"), oldd, newd); -} - -/* Redirect input and output to be from and to the specified pipes. - NO_PIPE and REDIRECT_BOTH are handled correctly. */ -static void -do_piping (pipe_in, pipe_out) - int pipe_in, pipe_out; -{ - if (pipe_in != NO_PIPE) - { - if (dup2 (pipe_in, 0) < 0) - dup_error (pipe_in, 0); - if (pipe_in > 0) - close (pipe_in); -#ifdef __CYGWIN__ - /* Let stdio know the fd may have changed from text to binary mode. */ - freopen (NULL, "r", stdin); -#endif /* __CYGWIN__ */ - } - if (pipe_out != NO_PIPE) - { - if (pipe_out != REDIRECT_BOTH) - { - if (dup2 (pipe_out, 1) < 0) - dup_error (pipe_out, 1); - if (pipe_out == 0 || pipe_out > 1) - close (pipe_out); - } - else - { - if (dup2 (1, 2) < 0) - dup_error (1, 2); - } -#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__ */ - } -} diff --git a/flags.c~ b/flags.c~ deleted file mode 100644 index a6c933efb..000000000 --- a/flags.c~ +++ /dev/null @@ -1,390 +0,0 @@ -/* flags.c -- Everything about flags except the `set' command. That - is in builtins.c */ - -/* Copyright (C) 1987-2009 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" -#if defined (HAVE_UNISTD_H) -# include -#endif - -#include "shell.h" -#include "flags.h" - -#if defined (BANG_HISTORY) -# include "bashhist.h" -#endif - -#if defined (JOB_CONTROL) -extern int set_job_control __P((int)); -#endif - -#if defined (RESTRICTED_SHELL) -extern char *shell_name; -#endif - -extern int shell_initialized; -extern int builtin_ignoring_errexit; - -/* -c, -s invocation options -- not really flags, but they show up in $- */ -extern int want_pending_command, read_from_stdin; - -/* **************************************************************** */ -/* */ -/* The Standard sh Flags. */ -/* */ -/* **************************************************************** */ - -/* Non-zero means automatically mark variables which are modified or created - as auto export variables. */ -int mark_modified_vars = 0; - -/* Non-zero causes asynchronous job notification. Otherwise, job state - notification only takes place just before a primary prompt is printed. */ -int asynchronous_notification = 0; - -/* Non-zero means exit immediately if a command exits with a non-zero - exit status. The first is what controls set -e; the second is what - bash uses internally. */ -int errexit_flag = 0; -int exit_immediately_on_error = 0; - -/* Non-zero means disable filename globbing. */ -int disallow_filename_globbing = 0; - -/* Non-zero means that all keyword arguments are placed into the environment - for a command, not just those that appear on the line before the command - name. */ -int place_keywords_in_env = 0; - -/* Non-zero means read commands, but don't execute them. This is useful - for debugging shell scripts that should do something hairy and possibly - destructive. */ -int read_but_dont_execute = 0; - -/* Non-zero means end of file is after one command. */ -int just_one_command = 0; - -/* Non-zero means don't overwrite existing files while doing redirections. */ -int noclobber = 0; - -/* Non-zero means trying to get the value of $i where $i is undefined - causes an error, instead of a null substitution. */ -int unbound_vars_is_error = 0; - -/* Non-zero means type out input lines after you read them. */ -int echo_input_at_read = 0; - -/* Non-zero means type out the command definition after reading, but - before executing. */ -int echo_command_at_execute = 0; - -/* Non-zero means turn on the job control features. */ -int jobs_m_flag = 0; - -/* Non-zero means this shell is interactive, even if running under a - pipe. */ -int forced_interactive = 0; - -/* By default, follow the symbolic links as if they were real directories - while hacking the `cd' command. This means that `cd ..' moves up in - the string of symbolic links that make up the current directory, instead - of the absolute directory. The shell variable `nolinks' also controls - this flag. */ -int no_symbolic_links = 0; - -/* **************************************************************** */ -/* */ -/* Non-Standard Flags Follow Here. */ -/* */ -/* **************************************************************** */ - -#if 0 -/* Non-zero means do lexical scoping in the body of a FOR command. */ -int lexical_scoping = 0; -#endif - -/* Non-zero means no such thing as invisible variables. */ -int no_invisible_vars = 0; - -/* Non-zero means look up and remember command names in a hash table, */ -int hashing_enabled = 1; - -#if defined (BANG_HISTORY) -/* Non-zero means that we are doing history expansion. The default. - This means !22 gets the 22nd line of history. */ -# if defined (STRICT_POSIX) -int history_expansion = 0; -# else -int history_expansion = 1; -# endif -#endif /* BANG_HISTORY */ - -/* Non-zero means that we allow comments to appear in interactive commands. */ -int interactive_comments = 1; - -#if defined (RESTRICTED_SHELL) -/* Non-zero means that this shell is `restricted'. A restricted shell - disallows: changing directories, command or path names containing `/', - unsetting or resetting the values of $PATH and $SHELL, and any type of - output redirection. */ -int restricted = 0; /* currently restricted */ -int restricted_shell = 0; /* shell was started in restricted mode. */ -#endif /* RESTRICTED_SHELL */ - -/* Non-zero means that this shell is running in `privileged' mode. This - is required if the shell is to run setuid. If the `-p' option is - not supplied at startup, and the real and effective uids or gids - differ, disable_priv_mode is called to relinquish setuid status. */ -int privileged_mode = 0; - -#if defined (BRACE_EXPANSION) -/* Zero means to disable brace expansion: foo{a,b} -> fooa foob */ -int brace_expansion = 1; -#endif - -/* Non-zero means that shell functions inherit the DEBUG trap. */ -int function_trace_mode = 0; - -/* Non-zero means that shell functions inherit the ERR trap. */ -int error_trace_mode = 0; - -/* Non-zero means that the rightmost non-zero exit status in a pipeline - is the exit status of the entire pipeline. If each processes exits - with a 0 status, the status of the pipeline is 0. */ -int pipefail_opt = 0; - -/* **************************************************************** */ -/* */ -/* The Flags ALIST. */ -/* */ -/* **************************************************************** */ - -const struct flags_alist shell_flags[] = { - /* Standard sh flags. */ - { 'a', &mark_modified_vars }, -#if defined (JOB_CONTROL) - { 'b', &asynchronous_notification }, -#endif /* JOB_CONTROL */ - { 'e', &errexit_flag }, - { 'f', &disallow_filename_globbing }, - { 'h', &hashing_enabled }, - { 'i', &forced_interactive }, - { 'k', &place_keywords_in_env }, -#if defined (JOB_CONTROL) - { 'm', &jobs_m_flag }, -#endif /* JOB_CONTROL */ - { 'n', &read_but_dont_execute }, - { 'p', &privileged_mode }, -#if defined (RESTRICTED_SHELL) - { 'r', &restricted }, -#endif /* RESTRICTED_SHELL */ - { 't', &just_one_command }, - { 'u', &unbound_vars_is_error }, - { 'v', &echo_input_at_read }, - { 'x', &echo_command_at_execute }, - - /* New flags that control non-standard things. */ -#if 0 - { 'l', &lexical_scoping }, -#endif -#if defined (BRACE_EXPANSION) - { 'B', &brace_expansion }, -#endif - { 'C', &noclobber }, - { 'E', &error_trace_mode }, -#if defined (BANG_HISTORY) - { 'H', &history_expansion }, -#endif /* BANG_HISTORY */ - { 'I', &no_invisible_vars }, - { 'P', &no_symbolic_links }, - { 'T', &function_trace_mode }, - {0, (int *)NULL} -}; - -#define NUM_SHELL_FLAGS (sizeof (shell_flags) / sizeof (struct flags_alist)) - -char optflags[NUM_SHELL_FLAGS+4] = { '+' }; - -int * -find_flag (name) - int name; -{ - int i; - for (i = 0; shell_flags[i].name; i++) - { - if (shell_flags[i].name == name) - return (shell_flags[i].value); - } - return (FLAG_UNKNOWN); -} - -/* Change the state of a flag, and return it's original value, or return - FLAG_ERROR if there is no flag FLAG. ON_OR_OFF must be either - FLAG_ON or FLAG_OFF. */ -int -change_flag (flag, on_or_off) - int flag; - int on_or_off; -{ - int *value, old_value; - -#if defined (RESTRICTED_SHELL) - /* Don't allow "set +r" in a shell which is `restricted'. */ - if (restricted && flag == 'r' && on_or_off == FLAG_OFF) - return (FLAG_ERROR); -#endif /* RESTRICTED_SHELL */ - - value = find_flag (flag); - - if ((value == (int *)FLAG_UNKNOWN) || (on_or_off != FLAG_ON && on_or_off != FLAG_OFF)) - return (FLAG_ERROR); - - old_value = *value; - *value = (on_or_off == FLAG_ON) ? 1 : 0; - - /* Special cases for a few flags. */ - switch (flag) - { -#if defined (BANG_HISTORY) - case 'H': - if (on_or_off == FLAG_ON) - bash_initialize_history (); - break; -#endif - -#if defined (JOB_CONTROL) - case 'm': - set_job_control (on_or_off == FLAG_ON); - break; -#endif /* JOB_CONTROL */ - - case 'e': - if (builtin_ignoring_errexit == 0) - exit_immediately_on_error = errexit_flag; - break; - - case 'n': - if (interactive_shell) - read_but_dont_execute = 0; - break; - - case 'p': - if (on_or_off == FLAG_OFF) - disable_priv_mode (); - break; - -#if defined (RESTRICTED_SHELL) - case 'r': - if (on_or_off == FLAG_ON && shell_initialized) - maybe_make_restricted (shell_name); - break; -#endif - - } - - return (old_value); -} - -/* Return a string which is the names of all the currently - set shell flags. */ -char * -which_set_flags () -{ - char *temp; - int i, string_index; - - temp = (char *)xmalloc (1 + NUM_SHELL_FLAGS + read_from_stdin + want_pending_command); - for (i = string_index = 0; shell_flags[i].name; i++) - if (*(shell_flags[i].value)) - temp[string_index++] = shell_flags[i].name; - - if (want_pending_command) - temp[string_index++] = 'c'; - if (read_from_stdin) - temp[string_index++] = 's'; - - temp[string_index] = '\0'; - return (temp); -} - -char * -get_current_flags () -{ - char *temp; - int i; - - temp = (char *)xmalloc (1 + NUM_SHELL_FLAGS); - for (i = 0; shell_flags[i].name; i++) - temp[i] = *(shell_flags[i].value); - temp[i] = '\0'; - return (temp); -} - -void -set_current_flags (bitmap) - const char *bitmap; -{ - int i; - - if (bitmap == 0) - return; - for (i = 0; shell_flags[i].name; i++) - *(shell_flags[i].value) = bitmap[i]; -} - -void -reset_shell_flags () -{ - mark_modified_vars = exit_immediately_on_error = disallow_filename_globbing = 0; - place_keywords_in_env = read_but_dont_execute = just_one_command = 0; - noclobber = unbound_vars_is_error = echo_input_at_read = 0; - echo_command_at_execute = jobs_m_flag = forced_interactive = 0; - no_symbolic_links = no_invisible_vars = privileged_mode = pipefail_opt = 0; - - hashing_enabled = interactive_comments = 1; - -#if defined (JOB_CONTROL) - asynchronous_notification = 0; -#endif - -#if defined (BANG_HISTORY) - history_expansion = 1; -#endif - -#if defined (BRACE_EXPANSION) - brace_expansion = 1; -#endif - -#if defined (RESTRICTED_SHELL) - restricted = 0; -#endif -} - -void -initialize_flags () -{ - register int i; - - for (i = 0; shell_flags[i].name; i++) - optflags[i+1] = shell_flags[i].name; - optflags[++i] = 'o'; - optflags[++i] = ';'; - optflags[i+1] = '\0'; -} diff --git a/flags.h~ b/flags.h~ deleted file mode 100644 index 58c68fdd6..000000000 --- a/flags.h~ +++ /dev/null @@ -1,83 +0,0 @@ -/* flags.h -- a list of all the flags that the shell knows about. You add - a flag to this program by adding the name here, and in flags.c. */ - -/* Copyright (C) 1993-2009 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 . -*/ - -#if !defined (_FLAGS_H_) -#define _FLAGS_H_ - -#include "stdc.h" - -/* Welcome to the world of Un*x, where everything is slightly backwards. */ -#define FLAG_ON '-' -#define FLAG_OFF '+' - -#define FLAG_ERROR -1 -#define FLAG_UNKNOWN (int *)0 - -/* The thing that we build the array of flags out of. */ -struct flags_alist { - char name; - int *value; -}; - -extern const struct flags_alist shell_flags[]; -extern char optflags[]; - -extern int - mark_modified_vars, errexit_flag, exit_immediately_on_error, - disallow_filename_globbing, - place_keywords_in_env, read_but_dont_execute, - just_one_command, unbound_vars_is_error, echo_input_at_read, - echo_command_at_execute, no_invisible_vars, noclobber, - hashing_enabled, forced_interactive, privileged_mode, jobs_m_flag, - asynchronous_notification, interactive_comments, no_symbolic_links, - function_trace_mode, error_trace_mode, pipefail_opt; - -#if 0 -extern int lexical_scoping; -#endif - -#if defined (BRACE_EXPANSION) -extern int brace_expansion; -#endif - -#if defined (BANG_HISTORY) -extern int history_expansion; -#endif /* BANG_HISTORY */ - -#if defined (RESTRICTED_SHELL) -extern int restricted; -extern int restricted_shell; -#endif /* RESTRICTED_SHELL */ - -extern int *find_flag __P((int)); -extern int change_flag __P((int, int)); -extern char *which_set_flags __P((void)); -extern void reset_shell_flags __P((void)); - -extern char *get_current_flags __P((void)); -extern void set_current_flags __P((const char *)); - -extern void initialize_flags __P((void)); - -/* A macro for efficiency. */ -#define change_flag_char(flag, on_or_off) change_flag (flag, on_or_off) - -#endif /* _FLAGS_H_ */ diff --git a/lib/readline/complete.c~ b/lib/readline/complete.c~ deleted file mode 100644 index 32429be14..000000000 --- a/lib/readline/complete.c~ +++ /dev/null @@ -1,2976 +0,0 @@ -/* complete.c -- filename completion for readline. */ - -/* Copyright (C) 1987-2014 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" - -#if defined (COLOR_SUPPORT) -# include "colors.h" -#endif - -#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) || defined (COLOR_SUPPORT) -# if !defined (X_OK) -# define X_OK 1 -# endif -#endif - -#if defined (VISIBLE_STATS) -static int stat_char PARAMS((char *)); -#endif - -#if defined (COLOR_SUPPORT) -static int colored_stat_start PARAMS((char *)); -static void colored_stat_end PARAMS((void)); -static int colored_prefix_start PARAMS((void)); -static void colored_prefix_end PARAMS((void)); -#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 defined (COLOR_SUPPORT) -/* Non-zero means to use colors to indicate file type when listing possible - completions. The colors used are taken from $LS_COLORS, if set. */ -int _rl_colored_stats = 0; - -int _rl_colored_completion_prefix = 1; -#endif - -/* 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; - -static int _rl_complete_display_matches_interrupt = 0; - -/*************************************/ -/* */ -/* 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); - _rl_complete_display_matches_interrupt = 1; - } -} - -/* 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; - - /* Reset private state. */ - _rl_complete_display_matches_interrupt = 0; -} - -/* 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; - char *f; - const char *fn; - - /* 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 - - f = 0; - if (rl_filename_stat_hook) - { - f = savestring (filename); - (*rl_filename_stat_hook) (&f); - fn = f; - } - else - fn = filename; - -#if defined (HAVE_LSTAT) && defined (S_ISLNK) - r = lstat (fn, &finfo); -#else - r = stat (fn, &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 defined (_WIN32) && !defined (__CYGWIN__) - char *ext; - - /* Windows doesn't do access and X_OK; check file extension instead */ - ext = strrchr (fn, '.'); - if (ext && (_rl_stricmp (ext, ".exe") == 0 || - _rl_stricmp (ext, ".cmd") == 0 || - _rl_stricmp (ext, ".bat") == 0 || - _rl_stricmp (ext, ".com") == 0)) - character = '*'; -#else - if (access (filename, X_OK) == 0) - character = '*'; -#endif - } - - xfree (f); - return (character); -} -#endif /* VISIBLE_STATS */ - -#if defined (COLOR_SUPPORT) -static int -colored_stat_start (filename) - char *filename; -{ - _rl_set_normal_color (); - return (_rl_print_color_indicator (filename)); -} - -static void -colored_stat_end () -{ - _rl_prep_non_filename_text (); - _rl_put_indicator (&_rl_color_indicator[C_CLR_TO_EOL]); -} - -static int -colored_prefix_start () -{ - _rl_set_normal_color (); - return (_rl_print_prefix_color ()); -} - -static void -colored_prefix_end () -{ - colored_stat_end (); /* for now */ -} -#endif - -/* 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; - int common_prefix_len; -#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 = common_prefix_len = 0; - - /* Don't print only the ellipsis if the common prefix is one of the - possible completions */ - if (to_print[prefix_bytes] == '\0') - prefix_bytes = 0; - - if (prefix_bytes && _rl_completion_prefix_display_length > 0) - { - char ellipsis; - - ellipsis = (to_print[prefix_bytes] == '.') ? '_' : '.'; - for (w = 0; w < ELLIPSIS_LEN; w++) - putc (ellipsis, rl_outstream); - printed_len = ELLIPSIS_LEN; - } -#if defined (COLOR_SUPPORT) - else if (prefix_bytes && _rl_colored_completion_prefix > 0) - { - common_prefix_len = prefix_bytes; - prefix_bytes = 0; - /* XXX - print color indicator start here */ - colored_prefix_start (); - } -#endif - - 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 - } - if (common_prefix_len > 0 && (s - to_print) >= common_prefix_len) - { - /* printed bytes = s - to_print */ - /* printed bytes should never be > but check for paranoia's sake */ - colored_prefix_end (); - common_prefix_len = 0; - } - } - - 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; -#if defined (COLOR_SUPPORT) - /* Defer printing if we want to prefix with a color indicator */ - if (_rl_colored_stats == 0 || rl_filename_completion_desired == 0) -#endif - printed_len = fnprint (to_print, prefix_bytes); - - if (rl_filename_completion_desired && ( -#if defined (VISIBLE_STATS) - rl_visible_stats || -#endif -#if defined (COLOR_SUPPORT) - _rl_colored_stats || -#endif - _rl_complete_mark_directories)) - { - /* 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 (_rl_complete_mark_directories) - { - dn = 0; - if (rl_directory_completion_hook == 0 && rl_filename_stat_hook) - { - dn = savestring (new_full_pathname); - (*rl_filename_stat_hook) (&dn); - xfree (new_full_pathname); - new_full_pathname = dn; - } - if (path_isdir (new_full_pathname)) - extension_char = '/'; - } - -#if defined (COLOR_SUPPORT) - if (_rl_colored_stats) - { - colored_stat_start (new_full_pathname); - printed_len = fnprint (to_print, prefix_bytes); - colored_stat_end (); - } -#endif - - 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 (_rl_complete_mark_directories && path_isdir (s)) - extension_char = '/'; - -#if defined (COLOR_SUPPORT) - if (_rl_colored_stats) - { - colored_stat_start (s); - printed_len = fnprint (to_print, prefix_bytes); - colored_stat_end (); - } -#endif - - } - - 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. */ - int lx; - char *dtext; /* dequoted TEXT, if needed */ -#if defined (HANDLE_MULTIBYTE) - int v; - size_t v1, v2; - 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) - { - v1 = mbrtowc(&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1); - v2 = mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2); - if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2)) - { - if (c1 != c2) /* do byte comparison */ - break; - continue; - } - wc1 = towlower (wc1); - wc2 = towlower (wc2); - if (wc1 != wc2) - break; - else if (v1 > 1) - si += v1 - 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); - lx = (si <= low) ? si : low; /* check shorter of text and matches */ - /* Try to preserve the case of what the user typed in the presence of - multiple matches: check each match for something that matches - what the user typed taking case into account; use it up to common - length of matches if one is found. If not, just use first match. */ - for (i = 1; i <= matches; i++) - if (strncmp (match_list[i], text, lx) == 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); - - 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 possibilities. 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, '/'); /* check again in case of /usr/src/ */ - 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; - } -#if defined (COLOR_SUPPORT) - else if (_rl_colored_completion_prefix > 0) - { - t = printable_part (matches[0]); - temp = strrchr (t, '/'); - common_length = temp ? fnwidth (temp) : fnwidth (t); - sind = temp ? RL_STRLEN (temp+1) : RL_STRLEN (t); /* want portion after final slash */ - } -#endif - - /* 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 (); -#if defined (SIGWINCH) - if (RL_SIG_RECEIVED () && RL_SIGWINCH_RECEIVED() == 0) -#else - if (RL_SIG_RECEIVED ()) -#endif - return; - 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 defined (SIGWINCH) - if (RL_SIG_RECEIVED () && RL_SIGWINCH_RECEIVED() == 0) -#else - if (RL_SIG_RECEIVED ()) -#endif - return; - if (matches[i+1]) - { - if (limit == 1 || (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, *fn; - 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) - { - fn = savestring (filename); - (*rl_filename_stat_hook) (&fn); - xfree (filename); - filename = fn; - } - 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; - _rl_complete_display_matches_interrupt = 0; - } - display_matches (matches); - if (_rl_complete_display_matches_interrupt) - { - matches = 0; /* already freed by rl_complete_sigcleanup */ - _rl_complete_display_matches_interrupt = 0; - if (rl_signal_event_hook) - (*rl_signal_event_hook) (); /* XXX */ - } - _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 (); - - RL_CHECK_SIGNALS (); - 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; - matches = 0; - RL_CHECK_SIGNALS (); - } - - if (matches + 1 >= match_list_size) - match_list = (char **)xrealloc - (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); - - if (match_list == 0) - return (match_list); - - 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); -#if defined (HAVE_GETPWENT) - setpwent (); -#endif - } - -#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. If - _rl_completion_case_map is set, make `-' and `_' equivalent. 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; -#if defined (HANDLE_MULTIBYTE) - size_t v1, v2; - mbstate_t ps1, ps2; - wchar_t wc1, wc2; -#endif - -#if defined (HANDLE_MULTIBYTE) - memset (&ps1, 0, sizeof (mbstate_t)); - memset (&ps2, 0, sizeof (mbstate_t)); -#endif - - if (filename_len == 0) - return 1; - if (convlen < filename_len) - return 0; - - len = filename_len; - s1 = (char *)convfn; - s2 = (char *)filename; - - /* 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 defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - do - { - v1 = mbrtowc (&wc1, s1, convlen, &ps1); - v2 = mbrtowc (&wc2, s2, filename_len, &ps2); - if (v1 == 0 && v2 == 0) - return 1; - else if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2)) - { - if (*s1 != *s2) /* do byte comparison */ - return 0; - else if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_')) - return 0; - s1++; s2++; len--; - continue; - } - wc1 = towlower (wc1); - wc2 = towlower (wc2); - s1 += v1; - s2 += v1; - len -= v1; - if ((wc1 == L'-' || wc1 == L'_') && (wc2 == L'-' || wc2 == L'_')) - continue; - if (wc1 != wc2) - return 0; - } - while (len != 0); - } - else -#endif - { - 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 defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - do - { - v1 = mbrtowc (&wc1, s1, convlen, &ps1); - v2 = mbrtowc (&wc2, s2, filename_len, &ps2); - if (v1 == 0 && v2 == 0) - return 1; - else if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2)) - { - if (*s1 != *s2) /* do byte comparison */ - return 0; - s1++; s2++; len--; - continue; - } - wc1 = towlower (wc1); - wc2 = towlower (wc2); - if (wc1 != wc2) - return 0; - s1 += v1; - s2 += v1; - len -= v1; - } - while (len != 0); - return 1; - } - else -#endif - 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 (_rl_menu_complete_prefix_first) - { - rl_ding (); - 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/display.c~ b/lib/readline/display.c~ deleted file mode 100644 index ceff058d7..000000000 --- a/lib/readline/display.c~ +++ /dev/null @@ -1,2885 +0,0 @@ -/* display.c -- readline redisplay facility. */ - -/* Copyright (C) 1987-2013 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 - -#if defined (HAVE_UNISTD_H) -# include -#endif /* HAVE_UNISTD_H */ - -#include "posixstat.h" - -#if defined (HAVE_STDLIB_H) -# include -#else -# include "ansi_stdlib.h" -#endif /* HAVE_STDLIB_H */ - -#include - -#ifdef __MSDOS__ -# include -#endif - -/* System-specific feature definitions and include files. */ -#include "rldefs.h" -#include "rlmbutil.h" - -/* Termcap library stuff. */ -#include "tcap.h" - -/* Some standard library routines. */ -#include "readline.h" -#include "history.h" - -#include "rlprivate.h" -#include "xmalloc.h" - -#if !defined (strchr) && !defined (__STDC__) -extern char *strchr (), *strrchr (); -#endif /* !strchr && !__STDC__ */ - -static void update_line PARAMS((char *, char *, int, int, int, int)); -static void space_to_eol PARAMS((int)); -static void delete_chars PARAMS((int)); -static void insert_some_chars PARAMS((char *, int, int)); -static void open_some_spaces PARAMS((int)); -static void cr PARAMS((void)); -static void redraw_prompt PARAMS((char *)); - -/* Values for FLAGS */ -#define PMT_MULTILINE 0x01 - -static char *expand_prompt PARAMS((char *, int, int *, int *, int *, int *)); - -/* State of visible and invisible lines. */ -struct line_state - { - char *line; - int *lbreaks; - int lbsize; -#if defined (HANDLE_MULTIBYTE) - int *wrapped_line; - int wbsize; -#endif - }; - -/* The line display buffers. One is the line currently displayed on - the screen. The other is the line about to be displayed. */ -static struct line_state line_state_array[2]; -static struct line_state *line_state_visible = &line_state_array[0]; -static struct line_state *line_state_invisible = &line_state_array[1]; -static int line_structures_initialized = 0; - -/* Backwards-compatible names. */ -#define inv_lbreaks (line_state_invisible->lbreaks) -#define inv_lbsize (line_state_invisible->lbsize) -#define vis_lbreaks (line_state_visible->lbreaks) -#define vis_lbsize (line_state_visible->lbsize) - -#define visible_line (line_state_visible->line) -#define invisible_line (line_state_invisible->line) - -#if defined (HANDLE_MULTIBYTE) -static int _rl_col_width PARAMS((const char *, int, int, int)); -#else -# define _rl_col_width(l, s, e, f) (((e) <= (s)) ? 0 : (e) - (s)) -#endif - -/* Heuristic used to decide whether it is faster to move from CUR to NEW - by backing up or outputting a carriage return and moving forward. CUR - and NEW are either both buffer positions or absolute screen positions. */ -#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new))) - -/* _rl_last_c_pos is an absolute cursor position in multibyte locales and a - buffer index in others. This macro is used when deciding whether the - current cursor position is in the middle of a prompt string containing - invisible characters. XXX - might need to take `modmark' into account. */ -#define PROMPT_ENDING_INDEX \ - ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1) - - -/* **************************************************************** */ -/* */ -/* Display stuff */ -/* */ -/* **************************************************************** */ - -/* This is the stuff that is hard for me. I never seem to write good - display routines in C. Let's see how I do this time. */ - -/* (PWP) Well... Good for a simple line updater, but totally ignores - the problems of input lines longer than the screen width. - - update_line and the code that calls it makes a multiple line, - automatically wrapping line update. Careful attention needs - to be paid to the vertical position variables. */ - -/* Keep two buffers; one which reflects the current contents of the - screen, and the other to draw what we think the new contents should - be. Then compare the buffers, and make whatever changes to the - screen itself that we should. Finally, make the buffer that we - just drew into be the one which reflects the current contents of the - screen, and place the cursor where it belongs. - - Commands that want to can fix the display themselves, and then let - this function know that the display has been fixed by setting the - RL_DISPLAY_FIXED variable. This is good for efficiency. */ - -/* Application-specific redisplay function. */ -rl_voidfunc_t *rl_redisplay_function = rl_redisplay; - -/* Global variables declared here. */ -/* What YOU turn on when you have handled all redisplay yourself. */ -int rl_display_fixed = 0; - -int _rl_suppress_redisplay = 0; -int _rl_want_redisplay = 0; - -/* The stuff that gets printed out before the actual text of the line. - This is usually pointing to rl_prompt. */ -char *rl_display_prompt = (char *)NULL; - -/* Variables used to include the editing mode in the prompt. */ -char *_rl_emacs_mode_str; -int _rl_emacs_modestr_len; - -char *_rl_vi_ins_mode_str; -int _rl_vi_ins_modestr_len; - -char *_rl_vi_cmd_mode_str; -int _rl_vi_cmd_modestr_len; - -/* Pseudo-global variables declared here. */ - -/* The visible cursor position. If you print some text, adjust this. */ -/* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale - supporting multibyte characters, and an absolute cursor position when - in such a locale. This is an artifact of the donated multibyte support. - Care must be taken when modifying its value. */ -int _rl_last_c_pos = 0; -int _rl_last_v_pos = 0; - -static int cpos_adjusted; -static int cpos_buffer_position; -static int displaying_prompt_first_line; -static int prompt_multibyte_chars; - -/* Number of lines currently on screen minus 1. */ -int _rl_vis_botlin = 0; - -/* Variables used only in this file. */ -/* The last left edge of text that was displayed. This is used when - doing horizontal scrolling. It shifts in thirds of a screenwidth. */ -static int last_lmargin; - -/* A buffer for `modeline' messages. */ -static char *msg_buf = 0; -static int msg_bufsiz = 0; - -/* Non-zero forces the redisplay even if we thought it was unnecessary. */ -static int forced_display; - -/* Default and initial buffer size. Can grow. */ -static int line_size = 1024; - -/* Variables to keep track of the expanded prompt string, which may - include invisible characters. */ - -static char *local_prompt, *local_prompt_prefix; -static int local_prompt_len; -static int prompt_visible_length, prompt_prefix_length; - -/* The number of invisible characters in the line currently being - displayed on the screen. */ -static int visible_wrap_offset; - -/* The number of invisible characters in the prompt string. Static so it - can be shared between rl_redisplay and update_line */ -static int wrap_offset; - -/* The index of the last invisible character in the prompt string. */ -static int prompt_last_invisible; - -/* The length (buffer offset) of the first line of the last (possibly - multi-line) buffer displayed on the screen. */ -static int visible_first_line_len; - -/* Number of invisible characters on the first physical line of the prompt. - Only valid when the number of physical characters in the prompt exceeds - (or is equal to) _rl_screenwidth. */ -static int prompt_invis_chars_first_line; - -static int prompt_last_screen_line; - -static int prompt_physical_chars; - -/* set to a non-zero value by rl_redisplay if we are marking modified history - lines and the current line is so marked. */ -static int modmark; - -/* Variables to save and restore prompt and display information. */ - -/* These are getting numerous enough that it's time to create a struct. */ - -static char *saved_local_prompt; -static char *saved_local_prefix; -static int saved_last_invisible; -static int saved_visible_length; -static int saved_prefix_length; -static int saved_local_length; -static int saved_invis_chars_first_line; -static int saved_physical_chars; - -/* Return a string indicating the editing mode, for use in the prompt. */ - -static char * -prompt_modestr (lenp) - int *lenp; -{ - if (rl_editing_mode == emacs_mode) - { - if (lenp) - *lenp = _rl_emacs_mode_str ? _rl_emacs_modestr_len : RL_EMACS_MODESTR_DEFLEN; - return _rl_emacs_mode_str ? _rl_emacs_mode_str : RL_EMACS_MODESTR_DEFAULT; - } - else if (_rl_keymap == vi_insertion_keymap) - { - if (lenp) - *lenp = _rl_vi_ins_mode_str ? _rl_vi_ins_modestr_len : RL_VI_INS_MODESTR_DEFLEN; - return _rl_vi_ins_mode_str ? _rl_vi_ins_mode_str : RL_VI_INS_MODESTR_DEFAULT; /* vi insert mode */ - } - else - { - if (lenp) - *lenp = _rl_vi_cmd_mode_str ? _rl_vi_cmd_modestr_len : RL_VI_CMD_MODESTR_DEFLEN; - return _rl_vi_cmd_mode_str ? _rl_vi_cmd_mode_str : RL_VI_CMD_MODESTR_DEFAULT; /* vi command mode */ - } -} - -/* Expand the prompt string S and return the number of visible - characters in *LP, if LP is not null. This is currently more-or-less - a placeholder for expansion. LIP, if non-null is a place to store the - index of the last invisible character in the returned string. NIFLP, - if non-zero, is a place to store the number of invisible characters in - the first prompt line. The previous are used as byte counts -- indexes - into a character buffer. */ - -/* Current implementation: - \001 (^A) start non-visible characters - \002 (^B) end non-visible characters - all characters except \001 and \002 (following a \001) are copied to - the returned string; all characters except those between \001 and - \002 are assumed to be `visible'. */ - -/* Possible values for FLAGS: - PMT_MULTILINE caller indicates that this is part of a multiline prompt -*/ - -static char * -expand_prompt (pmt, flags, lp, lip, niflp, vlp) - char *pmt; - int flags; - int *lp, *lip, *niflp, *vlp; -{ - char *r, *ret, *p, *igstart, *nprompt, *ms; - int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars; - int mlen; - - /* We only expand the mode string for the last line of a multiline prompt - (a prompt with embedded newlines). */ - ms = (((pmt == rl_prompt) ^ (flags & PMT_MULTILINE)) && _rl_show_mode_in_prompt) ? prompt_modestr (&mlen) : 0; - if (ms) - { - l = strlen (pmt); - nprompt = (char *)xmalloc (l + mlen + 1); - memcpy (nprompt, ms, mlen); - strcpy (nprompt + mlen, pmt); - } - else - nprompt = pmt; - - /* Short-circuit if we can. */ - if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (nprompt, RL_PROMPT_START_IGNORE) == 0) - { - r = (nprompt == pmt) ? savestring (pmt) : nprompt; - - if (lp) - *lp = strlen (r); - if (lip) - *lip = 0; - if (niflp) - *niflp = 0; - if (vlp) - *vlp = lp ? *lp : strlen (r); - return r; - } - - l = strlen (nprompt); /* XXX */ - r = ret = (char *)xmalloc (l + 1); - - rl = physchars = 0; /* mode string now part of nprompt */ - invfl = 0; /* invisible chars in first line of prompt */ - invflset = 0; /* we only want to set invfl once */ - igstart = 0; - - for (ignoring = last = ninvis = 0, p = nprompt; p && *p; p++) - { - /* This code strips the invisible character string markers - RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */ - if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */ - { - ignoring = 1; - igstart = p; - continue; - } - else if (ignoring && *p == RL_PROMPT_END_IGNORE) - { - ignoring = 0; - if (p != (igstart + 1)) - last = r - ret - 1; - continue; - } - else - { -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - pind = p - nprompt; - ind = _rl_find_next_mbchar (nprompt, pind, 1, MB_FIND_NONZERO); - l = ind - pind; - while (l--) - *r++ = *p++; - if (!ignoring) - { - /* rl ends up being assigned to prompt_visible_length, - which is the number of characters in the buffer that - contribute to characters on the screen, which might - not be the same as the number of physical characters - on the screen in the presence of multibyte characters */ - rl += ind - pind; - physchars += _rl_col_width (nprompt, pind, ind, 0); - } - else - ninvis += ind - pind; - p--; /* compensate for later increment */ - } - else -#endif - { - *r++ = *p; - if (!ignoring) - { - rl++; /* visible length byte counter */ - physchars++; - } - else - ninvis++; /* invisible chars byte counter */ - } - - if (invflset == 0 && rl >= _rl_screenwidth) - { - invfl = ninvis; - invflset = 1; - } - } - } - - if (rl < _rl_screenwidth) - invfl = ninvis; - - *r = '\0'; - if (lp) - *lp = rl; - if (lip) - *lip = last; - if (niflp) - *niflp = invfl; - if (vlp) - *vlp = physchars; - - if (nprompt != pmt) - free (nprompt); - - return ret; -} - -/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from - PMT and return the rest of PMT. */ -char * -_rl_strip_prompt (pmt) - char *pmt; -{ - char *ret; - - ret = expand_prompt (pmt, 0, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL); - return ret; -} - -void -_rl_reset_prompt () -{ - rl_visible_prompt_length = rl_expand_prompt (rl_prompt); -} - -/* - * Expand the prompt string into the various display components, if - * necessary. - * - * local_prompt = expanded last line of string in rl_display_prompt - * (portion after the final newline) - * local_prompt_prefix = portion before last newline of rl_display_prompt, - * expanded via expand_prompt - * prompt_visible_length = number of visible characters in local_prompt - * prompt_prefix_length = number of visible characters in local_prompt_prefix - * - * This function is called once per call to readline(). It may also be - * called arbitrarily to expand the primary prompt. - * - * The return value is the number of visible characters on the last line - * of the (possibly multi-line) prompt. - */ -int -rl_expand_prompt (prompt) - char *prompt; -{ - char *p, *t; - int c; - - /* Clear out any saved values. */ - FREE (local_prompt); - FREE (local_prompt_prefix); - - local_prompt = local_prompt_prefix = (char *)0; - local_prompt_len = 0; - prompt_last_invisible = prompt_invis_chars_first_line = 0; - prompt_visible_length = prompt_physical_chars = 0; - - if (prompt == 0 || *prompt == 0) - return (0); - - p = strrchr (prompt, '\n'); - if (p == 0) - { - /* The prompt is only one logical line, though it might wrap. */ - local_prompt = expand_prompt (prompt, 0, &prompt_visible_length, - &prompt_last_invisible, - &prompt_invis_chars_first_line, - &prompt_physical_chars); - local_prompt_prefix = (char *)0; - local_prompt_len = local_prompt ? strlen (local_prompt) : 0; - return (prompt_visible_length); - } - else - { - /* The prompt spans multiple lines. */ - t = ++p; - local_prompt = expand_prompt (p, PMT_MULTILINE, - &prompt_visible_length, - &prompt_last_invisible, - &prompt_invis_chars_first_line, - &prompt_physical_chars); - c = *t; *t = '\0'; - /* The portion of the prompt string up to and including the - final newline is now null-terminated. */ - local_prompt_prefix = expand_prompt (prompt, PMT_MULTILINE, - &prompt_prefix_length, - (int *)NULL, - (int *)NULL, - (int *)NULL); - *t = c; - local_prompt_len = local_prompt ? strlen (local_prompt) : 0; - return (prompt_prefix_length); - } -} - -/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated - arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE - and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is - increased. If the lines have already been allocated, this ensures that - they can hold at least MINSIZE characters. */ -static void -init_line_structures (minsize) - int minsize; -{ - register int n; - - if (invisible_line == 0) /* initialize it */ - { - if (line_size < minsize) - line_size = minsize; - visible_line = (char *)xmalloc (line_size); - invisible_line = (char *)xmalloc (line_size); - } - else if (line_size < minsize) /* ensure it can hold MINSIZE chars */ - { - line_size *= 2; - if (line_size < minsize) - line_size = minsize; - visible_line = (char *)xrealloc (visible_line, line_size); - invisible_line = (char *)xrealloc (invisible_line, line_size); - } - - for (n = minsize; n < line_size; n++) - { - visible_line[n] = 0; - invisible_line[n] = 1; - } - - if (vis_lbreaks == 0) - { - /* should be enough. */ - inv_lbsize = vis_lbsize = 256; - -#if defined (HANDLE_MULTIBYTE) - line_state_visible->wbsize = vis_lbsize; - line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int)); - - line_state_invisible->wbsize = inv_lbsize; - line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int)); -#endif - - inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int)); - vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int)); - inv_lbreaks[0] = vis_lbreaks[0] = 0; - } - - line_structures_initialized = 1; -} - -/* Basic redisplay algorithm. */ -void -rl_redisplay () -{ - register int in, out, c, linenum, cursor_linenum; - register char *line; - int inv_botlin, lb_botlin, lb_linenum, o_cpos; - int newlines, lpos, temp, n0, num, prompt_lines_estimate; - char *prompt_this_line; -#if defined (HANDLE_MULTIBYTE) - wchar_t wc; - size_t wc_bytes; - int wc_width; - mbstate_t ps; - int _rl_wrapped_multicolumn = 0; -#endif - - if (_rl_echoing_p == 0) - return; - - /* Block keyboard interrupts because this function manipulates global - data structures. */ - _rl_block_sigint (); - RL_SETSTATE (RL_STATE_REDISPLAYING); - - if (!rl_display_prompt) - rl_display_prompt = ""; - - if (line_structures_initialized == 0) - { - init_line_structures (0); - rl_on_new_line (); - } - - /* Draw the line into the buffer. */ - cpos_buffer_position = -1; - - prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars; - - line = invisible_line; - out = inv_botlin = 0; - - /* Mark the line as modified or not. We only do this for history - lines. */ - modmark = 0; - if (_rl_mark_modified_lines && current_history () && rl_undo_list) - { - line[out++] = '*'; - line[out] = '\0'; - modmark = 1; - } - - /* If someone thought that the redisplay was handled, but the currently - visible line has a different modification state than the one about - to become visible, then correct the caller's misconception. */ - if (visible_line[0] != invisible_line[0]) - rl_display_fixed = 0; - - /* If the prompt to be displayed is the `primary' readline prompt (the - one passed to readline()), use the values we have already expanded. - If not, use what's already in rl_display_prompt. WRAP_OFFSET is the - number of non-visible characters in the prompt string. */ - if (rl_display_prompt == rl_prompt || local_prompt) - { - if (local_prompt_prefix && forced_display) - _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix)); - - if (local_prompt_len > 0) - { - temp = local_prompt_len + out + 2; - if (temp >= line_size) - { - line_size = (temp + 1024) - (temp % 1024); - visible_line = (char *)xrealloc (visible_line, line_size); - line = invisible_line = (char *)xrealloc (invisible_line, line_size); - } - strncpy (line + out, local_prompt, local_prompt_len); - out += local_prompt_len; - } - line[out] = '\0'; - wrap_offset = local_prompt_len - prompt_visible_length; - } - else - { - int pmtlen; - prompt_this_line = strrchr (rl_display_prompt, '\n'); - if (!prompt_this_line) - prompt_this_line = rl_display_prompt; - else - { - prompt_this_line++; - pmtlen = prompt_this_line - rl_display_prompt; /* temp var */ - if (forced_display) - { - _rl_output_some_chars (rl_display_prompt, pmtlen); - /* Make sure we are at column zero even after a newline, - regardless of the state of terminal output processing. */ - if (pmtlen < 2 || prompt_this_line[-2] != '\r') - cr (); - } - } - - prompt_physical_chars = pmtlen = strlen (prompt_this_line); - temp = pmtlen + out + 2; - if (temp >= line_size) - { - line_size = (temp + 1024) - (temp % 1024); - visible_line = (char *)xrealloc (visible_line, line_size); - line = invisible_line = (char *)xrealloc (invisible_line, line_size); - } - strncpy (line + out, prompt_this_line, pmtlen); - out += pmtlen; - line[out] = '\0'; - wrap_offset = prompt_invis_chars_first_line = 0; - } - -#define CHECK_INV_LBREAKS() \ - do { \ - if (newlines >= (inv_lbsize - 2)) \ - { \ - inv_lbsize *= 2; \ - inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ - } \ - } while (0) - -#if defined (HANDLE_MULTIBYTE) -#define CHECK_LPOS() \ - do { \ - lpos++; \ - if (lpos >= _rl_screenwidth) \ - { \ - if (newlines >= (inv_lbsize - 2)) \ - { \ - inv_lbsize *= 2; \ - inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ - } \ - inv_lbreaks[++newlines] = out; \ - if (newlines >= (line_state_invisible->wbsize - 1)) \ - { \ - line_state_invisible->wbsize *= 2; \ - line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \ - } \ - line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; \ - lpos = 0; \ - } \ - } while (0) -#else -#define CHECK_LPOS() \ - do { \ - lpos++; \ - if (lpos >= _rl_screenwidth) \ - { \ - if (newlines >= (inv_lbsize - 2)) \ - { \ - inv_lbsize *= 2; \ - inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ - } \ - inv_lbreaks[++newlines] = out; \ - lpos = 0; \ - } \ - } while (0) -#endif - - /* inv_lbreaks[i] is where line i starts in the buffer. */ - inv_lbreaks[newlines = 0] = 0; - lpos = prompt_physical_chars + modmark; - -#if defined (HANDLE_MULTIBYTE) - memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int)); - num = 0; -#endif - - /* prompt_invis_chars_first_line is the number of invisible characters in - the first physical line of the prompt. - wrap_offset - prompt_invis_chars_first_line is the number of invis - chars on the second (or, more generally, last) line. */ - - /* This is zero-based, used to set the newlines */ - prompt_lines_estimate = lpos / _rl_screenwidth; - - /* what if lpos is already >= _rl_screenwidth before we start drawing the - contents of the command line? */ - while (lpos >= _rl_screenwidth) - { - int z; - /* fix from Darin Johnson for prompt string with - invisible characters that is longer than the screen width. The - prompt_invis_chars_first_line variable could be made into an array - saying how many invisible characters there are per line, but that's - probably too much work for the benefit gained. How many people have - prompts that exceed two physical lines? - Additional logic fix from Edward Catmur */ -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0) - { - n0 = num; - temp = local_prompt_len; - while (num < temp) - { - z = _rl_col_width (local_prompt, n0, num, 1); - if (z > _rl_screenwidth) - { - num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY); - break; - } - else if (z == _rl_screenwidth) - break; - num++; - } - temp = num; - } - else -#endif /* !HANDLE_MULTIBYTE */ - temp = ((newlines + 1) * _rl_screenwidth); - - /* Now account for invisible characters in the current line. */ - /* XXX - this assumes that the invisible characters may be split, but only - between the first and the last lines. */ - temp += (newlines == 0) ? prompt_invis_chars_first_line - : ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line); - - inv_lbreaks[++newlines] = temp; -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0) - lpos -= _rl_col_width (local_prompt, n0, num, 1); - else -#endif - lpos -= _rl_screenwidth; - } - - prompt_last_screen_line = newlines; - - /* Draw the rest of the line (after the prompt) into invisible_line, keeping - track of where the cursor is (cpos_buffer_position), the number of the line containing - the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin). - It maintains an array of line breaks for display (inv_lbreaks). - This handles expanding tabs for display and displaying meta characters. */ - lb_linenum = 0; -#if defined (HANDLE_MULTIBYTE) - in = 0; - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - memset (&ps, 0, sizeof (mbstate_t)); - /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */ - wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps); - } - else - wc_bytes = 1; - while (in < rl_end) -#else - for (in = 0; in < rl_end; in++) -#endif - { - c = (unsigned char)rl_line_buffer[in]; - -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - if (MB_INVALIDCH (wc_bytes)) - { - /* Byte sequence is invalid or shortened. Assume that the - first byte represents a character. */ - wc_bytes = 1; - /* Assume that a character occupies a single column. */ - wc_width = 1; - memset (&ps, 0, sizeof (mbstate_t)); - } - else if (MB_NULLWCH (wc_bytes)) - break; /* Found '\0' */ - else - { - temp = WCWIDTH (wc); - wc_width = (temp >= 0) ? temp : 1; - } - } -#endif - - if (out + 8 >= line_size) /* XXX - 8 for \t */ - { - line_size *= 2; - visible_line = (char *)xrealloc (visible_line, line_size); - invisible_line = (char *)xrealloc (invisible_line, line_size); - line = invisible_line; - } - - if (in == rl_point) - { - cpos_buffer_position = out; - lb_linenum = newlines; - } - -#if defined (HANDLE_MULTIBYTE) - if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */ -#else - if (META_CHAR (c)) -#endif - { - if (_rl_output_meta_chars == 0) - { - sprintf (line + out, "\\%o", c); - - if (lpos + 4 >= _rl_screenwidth) - { - temp = _rl_screenwidth - lpos; - CHECK_INV_LBREAKS (); - inv_lbreaks[++newlines] = out + temp; - lpos = 4 - temp; - } - else - lpos += 4; - - out += 4; - } - else - { - line[out++] = c; - CHECK_LPOS(); - } - } -#if defined (DISPLAY_TABS) - else if (c == '\t') - { - register int newout; - -#if 0 - newout = (out | (int)7) + 1; -#else - newout = out + 8 - lpos % 8; -#endif - temp = newout - out; - if (lpos + temp >= _rl_screenwidth) - { - register int temp2; - temp2 = _rl_screenwidth - lpos; - CHECK_INV_LBREAKS (); - inv_lbreaks[++newlines] = out + temp2; - lpos = temp - temp2; - while (out < newout) - line[out++] = ' '; - } - else - { - while (out < newout) - line[out++] = ' '; - lpos += temp; - } - } -#endif - else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) - { - line[out++] = '\0'; /* XXX - sentinel */ - CHECK_INV_LBREAKS (); - inv_lbreaks[++newlines] = out; - lpos = 0; - } - else if (CTRL_CHAR (c) || c == RUBOUT) - { - line[out++] = '^'; - CHECK_LPOS(); - line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?'; - CHECK_LPOS(); - } - else - { -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - register int i; - - _rl_wrapped_multicolumn = 0; - - if (_rl_screenwidth < lpos + wc_width) - for (i = lpos; i < _rl_screenwidth; i++) - { - /* The space will be removed in update_line() */ - line[out++] = ' '; - _rl_wrapped_multicolumn++; - CHECK_LPOS(); - } - if (in == rl_point) - { - cpos_buffer_position = out; - lb_linenum = newlines; - } - for (i = in; i < in+wc_bytes; i++) - line[out++] = rl_line_buffer[i]; - for (i = 0; i < wc_width; i++) - CHECK_LPOS(); - } - else - { - line[out++] = c; - CHECK_LPOS(); - } -#else - line[out++] = c; - CHECK_LPOS(); -#endif - } - -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - in += wc_bytes; - /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */ - wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps); - } - else - in++; -#endif - - } - line[out] = '\0'; - if (cpos_buffer_position < 0) - { - cpos_buffer_position = out; - lb_linenum = newlines; - } - - inv_botlin = lb_botlin = newlines; - CHECK_INV_LBREAKS (); - inv_lbreaks[newlines+1] = out; - cursor_linenum = lb_linenum; - - /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed. - CURSOR_LINENUM == line number where the cursor should be placed. */ - - /* PWP: now is when things get a bit hairy. The visible and invisible - line buffers are really multiple lines, which would wrap every - (screenwidth - 1) characters. Go through each in turn, finding - the changed region and updating it. The line order is top to bottom. */ - - /* If we can move the cursor up and down, then use multiple lines, - otherwise, let long lines display in a single terminal line, and - horizontally scroll it. */ - displaying_prompt_first_line = 1; - if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) - { - int nleft, pos, changed_screen_line, tx; - - if (!rl_display_fixed || forced_display) - { - forced_display = 0; - - /* If we have more than a screenful of material to display, then - only display a screenful. We should display the last screen, - not the first. */ - if (out >= _rl_screenchars) - { - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY); - else - out = _rl_screenchars - 1; - } - - /* The first line is at character position 0 in the buffer. The - second and subsequent lines start at inv_lbreaks[N], offset by - OFFSET (which has already been calculated above). */ - -#define INVIS_FIRST() (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset) -#define WRAP_OFFSET(line, offset) ((line == 0) \ - ? (offset ? INVIS_FIRST() : 0) \ - : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0)) -#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0) -#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l])) -#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l]) -#define VIS_CHARS(line) (visible_line + vis_lbreaks[line]) -#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line) -#define INV_LINE(line) (invisible_line + inv_lbreaks[line]) - -#define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \ - _rl_last_c_pos != o_cpos && \ - _rl_last_c_pos > wrap_offset && \ - o_cpos < prompt_last_invisible) - - /* For each line in the buffer, do the updating display. */ - for (linenum = 0; linenum <= inv_botlin; linenum++) - { - /* This can lead us astray if we execute a program that changes - the locale from a non-multibyte to a multibyte one. */ - o_cpos = _rl_last_c_pos; - cpos_adjusted = 0; - update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum, - VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin); - - /* update_line potentially changes _rl_last_c_pos, but doesn't - take invisible characters into account, since _rl_last_c_pos - is an absolute cursor position in a multibyte locale. See - if compensating here is the right thing, or if we have to - change update_line itself. There are several cases in which - update_line adjusts _rl_last_c_pos itself (so it can pass - _rl_move_cursor_relative accurate values); it communicates - this back by setting cpos_adjusted. If we assume that - _rl_last_c_pos is correct (an absolute cursor position) each - time update_line is called, then we can assume in our - calculations that o_cpos does not need to be adjusted by - wrap_offset. */ - if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT()) - _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */ - else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth && - (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && - cpos_adjusted == 0 && - _rl_last_c_pos != o_cpos && - _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line)) - _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line); - - /* If this is the line with the prompt, we might need to - compensate for invisible characters in the new line. Do - this only if there is not more than one new line (which - implies that we completely overwrite the old visible line) - and the new line is shorter than the old. Make sure we are - at the end of the new line before clearing. */ - if (linenum == 0 && - inv_botlin == 0 && _rl_last_c_pos == out && - (wrap_offset > visible_wrap_offset) && - (_rl_last_c_pos < visible_first_line_len)) - { - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - nleft = _rl_screenwidth - _rl_last_c_pos; - else - nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; - if (nleft) - _rl_clear_to_eol (nleft); - } -#if 0 - /* This segment is intended to handle the case where the prompt - has invisible characters on the second line and the new line - to be displayed needs to clear the rest of the old characters - out (e.g., when printing the i-search prompt). In general, - the case of the new line being shorter than the old. - Incomplete */ - else if (linenum == prompt_last_screen_line && - prompt_physical_chars > _rl_screenwidth && - wrap_offset != prompt_invis_chars_first_line && - _rl_last_c_pos == out && -#endif - - - /* Since the new first line is now visible, save its length. */ - if (linenum == 0) - visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset; - } - - /* We may have deleted some lines. If so, clear the left over - blank ones at the bottom out. */ - if (_rl_vis_botlin > inv_botlin) - { - char *tt; - for (; linenum <= _rl_vis_botlin; linenum++) - { - tt = VIS_CHARS (linenum); - _rl_move_vert (linenum); - _rl_move_cursor_relative (0, tt); - _rl_clear_to_eol - ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth); - } - } - _rl_vis_botlin = inv_botlin; - - /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a - different screen line during this redisplay. */ - changed_screen_line = _rl_last_v_pos != cursor_linenum; - if (changed_screen_line) - { - _rl_move_vert (cursor_linenum); - /* If we moved up to the line with the prompt using _rl_term_up, - the physical cursor position on the screen stays the same, - but the buffer position needs to be adjusted to account - for invisible characters. */ - if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset) - _rl_last_c_pos += wrap_offset; - } - - /* We have to reprint the prompt if it contains invisible - characters, since it's not generally OK to just reprint - the characters from the current cursor position. But we - only need to reprint it if the cursor is before the last - invisible character in the prompt string. */ - nleft = prompt_visible_length + wrap_offset; - if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 && -#if 0 - _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt) -#else - _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt) -#endif - { -#if defined (__MSDOS__) - putc ('\r', rl_outstream); -#else - if (_rl_term_cr) - tputs (_rl_term_cr, 1, _rl_output_character_function); -#endif - if (modmark) - _rl_output_some_chars ("*", 1); - - _rl_output_some_chars (local_prompt, nleft); - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark; - else - _rl_last_c_pos = nleft + modmark; - } - - /* Where on that line? And where does that line start - in the buffer? */ - pos = inv_lbreaks[cursor_linenum]; - /* nleft == number of characters in the line buffer between the - start of the line and the desired cursor position. */ - nleft = cpos_buffer_position - pos; - - /* NLEFT is now a number of characters in a buffer. When in a - multibyte locale, however, _rl_last_c_pos is an absolute cursor - position that doesn't take invisible characters in the prompt - into account. We use a fudge factor to compensate. */ - - /* Since _rl_backspace() doesn't know about invisible characters in the - prompt, and there's no good way to tell it, we compensate for - those characters here and call _rl_backspace() directly. */ - if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) - { - /* TX == new physical cursor position in multibyte locale. */ - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset; - else - tx = nleft; - if (tx >= 0 && _rl_last_c_pos > tx) - { - _rl_backspace (_rl_last_c_pos - tx); /* XXX */ - _rl_last_c_pos = tx; - } - } - - /* We need to note that in a multibyte locale we are dealing with - _rl_last_c_pos as an absolute cursor position, but moving to a - point specified by a buffer position (NLEFT) that doesn't take - invisible characters into account. */ - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_move_cursor_relative (nleft, &invisible_line[pos]); - else if (nleft != _rl_last_c_pos) - _rl_move_cursor_relative (nleft, &invisible_line[pos]); - } - } - else /* Do horizontal scrolling. */ - { -#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0) - int lmargin, ndisp, nleft, phys_c_pos, t; - - /* Always at top line. */ - _rl_last_v_pos = 0; - - /* Compute where in the buffer the displayed line should start. This - will be LMARGIN. */ - - /* The number of characters that will be displayed before the cursor. */ - ndisp = cpos_buffer_position - wrap_offset; - nleft = prompt_visible_length + wrap_offset; - /* Where the new cursor position will be on the screen. This can be - longer than SCREENWIDTH; if it is, lmargin will be adjusted. */ - phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset); - t = _rl_screenwidth / 3; - - /* If the number of characters had already exceeded the screenwidth, - last_lmargin will be > 0. */ - - /* If the number of characters to be displayed is more than the screen - width, compute the starting offset so that the cursor is about - two-thirds of the way across the screen. */ - if (phys_c_pos > _rl_screenwidth - 2) - { - lmargin = cpos_buffer_position - (2 * t); - if (lmargin < 0) - lmargin = 0; - /* If the left margin would be in the middle of a prompt with - invisible characters, don't display the prompt at all. */ - if (wrap_offset && lmargin > 0 && lmargin < nleft) - lmargin = nleft; - } - else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */ - lmargin = 0; - else if (phys_c_pos < 1) - { - /* If we are moving back towards the beginning of the line and - the last margin is no longer correct, compute a new one. */ - lmargin = ((cpos_buffer_position - 1) / t) * t; /* XXX */ - if (wrap_offset && lmargin > 0 && lmargin < nleft) - lmargin = nleft; - } - else - lmargin = last_lmargin; - - displaying_prompt_first_line = lmargin < nleft; - - /* If the first character on the screen isn't the first character - in the display line, indicate this with a special character. */ - if (lmargin > 0) - line[lmargin] = '<'; - - /* If SCREENWIDTH characters starting at LMARGIN do not encompass - the whole line, indicate that with a special character at the - right edge of the screen. If LMARGIN is 0, we need to take the - wrap offset into account. */ - t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth; - if (t < out) - line[t - 1] = '>'; - - if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin) - { - forced_display = 0; - o_cpos = _rl_last_c_pos; - cpos_adjusted = 0; - update_line (&visible_line[last_lmargin], - &invisible_line[lmargin], - 0, - _rl_screenwidth + visible_wrap_offset, - _rl_screenwidth + (lmargin ? 0 : wrap_offset), - 0); - - if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && - displaying_prompt_first_line && OLD_CPOS_IN_PROMPT()) - _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */ - - /* If the visible new line is shorter than the old, but the number - of invisible characters is greater, and we are at the end of - the new line, we need to clear to eol. */ - t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset); - if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) && - (_rl_last_c_pos == out) && displaying_prompt_first_line && - t < visible_first_line_len) - { - nleft = _rl_screenwidth - t; - _rl_clear_to_eol (nleft); - } - visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset); - if (visible_first_line_len > _rl_screenwidth) - visible_first_line_len = _rl_screenwidth; - - _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]); - last_lmargin = lmargin; - } - } - fflush (rl_outstream); - - /* Swap visible and non-visible lines. */ - { - struct line_state *vtemp = line_state_visible; - - line_state_visible = line_state_invisible; - line_state_invisible = vtemp; - - rl_display_fixed = 0; - /* If we are displaying on a single line, and last_lmargin is > 0, we - are not displaying any invisible characters, so set visible_wrap_offset - to 0. */ - if (_rl_horizontal_scroll_mode && last_lmargin) - visible_wrap_offset = 0; - else - visible_wrap_offset = wrap_offset; - } - - RL_UNSETSTATE (RL_STATE_REDISPLAYING); - _rl_release_sigint (); -} - -/* PWP: update_line() is based on finding the middle difference of each - line on the screen; vis: - - /old first difference - /beginning of line | /old last same /old EOL - v v v v -old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as -new: eddie> Oh, my little buggy says to me, as lurgid as - ^ ^ ^ ^ - \beginning of line | \new last same \new end of line - \new first difference - - All are character pointers for the sake of speed. Special cases for - no differences, as well as for end of line additions must be handled. - - Could be made even smarter, but this works well enough */ -static void -update_line (old, new, current_line, omax, nmax, inv_botlin) - register char *old, *new; - int current_line, omax, nmax, inv_botlin; -{ - register char *ofd, *ols, *oe, *nfd, *nls, *ne; - int temp, lendiff, wsatend, od, nd, twidth, o_cpos; - int current_invis_chars; - int col_lendiff, col_temp; - int bytes_to_insert; -#if defined (HANDLE_MULTIBYTE) - mbstate_t ps_new, ps_old; - int new_offset, old_offset; -#endif - - /* If we're at the right edge of a terminal that supports xn, we're - ready to wrap around, so do so. This fixes problems with knowing - the exact cursor position and cut-and-paste with certain terminal - emulators. In this calculation, TEMP is the physical screen - position of the cursor. */ - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - temp = _rl_last_c_pos; - else - temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset); - if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode - && _rl_last_v_pos == current_line - 1) - { -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - wchar_t wc; - mbstate_t ps; - int tempwidth, bytes; - size_t ret; - - /* This fixes only double-column characters, but if the wrapped - character consumes more than three columns, spaces will be - inserted in the string buffer. */ - if (current_line < line_state_visible->wbsize && line_state_visible->wrapped_line[current_line] > 0) - _rl_clear_to_eol (line_state_visible->wrapped_line[current_line]); - - memset (&ps, 0, sizeof (mbstate_t)); - ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps); - if (MB_INVALIDCH (ret)) - { - tempwidth = 1; - ret = 1; - } - else if (MB_NULLWCH (ret)) - tempwidth = 0; - else - tempwidth = WCWIDTH (wc); - - if (tempwidth > 0) - { - int count, i; - bytes = ret; - for (count = 0; count < bytes; count++) - putc (new[count], rl_outstream); - _rl_last_c_pos = tempwidth; - _rl_last_v_pos++; - memset (&ps, 0, sizeof (mbstate_t)); - ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps); - if (ret != 0 && bytes != 0) - { - if (MB_INVALIDCH (ret)) - ret = 1; - memmove (old+bytes, old+ret, strlen (old+ret)); - memcpy (old, new, bytes); - /* Fix up indices if we copy data from one line to another */ - omax += bytes - ret; - for (i = current_line+1; i <= inv_botlin+1; i++) - vis_lbreaks[i] += bytes - ret; - } - } - else - { - putc (' ', rl_outstream); - _rl_last_c_pos = 1; - _rl_last_v_pos++; - if (old[0] && new[0]) - old[0] = new[0]; - } - } - else -#endif - { - if (new[0]) - putc (new[0], rl_outstream); - else - putc (' ', rl_outstream); - _rl_last_c_pos = 1; - _rl_last_v_pos++; - if (old[0] && new[0]) - old[0] = new[0]; - } - } - - - /* Find first difference. */ -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - /* See if the old line is a subset of the new line, so that the - only change is adding characters. */ - temp = (omax < nmax) ? omax : nmax; - if (memcmp (old, new, temp) == 0) /* adding at the end */ - { - new_offset = old_offset = temp; - ofd = old + temp; - nfd = new + temp; - } - else - { - memset (&ps_new, 0, sizeof(mbstate_t)); - memset (&ps_old, 0, sizeof(mbstate_t)); - - if (omax == nmax && STREQN (new, old, omax)) - { - old_offset = omax; - new_offset = nmax; - ofd = old + omax; - nfd = new + nmax; - } - else - { - new_offset = old_offset = 0; - for (ofd = old, nfd = new; - (ofd - old < omax) && *ofd && - _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); ) - { - old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY); - new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY); - - ofd = old + old_offset; - nfd = new + new_offset; - } - } - } - } - else -#endif - for (ofd = old, nfd = new; - (ofd - old < omax) && *ofd && (*ofd == *nfd); - ofd++, nfd++) - ; - - /* Move to the end of the screen line. ND and OD are used to keep track - of the distance between ne and new and oe and old, respectively, to - move a subtraction out of each loop. */ - for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++); - for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++); - - /* If no difference, continue to next line. */ - if (ofd == oe && nfd == ne) - return; - -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_utf8locale) - { - wchar_t wc; - mbstate_t ps = { 0 }; - int t; - - /* If the first character in the difference is a zero-width character, - assume it's a combining character and back one up so the two base - characters no longer compare equivalently. */ - t = mbrtowc (&wc, ofd, MB_CUR_MAX, &ps); - if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0) - { - old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY); - new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY); - ofd = old + old_offset; /* equal by definition */ - nfd = new + new_offset; - } - } -#endif - - wsatend = 1; /* flag for trailing whitespace */ - -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY); - nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY); - - while ((ols > ofd) && (nls > nfd)) - { - memset (&ps_old, 0, sizeof (mbstate_t)); - memset (&ps_new, 0, sizeof (mbstate_t)); - -#if 0 - /* On advice from jir@yamato.ibm.com */ - _rl_adjust_point (old, ols - old, &ps_old); - _rl_adjust_point (new, nls - new, &ps_new); -#endif - - if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0) - break; - - if (*ols == ' ') - wsatend = 0; - - ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY); - nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY); - } - } - else - { -#endif /* HANDLE_MULTIBYTE */ - ols = oe - 1; /* find last same */ - nls = ne - 1; - while ((ols > ofd) && (nls > nfd) && (*ols == *nls)) - { - if (*ols != ' ') - wsatend = 0; - ols--; - nls--; - } -#if defined (HANDLE_MULTIBYTE) - } -#endif - - if (wsatend) - { - ols = oe; - nls = ne; - } -#if defined (HANDLE_MULTIBYTE) - /* This may not work for stateful encoding, but who cares? To handle - stateful encoding properly, we have to scan each string from the - beginning and compare. */ - else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0) -#else - else if (*ols != *nls) -#endif - { - if (*ols) /* don't step past the NUL */ - { - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY); - else - ols++; - } - if (*nls) - { - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY); - else - nls++; - } - } - - /* count of invisible characters in the current invisible line. */ - current_invis_chars = W_OFFSET (current_line, wrap_offset); - if (_rl_last_v_pos != current_line) - { - _rl_move_vert (current_line); - if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset) - _rl_last_c_pos += visible_wrap_offset; - } - - /* If this is the first line and there are invisible characters in the - prompt string, and the prompt string has not changed, and the current - cursor position is before the last invisible character in the prompt, - and the index of the character to move to is past the end of the prompt - string, then redraw the entire prompt string. We can only do this - reliably if the terminal supports a `cr' capability. - - This is not an efficiency hack -- there is a problem with redrawing - portions of the prompt string if they contain terminal escape - sequences (like drawing the `unbold' sequence without a corresponding - `bold') that manifests itself on certain terminals. */ - - lendiff = local_prompt_len; - od = ofd - old; /* index of first difference in visible line */ - if (current_line == 0 && !_rl_horizontal_scroll_mode && - _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 && - od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX) - { -#if defined (__MSDOS__) - putc ('\r', rl_outstream); -#else - tputs (_rl_term_cr, 1, _rl_output_character_function); -#endif - if (modmark) - _rl_output_some_chars ("*", 1); - _rl_output_some_chars (local_prompt, lendiff); - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - /* We take wrap_offset into account here so we can pass correct - information to _rl_move_cursor_relative. */ - _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark; - cpos_adjusted = 1; - } - else - _rl_last_c_pos = lendiff + modmark; - } - - o_cpos = _rl_last_c_pos; - - /* When this function returns, _rl_last_c_pos is correct, and an absolute - cursor position in multibyte mode, but a buffer index when not in a - multibyte locale. */ - _rl_move_cursor_relative (od, old); - -#if defined (HANDLE_MULTIBYTE) - /* We need to indicate that the cursor position is correct in the presence of - invisible characters in the prompt string. Let's see if setting this when - we make sure we're at the end of the drawn prompt string works. */ - if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && - (_rl_last_c_pos > 0 || o_cpos > 0) && - _rl_last_c_pos == prompt_physical_chars) - cpos_adjusted = 1; -#endif - - /* if (len (new) > len (old)) - lendiff == difference in buffer (bytes) - col_lendiff == difference on screen (columns) - When not using multibyte characters, these are equal */ - lendiff = (nls - nfd) - (ols - ofd); - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - col_lendiff = _rl_col_width (new, nfd - new, nls - new, 1) - _rl_col_width (old, ofd - old, ols - old, 1); - else - col_lendiff = lendiff; - - /* If we are changing the number of invisible characters in a line, and - the spot of first difference is before the end of the invisible chars, - lendiff needs to be adjusted. */ - if (current_line == 0 && /* !_rl_horizontal_scroll_mode && */ - current_invis_chars != visible_wrap_offset) - { - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - lendiff += visible_wrap_offset - current_invis_chars; - col_lendiff += visible_wrap_offset - current_invis_chars; - } - else - { - lendiff += visible_wrap_offset - current_invis_chars; - col_lendiff = lendiff; - } - } - - /* We use temp as a count of the number of bytes from the first difference - to the end of the new line. col_temp is the corresponding number of - screen columns. A `dumb' update moves to the spot of first difference - and writes TEMP bytes. */ - /* Insert (diff (len (old), len (new)) ch. */ - temp = ne - nfd; - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - col_temp = _rl_col_width (new, nfd - new, ne - new, 1); - else - col_temp = temp; - - /* how many bytes from the new line buffer to write to the display */ - bytes_to_insert = nls - nfd; - - /* col_lendiff > 0 if we are adding characters to the line */ - if (col_lendiff > 0) /* XXX - was lendiff */ - { - /* Non-zero if we're increasing the number of lines. */ - int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; - /* If col_lendiff is > 0, implying that the new string takes up more - screen real estate than the old, but lendiff is < 0, meaning that it - takes fewer bytes, we need to just output the characters starting - from the first difference. These will overwrite what is on the - display, so there's no reason to do a smart update. This can really - only happen in a multibyte environment. */ - if (lendiff < 0) - { - _rl_output_some_chars (nfd, temp); - _rl_last_c_pos += col_temp; /* XXX - was _rl_col_width (nfd, 0, temp, 1); */ - /* If nfd begins before any invisible characters in the prompt, - adjust _rl_last_c_pos to account for wrap_offset and set - cpos_adjusted to let the caller know. */ - if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible)) - { - _rl_last_c_pos -= wrap_offset; - cpos_adjusted = 1; - } - return; - } - /* Sometimes it is cheaper to print the characters rather than - use the terminal's capabilities. If we're growing the number - of lines, make sure we actually cause the new line to wrap - around on auto-wrapping terminals. */ - else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl)) - { - /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and - _rl_horizontal_scroll_mode == 1, inserting the characters with - _rl_term_IC or _rl_term_ic will screw up the screen because of the - invisible characters. We need to just draw them. */ - /* The same thing happens if we're trying to draw before the last - invisible character in the prompt string or we're increasing the - number of invisible characters in the line and we're not drawing - the entire prompt string. */ - if (*ols && ((_rl_horizontal_scroll_mode && - _rl_last_c_pos == 0 && - lendiff > prompt_visible_length && - current_invis_chars > 0) == 0) && - (((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && - current_line == 0 && wrap_offset && - ((nfd - new) <= prompt_last_invisible) && - (col_lendiff < prompt_visible_length)) == 0) && - (visible_wrap_offset >= current_invis_chars)) - { - open_some_spaces (col_lendiff); - _rl_output_some_chars (nfd, bytes_to_insert); - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1); - else - _rl_last_c_pos += bytes_to_insert; - } - else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0) - { - /* At the end of a line the characters do not have to - be "inserted". They can just be placed on the screen. */ - _rl_output_some_chars (nfd, temp); - _rl_last_c_pos += col_temp; - return; - } - else /* just write from first difference to end of new line */ - { - _rl_output_some_chars (nfd, temp); - _rl_last_c_pos += col_temp; - /* If nfd begins before the last invisible character in the - prompt, adjust _rl_last_c_pos to account for wrap_offset - and set cpos_adjusted to let the caller know. */ - if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible)) - { - _rl_last_c_pos -= wrap_offset; - cpos_adjusted = 1; - } - return; - } - - if (bytes_to_insert > lendiff) - { - /* If nfd begins before the last invisible character in the - prompt, adjust _rl_last_c_pos to account for wrap_offset - and set cpos_adjusted to let the caller know. */ - if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible)) - { - _rl_last_c_pos -= wrap_offset; - cpos_adjusted = 1; - } - } - } - else - { - /* cannot insert chars, write to EOL */ - _rl_output_some_chars (nfd, temp); - _rl_last_c_pos += col_temp; - /* If we're in a multibyte locale and were before the last invisible - char in the current line (which implies we just output some invisible - characters) we need to adjust _rl_last_c_pos, since it represents - a physical character position. */ - if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && - current_line == prompt_last_screen_line && wrap_offset && - displaying_prompt_first_line && - wrap_offset != prompt_invis_chars_first_line && - ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth)))) - { - _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line; - cpos_adjusted = 1; - } - } - } - else /* Delete characters from line. */ - { - /* If possible and inexpensive to use terminal deletion, then do so. */ - if (_rl_term_dc && (2 * col_temp) >= -col_lendiff) - { - /* If all we're doing is erasing the invisible characters in the - prompt string, don't bother. It screws up the assumptions - about what's on the screen. */ - if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 && - displaying_prompt_first_line && - -lendiff == visible_wrap_offset) - col_lendiff = 0; - - /* If we have moved lmargin and we're shrinking the line, we've - already moved the cursor to the first character of the new line, - so deleting -col_lendiff characters will mess up the cursor - position calculation */ - if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 && - col_lendiff && _rl_last_c_pos < -col_lendiff) - col_lendiff = 0; - - if (col_lendiff) - delete_chars (-col_lendiff); /* delete (diff) characters */ - - /* Copy (new) chars to screen from first diff to last match, - overwriting what is there. */ - if (bytes_to_insert > 0) - { - /* If nfd begins at the prompt, or before the invisible - characters in the prompt, we need to adjust _rl_last_c_pos - in a multibyte locale to account for the wrap offset and - set cpos_adjusted accordingly. */ - _rl_output_some_chars (nfd, bytes_to_insert); - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1); - if (current_line == 0 && wrap_offset && - displaying_prompt_first_line && - _rl_last_c_pos > wrap_offset && - ((nfd - new) <= prompt_last_invisible)) - { - _rl_last_c_pos -= wrap_offset; - cpos_adjusted = 1; - } - } - else - _rl_last_c_pos += bytes_to_insert; - - /* XXX - we only want to do this if we are at the end of the line - so we move there with _rl_move_cursor_relative */ - if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new))) - { - _rl_move_cursor_relative (ne-new, new); - goto clear_rest_of_line; - } - } - } - /* Otherwise, print over the existing material. */ - else - { - if (temp > 0) - { - /* If nfd begins at the prompt, or before the invisible - characters in the prompt, we need to adjust _rl_last_c_pos - in a multibyte locale to account for the wrap offset and - set cpos_adjusted accordingly. */ - _rl_output_some_chars (nfd, temp); - _rl_last_c_pos += col_temp; /* XXX */ - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - if (current_line == 0 && wrap_offset && - displaying_prompt_first_line && - _rl_last_c_pos > wrap_offset && - ((nfd - new) <= prompt_last_invisible)) - { - _rl_last_c_pos -= wrap_offset; - cpos_adjusted = 1; - } - } - } -clear_rest_of_line: - lendiff = (oe - old) - (ne - new); - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1); - else - col_lendiff = lendiff; - - /* If we've already printed over the entire width of the screen, - including the old material, then col_lendiff doesn't matter and - space_to_eol will insert too many spaces. XXX - maybe we should - adjust col_lendiff based on the difference between _rl_last_c_pos - and _rl_screenwidth */ - if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth))) - { - if (_rl_term_autowrap && current_line < inv_botlin) - space_to_eol (col_lendiff); - else - _rl_clear_to_eol (col_lendiff); - } - } - } -} - -/* Tell the update routines that we have moved onto a new (empty) line. */ -int -rl_on_new_line () -{ - if (visible_line) - visible_line[0] = '\0'; - - _rl_last_c_pos = _rl_last_v_pos = 0; - _rl_vis_botlin = last_lmargin = 0; - if (vis_lbreaks) - vis_lbreaks[0] = vis_lbreaks[1] = 0; - visible_wrap_offset = 0; - return 0; -} - -/* Tell the update routines that we have moved onto a new line with the - prompt already displayed. Code originally from the version of readline - distributed with CLISP. rl_expand_prompt must have already been called - (explicitly or implicitly). This still doesn't work exactly right. */ -int -rl_on_new_line_with_prompt () -{ - int prompt_size, i, l, real_screenwidth, newlines; - char *prompt_last_line, *lprompt; - - /* Initialize visible_line and invisible_line to ensure that they can hold - the already-displayed prompt. */ - prompt_size = strlen (rl_prompt) + 1; - init_line_structures (prompt_size); - - /* Make sure the line structures hold the already-displayed prompt for - redisplay. */ - lprompt = local_prompt ? local_prompt : rl_prompt; - strcpy (visible_line, lprompt); - strcpy (invisible_line, lprompt); - - /* If the prompt contains newlines, take the last tail. */ - prompt_last_line = strrchr (rl_prompt, '\n'); - if (!prompt_last_line) - prompt_last_line = rl_prompt; - - l = strlen (prompt_last_line); - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1); /* XXX */ - else - _rl_last_c_pos = l; - - /* Dissect prompt_last_line into screen lines. Note that here we have - to use the real screenwidth. Readline's notion of screenwidth might be - one less, see terminal.c. */ - real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1); - _rl_last_v_pos = l / real_screenwidth; - /* If the prompt length is a multiple of real_screenwidth, we don't know - whether the cursor is at the end of the last line, or already at the - beginning of the next line. Output a newline just to be safe. */ - if (l > 0 && (l % real_screenwidth) == 0) - _rl_output_some_chars ("\n", 1); - last_lmargin = 0; - - newlines = 0; i = 0; - while (i <= l) - { - _rl_vis_botlin = newlines; - vis_lbreaks[newlines++] = i; - i += real_screenwidth; - } - vis_lbreaks[newlines] = l; - visible_wrap_offset = 0; - - rl_display_prompt = rl_prompt; /* XXX - make sure it's set */ - - return 0; -} - -/* Actually update the display, period. */ -int -rl_forced_update_display () -{ - register char *temp; - - if (visible_line) - { - temp = visible_line; - while (*temp) - *temp++ = '\0'; - } - rl_on_new_line (); - forced_display++; - (*rl_redisplay_function) (); - return 0; -} - -/* Redraw only the last line of a multi-line prompt. */ -void -rl_redraw_prompt_last_line () -{ - char *t; - - t = strrchr (rl_display_prompt, '\n'); - if (t) - redraw_prompt (++t); - else - rl_forced_update_display (); -} - -/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices. - (Well, when we don't have multibyte characters, _rl_last_c_pos is a - buffer index.) - DATA is the contents of the screen line of interest; i.e., where - the movement is being done. */ -void -_rl_move_cursor_relative (new, data) - int new; - const char *data; -{ - register int i; - int woff; /* number of invisible chars on current line */ - int cpos, dpos; /* current and desired cursor positions */ - int adjust; - - woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset); - cpos = _rl_last_c_pos; - - if (cpos == 0 && cpos == new) - return; - -#if defined (HANDLE_MULTIBYTE) - /* If we have multibyte characters, NEW is indexed by the buffer point in - a multibyte string, but _rl_last_c_pos is the display position. In - this case, NEW's display position is not obvious and must be - calculated. We need to account for invisible characters in this line, - as long as we are past them and they are counted by _rl_col_width. */ - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - adjust = 1; - /* Try to short-circuit common cases and eliminate a bunch of multibyte - character function calls. */ - /* 1. prompt string */ - if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0) - { - dpos = prompt_physical_chars; - cpos_adjusted = 1; - adjust = 0; - } - /* 2. prompt_string + line contents */ - else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0) - { - dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1); - cpos_adjusted = 1; - adjust = 0; - } - else - dpos = _rl_col_width (data, 0, new, 1); - - if (displaying_prompt_first_line == 0) - adjust = 0; - - /* Use NEW when comparing against the last invisible character in the - prompt string, since they're both buffer indices and DPOS is a - desired display position. */ - if (adjust && ((new > prompt_last_invisible) || /* XXX - don't use woff here */ - (prompt_physical_chars >= _rl_screenwidth && - _rl_last_v_pos == prompt_last_screen_line && - wrap_offset >= woff && dpos >= woff && - new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset)))) - /* XXX last comparison might need to be >= */ - { - dpos -= woff; - /* Since this will be assigned to _rl_last_c_pos at the end (more - precisely, _rl_last_c_pos == dpos when this function returns), - let the caller know. */ - cpos_adjusted = 1; - } - } - else -#endif - dpos = new; - - /* If we don't have to do anything, then return. */ - if (cpos == dpos) - return; - - /* It may be faster to output a CR, and then move forwards instead - of moving backwards. */ - /* i == current physical cursor position. */ -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - i = _rl_last_c_pos; - else -#endif - i = _rl_last_c_pos - woff; - if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) || - (_rl_term_autowrap && i == _rl_screenwidth)) - { -#if defined (__MSDOS__) - putc ('\r', rl_outstream); -#else - tputs (_rl_term_cr, 1, _rl_output_character_function); -#endif /* !__MSDOS__ */ - cpos = _rl_last_c_pos = 0; - } - - if (cpos < dpos) - { - /* Move the cursor forward. We do it by printing the command - to move the cursor forward if there is one, else print that - portion of the output buffer again. Which is cheaper? */ - - /* The above comment is left here for posterity. It is faster - to print one character (non-control) than to print a control - sequence telling the terminal to move forward one character. - That kind of control is for people who don't know what the - data is underneath the cursor. */ - - /* However, we need a handle on where the current display position is - in the buffer for the immediately preceding comment to be true. - In multibyte locales, we don't currently have that info available. - Without it, we don't know where the data we have to display begins - in the buffer and we have to go back to the beginning of the screen - line. In this case, we can use the terminal sequence to move forward - if it's available. */ - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - if (_rl_term_forward_char) - { - for (i = cpos; i < dpos; i++) - tputs (_rl_term_forward_char, 1, _rl_output_character_function); - } - else - { - tputs (_rl_term_cr, 1, _rl_output_character_function); - for (i = 0; i < new; i++) - putc (data[i], rl_outstream); - } - } - else - for (i = cpos; i < new; i++) - putc (data[i], rl_outstream); - } - -#if defined (HANDLE_MULTIBYTE) - /* NEW points to the buffer point, but _rl_last_c_pos is the display point. - The byte length of the string is probably bigger than the column width - of the string, which means that if NEW == _rl_last_c_pos, then NEW's - display point is less than _rl_last_c_pos. */ -#endif - else if (cpos > dpos) - _rl_backspace (cpos - dpos); - - _rl_last_c_pos = dpos; -} - -/* PWP: move the cursor up or down. */ -void -_rl_move_vert (to) - int to; -{ - register int delta, i; - - if (_rl_last_v_pos == to || to > _rl_screenheight) - return; - - if ((delta = to - _rl_last_v_pos) > 0) - { - for (i = 0; i < delta; i++) - putc ('\n', rl_outstream); -#if defined (__MSDOS__) - putc ('\r', rl_outstream); -#else - tputs (_rl_term_cr, 1, _rl_output_character_function); -#endif - _rl_last_c_pos = 0; - } - else - { /* delta < 0 */ -#ifdef __DJGPP__ - int row, col; - - fflush (rl_outstream); - ScreenGetCursor (&row, &col); - ScreenSetCursor (row + delta, col); - i = -delta; -#else - if (_rl_term_up && *_rl_term_up) - for (i = 0; i < -delta; i++) - tputs (_rl_term_up, 1, _rl_output_character_function); -#endif /* !__DJGPP__ */ - } - - _rl_last_v_pos = to; /* Now TO is here */ -} - -/* Physically print C on rl_outstream. This is for functions which know - how to optimize the display. Return the number of characters output. */ -int -rl_show_char (c) - int c; -{ - int n = 1; - if (META_CHAR (c) && (_rl_output_meta_chars == 0)) - { - fprintf (rl_outstream, "M-"); - n += 2; - c = UNMETA (c); - } - -#if defined (DISPLAY_TABS) - if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT) -#else - if (CTRL_CHAR (c) || c == RUBOUT) -#endif /* !DISPLAY_TABS */ - { - fprintf (rl_outstream, "C-"); - n += 2; - c = CTRL_CHAR (c) ? UNCTRL (c) : '?'; - } - - putc (c, rl_outstream); - fflush (rl_outstream); - return n; -} - -int -rl_character_len (c, pos) - register int c, pos; -{ - unsigned char uc; - - uc = (unsigned char)c; - - if (META_CHAR (uc)) - return ((_rl_output_meta_chars == 0) ? 4 : 1); - - if (uc == '\t') - { -#if defined (DISPLAY_TABS) - return (((pos | 7) + 1) - pos); -#else - return (2); -#endif /* !DISPLAY_TABS */ - } - - if (CTRL_CHAR (c) || c == RUBOUT) - return (2); - - return ((ISPRINT (uc)) ? 1 : 2); -} -/* How to print things in the "echo-area". The prompt is treated as a - mini-modeline. */ -static int msg_saved_prompt = 0; - -#if defined (USE_VARARGS) -int -#if defined (PREFER_STDARG) -rl_message (const char *format, ...) -#else -rl_message (va_alist) - va_dcl -#endif -{ - va_list args; -#if defined (PREFER_VARARGS) - char *format; -#endif -#if defined (HAVE_VSNPRINTF) - int bneed; -#endif - -#if defined (PREFER_STDARG) - va_start (args, format); -#else - va_start (args); - format = va_arg (args, char *); -#endif - - if (msg_buf == 0) - msg_buf = xmalloc (msg_bufsiz = 128); - -#if defined (HAVE_VSNPRINTF) - bneed = vsnprintf (msg_buf, msg_bufsiz, format, args); - if (bneed >= msg_bufsiz - 1) - { - msg_bufsiz = bneed + 1; - msg_buf = xrealloc (msg_buf, msg_bufsiz); - va_end (args); - -#if defined (PREFER_STDARG) - va_start (args, format); -#else - va_start (args); - format = va_arg (args, char *); -#endif - vsnprintf (msg_buf, msg_bufsiz - 1, format, args); - } -#else - vsprintf (msg_buf, format, args); - msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */ -#endif - va_end (args); - - if (saved_local_prompt == 0) - { - rl_save_prompt (); - msg_saved_prompt = 1; - } - else if (local_prompt != saved_local_prompt) - { - FREE (local_prompt); - FREE (local_prompt_prefix); - local_prompt = (char *)NULL; - } - rl_display_prompt = msg_buf; - local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length, - &prompt_last_invisible, - &prompt_invis_chars_first_line, - &prompt_physical_chars); - local_prompt_prefix = (char *)NULL; - local_prompt_len = local_prompt ? strlen (local_prompt) : 0; - (*rl_redisplay_function) (); - - return 0; -} -#else /* !USE_VARARGS */ -int -rl_message (format, arg1, arg2) - char *format; -{ - if (msg_buf == 0) - msg_buf = xmalloc (msg_bufsiz = 128); - - sprintf (msg_buf, format, arg1, arg2); - msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */ - - rl_display_prompt = msg_buf; - if (saved_local_prompt == 0) - { - rl_save_prompt (); - msg_saved_prompt = 1; - } - else if (local_prompt != saved_local_prompt) - { - FREE (local_prompt); - FREE (local_prompt_prefix); - local_prompt = (char *)NULL; - } - local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length, - &prompt_last_invisible, - &prompt_invis_chars_first_line, - &prompt_physical_chars); - local_prompt_prefix = (char *)NULL; - local_prompt_len = local_prompt ? strlen (local_prompt) : 0; - (*rl_redisplay_function) (); - - return 0; -} -#endif /* !USE_VARARGS */ - -/* How to clear things from the "echo-area". */ -int -rl_clear_message () -{ - rl_display_prompt = rl_prompt; - if (msg_saved_prompt) - { - rl_restore_prompt (); - msg_saved_prompt = 0; - } - (*rl_redisplay_function) (); - return 0; -} - -int -rl_reset_line_state () -{ - rl_on_new_line (); - - rl_display_prompt = rl_prompt ? rl_prompt : ""; - forced_display = 1; - return 0; -} - -void -rl_save_prompt () -{ - saved_local_prompt = local_prompt; - saved_local_prefix = local_prompt_prefix; - saved_prefix_length = prompt_prefix_length; - saved_local_length = local_prompt_len; - saved_last_invisible = prompt_last_invisible; - saved_visible_length = prompt_visible_length; - saved_invis_chars_first_line = prompt_invis_chars_first_line; - saved_physical_chars = prompt_physical_chars; - - local_prompt = local_prompt_prefix = (char *)0; - local_prompt_len = 0; - prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0; - prompt_invis_chars_first_line = prompt_physical_chars = 0; -} - -void -rl_restore_prompt () -{ - FREE (local_prompt); - FREE (local_prompt_prefix); - - local_prompt = saved_local_prompt; - local_prompt_prefix = saved_local_prefix; - local_prompt_len = saved_local_length; - prompt_prefix_length = saved_prefix_length; - prompt_last_invisible = saved_last_invisible; - prompt_visible_length = saved_visible_length; - prompt_invis_chars_first_line = saved_invis_chars_first_line; - prompt_physical_chars = saved_physical_chars; - - /* can test saved_local_prompt to see if prompt info has been saved. */ - saved_local_prompt = saved_local_prefix = (char *)0; - saved_local_length = 0; - saved_last_invisible = saved_visible_length = saved_prefix_length = 0; - saved_invis_chars_first_line = saved_physical_chars = 0; -} - -char * -_rl_make_prompt_for_search (pchar) - int pchar; -{ - int len; - char *pmt, *p; - - rl_save_prompt (); - - /* We've saved the prompt, and can do anything with the various prompt - strings we need before they're restored. We want the unexpanded - portion of the prompt string after any final newline. */ - p = rl_prompt ? strrchr (rl_prompt, '\n') : 0; - if (p == 0) - { - len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0; - pmt = (char *)xmalloc (len + 2); - if (len) - strcpy (pmt, rl_prompt); - pmt[len] = pchar; - pmt[len+1] = '\0'; - } - else - { - p++; - len = strlen (p); - pmt = (char *)xmalloc (len + 2); - if (len) - strcpy (pmt, p); - pmt[len] = pchar; - pmt[len+1] = '\0'; - } - - /* will be overwritten by expand_prompt, called from rl_message */ - prompt_physical_chars = saved_physical_chars + 1; - return pmt; -} - -/* Quick redisplay hack when erasing characters at the end of the line. */ -void -_rl_erase_at_end_of_line (l) - int l; -{ - register int i; - - _rl_backspace (l); - for (i = 0; i < l; i++) - putc (' ', rl_outstream); - _rl_backspace (l); - for (i = 0; i < l; i++) - visible_line[--_rl_last_c_pos] = '\0'; - rl_display_fixed++; -} - -/* Clear to the end of the line. COUNT is the minimum - number of character spaces to clear, */ -void -_rl_clear_to_eol (count) - int count; -{ -#ifndef __MSDOS__ - if (_rl_term_clreol) - tputs (_rl_term_clreol, 1, _rl_output_character_function); - else -#endif - if (count) - space_to_eol (count); -} - -/* Clear to the end of the line using spaces. COUNT is the minimum - number of character spaces to clear, */ -static void -space_to_eol (count) - int count; -{ - register int i; - - for (i = 0; i < count; i++) - putc (' ', rl_outstream); - - _rl_last_c_pos += count; -} - -void -_rl_clear_screen () -{ -#ifndef __DJGPP__ - if (_rl_term_clrpag) - tputs (_rl_term_clrpag, 1, _rl_output_character_function); - else - rl_crlf (); -#else - ScreenClear (); - ScreenSetCursor (0, 0); -#endif /* __DJGPP__ */ -} - -/* Insert COUNT characters from STRING to the output stream at column COL. */ -static void -insert_some_chars (string, count, col) - char *string; - int count, col; -{ - open_some_spaces (col); - _rl_output_some_chars (string, count); -} - -/* Insert COL spaces, keeping the cursor at the same position. We follow the - ncurses documentation and use either im/ei with explicit spaces, or IC/ic - by itself. We assume there will either be ei or we don't need to use it. */ -static void -open_some_spaces (col) - int col; -{ -#if !defined (__MSDOS__) && !defined (__MINGW32__) - char *buffer; - register int i; - - /* If IC is defined, then we do not have to "enter" insert mode. */ - if (_rl_term_IC) - { - buffer = tgoto (_rl_term_IC, 0, col); - tputs (buffer, 1, _rl_output_character_function); - } - else if (_rl_term_im && *_rl_term_im) - { - tputs (_rl_term_im, 1, _rl_output_character_function); - /* just output the desired number of spaces */ - for (i = col; i--; ) - _rl_output_character_function (' '); - /* If there is a string to turn off insert mode, use it now. */ - if (_rl_term_ei && *_rl_term_ei) - tputs (_rl_term_ei, 1, _rl_output_character_function); - /* and move back the right number of spaces */ - _rl_backspace (col); - } - else if (_rl_term_ic && *_rl_term_ic) - { - /* If there is a special command for inserting characters, then - use that first to open up the space. */ - for (i = col; i--; ) - tputs (_rl_term_ic, 1, _rl_output_character_function); - } -#endif /* !__MSDOS__ && !__MINGW32__ */ -} - -/* Delete COUNT characters from the display line. */ -static void -delete_chars (count) - int count; -{ - if (count > _rl_screenwidth) /* XXX */ - return; - -#if !defined (__MSDOS__) && !defined (__MINGW32__) - if (_rl_term_DC && *_rl_term_DC) - { - char *buffer; - buffer = tgoto (_rl_term_DC, count, count); - tputs (buffer, count, _rl_output_character_function); - } - else - { - if (_rl_term_dc && *_rl_term_dc) - while (count--) - tputs (_rl_term_dc, 1, _rl_output_character_function); - } -#endif /* !__MSDOS__ && !__MINGW32__ */ -} - -void -_rl_update_final () -{ - int full_lines; - - full_lines = 0; - /* If the cursor is the only thing on an otherwise-blank last line, - compensate so we don't print an extra CRLF. */ - if (_rl_vis_botlin && _rl_last_c_pos == 0 && - visible_line[vis_lbreaks[_rl_vis_botlin]] == 0) - { - _rl_vis_botlin--; - full_lines = 1; - } - _rl_move_vert (_rl_vis_botlin); - /* If we've wrapped lines, remove the final xterm line-wrap flag. */ - if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth)) - { - char *last_line; - - last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; - cpos_buffer_position = -1; /* don't know where we are in buffer */ - _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */ - _rl_clear_to_eol (0); - putc (last_line[_rl_screenwidth - 1], rl_outstream); - } - _rl_vis_botlin = 0; - rl_crlf (); - fflush (rl_outstream); - rl_display_fixed++; -} - -/* Move to the start of the current line. */ -static void -cr () -{ - if (_rl_term_cr) - { -#if defined (__MSDOS__) - putc ('\r', rl_outstream); -#else - tputs (_rl_term_cr, 1, _rl_output_character_function); -#endif - _rl_last_c_pos = 0; - } -} - -/* Redraw the last line of a multi-line prompt that may possibly contain - terminal escape sequences. Called with the cursor at column 0 of the - line to draw the prompt on. */ -static void -redraw_prompt (t) - char *t; -{ - char *oldp; - - oldp = rl_display_prompt; - rl_save_prompt (); - - rl_display_prompt = t; - local_prompt = expand_prompt (t, PMT_MULTILINE, - &prompt_visible_length, - &prompt_last_invisible, - &prompt_invis_chars_first_line, - &prompt_physical_chars); - local_prompt_prefix = (char *)NULL; - local_prompt_len = local_prompt ? strlen (local_prompt) : 0; - - rl_forced_update_display (); - - rl_display_prompt = oldp; - rl_restore_prompt(); -} - -/* Redisplay the current line after a SIGWINCH is received. */ -void -_rl_redisplay_after_sigwinch () -{ - char *t; - - /* Clear the last line (assuming that the screen size change will result in - either more or fewer characters on that line only) and put the cursor at - column 0. Make sure the right thing happens if we have wrapped to a new - screen line. */ - if (_rl_term_cr) - { - _rl_move_vert (_rl_vis_botlin); - -#if defined (__MSDOS__) - putc ('\r', rl_outstream); -#else - tputs (_rl_term_cr, 1, _rl_output_character_function); -#endif - _rl_last_c_pos = 0; -#if defined (__MSDOS__) - space_to_eol (_rl_screenwidth); - putc ('\r', rl_outstream); -#else - if (_rl_term_clreol) - tputs (_rl_term_clreol, 1, _rl_output_character_function); - else - { - space_to_eol (_rl_screenwidth); - tputs (_rl_term_cr, 1, _rl_output_character_function); - } -#endif - if (_rl_last_v_pos > 0) - _rl_move_vert (0); - } - else - rl_crlf (); - - /* Redraw only the last line of a multi-line prompt. */ - t = strrchr (rl_display_prompt, '\n'); - if (t) - redraw_prompt (++t); - else - rl_forced_update_display (); -} - -void -_rl_clean_up_for_exit () -{ - if (_rl_echoing_p) - { - if (_rl_vis_botlin > 0) /* minor optimization plus bug fix */ - _rl_move_vert (_rl_vis_botlin); - _rl_vis_botlin = 0; - fflush (rl_outstream); - rl_restart_output (1, 0); - } -} - -void -_rl_erase_entire_line () -{ - cr (); - _rl_clear_to_eol (0); - cr (); - fflush (rl_outstream); -} - -void -_rl_ttyflush () -{ - fflush (rl_outstream); -} - -/* return the `current display line' of the cursor -- the number of lines to - move up to get to the first screen line of the current readline line. */ -int -_rl_current_display_line () -{ - int ret, nleft; - - /* Find out whether or not there might be invisible characters in the - editing buffer. */ - if (rl_display_prompt == rl_prompt) - nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length; - else - nleft = _rl_last_c_pos - _rl_screenwidth; - - if (nleft > 0) - ret = 1 + nleft / _rl_screenwidth; - else - ret = 0; - - return ret; -} - -#if defined (HANDLE_MULTIBYTE) -/* Calculate the number of screen columns occupied by STR from START to END. - In the case of multibyte characters with stateful encoding, we have to - scan from the beginning of the string to take the state into account. */ -static int -_rl_col_width (str, start, end, flags) - const char *str; - int start, end, flags; -{ - wchar_t wc; - mbstate_t ps; - int tmp, point, width, max; - - if (end <= start) - return 0; - if (MB_CUR_MAX == 1 || rl_byte_oriented) - /* this can happen in some cases where it's inconvenient to check */ - return (end - start); - - memset (&ps, 0, sizeof (mbstate_t)); - - point = 0; - max = end; - - /* Try to short-circuit common cases. The adjustment to remove wrap_offset - is done by the caller. */ - /* 1. prompt string */ - if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0) - return (prompt_physical_chars + wrap_offset); - /* 2. prompt string + line contents */ - else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0) - { - tmp = prompt_physical_chars + wrap_offset; - /* XXX - try to call ourselves recursively with non-prompt portion */ - tmp += _rl_col_width (str, local_prompt_len, end, flags); - return (tmp); - } - - while (point < start) - { - tmp = mbrlen (str + point, max, &ps); - if (MB_INVALIDCH ((size_t)tmp)) - { - /* In this case, the bytes are invalid or too short to compose a - multibyte character, so we assume that the first byte represents - a single character. */ - point++; - max--; - - /* Clear the state of the byte sequence, because in this case the - effect of mbstate is undefined. */ - memset (&ps, 0, sizeof (mbstate_t)); - } - else if (MB_NULLWCH (tmp)) - break; /* Found '\0' */ - else - { - point += tmp; - max -= tmp; - } - } - - /* If START is not a byte that starts a character, then POINT will be - greater than START. In this case, assume that (POINT - START) gives - a byte count that is the number of columns of difference. */ - width = point - start; - - while (point < end) - { - tmp = mbrtowc (&wc, str + point, max, &ps); - if (MB_INVALIDCH ((size_t)tmp)) - { - /* In this case, the bytes are invalid or too short to compose a - multibyte character, so we assume that the first byte represents - a single character. */ - point++; - max--; - - /* and assume that the byte occupies a single column. */ - width++; - - /* Clear the state of the byte sequence, because in this case the - effect of mbstate is undefined. */ - memset (&ps, 0, sizeof (mbstate_t)); - } - else if (MB_NULLWCH (tmp)) - break; /* Found '\0' */ - else - { - point += tmp; - max -= tmp; - tmp = WCWIDTH(wc); - width += (tmp >= 0) ? tmp : 1; - } - } - - width += point - end; - - return width; -} -#endif /* HANDLE_MULTIBYTE */ diff --git a/lib/readline/doc/Makefile.old b/lib/readline/doc/Makefile.old deleted file mode 100644 index 58d4dd762..000000000 --- a/lib/readline/doc/Makefile.old +++ /dev/null @@ -1,76 +0,0 @@ -# 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/lib/readline/funmap.c~ b/lib/readline/funmap.c~ deleted file mode 100644 index e55335db0..000000000 --- a/lib/readline/funmap.c~ +++ /dev/null @@ -1,267 +0,0 @@ -/* funmap.c -- attach names to functions. */ - -/* Copyright (C) 1987-2010 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 - -#if !defined (BUFSIZ) -#include -#endif /* BUFSIZ */ - -#if defined (HAVE_STDLIB_H) -# include -#else -# include "ansi_stdlib.h" -#endif /* HAVE_STDLIB_H */ - -#include "rlconf.h" -#include "readline.h" - -#include "xmalloc.h" - -#ifdef __STDC__ -typedef int QSFUNC (const void *, const void *); -#else -typedef int QSFUNC (); -#endif - -extern int _rl_qsort_string_compare PARAMS((char **, char **)); - -FUNMAP **funmap; -static int funmap_size; -static int funmap_entry; - -/* After initializing the function map, this is the index of the first - program specific function. */ -int funmap_program_specific_entry_start; - -static const FUNMAP default_funmap[] = { - { "abort", rl_abort }, - { "accept-line", rl_newline }, - { "arrow-key-prefix", rl_arrow_keys }, - { "backward-byte", rl_backward_byte }, - { "backward-char", rl_backward_char }, - { "backward-delete-char", rl_rubout }, - { "backward-kill-line", rl_backward_kill_line }, - { "backward-kill-word", rl_backward_kill_word }, - { "backward-word", rl_backward_word }, - { "beginning-of-history", rl_beginning_of_history }, - { "beginning-of-line", rl_beg_of_line }, - { "bracketed-paste-begin", rl_bracketed_paste_begin }, - { "call-last-kbd-macro", rl_call_last_kbd_macro }, - { "capitalize-word", rl_capitalize_word }, - { "character-search", rl_char_search }, - { "character-search-backward", rl_backward_char_search }, - { "clear-screen", rl_clear_screen }, - { "complete", rl_complete }, - { "copy-backward-word", rl_copy_backward_word }, - { "copy-forward-word", rl_copy_forward_word }, - { "copy-region-as-kill", rl_copy_region_to_kill }, - { "delete-char", rl_delete }, - { "delete-char-or-list", rl_delete_or_show_completions }, - { "delete-horizontal-space", rl_delete_horizontal_space }, - { "digit-argument", rl_digit_argument }, - { "do-lowercase-version", rl_do_lowercase_version }, - { "downcase-word", rl_downcase_word }, - { "dump-functions", rl_dump_functions }, - { "dump-macros", rl_dump_macros }, - { "dump-variables", rl_dump_variables }, - { "emacs-editing-mode", rl_emacs_editing_mode }, - { "end-kbd-macro", rl_end_kbd_macro }, - { "end-of-history", rl_end_of_history }, - { "end-of-line", rl_end_of_line }, - { "exchange-point-and-mark", rl_exchange_point_and_mark }, - { "forward-backward-delete-char", rl_rubout_or_delete }, - { "forward-byte", rl_forward_byte }, - { "forward-char", rl_forward_char }, - { "forward-search-history", rl_forward_search_history }, - { "forward-word", rl_forward_word }, - { "history-search-backward", rl_history_search_backward }, - { "history-search-forward", rl_history_search_forward }, - { "history-substring-search-backward", rl_history_substr_search_backward }, - { "history-substring-search-forward", rl_history_substr_search_forward }, - { "insert-comment", rl_insert_comment }, - { "insert-completions", rl_insert_completions }, - { "kill-whole-line", rl_kill_full_line }, - { "kill-line", rl_kill_line }, - { "kill-region", rl_kill_region }, - { "kill-word", rl_kill_word }, - { "menu-complete", rl_menu_complete }, - { "menu-complete-backward", rl_backward_menu_complete }, - { "next-history", rl_get_next_history }, - { "non-incremental-forward-search-history", rl_noninc_forward_search }, - { "non-incremental-reverse-search-history", rl_noninc_reverse_search }, - { "non-incremental-forward-search-history-again", rl_noninc_forward_search_again }, - { "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again }, - { "old-menu-complete", rl_old_menu_complete }, - { "overwrite-mode", rl_overwrite_mode }, -#ifdef __CYGWIN__ - { "paste-from-clipboard", rl_paste_from_clipboard }, -#endif - { "possible-completions", rl_possible_completions }, - { "previous-history", rl_get_previous_history }, - { "print-last-kbd-macro", rl_print_last_kbd_macro }, - { "quoted-insert", rl_quoted_insert }, - { "re-read-init-file", rl_re_read_init_file }, - { "redraw-current-line", rl_refresh_line}, - { "reverse-search-history", rl_reverse_search_history }, - { "revert-line", rl_revert_line }, - { "self-insert", rl_insert }, - { "set-mark", rl_set_mark }, - { "skip-csi-sequence", rl_skip_csi_sequence }, - { "start-kbd-macro", rl_start_kbd_macro }, - { "tab-insert", rl_tab_insert }, - { "tilde-expand", rl_tilde_expand }, - { "transpose-chars", rl_transpose_chars }, - { "transpose-words", rl_transpose_words }, - { "tty-status", rl_tty_status }, - { "undo", rl_undo_command }, - { "universal-argument", rl_universal_argument }, - { "unix-filename-rubout", rl_unix_filename_rubout }, - { "unix-line-discard", rl_unix_line_discard }, - { "unix-word-rubout", rl_unix_word_rubout }, - { "upcase-word", rl_upcase_word }, - { "yank", rl_yank }, - { "yank-last-arg", rl_yank_last_arg }, - { "yank-nth-arg", rl_yank_nth_arg }, - { "yank-pop", rl_yank_pop }, - -#if defined (VI_MODE) - { "vi-append-eol", rl_vi_append_eol }, - { "vi-append-mode", rl_vi_append_mode }, - { "vi-arg-digit", rl_vi_arg_digit }, - { "vi-back-to-indent", rl_vi_back_to_indent }, - { "vi-backward-bigword", rl_vi_bWord }, - { "vi-backward-word", rl_vi_bword }, - { "vi-bWord", rl_vi_bWord }, - { "vi-bword", rl_vi_bword }, - { "vi-change-case", rl_vi_change_case }, - { "vi-change-char", rl_vi_change_char }, - { "vi-change-to", rl_vi_change_to }, - { "vi-char-search", rl_vi_char_search }, - { "vi-column", rl_vi_column }, - { "vi-complete", rl_vi_complete }, - { "vi-delete", rl_vi_delete }, - { "vi-delete-to", rl_vi_delete_to }, - { "vi-eWord", rl_vi_eWord }, - { "vi-editing-mode", rl_vi_editing_mode }, - { "vi-end-bigword", rl_vi_eWord }, - { "vi-end-word", rl_vi_end_word }, - { "vi-eof-maybe", rl_vi_eof_maybe }, - { "vi-eword", rl_vi_eword }, - { "vi-fWord", rl_vi_fWord }, - { "vi-fetch-history", rl_vi_fetch_history }, - { "vi-first-print", rl_vi_first_print }, - { "vi-forward-bigword", rl_vi_fWord }, - { "vi-forward-word", rl_vi_fword }, - { "vi-fword", rl_vi_fword }, - { "vi-goto-mark", rl_vi_goto_mark }, - { "vi-insert-beg", rl_vi_insert_beg }, - { "vi-insertion-mode", rl_vi_insertion_mode }, - { "vi-match", rl_vi_match }, - { "vi-movement-mode", rl_vi_movement_mode }, - { "vi-next-word", rl_vi_next_word }, - { "vi-overstrike", rl_vi_overstrike }, - { "vi-overstrike-delete", rl_vi_overstrike_delete }, - { "vi-prev-word", rl_vi_prev_word }, - { "vi-put", rl_vi_put }, - { "vi-redo", rl_vi_redo }, - { "vi-replace", rl_vi_replace }, - { "vi-rubout", rl_vi_rubout }, - { "vi-search", rl_vi_search }, - { "vi-search-again", rl_vi_search_again }, - { "vi-set-mark", rl_vi_set_mark }, - { "vi-subst", rl_vi_subst }, - { "vi-tilde-expand", rl_vi_tilde_expand }, - { "vi-yank-arg", rl_vi_yank_arg }, - { "vi-yank-to", rl_vi_yank_to }, -#endif /* VI_MODE */ - - {(char *)NULL, (rl_command_func_t *)NULL } -}; - -int -rl_add_funmap_entry (name, function) - const char *name; - rl_command_func_t *function; -{ - if (funmap_entry + 2 >= funmap_size) - { - funmap_size += 64; - funmap = (FUNMAP **)xrealloc (funmap, funmap_size * sizeof (FUNMAP *)); - } - - funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP)); - funmap[funmap_entry]->name = name; - funmap[funmap_entry]->function = function; - - funmap[++funmap_entry] = (FUNMAP *)NULL; - return funmap_entry; -} - -static int funmap_initialized; - -/* Make the funmap contain all of the default entries. */ -void -rl_initialize_funmap () -{ - register int i; - - if (funmap_initialized) - return; - - for (i = 0; default_funmap[i].name; i++) - rl_add_funmap_entry (default_funmap[i].name, default_funmap[i].function); - - funmap_initialized = 1; - funmap_program_specific_entry_start = i; -} - -/* Produce a NULL terminated array of known function names. The array - is sorted. The array itself is allocated, but not the strings inside. - You should free () the array when you done, but not the pointers. */ -const char ** -rl_funmap_names () -{ - const char **result; - int result_size, result_index; - - /* Make sure that the function map has been initialized. */ - rl_initialize_funmap (); - - for (result_index = result_size = 0, result = (const char **)NULL; funmap[result_index]; result_index++) - { - if (result_index + 2 > result_size) - { - result_size += 20; - result = (const char **)xrealloc (result, result_size * sizeof (char *)); - } - - result[result_index] = funmap[result_index]->name; - result[result_index + 1] = (char *)NULL; - } - - qsort (result, result_index, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); - return (result); -} diff --git a/lib/readline/histfile.c~ b/lib/readline/histfile.c~ deleted file mode 100644 index 30bfe86b7..000000000 --- a/lib/readline/histfile.c~ +++ /dev/null @@ -1,646 +0,0 @@ -/* histfile.c - functions to manipulate the history file. */ - -/* Copyright (C) 1989-2010 Free Software Foundation, Inc. - - This file contains the GNU History Library (History), a set of - routines for managing the text of previously typed lines. - - History 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. - - History 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 History. If not, see . -*/ - -/* The goal is to make the implementation transparent, so that you - don't have to know what data types are used, just what functions - you can call. I think I have done that. */ - -#define READLINE_LIBRARY - -#if defined (__TANDEM) -# include -#endif - -#if defined (HAVE_CONFIG_H) -# include -#endif - -#include - -#include -#if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H) -# include -#endif -#include "posixstat.h" -#include - -#if defined (HAVE_STDLIB_H) -# include -#else -# include "ansi_stdlib.h" -#endif /* HAVE_STDLIB_H */ - -#if defined (HAVE_UNISTD_H) -# include -#endif - -#include - -#if defined (__EMX__) -# undef HAVE_MMAP -#endif - -#ifdef HISTORY_USE_MMAP -# include - -# ifdef MAP_FILE -# define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE) -# define MAP_WFLAGS (MAP_FILE|MAP_SHARED) -# else -# define MAP_RFLAGS MAP_PRIVATE -# define MAP_WFLAGS MAP_SHARED -# endif - -# ifndef MAP_FAILED -# define MAP_FAILED ((void *)-1) -# endif - -#endif /* HISTORY_USE_MMAP */ - -/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment - on win 95/98/nt), we want to open files with O_BINARY mode so that there - is no \n -> \r\n conversion performed. On other systems, we don't want to - mess around with O_BINARY at all, so we ensure that it's defined to 0. */ -#if defined (__EMX__) || defined (__CYGWIN__) -# ifndef O_BINARY -# define O_BINARY 0 -# endif -#else /* !__EMX__ && !__CYGWIN__ */ -# undef O_BINARY -# define O_BINARY 0 -#endif /* !__EMX__ && !__CYGWIN__ */ - -#include -#if !defined (errno) -extern int errno; -#endif /* !errno */ - -#include "history.h" -#include "histlib.h" - -#include "rlshell.h" -#include "xmalloc.h" - -/* If non-zero, we write timestamps to the history file in history_do_write() */ -int history_write_timestamps = 0; - -/* Immediately after a call to read_history() or read_history_range(), this - will return the number of lines just read from the history file in that - call. */ -int history_lines_read_from_file = 0; - -/* Immediately after a call to write_history() or history_do_write(), this - will return the number of lines just written to the history file in that - call. This also works with history_truncate_file. */ -int history_lines_written_to_file = 0; - -/* Does S look like the beginning of a history timestamp entry? Placeholder - for more extensive tests. */ -#define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char && isdigit ((s)[1]) ) - -/* Return the string that should be used in the place of this - filename. This only matters when you don't specify the - filename to read_history (), or write_history (). */ -static char * -history_filename (filename) - const char *filename; -{ - char *return_val; - const char *home; - int home_len; - - return_val = filename ? savestring (filename) : (char *)NULL; - - if (return_val) - return (return_val); - - home = sh_get_env_value ("HOME"); - - if (home == 0) - return (NULL); - else - home_len = strlen (home); - - return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */ - strcpy (return_val, home); - return_val[home_len] = '/'; -#if defined (__MSDOS__) - strcpy (return_val + home_len + 1, "_history"); -#else - strcpy (return_val + home_len + 1, ".history"); -#endif - - return (return_val); -} - -static char * -history_backupfile (filename) - const char *filename; -{ - char *ret; - size_t len; - - len = strlen (filename); - ret = xmalloc (len + 2); - strcpy (ret, filename); - ret[len] = '-'; - ret[len+1] = '\0'; - return ret; -} - -/* Add the contents of FILENAME to the history list, a line at a time. - If FILENAME is NULL, then read from ~/.history. Returns 0 if - successful, or errno if not. */ -int -read_history (filename) - const char *filename; -{ - return (read_history_range (filename, 0, -1)); -} - -/* Read a range of lines from FILENAME, adding them to the history list. - Start reading at the FROM'th line and end at the TO'th. If FROM - is zero, start at the beginning. If TO is less than FROM, read - until the end of the file. If FILENAME is NULL, then read from - ~/.history. Returns 0 if successful, or errno if not. */ -int -read_history_range (filename, from, to) - const char *filename; - int from, to; -{ - register char *line_start, *line_end, *p; - char *input, *buffer, *bufend, *last_ts; - int file, current_line, chars_read; - struct stat finfo; - size_t file_size; -#if defined (EFBIG) - int overflow_errno = EFBIG; -#elif defined (EOVERFLOW) - int overflow_errno = EOVERFLOW; -#else - int overflow_errno = EIO; -#endif - - history_lines_read_from_file = 0; - - buffer = last_ts = (char *)NULL; - input = history_filename (filename); - file = input ? open (input, O_RDONLY|O_BINARY, 0666) : -1; - - if ((file < 0) || (fstat (file, &finfo) == -1)) - goto error_and_exit; - - file_size = (size_t)finfo.st_size; - - /* check for overflow on very large files */ - if (file_size != finfo.st_size || file_size + 1 < file_size) - { - errno = overflow_errno; - goto error_and_exit; - } - -#ifdef HISTORY_USE_MMAP - /* We map read/write and private so we can change newlines to NULs without - affecting the underlying object. */ - buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0); - if ((void *)buffer == MAP_FAILED) - { - errno = overflow_errno; - goto error_and_exit; - } - chars_read = file_size; -#else - buffer = (char *)malloc (file_size + 1); - if (buffer == 0) - { - errno = overflow_errno; - goto error_and_exit; - } - - chars_read = read (file, buffer, file_size); -#endif - if (chars_read < 0) - { - error_and_exit: - if (errno != 0) - chars_read = errno; - else - chars_read = EIO; - if (file >= 0) - close (file); - - FREE (input); -#ifndef HISTORY_USE_MMAP - FREE (buffer); -#endif - - return (chars_read); - } - - close (file); - - /* Set TO to larger than end of file if negative. */ - if (to < 0) - to = chars_read; - - /* Start at beginning of file, work to end. */ - bufend = buffer + chars_read; - current_line = 0; - - /* Skip lines until we are at FROM. */ - for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++) - if (*line_end == '\n') - { - p = line_end + 1; - /* If we see something we think is a timestamp, continue with this - line. We should check more extensively here... */ - if (HIST_TIMESTAMP_START(p) == 0) - current_line++; - line_start = p; - } - - /* If there are lines left to gobble, then gobble them now. */ - for (line_end = line_start; line_end < bufend; line_end++) - if (*line_end == '\n') - { - /* Change to allow Windows-like \r\n end of line delimiter. */ - if (line_end > line_start && line_end[-1] == '\r') - line_end[-1] = '\0'; - else - *line_end = '\0'; - - if (*line_start) - { - if (HIST_TIMESTAMP_START(line_start) == 0) - { - add_history (line_start); - if (last_ts) - { - add_history_time (last_ts); - last_ts = NULL; - } - } - else - { - last_ts = line_start; - current_line--; - } - } - - current_line++; - - if (current_line >= to) - break; - - line_start = line_end + 1; - } - - history_lines_read_from_file = current_line; - - FREE (input); -#ifndef HISTORY_USE_MMAP - FREE (buffer); -#else - munmap (buffer, file_size); -#endif - - return (0); -} - -/* Truncate the history file FNAME, leaving only LINES trailing lines. - If FNAME is NULL, then use ~/.history. Returns 0 on success, errno - on failure. */ -int -history_truncate_file (fname, lines) - const char *fname; - int lines; -{ - char *buffer, *filename, *bakname, *bp, *bp1; /* bp1 == bp+1 */ - int file, chars_read, rv, orig_lines, exists; - struct stat finfo; - size_t file_size; - - history_lines_written_to_file = 0; - - buffer = (char *)NULL; - filename = history_filename (fname); - bakname = 0; - file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1; - rv = exists = 0; - - /* Don't try to truncate non-regular files. */ - if (file == -1 || fstat (file, &finfo) == -1) - { - rv = errno; - if (file != -1) - close (file); - goto truncate_exit; - } - exists = 1; - - if (S_ISREG (finfo.st_mode) == 0) - { - close (file); -#ifdef EFTYPE - rv = EFTYPE; -#else - rv = EINVAL; -#endif - goto truncate_exit; - } - - file_size = (size_t)finfo.st_size; - - /* check for overflow on very large files */ - if (file_size != finfo.st_size || file_size + 1 < file_size) - { - close (file); -#if defined (EFBIG) - rv = errno = EFBIG; -#elif defined (EOVERFLOW) - rv = errno = EOVERFLOW; -#else - rv = errno = EINVAL; -#endif - goto truncate_exit; - } - - buffer = (char *)malloc (file_size + 1); - if (buffer == 0) - { - rv = errno; - close (file); - goto truncate_exit; - } - - chars_read = read (file, buffer, file_size); - close (file); - - if (chars_read <= 0) - { - rv = (chars_read < 0) ? errno : 0; - goto truncate_exit; - } - - orig_lines = lines; - /* Count backwards from the end of buffer until we have passed - LINES lines. bp1 is set funny initially. But since bp[1] can't - be a comment character (since it's off the end) and *bp can't be - both a newline and the history comment character, it should be OK. */ - for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--) - { - if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0) - lines--; - bp1 = bp; - } - - /* If this is the first line, then the file contains exactly the - number of lines we want to truncate to, so we don't need to do - anything. It's the first line if we don't find a newline between - the current value of i and 0. Otherwise, write from the start of - this line until the end of the buffer. */ - for ( ; bp > buffer; bp--) - { - if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0) - { - bp++; - break; - } - bp1 = bp; - } - - /* Write only if there are more lines in the file than we want to - truncate to. */ - if (bp <= buffer) - { - rv = 0; - /* No-op if LINES == 0 at this point */ - history_lines_written_to_file = orig_lines - lines; - goto truncate_exit; - } - - bakname = history_backupfile (filename); - if (filename && bakname) - rename (filename, bakname); - - if ((file = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600)) != -1) - { - if (write (file, bp, chars_read - (bp - buffer)) < 0) - rv = errno; - -#if defined (__BEOS__) - /* BeOS ignores O_TRUNC. */ - ftruncate (file, chars_read - (bp - buffer)); -#endif - - if (close (file) < 0 && rv == 0) - rv = errno; - } - else - rv = errno; - - truncate_exit: - FREE (buffer); - - history_lines_written_to_file = orig_lines - lines; - - if (rv != 0 && filename && bakname) - rename (bakname, filename); - else if (rv == 0 && bakname) - unlink (bakname); - - /* Make sure the new filename is owned by the same user as the old. If one - user is running this, it's a no-op. If the shell is running after sudo - with a shared history file, we don't want to leave the history file - owned by root. */ - if (rv == 0 && exists) - chown (filename, finfo.st_uid, finfo.st_gid); - - xfree (filename); - FREE (bakname); - - return rv; -} - -/* Workhorse function for writing history. Writes the last NELEMENT entries - from the history list to FILENAME. OVERWRITE is non-zero if you - wish to replace FILENAME with the entries. */ -static int -history_do_write (filename, nelements, overwrite) - const char *filename; - int nelements, overwrite; -{ - register int i; - char *output, *bakname; - int file, mode, rv, exists; - struct stat finfo; -#ifdef HISTORY_USE_MMAP - size_t cursize; - - history_lines_written_to_file = 0; - - mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY; -#else - mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY; -#endif - output = history_filename (filename); - bakname = (overwrite && output) ? history_backupfile (output) : 0; - exists = output ? (stat (output, &finfo) == 0) : 0; - - if (output && bakname) - rename (output, bakname); - - file = output ? open (output, mode, 0600) : -1; - rv = 0; - - if (file == -1) - { - rv = errno; - if (output && bakname) - rename (bakname, output); - FREE (output); - FREE (bakname); - return (rv); - } - -#ifdef HISTORY_USE_MMAP - cursize = overwrite ? 0 : lseek (file, 0, SEEK_END); -#endif - - if (nelements > history_length) - nelements = history_length; - - /* Build a buffer of all the lines to write, and write them in one syscall. - Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */ - { - HIST_ENTRY **the_history; /* local */ - register int j; - int buffer_size; - char *buffer; - - the_history = history_list (); - /* Calculate the total number of bytes to write. */ - for (buffer_size = 0, i = history_length - nelements; i < history_length; i++) -#if 0 - buffer_size += 2 + HISTENT_BYTES (the_history[i]); -#else - { - if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0]) - buffer_size += strlen (the_history[i]->timestamp) + 1; - buffer_size += strlen (the_history[i]->line) + 1; - } -#endif - - /* Allocate the buffer, and fill it. */ -#ifdef HISTORY_USE_MMAP - if (ftruncate (file, buffer_size+cursize) == -1) - goto mmap_error; - buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize); - if ((void *)buffer == MAP_FAILED) - { -mmap_error: - rv = errno; - close (file); - if (output && bakname) - rename (bakname, output); - FREE (output); - FREE (bakname); - return rv; - } -#else - buffer = (char *)malloc (buffer_size); - if (buffer == 0) - { - rv = errno; - close (file); - if (output && bakname) - rename (bakname, output); - FREE (output); - FREE (bakname); - return rv; - } -#endif - - for (j = 0, i = history_length - nelements; i < history_length; i++) - { - if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0]) - { - strcpy (buffer + j, the_history[i]->timestamp); - j += strlen (the_history[i]->timestamp); - buffer[j++] = '\n'; - } - strcpy (buffer + j, the_history[i]->line); - j += strlen (the_history[i]->line); - buffer[j++] = '\n'; - } - -#ifdef HISTORY_USE_MMAP - if (msync (buffer, buffer_size, MS_ASYNC) != 0 || munmap (buffer, buffer_size) != 0) - rv = errno; -#else - if (write (file, buffer, buffer_size) < 0) - rv = errno; - xfree (buffer); -#endif - } - - history_lines_written_to_file = nelements; - - if (close (file) < 0 && rv == 0) - rv = errno; - - if (rv != 0 && output && bakname) - rename (bakname, output); - else if (rv == 0 && bakname) - unlink (bakname); - - /* Make sure the new filename is owned by the same user as the old. If one - user is running this, it's a no-op. If the shell is running after sudo - with a shared history file, we don't want to leave the history file - owned by root. */ - if (rv == 0 && exists) - chown (output, finfo.st_uid, finfo.st_gid); - - FREE (output); - FREE (bakname); - - return (rv); -} - -/* Append NELEMENT entries to FILENAME. The entries appended are from - the end of the list minus NELEMENTs up to the end of the list. */ -int -append_history (nelements, filename) - int nelements; - const char *filename; -{ - return (history_do_write (filename, nelements, HISTORY_APPEND)); -} - -/* Overwrite FILENAME with the current history. If FILENAME is NULL, - then write the history list to ~/.history. Values returned - are as in read_history ().*/ -int -write_history (filename) - const char *filename; -{ - return (history_do_write (filename, history_length, HISTORY_OVERWRITE)); -} diff --git a/lib/readline/input.c~ b/lib/readline/input.c~ deleted file mode 100644 index 12421e564..000000000 --- a/lib/readline/input.c~ +++ /dev/null @@ -1,656 +0,0 @@ -/* input.c -- character input functions for readline. */ - -/* Copyright (C) 1994-2013 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 (__TANDEM) -# include -#endif - -#if defined (HAVE_CONFIG_H) -# include -#endif - -#include -#include -#if defined (HAVE_SYS_FILE_H) -# include -#endif /* HAVE_SYS_FILE_H */ - -#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 "posixselect.h" - -#if defined (FIONREAD_IN_SYS_IOCTL) -# include -#endif - -#include -#include - -#if !defined (errno) -extern int errno; -#endif /* !errno */ - -/* System-specific feature definitions and include files. */ -#include "rldefs.h" -#include "rlmbutil.h" - -/* Some standard library routines. */ -#include "readline.h" - -#include "rlprivate.h" -#include "rlshell.h" -#include "xmalloc.h" - -/* What kind of non-blocking I/O do we have? */ -#if !defined (O_NDELAY) && defined (O_NONBLOCK) -# define O_NDELAY O_NONBLOCK /* Posix style */ -#endif - -/* Non-null means it is a pointer to a function to run while waiting for - character input. */ -rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL; - -/* A function to call if a read(2) is interrupted by a signal. */ -rl_hook_func_t *rl_signal_event_hook = (rl_hook_func_t *)NULL; - -/* A function to replace _rl_input_available for applications using the - callback interface. */ -rl_hook_func_t *rl_input_available_hook = (rl_hook_func_t *)NULL; - -rl_getc_func_t *rl_getc_function = rl_getc; - -static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */ - -static int ibuffer_space PARAMS((void)); -static int rl_get_char PARAMS((int *)); -static int rl_gather_tyi PARAMS((void)); - -/* **************************************************************** */ -/* */ -/* Character Input Buffering */ -/* */ -/* **************************************************************** */ - -static int pop_index, push_index; -static unsigned char ibuffer[512]; -static int ibuffer_len = sizeof (ibuffer) - 1; - -#define any_typein (push_index != pop_index) - -int -_rl_any_typein () -{ - return any_typein; -} - -int -_rl_pushed_input_available () -{ - return (push_index != pop_index); -} - -/* Return the amount of space available in the buffer for stuffing - characters. */ -static int -ibuffer_space () -{ - if (pop_index > push_index) - return (pop_index - push_index - 1); - else - return (ibuffer_len - (push_index - pop_index)); -} - -/* Get a key from the buffer of characters to be read. - Return the key in KEY. - Result is non-zero if there was a key, or 0 if there wasn't. */ -static int -rl_get_char (key) - int *key; -{ - if (push_index == pop_index) - return (0); - - *key = ibuffer[pop_index++]; -#if 0 - if (pop_index >= ibuffer_len) -#else - if (pop_index > ibuffer_len) -#endif - pop_index = 0; - - return (1); -} - -/* Stuff KEY into the *front* of the input buffer. - Returns non-zero if successful, zero if there is - no space left in the buffer. */ -int -_rl_unget_char (key) - int key; -{ - if (ibuffer_space ()) - { - pop_index--; - if (pop_index < 0) - pop_index = ibuffer_len; - ibuffer[pop_index] = key; - return (1); - } - return (0); -} - -/* If a character is available to be read, then read it and stuff it into - IBUFFER. Otherwise, just return. Returns number of characters read - (0 if none available) and -1 on error (EIO). */ -static int -rl_gather_tyi () -{ - int tty; - register int tem, result; - int chars_avail, k; - char input; -#if defined(HAVE_SELECT) - fd_set readfds, exceptfds; - struct timeval timeout; -#endif - - chars_avail = 0; - input = 0; - tty = fileno (rl_instream); - -#if defined (HAVE_SELECT) - FD_ZERO (&readfds); - FD_ZERO (&exceptfds); - FD_SET (tty, &readfds); - FD_SET (tty, &exceptfds); - USEC_TO_TIMEVAL (_keyboard_input_timeout, timeout); - result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout); - if (result <= 0) - return 0; /* Nothing to read. */ -#endif - - result = -1; -#if defined (FIONREAD) - errno = 0; - result = ioctl (tty, FIONREAD, &chars_avail); - if (result == -1 && errno == EIO) - return -1; - if (result == -1) - chars_avail = 0; -#endif - -#if defined (O_NDELAY) - if (result == -1) - { - tem = fcntl (tty, F_GETFL, 0); - - fcntl (tty, F_SETFL, (tem | O_NDELAY)); - chars_avail = read (tty, &input, 1); - - fcntl (tty, F_SETFL, tem); - if (chars_avail == -1 && errno == EAGAIN) - return 0; - if (chars_avail == 0) /* EOF */ - { - rl_stuff_char (EOF); - return (0); - } - } -#endif /* O_NDELAY */ - -#if defined (__MINGW32__) - /* Use getch/_kbhit to check for available console input, in the same way - that we read it normally. */ - chars_avail = isatty (tty) ? _kbhit () : 0; - result = 0; -#endif - - /* If there's nothing available, don't waste time trying to read - something. */ - if (chars_avail <= 0) - return 0; - - tem = ibuffer_space (); - - if (chars_avail > tem) - chars_avail = tem; - - /* One cannot read all of the available input. I can only read a single - character at a time, or else programs which require input can be - thwarted. If the buffer is larger than one character, I lose. - Damn! */ - if (tem < ibuffer_len) - chars_avail = 0; - - if (result != -1) - { - while (chars_avail--) - { - RL_CHECK_SIGNALS (); - k = (*rl_getc_function) (rl_instream); - if (rl_stuff_char (k) == 0) - break; /* some problem; no more room */ - if (k == NEWLINE || k == RETURN) - break; - } - } - else - { - if (chars_avail) - rl_stuff_char (input); - } - - return 1; -} - -int -rl_set_keyboard_input_timeout (u) - int u; -{ - int o; - - o = _keyboard_input_timeout; - if (u >= 0) - _keyboard_input_timeout = u; - return (o); -} - -/* Is there input available to be read on the readline input file - descriptor? Only works if the system has select(2) or FIONREAD. - Uses the value of _keyboard_input_timeout as the timeout; if another - readline function wants to specify a timeout and not leave it up to - the user, it should use _rl_input_queued(timeout_value_in_microseconds) - instead. */ -int -_rl_input_available () -{ -#if defined(HAVE_SELECT) - fd_set readfds, exceptfds; - struct timeval timeout; -#endif -#if !defined (HAVE_SELECT) && defined(FIONREAD) - int chars_avail; -#endif - int tty; - - if (rl_input_available_hook) - return (*rl_input_available_hook) (); - - tty = fileno (rl_instream); - -#if defined (HAVE_SELECT) - FD_ZERO (&readfds); - FD_ZERO (&exceptfds); - FD_SET (tty, &readfds); - FD_SET (tty, &exceptfds); - timeout.tv_sec = 0; - timeout.tv_usec = _keyboard_input_timeout; - return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0); -#else - -#if defined (FIONREAD) - if (ioctl (tty, FIONREAD, &chars_avail) == 0) - return (chars_avail); -#endif - -#endif - -#if defined (__MINGW32__) - if (isatty (tty)) - return (_kbhit ()); -#endif - - return 0; -} - -int -_rl_input_queued (t) - int t; -{ - int old_timeout, r; - - old_timeout = rl_set_keyboard_input_timeout (t); - r = _rl_input_available (); - rl_set_keyboard_input_timeout (old_timeout); - return r; -} - -void -_rl_insert_typein (c) - int c; -{ - int key, t, i; - char *string; - - i = key = 0; - string = (char *)xmalloc (ibuffer_len + 1); - string[i++] = (char) c; - - while ((t = rl_get_char (&key)) && - _rl_keymap[key].type == ISFUNC && - _rl_keymap[key].function == rl_insert) - string[i++] = key; - - if (t) - _rl_unget_char (key); - - string[i] = '\0'; - rl_insert_text (string); - xfree (string); -} - -/* Add KEY to the buffer of characters to be read. Returns 1 if the - character was stuffed correctly; 0 otherwise. */ -int -rl_stuff_char (key) - int key; -{ - if (ibuffer_space () == 0) - return 0; - - if (key == EOF) - { - key = NEWLINE; - rl_pending_input = EOF; - RL_SETSTATE (RL_STATE_INPUTPENDING); - } - ibuffer[push_index++] = key; -#if 0 - if (push_index >= ibuffer_len) -#else - if (push_index > ibuffer_len) -#endif - push_index = 0; - - return 1; -} - -/* Make C be the next command to be executed. */ -int -rl_execute_next (c) - int c; -{ - rl_pending_input = c; - RL_SETSTATE (RL_STATE_INPUTPENDING); - return 0; -} - -/* Clear any pending input pushed with rl_execute_next() */ -int -rl_clear_pending_input () -{ - rl_pending_input = 0; - RL_UNSETSTATE (RL_STATE_INPUTPENDING); - return 0; -} - -/* **************************************************************** */ -/* */ -/* Character Input */ -/* */ -/* **************************************************************** */ - -/* Read a key, including pending input. */ -int -rl_read_key () -{ - int c, r; - - if (rl_pending_input) - { - c = rl_pending_input; - rl_clear_pending_input (); - } - else - { - /* If input is coming from a macro, then use that. */ - if (c = _rl_next_macro_key ()) - return (c); - - /* If the user has an event function, then call it periodically. */ - if (rl_event_hook) - { - while (rl_event_hook) - { - if (rl_get_char (&c) != 0) - break; - - if ((r = rl_gather_tyi ()) < 0) /* XXX - EIO */ - { - rl_done = 1; - return ('\n'); - } - else if (r > 0) /* read something */ - continue; - - RL_CHECK_SIGNALS (); - if (rl_done) /* XXX - experimental */ - return ('\n'); - (*rl_event_hook) (); - } - } - else - { - if (rl_get_char (&c) == 0) - c = (*rl_getc_function) (rl_instream); -/* fprintf(stderr, "rl_read_key: calling RL_CHECK_SIGNALS: _rl_caught_signal = %d", _rl_caught_signal); */ - RL_CHECK_SIGNALS (); - } - } - - return (c); -} - -int -rl_getc (stream) - FILE *stream; -{ - int result; - unsigned char c; -#if defined (HAVE_PSELECT) - sigset_t empty_set; - fd_set readfds; -#endif - - while (1) - { - RL_CHECK_SIGNALS (); - - /* We know at this point that _rl_caught_signal == 0 */ - -#if defined (__MINGW32__) - if (isatty (fileno (stream))) - return (_getch ()); /* "There is no error return." */ -#endif - result = 0; -#if defined (HAVE_PSELECT) - sigemptyset (&empty_set); - FD_ZERO (&readfds); - FD_SET (fileno (stream), &readfds); - result = pselect (fileno (stream) + 1, &readfds, NULL, NULL, NULL, &empty_set); -# if 0 - if (result < 0 && errno == EINTR) - goto handle_error; -# endif -#endif - if (result >= 0) - result = read (fileno (stream), &c, sizeof (unsigned char)); - - if (result == sizeof (unsigned char)) - return (c); - - /* If zero characters are returned, then the file that we are - reading from is empty! Return EOF in that case. */ - if (result == 0) - return (EOF); - -#if defined (__BEOS__) - if (errno == EINTR) - continue; -#endif - -#if defined (EWOULDBLOCK) -# define X_EWOULDBLOCK EWOULDBLOCK -#else -# define X_EWOULDBLOCK -99 -#endif - -#if defined (EAGAIN) -# define X_EAGAIN EAGAIN -#else -# define X_EAGAIN -99 -#endif - - if (errno == X_EWOULDBLOCK || errno == X_EAGAIN) - { - if (sh_unset_nodelay_mode (fileno (stream)) < 0) - return (EOF); - continue; - } - -#undef X_EWOULDBLOCK -#undef X_EAGAIN - -/* fprintf(stderr, "rl_getc: result = %d errno = %d\n", result, errno); */ - -handle_error: - /* If the error that we received was EINTR, then try again, - this is simply an interrupted system call to read (). We allow - the read to be interrupted if we caught SIGHUP, SIGTERM, or any - of the other signals readline treats specially. If the - application sets an event hook, call it for other signals. - Otherwise (not EINTR), some error occurred, also signifying EOF. */ - if (errno != EINTR) - return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF); - /* fatal signals of interest */ - else if (_rl_caught_signal == SIGHUP || _rl_caught_signal == SIGTERM) - return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF); - /* keyboard-generated signals of interest */ - else if (_rl_caught_signal == SIGINT || _rl_caught_signal == SIGQUIT) - RL_CHECK_SIGNALS (); - /* non-keyboard-generated signals of interest */ - else if (_rl_caught_signal == SIGWINCH) - RL_CHECK_SIGNALS (); - else if (_rl_caught_signal == SIGALRM -#if defined (SIGVTALRM) - || _rl_caught_signal == SIGVTALRM -#endif - ) - RL_CHECK_SIGNALS (); - - if (rl_signal_event_hook) - (*rl_signal_event_hook) (); - } -} - -#if defined (HANDLE_MULTIBYTE) -/* read multibyte char */ -int -_rl_read_mbchar (mbchar, size) - char *mbchar; - int size; -{ - int mb_len, c; - size_t mbchar_bytes_length; - wchar_t wc; - mbstate_t ps, ps_back; - - memset(&ps, 0, sizeof (mbstate_t)); - memset(&ps_back, 0, sizeof (mbstate_t)); - - mb_len = 0; - while (mb_len < size) - { - RL_SETSTATE(RL_STATE_MOREINPUT); - c = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); - - if (c < 0) - break; - - mbchar[mb_len++] = c; - - mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps); - if (mbchar_bytes_length == (size_t)(-1)) - break; /* invalid byte sequence for the current locale */ - else if (mbchar_bytes_length == (size_t)(-2)) - { - /* shorted bytes */ - ps = ps_back; - continue; - } - else if (mbchar_bytes_length == 0) - { - mbchar[0] = '\0'; /* null wide character */ - mb_len = 1; - break; - } - else if (mbchar_bytes_length > (size_t)(0)) - break; - } - - return mb_len; -} - -/* Read a multibyte-character string whose first character is FIRST into - the buffer MB of length MLEN. Returns the last character read, which - may be FIRST. Used by the search functions, among others. Very similar - to _rl_read_mbchar. */ -int -_rl_read_mbstring (first, mb, mlen) - int first; - char *mb; - int mlen; -{ - int i, c; - mbstate_t ps; - - c = first; - memset (mb, 0, mlen); - for (i = 0; c >= 0 && i < mlen; i++) - { - mb[i] = (char)c; - memset (&ps, 0, sizeof (mbstate_t)); - if (_rl_get_char_len (mb, &ps) == -2) - { - /* Read more for multibyte character */ - RL_SETSTATE (RL_STATE_MOREINPUT); - c = rl_read_key (); - RL_UNSETSTATE (RL_STATE_MOREINPUT); - } - else - break; - } - return c; -} -#endif /* HANDLE_MULTIBYTE */ diff --git a/lib/readline/kill.c~ b/lib/readline/kill.c~ deleted file mode 100644 index 79b261227..000000000 --- a/lib/readline/kill.c~ +++ /dev/null @@ -1,744 +0,0 @@ -/* kill.c -- kill ring management. */ - -/* Copyright (C) 1994 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 - -#if defined (HAVE_UNISTD_H) -# include /* for _POSIX_VERSION */ -#endif /* HAVE_UNISTD_H */ - -#if defined (HAVE_STDLIB_H) -# include -#else -# include "ansi_stdlib.h" -#endif /* HAVE_STDLIB_H */ - -#include - -/* System-specific feature definitions and include files. */ -#include "rldefs.h" - -/* Some standard library routines. */ -#include "readline.h" -#include "history.h" - -#include "rlprivate.h" -#include "xmalloc.h" - -/* **************************************************************** */ -/* */ -/* Killing Mechanism */ -/* */ -/* **************************************************************** */ - -/* What we assume for a max number of kills. */ -#define DEFAULT_MAX_KILLS 10 - -/* The real variable to look at to find out when to flush kills. */ -static int rl_max_kills = DEFAULT_MAX_KILLS; - -/* Where to store killed text. */ -static char **rl_kill_ring = (char **)NULL; - -/* Where we are in the kill ring. */ -static int rl_kill_index; - -/* How many slots we have in the kill ring. */ -static int rl_kill_ring_length; - -static int _rl_copy_to_kill_ring PARAMS((char *, int)); -static int region_kill_internal PARAMS((int)); -static int _rl_copy_word_as_kill PARAMS((int, int)); -static int rl_yank_nth_arg_internal PARAMS((int, int, int)); - -/* How to say that you only want to save a certain amount - of kill material. */ -int -rl_set_retained_kills (num) - int num; -{ - return 0; -} - -/* Add TEXT to the kill ring, allocating a new kill ring slot as necessary. - This uses TEXT directly, so the caller must not free it. If APPEND is - non-zero, and the last command was a kill, the text is appended to the - current kill ring slot, otherwise prepended. */ -static int -_rl_copy_to_kill_ring (text, append) - char *text; - int append; -{ - char *old, *new; - int slot; - - /* First, find the slot to work with. */ - if (_rl_last_command_was_kill == 0) - { - /* Get a new slot. */ - if (rl_kill_ring == 0) - { - /* If we don't have any defined, then make one. */ - rl_kill_ring = (char **) - xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *)); - rl_kill_ring[slot = 0] = (char *)NULL; - } - else - { - /* We have to add a new slot on the end, unless we have - exceeded the max limit for remembering kills. */ - slot = rl_kill_ring_length; - if (slot == rl_max_kills) - { - register int i; - xfree (rl_kill_ring[0]); - for (i = 0; i < slot; i++) - rl_kill_ring[i] = rl_kill_ring[i + 1]; - } - else - { - slot = rl_kill_ring_length += 1; - rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *)); - } - rl_kill_ring[--slot] = (char *)NULL; - } - } - else - slot = rl_kill_ring_length - 1; - - /* If the last command was a kill, prepend or append. */ - if (_rl_last_command_was_kill && rl_editing_mode != vi_mode) - { - old = rl_kill_ring[slot]; - new = (char *)xmalloc (1 + strlen (old) + strlen (text)); - - if (append) - { - strcpy (new, old); - strcat (new, text); - } - else - { - strcpy (new, text); - strcat (new, old); - } - xfree (old); - xfree (text); - rl_kill_ring[slot] = new; - } - else - rl_kill_ring[slot] = text; - - rl_kill_index = slot; - return 0; -} - -/* The way to kill something. This appends or prepends to the last - kill, if the last command was a kill command. if FROM is less - than TO, then the text is appended, otherwise prepended. If the - last command was not a kill command, then a new slot is made for - this kill. */ -int -rl_kill_text (from, to) - int from, to; -{ - char *text; - - /* Is there anything to kill? */ - if (from == to) - { - _rl_last_command_was_kill++; - return 0; - } - - text = rl_copy_text (from, to); - - /* Delete the copied text from the line. */ - rl_delete_text (from, to); - - _rl_copy_to_kill_ring (text, from < to); - - _rl_last_command_was_kill++; - return 0; -} - -/* Now REMEMBER! In order to do prepending or appending correctly, kill - commands always make rl_point's original position be the FROM argument, - and rl_point's extent be the TO argument. */ - -/* **************************************************************** */ -/* */ -/* Killing Commands */ -/* */ -/* **************************************************************** */ - -/* Delete the word at point, saving the text in the kill ring. */ -int -rl_kill_word (count, key) - int count, key; -{ - int orig_point; - - if (count < 0) - return (rl_backward_kill_word (-count, key)); - else - { - orig_point = rl_point; - rl_forward_word (count, key); - - if (rl_point != orig_point) - rl_kill_text (orig_point, rl_point); - - rl_point = orig_point; - if (rl_editing_mode == emacs_mode) - rl_mark = rl_point; - } - return 0; -} - -/* Rubout the word before point, placing it on the kill ring. */ -int -rl_backward_kill_word (count, ignore) - int count, ignore; -{ - int orig_point; - - if (count < 0) - return (rl_kill_word (-count, ignore)); - else - { - orig_point = rl_point; - rl_backward_word (count, ignore); - - if (rl_point != orig_point) - rl_kill_text (orig_point, rl_point); - - if (rl_editing_mode == emacs_mode) - rl_mark = rl_point; - } - return 0; -} - -/* Kill from here to the end of the line. If DIRECTION is negative, kill - back to the line start instead. */ -int -rl_kill_line (direction, ignore) - int direction, ignore; -{ - int orig_point; - - if (direction < 0) - return (rl_backward_kill_line (1, ignore)); - else - { - orig_point = rl_point; - rl_end_of_line (1, ignore); - if (orig_point != rl_point) - rl_kill_text (orig_point, rl_point); - rl_point = orig_point; - if (rl_editing_mode == emacs_mode) - rl_mark = rl_point; - } - return 0; -} - -/* Kill backwards to the start of the line. If DIRECTION is negative, kill - forwards to the line end instead. */ -int -rl_backward_kill_line (direction, ignore) - int direction, ignore; -{ - int orig_point; - - if (direction < 0) - return (rl_kill_line (1, ignore)); - else - { - if (rl_point == 0) - rl_ding (); - else - { - orig_point = rl_point; - rl_beg_of_line (1, ignore); - if (rl_point != orig_point) - rl_kill_text (orig_point, rl_point); - if (rl_editing_mode == emacs_mode) - rl_mark = rl_point; - } - } - return 0; -} - -/* Kill the whole line, no matter where point is. */ -int -rl_kill_full_line (count, ignore) - int count, ignore; -{ - rl_begin_undo_group (); - rl_point = 0; - rl_kill_text (rl_point, rl_end); - rl_mark = 0; - rl_end_undo_group (); - return 0; -} - -/* The next two functions mimic unix line editing behaviour, except they - save the deleted text on the kill ring. This is safer than not saving - it, and since we have a ring, nobody should get screwed. */ - -/* This does what C-w does in Unix. We can't prevent people from - using behaviour that they expect. */ -int -rl_unix_word_rubout (count, key) - int count, key; -{ - int orig_point; - - if (rl_point == 0) - rl_ding (); - else - { - orig_point = rl_point; - if (count <= 0) - count = 1; - - while (count--) - { - while (rl_point && whitespace (rl_line_buffer[rl_point - 1])) - rl_point--; - - while (rl_point && (whitespace (rl_line_buffer[rl_point - 1]) == 0)) - rl_point--; - } - - rl_kill_text (orig_point, rl_point); - if (rl_editing_mode == emacs_mode) - rl_mark = rl_point; - } - - return 0; -} - -/* This deletes one filename component in a Unix pathname. That is, it - deletes backward to directory separator (`/') or whitespace. */ -int -rl_unix_filename_rubout (count, key) - int count, key; -{ - int orig_point, c; - - if (rl_point == 0) - rl_ding (); - else - { - orig_point = rl_point; - if (count <= 0) - count = 1; - - while (count--) - { - c = rl_line_buffer[rl_point - 1]; - while (rl_point && (whitespace (c) || c == '/')) - { - rl_point--; - c = rl_line_buffer[rl_point - 1]; - } - - while (rl_point && (whitespace (c) == 0) && c != '/') - { - rl_point--; - c = rl_line_buffer[rl_point - 1]; - } - } - - rl_kill_text (orig_point, rl_point); - if (rl_editing_mode == emacs_mode) - rl_mark = rl_point; - } - - return 0; -} - -/* Here is C-u doing what Unix does. You don't *have* to use these - key-bindings. We have a choice of killing the entire line, or - killing from where we are to the start of the line. We choose the - latter, because if you are a Unix weenie, then you haven't backspaced - into the line at all, and if you aren't, then you know what you are - doing. */ -int -rl_unix_line_discard (count, key) - int count, key; -{ - if (rl_point == 0) - rl_ding (); - else - { - rl_kill_text (rl_point, 0); - rl_point = 0; - if (rl_editing_mode == emacs_mode) - rl_mark = rl_point; - } - return 0; -} - -/* Copy the text in the `region' to the kill ring. If DELETE is non-zero, - delete the text from the line as well. */ -static int -region_kill_internal (delete) - int delete; -{ - char *text; - - if (rl_mark != rl_point) - { - text = rl_copy_text (rl_point, rl_mark); - if (delete) - rl_delete_text (rl_point, rl_mark); - _rl_copy_to_kill_ring (text, rl_point < rl_mark); - } - - _rl_last_command_was_kill++; - return 0; -} - -/* Copy the text in the region to the kill ring. */ -int -rl_copy_region_to_kill (count, ignore) - int count, ignore; -{ - return (region_kill_internal (0)); -} - -/* Kill the text between the point and mark. */ -int -rl_kill_region (count, ignore) - int count, ignore; -{ - int r, npoint; - - npoint = (rl_point < rl_mark) ? rl_point : rl_mark; - r = region_kill_internal (1); - _rl_fix_point (1); - rl_point = npoint; - return r; -} - -/* Copy COUNT words to the kill ring. DIR says which direction we look - to find the words. */ -static int -_rl_copy_word_as_kill (count, dir) - int count, dir; -{ - int om, op, r; - - om = rl_mark; - op = rl_point; - - if (dir > 0) - rl_forward_word (count, 0); - else - rl_backward_word (count, 0); - - rl_mark = rl_point; - - if (dir > 0) - rl_backward_word (count, 0); - else - rl_forward_word (count, 0); - - r = region_kill_internal (0); - - rl_mark = om; - rl_point = op; - - return r; -} - -int -rl_copy_forward_word (count, key) - int count, key; -{ - if (count < 0) - return (rl_copy_backward_word (-count, key)); - - return (_rl_copy_word_as_kill (count, 1)); -} - -int -rl_copy_backward_word (count, key) - int count, key; -{ - if (count < 0) - return (rl_copy_forward_word (-count, key)); - - return (_rl_copy_word_as_kill (count, -1)); -} - -/* Yank back the last killed text. This ignores arguments. */ -int -rl_yank (count, ignore) - int count, ignore; -{ - if (rl_kill_ring == 0) - { - _rl_abort_internal (); - return 1; - } - - _rl_set_mark_at_pos (rl_point); - rl_insert_text (rl_kill_ring[rl_kill_index]); - return 0; -} - -/* If the last command was yank, or yank_pop, and the text just - before point is identical to the current kill item, then - delete that text from the line, rotate the index down, and - yank back some other text. */ -int -rl_yank_pop (count, key) - int count, key; -{ - int l, n; - - if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) || - !rl_kill_ring) - { - _rl_abort_internal (); - return 1; - } - - l = strlen (rl_kill_ring[rl_kill_index]); - n = rl_point - l; - if (n >= 0 && STREQN (rl_line_buffer + n, rl_kill_ring[rl_kill_index], l)) - { - rl_delete_text (n, rl_point); - rl_point = n; - rl_kill_index--; - if (rl_kill_index < 0) - rl_kill_index = rl_kill_ring_length - 1; - rl_yank (1, 0); - return 0; - } - else - { - _rl_abort_internal (); - return 1; - } -} - -/* Yank the COUNTh argument from the previous history line, skipping - HISTORY_SKIP lines before looking for the `previous line'. */ -static int -rl_yank_nth_arg_internal (count, ignore, history_skip) - int count, ignore, history_skip; -{ - register HIST_ENTRY *entry; - char *arg; - int i, pos; - - pos = where_history (); - - if (history_skip) - { - for (i = 0; i < history_skip; i++) - entry = previous_history (); - } - - entry = previous_history (); - - history_set_pos (pos); - - if (entry == 0) - { - rl_ding (); - return 1; - } - - arg = history_arg_extract (count, count, entry->line); - if (!arg || !*arg) - { - rl_ding (); - FREE (arg); - return 1; - } - - rl_begin_undo_group (); - - _rl_set_mark_at_pos (rl_point); - -#if defined (VI_MODE) - /* Vi mode always inserts a space before yanking the argument, and it - inserts it right *after* rl_point. */ - if (rl_editing_mode == vi_mode) - { - rl_vi_append_mode (1, ignore); - rl_insert_text (" "); - } -#endif /* VI_MODE */ - - rl_insert_text (arg); - xfree (arg); - - rl_end_undo_group (); - return 0; -} - -/* Yank the COUNTth argument from the previous history line. */ -int -rl_yank_nth_arg (count, ignore) - int count, ignore; -{ - return (rl_yank_nth_arg_internal (count, ignore, 0)); -} - -/* Yank the last argument from the previous history line. This `knows' - how rl_yank_nth_arg treats a count of `$'. With an argument, this - behaves the same as rl_yank_nth_arg. */ -int -rl_yank_last_arg (count, key) - int count, key; -{ - static int history_skip = 0; - static int explicit_arg_p = 0; - static int count_passed = 1; - static int direction = 1; - static int undo_needed = 0; - int retval; - - if (rl_last_func != rl_yank_last_arg) - { - history_skip = 0; - explicit_arg_p = rl_explicit_arg; - count_passed = count; - direction = 1; - } - else - { - if (undo_needed) - rl_do_undo (); - if (count < 0) /* XXX - was < 1 */ - direction = -direction; - history_skip += direction; - if (history_skip < 0) - history_skip = 0; - } - - if (explicit_arg_p) - retval = rl_yank_nth_arg_internal (count_passed, key, history_skip); - else - retval = rl_yank_nth_arg_internal ('$', key, history_skip); - - undo_needed = retval == 0; - return retval; -} - -/* Having read the special escape sequence denoting the beginning of a - `bracketed paste' sequence, read the rest of the pasted input until the - closing sequence and insert the pasted text as a single unit without - interpretation. */ -int -rl_bracketed_paste_begin (count, key) - int count, key; -{ - int retval, c; - size_t len, cap; - char *buf; - - retval = 1; - len = 0; - buf = xmalloc (cap = 64); - - RL_SETSTATE (RL_STATE_MOREINPUT); - while ((c = rl_read_key ()) >= 0) - { - if (RL_ISSTATE (RL_STATE_MACRODEF)) - _rl_add_macro_char (c); - - if (c == '\r') /* XXX */ - c = '\n'; - - if (len == cap) - buf = xrealloc (buf, cap *= 2); - - buf[len++] = c; - if (len >= BRACK_PASTE_SLEN && c == BRACK_PASTE_LAST && - STREQN (buf + len - BRACK_PASTE_SLEN, BRACK_PASTE_SUFF, BRACK_PASTE_SLEN)) - { - len -= BRACK_PASTE_SLEN; - break; - } - } - RL_UNSETSTATE (RL_STATE_MOREINPUT); - - if (c >= 0) - { - if (len == cap) - buf = xrealloc (buf, cap + 1); - buf[len] = '\0'; - retval = rl_insert_text (buf); - } - - xfree (buf); - return (retval); -} - -/* A special paste command for users of Cygnus's cygwin32. */ -#if defined (__CYGWIN__) -#include - -int -rl_paste_from_clipboard (count, key) - int count, key; -{ - char *data, *ptr; - int len; - - if (OpenClipboard (NULL) == 0) - return (0); - - data = (char *)GetClipboardData (CF_TEXT); - if (data) - { - ptr = strchr (data, '\r'); - if (ptr) - { - len = ptr - data; - ptr = (char *)xmalloc (len + 1); - ptr[len] = '\0'; - strncpy (ptr, data, len); - } - else - ptr = data; - _rl_set_mark_at_pos (rl_point); - rl_insert_text (ptr); - if (ptr != data) - xfree (ptr); - CloseClipboard (); - } - return (0); -} -#endif /* __CYGWIN__ */ diff --git a/lib/readline/readline.h~ b/lib/readline/readline.h~ deleted file mode 100644 index 95f63a6b5..000000000 --- a/lib/readline/readline.h~ +++ /dev/null @@ -1,933 +0,0 @@ -/* Readline.h -- the names of functions callable from within readline. */ - -/* Copyright (C) 1987-2013 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 . -*/ - -#if !defined (_READLINE_H_) -#define _READLINE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined (READLINE_LIBRARY) -# include "rlstdc.h" -# include "rltypedefs.h" -# include "keymaps.h" -# include "tilde.h" -#else -# include -# include -# include -# include -#endif - -/* Hex-encoded Readline version number. */ -#define RL_READLINE_VERSION 0x0604 /* Readline 6.4 */ -#define RL_VERSION_MAJOR 6 -#define RL_VERSION_MINOR 4 - -/* Readline data structures. */ - -/* Maintaining the state of undo. We remember individual deletes and inserts - on a chain of things to do. */ - -/* The actions that undo knows how to undo. Notice that UNDO_DELETE means - to insert some text, and UNDO_INSERT means to delete some text. I.e., - the code tells undo what to undo, not how to undo it. */ -enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END }; - -/* What an element of THE_UNDO_LIST looks like. */ -typedef struct undo_list { - struct undo_list *next; - int start, end; /* Where the change took place. */ - char *text; /* The text to insert, if undoing a delete. */ - enum undo_code what; /* Delete, Insert, Begin, End. */ -} UNDO_LIST; - -/* The current undo list for RL_LINE_BUFFER. */ -extern UNDO_LIST *rl_undo_list; - -/* The data structure for mapping textual names to code addresses. */ -typedef struct _funmap { - const char *name; - rl_command_func_t *function; -} FUNMAP; - -extern FUNMAP **funmap; - -/* **************************************************************** */ -/* */ -/* Functions available to bind to key sequences */ -/* */ -/* **************************************************************** */ - -/* Bindable commands for numeric arguments. */ -extern int rl_digit_argument PARAMS((int, int)); -extern int rl_universal_argument PARAMS((int, int)); - -/* Bindable commands for moving the cursor. */ -extern int rl_forward_byte PARAMS((int, int)); -extern int rl_forward_char PARAMS((int, int)); -extern int rl_forward PARAMS((int, int)); -extern int rl_backward_byte PARAMS((int, int)); -extern int rl_backward_char PARAMS((int, int)); -extern int rl_backward PARAMS((int, int)); -extern int rl_beg_of_line PARAMS((int, int)); -extern int rl_end_of_line PARAMS((int, int)); -extern int rl_forward_word PARAMS((int, int)); -extern int rl_backward_word PARAMS((int, int)); -extern int rl_refresh_line PARAMS((int, int)); -extern int rl_clear_screen PARAMS((int, int)); -extern int rl_skip_csi_sequence PARAMS((int, int)); -extern int rl_arrow_keys PARAMS((int, int)); - -/* Bindable commands for inserting and deleting text. */ -extern int rl_insert PARAMS((int, int)); -extern int rl_quoted_insert PARAMS((int, int)); -extern int rl_tab_insert PARAMS((int, int)); -extern int rl_newline PARAMS((int, int)); -extern int rl_do_lowercase_version PARAMS((int, int)); -extern int rl_rubout PARAMS((int, int)); -extern int rl_delete PARAMS((int, int)); -extern int rl_rubout_or_delete PARAMS((int, int)); -extern int rl_delete_horizontal_space PARAMS((int, int)); -extern int rl_delete_or_show_completions PARAMS((int, int)); -extern int rl_insert_comment PARAMS((int, int)); - -/* Bindable commands for changing case. */ -extern int rl_upcase_word PARAMS((int, int)); -extern int rl_downcase_word PARAMS((int, int)); -extern int rl_capitalize_word PARAMS((int, int)); - -/* Bindable commands for transposing characters and words. */ -extern int rl_transpose_words PARAMS((int, int)); -extern int rl_transpose_chars PARAMS((int, int)); - -/* Bindable commands for searching within a line. */ -extern int rl_char_search PARAMS((int, int)); -extern int rl_backward_char_search PARAMS((int, int)); - -/* Bindable commands for readline's interface to the command history. */ -extern int rl_beginning_of_history PARAMS((int, int)); -extern int rl_end_of_history PARAMS((int, int)); -extern int rl_get_next_history PARAMS((int, int)); -extern int rl_get_previous_history PARAMS((int, int)); - -/* Bindable commands for managing the mark and region. */ -extern int rl_set_mark PARAMS((int, int)); -extern int rl_exchange_point_and_mark PARAMS((int, int)); - -/* Bindable commands to set the editing mode (emacs or vi). */ -extern int rl_vi_editing_mode PARAMS((int, int)); -extern int rl_emacs_editing_mode PARAMS((int, int)); - -/* Bindable commands to change the insert mode (insert or overwrite) */ -extern int rl_overwrite_mode PARAMS((int, int)); - -/* Bindable commands for managing key bindings. */ -extern int rl_re_read_init_file PARAMS((int, int)); -extern int rl_dump_functions PARAMS((int, int)); -extern int rl_dump_macros PARAMS((int, int)); -extern int rl_dump_variables PARAMS((int, int)); - -/* Bindable commands for word completion. */ -extern int rl_complete PARAMS((int, int)); -extern int rl_possible_completions PARAMS((int, int)); -extern int rl_insert_completions PARAMS((int, int)); -extern int rl_old_menu_complete PARAMS((int, int)); -extern int rl_menu_complete PARAMS((int, int)); -extern int rl_backward_menu_complete PARAMS((int, int)); - -/* Bindable commands for killing and yanking text, and managing the kill ring. */ -extern int rl_kill_word PARAMS((int, int)); -extern int rl_backward_kill_word PARAMS((int, int)); -extern int rl_kill_line PARAMS((int, int)); -extern int rl_backward_kill_line PARAMS((int, int)); -extern int rl_kill_full_line PARAMS((int, int)); -extern int rl_unix_word_rubout PARAMS((int, int)); -extern int rl_unix_filename_rubout PARAMS((int, int)); -extern int rl_unix_line_discard PARAMS((int, int)); -extern int rl_copy_region_to_kill PARAMS((int, int)); -extern int rl_kill_region PARAMS((int, int)); -extern int rl_copy_forward_word PARAMS((int, int)); -extern int rl_copy_backward_word PARAMS((int, int)); -extern int rl_yank PARAMS((int, int)); -extern int rl_yank_pop PARAMS((int, int)); -extern int rl_yank_nth_arg PARAMS((int, int)); -extern int rl_yank_last_arg PARAMS((int, int)); -extern int rl_bracketed_paste_begin PARAMS((int, int)); -/* Not available unless __CYGWIN__ is defined. */ -#ifdef __CYGWIN__ -extern int rl_paste_from_clipboard PARAMS((int, int)); -#endif - -/* Bindable commands for incremental searching. */ -extern int rl_reverse_search_history PARAMS((int, int)); -extern int rl_forward_search_history PARAMS((int, int)); - -/* Bindable keyboard macro commands. */ -extern int rl_start_kbd_macro PARAMS((int, int)); -extern int rl_end_kbd_macro PARAMS((int, int)); -extern int rl_call_last_kbd_macro PARAMS((int, int)); -extern int rl_print_last_kbd_macro PARAMS((int, int)); - -/* Bindable undo commands. */ -extern int rl_revert_line PARAMS((int, int)); -extern int rl_undo_command PARAMS((int, int)); - -/* Bindable tilde expansion commands. */ -extern int rl_tilde_expand PARAMS((int, int)); - -/* Bindable terminal control commands. */ -extern int rl_restart_output PARAMS((int, int)); -extern int rl_stop_output PARAMS((int, int)); - -/* Miscellaneous bindable commands. */ -extern int rl_abort PARAMS((int, int)); -extern int rl_tty_status PARAMS((int, int)); - -/* Bindable commands for incremental and non-incremental history searching. */ -extern int rl_history_search_forward PARAMS((int, int)); -extern int rl_history_search_backward PARAMS((int, int)); -extern int rl_history_substr_search_forward PARAMS((int, int)); -extern int rl_history_substr_search_backward PARAMS((int, int)); -extern int rl_noninc_forward_search PARAMS((int, int)); -extern int rl_noninc_reverse_search PARAMS((int, int)); -extern int rl_noninc_forward_search_again PARAMS((int, int)); -extern int rl_noninc_reverse_search_again PARAMS((int, int)); - -/* Bindable command used when inserting a matching close character. */ -extern int rl_insert_close PARAMS((int, int)); - -/* Not available unless READLINE_CALLBACKS is defined. */ -extern void rl_callback_handler_install PARAMS((const char *, rl_vcpfunc_t *)); -extern void rl_callback_read_char PARAMS((void)); -extern void rl_callback_handler_remove PARAMS((void)); - -/* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */ -/* VI-mode bindable commands. */ -extern int rl_vi_redo PARAMS((int, int)); -extern int rl_vi_undo PARAMS((int, int)); -extern int rl_vi_yank_arg PARAMS((int, int)); -extern int rl_vi_fetch_history PARAMS((int, int)); -extern int rl_vi_search_again PARAMS((int, int)); -extern int rl_vi_search PARAMS((int, int)); -extern int rl_vi_complete PARAMS((int, int)); -extern int rl_vi_tilde_expand PARAMS((int, int)); -extern int rl_vi_prev_word PARAMS((int, int)); -extern int rl_vi_next_word PARAMS((int, int)); -extern int rl_vi_end_word PARAMS((int, int)); -extern int rl_vi_insert_beg PARAMS((int, int)); -extern int rl_vi_append_mode PARAMS((int, int)); -extern int rl_vi_append_eol PARAMS((int, int)); -extern int rl_vi_eof_maybe PARAMS((int, int)); -extern int rl_vi_insertion_mode PARAMS((int, int)); -extern int rl_vi_insert_mode PARAMS((int, int)); -extern int rl_vi_movement_mode PARAMS((int, int)); -extern int rl_vi_arg_digit PARAMS((int, int)); -extern int rl_vi_change_case PARAMS((int, int)); -extern int rl_vi_put PARAMS((int, int)); -extern int rl_vi_column PARAMS((int, int)); -extern int rl_vi_delete_to PARAMS((int, int)); -extern int rl_vi_change_to PARAMS((int, int)); -extern int rl_vi_yank_to PARAMS((int, int)); -extern int rl_vi_rubout PARAMS((int, int)); -extern int rl_vi_delete PARAMS((int, int)); -extern int rl_vi_back_to_indent PARAMS((int, int)); -extern int rl_vi_first_print PARAMS((int, int)); -extern int rl_vi_char_search PARAMS((int, int)); -extern int rl_vi_match PARAMS((int, int)); -extern int rl_vi_change_char PARAMS((int, int)); -extern int rl_vi_subst PARAMS((int, int)); -extern int rl_vi_overstrike PARAMS((int, int)); -extern int rl_vi_overstrike_delete PARAMS((int, int)); -extern int rl_vi_replace PARAMS((int, int)); -extern int rl_vi_set_mark PARAMS((int, int)); -extern int rl_vi_goto_mark PARAMS((int, int)); - -/* VI-mode utility functions. */ -extern int rl_vi_check PARAMS((void)); -extern int rl_vi_domove PARAMS((int, int *)); -extern int rl_vi_bracktype PARAMS((int)); - -extern void rl_vi_start_inserting PARAMS((int, int, int)); - -/* VI-mode pseudo-bindable commands, used as utility functions. */ -extern int rl_vi_fWord PARAMS((int, int)); -extern int rl_vi_bWord PARAMS((int, int)); -extern int rl_vi_eWord PARAMS((int, int)); -extern int rl_vi_fword PARAMS((int, int)); -extern int rl_vi_bword PARAMS((int, int)); -extern int rl_vi_eword PARAMS((int, int)); - -/* **************************************************************** */ -/* */ -/* Well Published Functions */ -/* */ -/* **************************************************************** */ - -/* Readline functions. */ -/* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. */ -extern char *readline PARAMS((const char *)); - -extern int rl_set_prompt PARAMS((const char *)); -extern int rl_expand_prompt PARAMS((char *)); - -extern int rl_initialize PARAMS((void)); - -/* Undocumented; unused by readline */ -extern int rl_discard_argument PARAMS((void)); - -/* Utility functions to bind keys to readline commands. */ -extern int rl_add_defun PARAMS((const char *, rl_command_func_t *, int)); -extern int rl_bind_key PARAMS((int, rl_command_func_t *)); -extern int rl_bind_key_in_map PARAMS((int, rl_command_func_t *, Keymap)); -extern int rl_unbind_key PARAMS((int)); -extern int rl_unbind_key_in_map PARAMS((int, Keymap)); -extern int rl_bind_key_if_unbound PARAMS((int, rl_command_func_t *)); -extern int rl_bind_key_if_unbound_in_map PARAMS((int, rl_command_func_t *, Keymap)); -extern int rl_unbind_function_in_map PARAMS((rl_command_func_t *, Keymap)); -extern int rl_unbind_command_in_map PARAMS((const char *, Keymap)); -extern int rl_bind_keyseq PARAMS((const char *, rl_command_func_t *)); -extern int rl_bind_keyseq_in_map PARAMS((const char *, rl_command_func_t *, Keymap)); -extern int rl_bind_keyseq_if_unbound PARAMS((const char *, rl_command_func_t *)); -extern int rl_bind_keyseq_if_unbound_in_map PARAMS((const char *, rl_command_func_t *, Keymap)); -extern int rl_generic_bind PARAMS((int, const char *, char *, Keymap)); - -extern char *rl_variable_value PARAMS((const char *)); -extern int rl_variable_bind PARAMS((const char *, const char *)); - -/* Backwards compatibility, use rl_bind_keyseq_in_map instead. */ -extern int rl_set_key PARAMS((const char *, rl_command_func_t *, Keymap)); - -/* Backwards compatibility, use rl_generic_bind instead. */ -extern int rl_macro_bind PARAMS((const char *, const char *, Keymap)); - -/* Undocumented in the texinfo manual; not really useful to programs. */ -extern int rl_translate_keyseq PARAMS((const char *, char *, int *)); -extern char *rl_untranslate_keyseq PARAMS((int)); - -extern rl_command_func_t *rl_named_function PARAMS((const char *)); -extern rl_command_func_t *rl_function_of_keyseq PARAMS((const char *, Keymap, int *)); - -extern void rl_list_funmap_names PARAMS((void)); -extern char **rl_invoking_keyseqs_in_map PARAMS((rl_command_func_t *, Keymap)); -extern char **rl_invoking_keyseqs PARAMS((rl_command_func_t *)); - -extern void rl_function_dumper PARAMS((int)); -extern void rl_macro_dumper PARAMS((int)); -extern void rl_variable_dumper PARAMS((int)); - -extern int rl_read_init_file PARAMS((const char *)); -extern int rl_parse_and_bind PARAMS((char *)); - -/* Functions for manipulating keymaps. */ -extern Keymap rl_make_bare_keymap PARAMS((void)); -extern Keymap rl_copy_keymap PARAMS((Keymap)); -extern Keymap rl_make_keymap PARAMS((void)); -extern void rl_discard_keymap PARAMS((Keymap)); -extern void rl_free_keymap PARAMS((Keymap)); - -extern Keymap rl_get_keymap_by_name PARAMS((const char *)); -extern char *rl_get_keymap_name PARAMS((Keymap)); -extern void rl_set_keymap PARAMS((Keymap)); -extern Keymap rl_get_keymap PARAMS((void)); -/* Undocumented; used internally only. */ -extern void rl_set_keymap_from_edit_mode PARAMS((void)); -extern char *rl_get_keymap_name_from_edit_mode PARAMS((void)); - -/* Functions for manipulating the funmap, which maps command names to functions. */ -extern int rl_add_funmap_entry PARAMS((const char *, rl_command_func_t *)); -extern const char **rl_funmap_names PARAMS((void)); -/* Undocumented, only used internally -- there is only one funmap, and this - function may be called only once. */ -extern void rl_initialize_funmap PARAMS((void)); - -/* Utility functions for managing keyboard macros. */ -extern void rl_push_macro_input PARAMS((char *)); - -/* Functions for undoing, from undo.c */ -extern void rl_add_undo PARAMS((enum undo_code, int, int, char *)); -extern void rl_free_undo_list PARAMS((void)); -extern int rl_do_undo PARAMS((void)); -extern int rl_begin_undo_group PARAMS((void)); -extern int rl_end_undo_group PARAMS((void)); -extern int rl_modifying PARAMS((int, int)); - -/* Functions for redisplay. */ -extern void rl_redisplay PARAMS((void)); -extern int rl_on_new_line PARAMS((void)); -extern int rl_on_new_line_with_prompt PARAMS((void)); -extern int rl_forced_update_display PARAMS((void)); -extern int rl_clear_message PARAMS((void)); -extern int rl_reset_line_state PARAMS((void)); -extern int rl_crlf PARAMS((void)); - -#if defined (USE_VARARGS) && defined (PREFER_STDARG) -extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2))); -#else -extern int rl_message (); -#endif - -extern int rl_show_char PARAMS((int)); - -/* Undocumented in texinfo manual. */ -extern int rl_character_len PARAMS((int, int)); -extern void rl_redraw_prompt_last_line PARAMS((void)); - -/* Save and restore internal prompt redisplay information. */ -extern void rl_save_prompt PARAMS((void)); -extern void rl_restore_prompt PARAMS((void)); - -/* Modifying text. */ -extern void rl_replace_line PARAMS((const char *, int)); -extern int rl_insert_text PARAMS((const char *)); -extern int rl_delete_text PARAMS((int, int)); -extern int rl_kill_text PARAMS((int, int)); -extern char *rl_copy_text PARAMS((int, int)); - -/* Terminal and tty mode management. */ -extern void rl_prep_terminal PARAMS((int)); -extern void rl_deprep_terminal PARAMS((void)); -extern void rl_tty_set_default_bindings PARAMS((Keymap)); -extern void rl_tty_unset_default_bindings PARAMS((Keymap)); - -extern int rl_reset_terminal PARAMS((const char *)); -extern void rl_resize_terminal PARAMS((void)); -extern void rl_set_screen_size PARAMS((int, int)); -extern void rl_get_screen_size PARAMS((int *, int *)); -extern void rl_reset_screen_size PARAMS((void)); - -extern char *rl_get_termcap PARAMS((const char *)); - -/* Functions for character input. */ -extern int rl_stuff_char PARAMS((int)); -extern int rl_execute_next PARAMS((int)); -extern int rl_clear_pending_input PARAMS((void)); -extern int rl_read_key PARAMS((void)); -extern int rl_getc PARAMS((FILE *)); -extern int rl_set_keyboard_input_timeout PARAMS((int)); - -/* `Public' utility functions . */ -extern void rl_extend_line_buffer PARAMS((int)); -extern int rl_ding PARAMS((void)); -extern int rl_alphabetic PARAMS((int)); -extern void rl_free PARAMS((void *)); - -/* Readline signal handling, from signals.c */ -extern int rl_set_signals PARAMS((void)); -extern int rl_clear_signals PARAMS((void)); -extern void rl_cleanup_after_signal PARAMS((void)); -extern void rl_reset_after_signal PARAMS((void)); -extern void rl_free_line_state PARAMS((void)); - -extern void rl_echo_signal_char PARAMS((int)); - -extern int rl_set_paren_blink_timeout PARAMS((int)); - -/* History management functions. */ - -extern void rl_clear_history PARAMS((void)); - -/* Undocumented. */ -extern int rl_maybe_save_line PARAMS((void)); -extern int rl_maybe_unsave_line PARAMS((void)); -extern int rl_maybe_replace_line PARAMS((void)); - -/* Completion functions. */ -extern int rl_complete_internal PARAMS((int)); -extern void rl_display_match_list PARAMS((char **, int, int)); - -extern char **rl_completion_matches PARAMS((const char *, rl_compentry_func_t *)); -extern char *rl_username_completion_function PARAMS((const char *, int)); -extern char *rl_filename_completion_function PARAMS((const char *, int)); - -extern int rl_completion_mode PARAMS((rl_command_func_t *)); - -#if 0 -/* Backwards compatibility (compat.c). These will go away sometime. */ -extern void free_undo_list PARAMS((void)); -extern int maybe_save_line PARAMS((void)); -extern int maybe_unsave_line PARAMS((void)); -extern int maybe_replace_line PARAMS((void)); - -extern int ding PARAMS((void)); -extern int alphabetic PARAMS((int)); -extern int crlf PARAMS((void)); - -extern char **completion_matches PARAMS((char *, rl_compentry_func_t *)); -extern char *username_completion_function PARAMS((const char *, int)); -extern char *filename_completion_function PARAMS((const char *, int)); -#endif - -/* **************************************************************** */ -/* */ -/* Well Published Variables */ -/* */ -/* **************************************************************** */ - -/* The version of this incarnation of the readline library. */ -extern const char *rl_library_version; /* e.g., "4.2" */ -extern int rl_readline_version; /* e.g., 0x0402 */ - -/* True if this is real GNU readline. */ -extern int rl_gnu_readline_p; - -/* Flags word encapsulating the current readline state. */ -extern int rl_readline_state; - -/* Says which editing mode readline is currently using. 1 means emacs mode; - 0 means vi mode. */ -extern int rl_editing_mode; - -/* Insert or overwrite mode for emacs mode. 1 means insert mode; 0 means - overwrite mode. Reset to insert mode on each input line. */ -extern int rl_insert_mode; - -/* The name of the calling program. You should initialize this to - whatever was in argv[0]. It is used when parsing conditionals. */ -extern const char *rl_readline_name; - -/* The prompt readline uses. This is set from the argument to - readline (), and should not be assigned to directly. */ -extern char *rl_prompt; - -/* The prompt string that is actually displayed by rl_redisplay. Public so - applications can more easily supply their own redisplay functions. */ -extern char *rl_display_prompt; - -/* The line buffer that is in use. */ -extern char *rl_line_buffer; - -/* The location of point, and end. */ -extern int rl_point; -extern int rl_end; - -/* The mark, or saved cursor position. */ -extern int rl_mark; - -/* Flag to indicate that readline has finished with the current input - line and should return it. */ -extern int rl_done; - -/* If set to a character value, that will be the next keystroke read. */ -extern int rl_pending_input; - -/* Non-zero if we called this function from _rl_dispatch(). It's present - so functions can find out whether they were called from a key binding - or directly from an application. */ -extern int rl_dispatching; - -/* Non-zero if the user typed a numeric argument before executing the - current function. */ -extern int rl_explicit_arg; - -/* The current value of the numeric argument specified by the user. */ -extern int rl_numeric_arg; - -/* The address of the last command function Readline executed. */ -extern rl_command_func_t *rl_last_func; - -/* The name of the terminal to use. */ -extern const char *rl_terminal_name; - -/* The input and output streams. */ -extern FILE *rl_instream; -extern FILE *rl_outstream; - -/* If non-zero, Readline gives values of LINES and COLUMNS from the environment - greater precedence than values fetched from the kernel when computing the - screen dimensions. */ -extern int rl_prefer_env_winsize; - -/* If non-zero, then this is the address of a function to call just - before readline_internal () prints the first prompt. */ -extern rl_hook_func_t *rl_startup_hook; - -/* If non-zero, this is the address of a function to call just before - readline_internal_setup () returns and readline_internal starts - reading input characters. */ -extern rl_hook_func_t *rl_pre_input_hook; - -/* The address of a function to call periodically while Readline is - awaiting character input, or NULL, for no event handling. */ -extern rl_hook_func_t *rl_event_hook; - -/* The address of a function to call if a read is interrupted by a signal. */ -extern rl_hook_func_t *rl_signal_event_hook; - -/* The address of a function to call if Readline needs to know whether or not - there is data available from the current input source. */ -extern rl_hook_func_t *rl_input_available_hook; - -/* The address of the function to call to fetch a character from the current - Readline input stream */ -extern rl_getc_func_t *rl_getc_function; - -extern rl_voidfunc_t *rl_redisplay_function; - -extern rl_vintfunc_t *rl_prep_term_function; -extern rl_voidfunc_t *rl_deprep_term_function; - -/* Dispatch variables. */ -extern Keymap rl_executing_keymap; -extern Keymap rl_binding_keymap; - -extern int rl_executing_key; -extern char *rl_executing_keyseq; -extern int rl_key_sequence_length; - -/* Display variables. */ -/* If non-zero, readline will erase the entire line, including any prompt, - if the only thing typed on an otherwise-blank line is something bound to - rl_newline. */ -extern int rl_erase_empty_line; - -/* If non-zero, the application has already printed the prompt (rl_prompt) - before calling readline, so readline should not output it the first time - redisplay is done. */ -extern int rl_already_prompted; - -/* A non-zero value means to read only this many characters rather than - up to a character bound to accept-line. */ -extern int rl_num_chars_to_read; - -/* The text of a currently-executing keyboard macro. */ -extern char *rl_executing_macro; - -/* Variables to control readline signal handling. */ -/* If non-zero, readline will install its own signal handlers for - SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */ -extern int rl_catch_signals; - -/* If non-zero, readline will install a signal handler for SIGWINCH - that also attempts to call any calling application's SIGWINCH signal - handler. Note that the terminal is not cleaned up before the - application's signal handler is called; use rl_cleanup_after_signal() - to do that. */ -extern int rl_catch_sigwinch; - -/* If non-zero, the readline SIGWINCH handler will modify LINES and - COLUMNS in the environment. */ -extern int rl_change_environment; - -/* Completion variables. */ -/* Pointer to the generator function for completion_matches (). - NULL means to use rl_filename_completion_function (), the default - filename completer. */ -extern rl_compentry_func_t *rl_completion_entry_function; - -/* Optional generator for menu completion. Default is - rl_completion_entry_function (rl_filename_completion_function). */ - extern rl_compentry_func_t *rl_menu_completion_entry_function; - -/* If rl_ignore_some_completions_function is non-NULL it is the address - of a function to call after all of the possible matches have been - generated, but before the actual completion is done to the input line. - The function is called with one argument; a NULL terminated array - of (char *). If your function removes any of the elements, they - must be free()'ed. */ -extern rl_compignore_func_t *rl_ignore_some_completions_function; - -/* 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. */ -extern rl_completion_func_t *rl_attempted_completion_function; - -/* The basic list of characters that signal a break between words for the - completer routine. The initial contents of this variable is what - breaks words in the shell, i.e. "n\"\\'`@$>". */ -extern const char *rl_basic_word_break_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. */ -extern /*const*/ char *rl_completer_word_break_characters; - -/* 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. */ -extern rl_cpvfunc_t *rl_completion_word_break_hook; - -/* 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. */ -extern const char *rl_completer_quote_characters; - -/* List of quote characters which cause a word break. */ -extern const char *rl_basic_quote_characters; - -/* List of characters that need to be quoted in filenames by the completer. */ -extern const char *rl_filename_quote_characters; - -/* 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. */ -extern const char *rl_special_prefixes; - -/* 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. It - changes what is displayed when the possible completions are printed - or inserted. The directory completion hook should perform - any necessary dequoting. This function should return 1 if it modifies - the directory name pointer passed as an argument. If the directory - completion hook returns 0, it should not modify the directory name - pointer passed as an argument. */ -extern rl_icppfunc_t *rl_directory_completion_hook; - -/* If non-zero, this is the address of a function to call when completing - a directory name. This function takes the address of the directory name - to be modified as an argument. Unlike rl_directory_completion_hook, it - only modifies the directory name used in opendir(2), not what is displayed - when the possible completions are printed or inserted. If set, it takes - precedence over rl_directory_completion_hook. The directory rewrite - hook should perform any necessary dequoting. This function has the same - return value properties as the directory_completion_hook. - - I'm not happy with how this works yet, so it's undocumented. I'm trying - it in bash to see how well it goes. */ -extern rl_icppfunc_t *rl_directory_rewrite_hook; - -/* If non-zero, this is the address of a function for the completer to call - before deciding which character to append to a completed name. It should - modify the directory name passed as an argument if appropriate, and return - non-zero if it modifies the name. This should not worry about dequoting - the filename; that has already happened by the time it gets here. */ -extern rl_icppfunc_t *rl_filename_stat_hook; - -/* 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. */ -extern rl_dequote_func_t *rl_filename_rewrite_hook; - -/* Backwards compatibility with previous versions of readline. */ -#define rl_symbolic_link_hook rl_directory_completion_hook - -/* 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. */ -extern rl_compdisp_func_t *rl_completion_display_matches_hook; - -/* 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. */ -extern int rl_filename_completion_desired; - -/* 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_word_break_chars. This is - ALWAYS non-zero on entry, and can only be changed within a completion - entry finder function. */ -extern int rl_filename_quoting_desired; - -/* 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. */ -extern rl_quote_func_t *rl_filename_quoting_function; - -/* 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. */ -extern rl_dequote_func_t *rl_filename_dequoting_function; - -/* 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. */ -extern rl_linebuf_func_t *rl_char_is_quoted_p; - -/* Non-zero means to suppress normal filename completion after the - user-specified completion function has been called. */ -extern int rl_attempted_completion_over; - -/* Set to a character describing the type of completion being attempted by - rl_complete_internal; available for use by application completion - functions. */ -extern int rl_completion_type; - -/* Set to the last key used to invoke one of the completion functions */ -extern int rl_completion_invoking_key; - -/* 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. The default value is 100. */ -extern int rl_completion_query_items; - -/* Character appended to completed words when at the end of the line. The - default is a space. Nothing is added if this is '\0'. */ -extern int rl_completion_append_character; - -/* If set to non-zero by an application completion function, - rl_completion_append_character will not be appended. */ -extern int rl_completion_suppress_append; - -/* Set to any quote character readline thinks it finds before any application - completion function is called. */ -extern 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. */ -extern int rl_completion_found_quote; - -/* 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. */ -extern int rl_completion_suppress_quote; - -/* If non-zero, readline will sort the completion matches. On by default. */ -extern int rl_sort_completion_matches; - -/* 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. */ -extern int rl_completion_mark_symlink_dirs; - -/* If non-zero, then disallow duplicates in the matches. */ -extern int rl_ignore_completion_duplicates; - -/* If this is non-zero, completion is (temporarily) inhibited, and the - completion character will be inserted as any other. */ -extern int rl_inhibit_completion; - -/* Input error; can be returned by (*rl_getc_function) if readline is reading - a top-level command (RL_ISSTATE (RL_STATE_READCMD)). */ -#define READERR (-2) - -/* Definitions available for use by readline clients. */ -#define RL_PROMPT_START_IGNORE '\001' -#define RL_PROMPT_END_IGNORE '\002' - -/* Possible values for do_replace argument to rl_filename_quoting_function, - called by rl_complete_internal. */ -#define NO_MATCH 0 -#define SINGLE_MATCH 1 -#define MULT_MATCH 2 - -/* Possible state values for rl_readline_state */ -#define RL_STATE_NONE 0x000000 /* no state; before first call */ - -#define RL_STATE_INITIALIZING 0x0000001 /* initializing */ -#define RL_STATE_INITIALIZED 0x0000002 /* initialization done */ -#define RL_STATE_TERMPREPPED 0x0000004 /* terminal is prepped */ -#define RL_STATE_READCMD 0x0000008 /* reading a command key */ -#define RL_STATE_METANEXT 0x0000010 /* reading input after ESC */ -#define RL_STATE_DISPATCHING 0x0000020 /* dispatching to a command */ -#define RL_STATE_MOREINPUT 0x0000040 /* reading more input in a command function */ -#define RL_STATE_ISEARCH 0x0000080 /* doing incremental search */ -#define RL_STATE_NSEARCH 0x0000100 /* doing non-inc search */ -#define RL_STATE_SEARCH 0x0000200 /* doing a history search */ -#define RL_STATE_NUMERICARG 0x0000400 /* reading numeric argument */ -#define RL_STATE_MACROINPUT 0x0000800 /* getting input from a macro */ -#define RL_STATE_MACRODEF 0x0001000 /* defining keyboard macro */ -#define RL_STATE_OVERWRITE 0x0002000 /* overwrite mode */ -#define RL_STATE_COMPLETING 0x0004000 /* doing completion */ -#define RL_STATE_SIGHANDLER 0x0008000 /* in readline sighandler */ -#define RL_STATE_UNDOING 0x0010000 /* doing an undo */ -#define RL_STATE_INPUTPENDING 0x0020000 /* rl_execute_next called */ -#define RL_STATE_TTYCSAVED 0x0040000 /* tty special chars saved */ -#define RL_STATE_CALLBACK 0x0080000 /* using the callback interface */ -#define RL_STATE_VIMOTION 0x0100000 /* reading vi motion arg */ -#define RL_STATE_MULTIKEY 0x0200000 /* reading multiple-key command */ -#define RL_STATE_VICMDONCE 0x0400000 /* entered vi command mode at least once */ -#define RL_STATE_REDISPLAYING 0x0800000 /* updating terminal display */ - -#define RL_STATE_DONE 0x1000000 /* done; accepted line */ - -#define RL_SETSTATE(x) (rl_readline_state |= (x)) -#define RL_UNSETSTATE(x) (rl_readline_state &= ~(x)) -#define RL_ISSTATE(x) (rl_readline_state & (x)) - -struct readline_state { - /* line state */ - int point; - int end; - int mark; - char *buffer; - int buflen; - UNDO_LIST *ul; - char *prompt; - - /* global state */ - int rlstate; - int done; - Keymap kmap; - - /* input state */ - rl_command_func_t *lastfunc; - int insmode; - int edmode; - char *kseq; - int kseqlen; - FILE *inf; - FILE *outf; - int pendingin; - char *macro; - - /* signal state */ - int catchsigs; - int catchsigwinch; - - /* search state */ - - /* completion state */ - rl_compentry_func_t *entryfunc; - rl_compentry_func_t *menuentryfunc; - rl_compignore_func_t *ignorefunc; - rl_completion_func_t *attemptfunc; - char *wordbreakchars; - - /* options state */ - - /* hook state */ - - /* reserved for future expansion, so the struct size doesn't change */ - char reserved[64]; -}; - -extern int rl_save_state PARAMS((struct readline_state *)); -extern int rl_restore_state PARAMS((struct readline_state *)); - -#ifdef __cplusplus -} -#endif - -#endif /* _READLINE_H_ */ diff --git a/lib/readline/util.c~ b/lib/readline/util.c~ deleted file mode 100644 index 8192bf0a2..000000000 --- a/lib/readline/util.c~ +++ /dev/null @@ -1,595 +0,0 @@ -/* util.c -- readline utility functions */ - -/* Copyright (C) 1987-2012 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 -#include "posixjmp.h" - -#if defined (HAVE_UNISTD_H) -# include /* for _POSIX_VERSION */ -#endif /* HAVE_UNISTD_H */ - -#if defined (HAVE_STDLIB_H) -# include -#else -# include "ansi_stdlib.h" -#endif /* HAVE_STDLIB_H */ - -#include -#include - -/* System-specific feature definitions and include files. */ -#include "rldefs.h" -#include "rlmbutil.h" - -#if defined (TIOCSTAT_IN_SYS_IOCTL) -# include -#endif /* TIOCSTAT_IN_SYS_IOCTL */ - -/* Some standard library routines. */ -#include "readline.h" - -#include "rlprivate.h" -#include "xmalloc.h" - -/* **************************************************************** */ -/* */ -/* Utility Functions */ -/* */ -/* **************************************************************** */ - -/* Return 0 if C is not a member of the class of characters that belong - in words, or 1 if it is. */ - -int _rl_allow_pathname_alphabetic_chars = 0; -static const char * const pathname_alphabetic_chars = "/-_=~.#$"; - -int -rl_alphabetic (c) - int c; -{ - if (ALPHABETIC (c)) - return (1); - - return (_rl_allow_pathname_alphabetic_chars && - strchr (pathname_alphabetic_chars, c) != NULL); -} - -#if defined (HANDLE_MULTIBYTE) -int -_rl_walphabetic (wchar_t wc) -{ - int c; - - if (iswalnum (wc)) - return (1); - - c = wc & 0177; - return (_rl_allow_pathname_alphabetic_chars && - strchr (pathname_alphabetic_chars, c) != NULL); -} -#endif - -/* How to abort things. */ -int -_rl_abort_internal () -{ - rl_ding (); - rl_clear_message (); - _rl_reset_argument (); - rl_clear_pending_input (); - - RL_UNSETSTATE (RL_STATE_MACRODEF); - while (rl_executing_macro) - _rl_pop_executing_macro (); - - RL_UNSETSTATE (RL_STATE_MULTIKEY); /* XXX */ - - rl_last_func = (rl_command_func_t *)NULL; -#if defined (HAVE_POSIX_SIGSETJMP) - siglongjmp (_rl_top_level, 1); -#else - longjmp (_rl_top_level, 1); -#endif - return (0); -} - -int -rl_abort (count, key) - int count, key; -{ - return (_rl_abort_internal ()); -} - -int -_rl_null_function (count, key) - int count, key; -{ - return 0; -} - -int -rl_tty_status (count, key) - int count, key; -{ -#if defined (TIOCSTAT) - ioctl (1, TIOCSTAT, (char *)0); - rl_refresh_line (count, key); -#else - rl_ding (); -#endif - return 0; -} - -/* Return a copy of the string between FROM and TO. - FROM is inclusive, TO is not. */ -char * -rl_copy_text (from, to) - int from, to; -{ - register int length; - char *copy; - - /* Fix it if the caller is confused. */ - if (from > to) - SWAP (from, to); - - length = to - from; - copy = (char *)xmalloc (1 + length); - strncpy (copy, rl_line_buffer + from, length); - copy[length] = '\0'; - return (copy); -} - -/* Increase the size of RL_LINE_BUFFER until it has enough space to hold - LEN characters. */ -void -rl_extend_line_buffer (len) - int len; -{ - while (len >= rl_line_buffer_len) - { - rl_line_buffer_len += DEFAULT_BUFFER_SIZE; - rl_line_buffer = (char *)xrealloc (rl_line_buffer, rl_line_buffer_len); - } - - _rl_set_the_line (); -} - - -/* A function for simple tilde expansion. */ -int -rl_tilde_expand (ignore, key) - int ignore, key; -{ - register int start, end; - char *homedir, *temp; - int len; - - end = rl_point; - start = end - 1; - - if (rl_point == rl_end && rl_line_buffer[rl_point] == '~') - { - homedir = tilde_expand ("~"); - _rl_replace_text (homedir, start, end); - xfree (homedir); - return (0); - } - else if (rl_line_buffer[start] != '~') - { - for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--) - ; - start++; - } - - end = start; - do - end++; - while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end); - - if (whitespace (rl_line_buffer[end]) || end >= rl_end) - end--; - - /* If the first character of the current word is a tilde, perform - tilde expansion and insert the result. If not a tilde, do - nothing. */ - if (rl_line_buffer[start] == '~') - { - len = end - start + 1; - temp = (char *)xmalloc (len + 1); - strncpy (temp, rl_line_buffer + start, len); - temp[len] = '\0'; - homedir = tilde_expand (temp); - xfree (temp); - - _rl_replace_text (homedir, start, end); - xfree (homedir); - } - - return (0); -} - -#if defined (USE_VARARGS) -void -#if defined (PREFER_STDARG) -_rl_ttymsg (const char *format, ...) -#else -_rl_ttymsg (va_alist) - va_dcl -#endif -{ - va_list args; -#if defined (PREFER_VARARGS) - char *format; -#endif - -#if defined (PREFER_STDARG) - va_start (args, format); -#else - va_start (args); - format = va_arg (args, char *); -#endif - - fprintf (stderr, "readline: "); - vfprintf (stderr, format, args); - fprintf (stderr, "\n"); - fflush (stderr); - - va_end (args); - - rl_forced_update_display (); -} - -void -#if defined (PREFER_STDARG) -_rl_errmsg (const char *format, ...) -#else -_rl_errmsg (va_alist) - va_dcl -#endif -{ - va_list args; -#if defined (PREFER_VARARGS) - char *format; -#endif - -#if defined (PREFER_STDARG) - va_start (args, format); -#else - va_start (args); - format = va_arg (args, char *); -#endif - - fprintf (stderr, "readline: "); - vfprintf (stderr, format, args); - fprintf (stderr, "\n"); - fflush (stderr); - - va_end (args); -} - -#else /* !USE_VARARGS */ -void -_rl_ttymsg (format, arg1, arg2) - char *format; -{ - fprintf (stderr, "readline: "); - fprintf (stderr, format, arg1, arg2); - fprintf (stderr, "\n"); - - rl_forced_update_display (); -} - -void -_rl_errmsg (format, arg1, arg2) - char *format; -{ - fprintf (stderr, "readline: "); - fprintf (stderr, format, arg1, arg2); - fprintf (stderr, "\n"); -} -#endif /* !USE_VARARGS */ - -/* **************************************************************** */ -/* */ -/* String Utility Functions */ -/* */ -/* **************************************************************** */ - -/* Determine if s2 occurs in s1. If so, return a pointer to the - match in s1. The compare is case insensitive. */ -char * -_rl_strindex (s1, s2) - register const char *s1, *s2; -{ - register int i, l, len; - - for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++) - if (_rl_strnicmp (s1 + i, s2, l) == 0) - return ((char *) (s1 + i)); - return ((char *)NULL); -} - -#ifndef HAVE_STRPBRK -/* Find the first occurrence in STRING1 of any character from STRING2. - Return a pointer to the character in STRING1. */ -char * -_rl_strpbrk (string1, string2) - const char *string1, *string2; -{ - register const char *scan; -#if defined (HANDLE_MULTIBYTE) - mbstate_t ps; - register int i, v; - - memset (&ps, 0, sizeof (mbstate_t)); -#endif - - for (; *string1; string1++) - { - for (scan = string2; *scan; scan++) - { - if (*string1 == *scan) - return ((char *)string1); - } -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - v = _rl_get_char_len (string1, &ps); - if (v > 1) - string1 += v - 1; /* -1 to account for auto-increment in loop */ - } -#endif - } - return ((char *)NULL); -} -#endif - -#if !defined (HAVE_STRCASECMP) -/* Compare at most COUNT characters from string1 to string2. Case - doesn't matter (strncasecmp). */ -int -_rl_strnicmp (string1, string2, count) - const char *string1; - const char *string2; - int count; -{ - register const char *s1; - register const char *s2; - register int d; - - if (count <= 0 || (string1 == string2)) - return 0; - - s1 = string1; - s2 = string2; - do - { - d = _rl_to_lower (*s1) - _rl_to_lower (*s2); /* XXX - cast to unsigned char? */ - if (d != 0) - return d; - if (*s1++ == '\0') - break; - s2++; - } - while (--count != 0); - - return (0); -} - -/* strcmp (), but caseless (strcasecmp). */ -int -_rl_stricmp (string1, string2) - const char *string1; - const char *string2; -{ - register const char *s1; - register const char *s2; - register int d; - - s1 = string1; - s2 = string2; - - if (s1 == s2) - return 0; - - while ((d = _rl_to_lower (*s1) - _rl_to_lower (*s2)) == 0) - { - if (*s1++ == '\0') - return 0; - s2++; - } - - return (d); -} -#endif /* !HAVE_STRCASECMP */ - -/* Stupid comparison routine for qsort () ing strings. */ -int -_rl_qsort_string_compare (s1, s2) - char **s1, **s2; -{ -#if defined (HAVE_STRCOLL) - return (strcoll (*s1, *s2)); -#else - int result; - - result = **s1 - **s2; - if (result == 0) - result = strcmp (*s1, *s2); - - return result; -#endif -} - -/* Function equivalents for the macros defined in chardefs.h. */ -#define FUNCTION_FOR_MACRO(f) int (f) (c) int c; { return f (c); } - -FUNCTION_FOR_MACRO (_rl_digit_p) -FUNCTION_FOR_MACRO (_rl_digit_value) -FUNCTION_FOR_MACRO (_rl_lowercase_p) -FUNCTION_FOR_MACRO (_rl_pure_alphabetic) -FUNCTION_FOR_MACRO (_rl_to_lower) -FUNCTION_FOR_MACRO (_rl_to_upper) -FUNCTION_FOR_MACRO (_rl_uppercase_p) - -/* A convenience function, to force memory deallocation to be performed - by readline. DLLs on Windows apparently require this. */ -void -rl_free (mem) - void *mem; -{ - if (mem) - free (mem); -} - -/* Backwards compatibility, now that savestring has been removed from - all `public' readline header files. */ -#undef _rl_savestring -char * -_rl_savestring (s) - const char *s; -{ - return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s))); -} - -#if defined (DEBUG) -#if defined (USE_VARARGS) -static FILE *_rl_tracefp; - -void -#if defined (PREFER_STDARG) -_rl_trace (const char *format, ...) -#else -_rl_trace (va_alist) - va_dcl -#endif -{ - va_list args; -#if defined (PREFER_VARARGS) - char *format; -#endif - -#if defined (PREFER_STDARG) - va_start (args, format); -#else - va_start (args); - format = va_arg (args, char *); -#endif - - if (_rl_tracefp == 0) - _rl_tropen (); - vfprintf (_rl_tracefp, format, args); - fprintf (_rl_tracefp, "\n"); - fflush (_rl_tracefp); - - va_end (args); -} - -int -_rl_tropen () -{ - char fnbuf[128]; - - if (_rl_tracefp) - fclose (_rl_tracefp); - sprintf (fnbuf, "/var/tmp/rltrace.%ld", (long)getpid()); - unlink(fnbuf); - _rl_tracefp = fopen (fnbuf, "w+"); - return _rl_tracefp != 0; -} - -int -_rl_trclose () -{ - int r; - - r = fclose (_rl_tracefp); - _rl_tracefp = 0; - return r; -} - -void -_rl_settracefp (fp) - FILE *fp; -{ - _rl_tracefp = fp; -} -#endif -#endif /* DEBUG */ - - -#if HAVE_DECL_AUDIT_USER_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT) -#include -#include -#include - -/* Report STRING to the audit system. */ -void -_rl_audit_tty (string) - char *string; -{ - struct sockaddr_nl addr; - struct msghdr msg; - struct nlmsghdr nlm; - struct iovec iov[2]; - size_t size; - int fd; - - fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_AUDIT); - if (fd < 0) - return; - size = strlen (string) + 1; - - nlm.nlmsg_len = NLMSG_LENGTH (size); - nlm.nlmsg_type = AUDIT_USER_TTY; - nlm.nlmsg_flags = NLM_F_REQUEST; - nlm.nlmsg_seq = 0; - nlm.nlmsg_pid = 0; - - iov[0].iov_base = &nlm; - iov[0].iov_len = sizeof (nlm); - iov[1].iov_base = string; - iov[1].iov_len = size; - - addr.nl_family = AF_NETLINK; - addr.nl_pid = 0; - addr.nl_groups = 0; - - msg.msg_name = &addr; - msg.msg_namelen = sizeof (addr); - msg.msg_iov = iov; - msg.msg_iovlen = 2; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - - (void)sendmsg (fd, &msg, 0); - close (fd); -} -#endif diff --git a/lib/tilde/tilde.c~ b/lib/tilde/tilde.c~ deleted file mode 100644 index 1c53a457d..000000000 --- a/lib/tilde/tilde.c~ +++ /dev/null @@ -1,502 +0,0 @@ -/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */ - -/* Copyright (C) 1988-2009 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 . -*/ - -#if defined (HAVE_CONFIG_H) -# include -#endif - -#if defined (HAVE_UNISTD_H) -# ifdef _MINIX -# include -# endif -# include -#endif - -#if defined (HAVE_STRING_H) -# include -#else /* !HAVE_STRING_H */ -# include -#endif /* !HAVE_STRING_H */ - -#if defined (HAVE_STDLIB_H) -# include -#else -# include "ansi_stdlib.h" -#endif /* HAVE_STDLIB_H */ - -#include -#if defined (HAVE_PWD_H) -#include -#endif - -#include "tilde.h" - -#if defined (TEST) || defined (STATIC_MALLOC) -static void *xmalloc (), *xrealloc (); -#else -# include "xmalloc.h" -#endif /* TEST || STATIC_MALLOC */ - -#if !defined (HAVE_GETPW_DECLS) -# if defined (HAVE_GETPWUID) -extern struct passwd *getpwuid PARAMS((uid_t)); -# endif -# if defined (HAVE_GETPWNAM) -extern struct passwd *getpwnam PARAMS((const char *)); -# endif -#endif /* !HAVE_GETPW_DECLS */ - -#if !defined (savestring) -#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x)) -#endif /* !savestring */ - -#if !defined (NULL) -# if defined (__STDC__) -# define NULL ((void *) 0) -# else -# define NULL 0x0 -# endif /* !__STDC__ */ -#endif /* !NULL */ - -/* If being compiled as part of bash, these will be satisfied from - variables.o. If being compiled as part of readline, they will - be satisfied from shell.o. */ -extern char *sh_get_home_dir PARAMS((void)); -extern char *sh_get_env_value PARAMS((const char *)); - -/* The default value of tilde_additional_prefixes. This is set to - whitespace preceding a tilde so that simple programs which do not - perform any word separation get desired behaviour. */ -static const char *default_prefixes[] = - { " ~", "\t~", (const char *)NULL }; - -/* The default value of tilde_additional_suffixes. This is set to - whitespace or newline so that simple programs which do not - perform any word separation get desired behaviour. */ -static const char *default_suffixes[] = - { " ", "\n", (const char *)NULL }; - -/* If non-null, this contains the address of a function that the application - wants called before trying the standard tilde expansions. The function - is called with the text sans tilde, and returns a malloc()'ed string - which is the expansion, or a NULL pointer if the expansion fails. */ -tilde_hook_func_t *tilde_expansion_preexpansion_hook = (tilde_hook_func_t *)NULL; - -/* If non-null, this contains the address of a function to call if the - standard meaning for expanding a tilde fails. The function is called - with the text (sans tilde, as in "foo"), and returns a malloc()'ed string - which is the expansion, or a NULL pointer if there is no expansion. */ -tilde_hook_func_t *tilde_expansion_failure_hook = (tilde_hook_func_t *)NULL; - -/* When non-null, this is a NULL terminated array of strings which - are duplicates for a tilde prefix. Bash uses this to expand - `=~' and `:~'. */ -char **tilde_additional_prefixes = (char **)default_prefixes; - -/* When non-null, this is a NULL terminated array of strings which match - the end of a username, instead of just "/". Bash sets this to - `:' and `=~'. */ -char **tilde_additional_suffixes = (char **)default_suffixes; - -static int tilde_find_prefix PARAMS((const char *, int *)); -static int tilde_find_suffix PARAMS((const char *)); -static char *isolate_tilde_prefix PARAMS((const char *, int *)); -static char *glue_prefix_and_suffix PARAMS((char *, const char *, int)); - -/* Find the start of a tilde expansion in STRING, and return the index of - the tilde which starts the expansion. Place the length of the text - which identified this tilde starter in LEN, excluding the tilde itself. */ -static int -tilde_find_prefix (string, len) - const char *string; - int *len; -{ - register int i, j, string_len; - register char **prefixes; - - prefixes = tilde_additional_prefixes; - - string_len = strlen (string); - *len = 0; - - if (*string == '\0' || *string == '~') - return (0); - - if (prefixes) - { - for (i = 0; i < string_len; i++) - { - for (j = 0; prefixes[j]; j++) - { - if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0) - { - *len = strlen (prefixes[j]) - 1; - return (i + *len); - } - } - } - } - return (string_len); -} - -/* Find the end of a tilde expansion in STRING, and return the index of - the character which ends the tilde definition. */ -static int -tilde_find_suffix (string) - const char *string; -{ - register int i, j, string_len; - register char **suffixes; - - suffixes = tilde_additional_suffixes; - string_len = strlen (string); - - for (i = 0; i < string_len; i++) - { -#if defined (__MSDOS__) - if (string[i] == '/' || string[i] == '\\' /* || !string[i] */) -#else - if (string[i] == '/' /* || !string[i] */) -#endif - break; - - for (j = 0; suffixes && suffixes[j]; j++) - { - if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0) - return (i); - } - } - return (i); -} - -/* Return a new string which is the result of tilde expanding STRING. */ -char * -tilde_expand (string) - const char *string; -{ - char *result; - int result_size, result_index; - - result_index = result_size = 0; - if (result = strchr (string, '~')) - result = (char *)xmalloc (result_size = (strlen (string) + 16)); - else - result = (char *)xmalloc (result_size = (strlen (string) + 1)); - - /* Scan through STRING expanding tildes as we come to them. */ - while (1) - { - register int start, end; - char *tilde_word, *expansion; - int len; - - /* Make START point to the tilde which starts the expansion. */ - start = tilde_find_prefix (string, &len); - - /* Copy the skipped text into the result. */ - if ((result_index + start + 1) > result_size) - result = (char *)xrealloc (result, 1 + (result_size += (start + 20))); - - strncpy (result + result_index, string, start); - result_index += start; - - /* Advance STRING to the starting tilde. */ - string += start; - - /* Make END be the index of one after the last character of the - username. */ - end = tilde_find_suffix (string); - - /* If both START and END are zero, we are all done. */ - if (!start && !end) - break; - - /* Expand the entire tilde word, and copy it into RESULT. */ - tilde_word = (char *)xmalloc (1 + end); - strncpy (tilde_word, string, end); - tilde_word[end] = '\0'; - string += end; - - expansion = tilde_expand_word (tilde_word); - xfree (tilde_word); - - len = strlen (expansion); -#ifdef __CYGWIN__ - /* Fix for Cygwin to prevent ~user/xxx from expanding to //xxx when - $HOME for `user' is /. On cygwin, // denotes a network drive. */ - if (len > 1 || *expansion != '/' || *string != '/') -#endif - { - if ((result_index + len + 1) > result_size) - result = (char *)xrealloc (result, 1 + (result_size += (len + 20))); - - strcpy (result + result_index, expansion); - result_index += len; - } - xfree (expansion); - } - - result[result_index] = '\0'; - - return (result); -} - -/* Take FNAME and return the tilde prefix we want expanded. If LENP is - non-null, the index of the end of the prefix into FNAME is returned in - the location it points to. */ -static char * -isolate_tilde_prefix (fname, lenp) - const char *fname; - int *lenp; -{ - char *ret; - int i; - - ret = (char *)xmalloc (strlen (fname)); -#if defined (__MSDOS__) - for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++) -#else - for (i = 1; fname[i] && fname[i] != '/'; i++) -#endif - ret[i - 1] = fname[i]; - ret[i - 1] = '\0'; - if (lenp) - *lenp = i; - return ret; -} - -#if 0 -/* Public function to scan a string (FNAME) beginning with a tilde and find - the portion of the string that should be passed to the tilde expansion - function. Right now, it just calls tilde_find_suffix and allocates new - memory, but it can be expanded to do different things later. */ -char * -tilde_find_word (fname, flags, lenp) - const char *fname; - int flags, *lenp; -{ - int x; - char *r; - - x = tilde_find_suffix (fname); - if (x == 0) - { - r = savestring (fname); - if (lenp) - *lenp = 0; - } - else - { - r = (char *)xmalloc (1 + x); - strncpy (r, fname, x); - r[x] = '\0'; - if (lenp) - *lenp = x; - } - - return r; -} -#endif - -/* Return a string that is PREFIX concatenated with SUFFIX starting at - SUFFIND. */ -static char * -glue_prefix_and_suffix (prefix, suffix, suffind) - char *prefix; - const char *suffix; - int suffind; -{ - char *ret; - int plen, slen; - - plen = (prefix && *prefix) ? strlen (prefix) : 0; - slen = strlen (suffix + suffind); - ret = (char *)xmalloc (plen + slen + 1); - if (plen) - strcpy (ret, prefix); - strcpy (ret + plen, suffix + suffind); - return ret; -} - -/* Do the work of tilde expansion on FILENAME. FILENAME starts with a - tilde. If there is no expansion, call tilde_expansion_failure_hook. - This always returns a newly-allocated string, never static storage. */ -char * -tilde_expand_word (filename) - const char *filename; -{ - char *dirname, *expansion, *username; - int user_len; - struct passwd *user_entry; - - if (filename == 0) - return ((char *)NULL); - - if (*filename != '~') - return (savestring (filename)); - - /* A leading `~/' or a bare `~' is *always* translated to the value of - $HOME or the home directory of the current user, regardless of any - preexpansion hook. */ - if (filename[1] == '\0' || filename[1] == '/') - { - /* Prefix $HOME to the rest of the string. */ - expansion = sh_get_env_value ("HOME"); - - /* If there is no HOME variable, look up the directory in - the password database. */ - if (expansion == 0) - expansion = sh_get_home_dir (); - - return (glue_prefix_and_suffix (expansion, filename, 1)); - } - - username = isolate_tilde_prefix (filename, &user_len); - - if (tilde_expansion_preexpansion_hook) - { - expansion = (*tilde_expansion_preexpansion_hook) (username); - if (expansion) - { - dirname = glue_prefix_and_suffix (expansion, filename, user_len); - xfree (username); - xfree (expansion); - return (dirname); - } - } - - /* No preexpansion hook, or the preexpansion hook failed. Look in the - password database. */ - dirname = (char *)NULL; -#if defined (HAVE_GETPWNAM) - user_entry = getpwnam (username); -#else - user_entry = 0; -#endif - if (user_entry == 0) - { - /* If the calling program has a special syntax for expanding tildes, - and we couldn't find a standard expansion, then let them try. */ - if (tilde_expansion_failure_hook) - { - expansion = (*tilde_expansion_failure_hook) (username); - if (expansion) - { - dirname = glue_prefix_and_suffix (expansion, filename, user_len); - xfree (expansion); - } - } - /* If we don't have a failure hook, or if the failure hook did not - expand the tilde, return a copy of what we were passed. */ - if (dirname == 0) - dirname = savestring (filename); - } -#if defined (HAVE_GETPWENT) - else - dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len); -#endif - - xfree (username); -#if defined (HAVE_GETPWENT) - endpwent (); -#endif - return (dirname); -} - - -#if defined (TEST) -#undef NULL -#include - -main (argc, argv) - int argc; - char **argv; -{ - char *result, line[512]; - int done = 0; - - while (!done) - { - printf ("~expand: "); - fflush (stdout); - - if (!gets (line)) - strcpy (line, "done"); - - if ((strcmp (line, "done") == 0) || - (strcmp (line, "quit") == 0) || - (strcmp (line, "exit") == 0)) - { - done = 1; - break; - } - - result = tilde_expand (line); - printf (" --> %s\n", result); - free (result); - } - exit (0); -} - -static void memory_error_and_abort (); - -static void * -xmalloc (bytes) - size_t bytes; -{ - void *temp = (char *)malloc (bytes); - - if (!temp) - memory_error_and_abort (); - return (temp); -} - -static void * -xrealloc (pointer, bytes) - void *pointer; - int bytes; -{ - void *temp; - - if (!pointer) - temp = malloc (bytes); - else - temp = realloc (pointer, bytes); - - if (!temp) - memory_error_and_abort (); - - return (temp); -} - -static void -memory_error_and_abort () -{ - fprintf (stderr, "readline: out of virtual memory\n"); - abort (); -} - -/* - * Local variables: - * compile-command: "gcc -g -DTEST -o tilde tilde.c" - * end: - */ -#endif /* TEST */ diff --git a/tests/RUN-ONE-TEST~ b/tests/RUN-ONE-TEST~ deleted file mode 100755 index 3efcf32d6..000000000 --- a/tests/RUN-ONE-TEST~ +++ /dev/null @@ -1,9 +0,0 @@ -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/misc/regress/log.orig b/tests/misc/regress/log.orig deleted file mode 100644 index c1f1e1991..000000000 --- a/tests/misc/regress/log.orig +++ /dev/null @@ -1,50 +0,0 @@ -:; ./shx - -sh: -<&$fd ok -nlbq Mon Aug 3 02:45:00 EDT 1992 -bang geoff -quote 712824302 -setbq defmsgid=<1992Aug3.024502.6176@host> -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 deleted file mode 100644 index 4b3bf2b82..000000000 --- a/tests/misc/regress/shx.orig +++ /dev/null @@ -1,10 +0,0 @@ -#! /bin/sh -for cmd in sh bash ash ksh zsh -do - echo - echo $cmd: - for demo in shx? - do - $cmd $demo - done -done