diff options
author | Chet Ramey <chet.ramey@case.edu> | 2014-07-11 15:55:56 -0400 |
---|---|---|
committer | Chet Ramey <chet.ramey@case.edu> | 2014-07-11 15:55:56 -0400 |
commit | 7d4f37ad63a384c076bb8277822f10d316d8526e (patch) | |
tree | 088ed8368565a76b6c8ffb34129ff236b9d5c06b | |
parent | 25a0eacfeb479ab03387295485233cd53da2afb0 (diff) | |
download | bash-7d4f37ad63a384c076bb8277822f10d316d8526e.tar.gz |
bash-20140625 remove leftover and stray files
36 files changed, 0 insertions, 54330 deletions
diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ deleted file mode 100644 index d7c6b8a5..00000000 --- a/CWRU/CWRU.chlog~ +++ /dev/null @@ -1,6488 +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 <dearvoid@gmail.com> - - 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 <jue@jue.li> - -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 - <dearvoid@gmail.com> - -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 <dearvoid@gmail.com> - -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 - <vapier@gentoo.org> - - 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 <dennistwilliamson@gmail.com> - -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 <jojo@schmitz-digital.de> - -support/shobj-conf - - add a stanza for nsk on the Tandem from Joachim Schmitz - <jojo@schmitz-digital.de> - -{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 - <jojo@schmitz-digital.de> - - 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 <foutrelis@gmail.com> - - 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 <mfwitten@gmail.com> - -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 - <nathanael@gnat.ca> and Matthias Klose <doko@debian.org> - -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 <mfwitten@gmail.com> - - 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 <mfwitten@gmail.com> - - 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 <mfwitten@gmail.com> - - 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 <mfwitten@gmail.com> - -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 <andres.p@zoho.com> - - 3/4 - --- -lib/readline/bind.c - - add a missing free of `names' in rl_function_dumper. Bug report - and fix from Michael Snyder <msnyder@vmware.com> - - 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 <micah@cowan.name> - - 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 <torvalds@linux-foundation.org>, bug report originally - from Oleg Nesterov <oleg@redhat.com> - - 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 <cfajohnson@gmail.com> - -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 <rrakus@redhat.com> - - 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 <werner@suse.de> - - 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 <sam@liddicott.com> - - 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 <blue3waters@gmail.com> - - 3/26 - ---- -lib/readline/rltypedefs.h - - remove old Function/VFunction/CPFunction/CPPFunction typedefs as - suggested by Tom Tromey <tromey@redhat.com> - -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 - <tromey@redhat.com> - - 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 <dennistwilliamson@gmail.com> - -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 <h.bekel@googlemail.com> - - 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 <mfwitten@gmail.com> - -lib/readline/display.c - - include <pc.h> 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 <pc.h> 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 <eliz@gnu.org> - - 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 <arbogast.cedric@gmail.com> - - 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 <mdinger.bugzilla@gmail.com> - -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 <dearvoid@gmail.com> - - 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 <rrakus@redhat.com> - - 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 - <piuma@piumalab.org> - - 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." <skunk@iSKUNK.ORG> - - 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 - <johan.hattne@utsouthwestern.edu> - - 5/2 - --- -doc/{bash.1,bashref.texi} - - add forward reference to `Pattern Matching' from `Pathname - Expansion', suggested by Greg Wooledge <wooledg@eeg.ccf.org> - - 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 \<CTLESC> 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 <sbohrer@rgmadvisors.com> - - 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 <rrakus@redhat.com> - - 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 <rbyshko@gmail.com> - - 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 <marten.wikstrom@keystream.se> - - 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 <arbogast.cedric@gmail.com> - - 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 <mlichvar@redhat.com> - -builtins/help.def - - help_builtin: change strncmp to strcmp so that `help read' no longer - matches `readonly'. Suggested by Clark Wang <dearvoid@gmail.com> - -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 <samuel.thibault@gnu.org> - -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 - <d.l.tDecontes@free.fr> - - 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 - <keithw@mit.edu> - -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 - <cubranic@stat.ubc.ca> - - 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 <eblake@redhat.com> - - 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 - <kulkarniniraj14@gmail.com> - -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 - <mark.herbert@gmail.com> - -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 - <qiaomuf@gentoo.org> - - 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 <jrnieder@gmail.com> - -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 - <curtis@greenkey.net> - - 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 <lrhorer@satx.rr.com> - -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 <ville.skytta@iki.fi> - -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 <rsantos@grupopie.com> - -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 - <arnold@skeeve.com> - - 6/30 - ---- -execute_cmd.c - - execute_pipeline: make sure the lastpipe code is protected by - #ifdef JOB_CONTROL. Fixes problem reported by Thomas Cort - <tcort@minix3.org> - - 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 <jan.ktratochvil@redhat.com> 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 <arnold@skeeve.com> - - 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 <dearvoid@gmail.com> - - _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 - <jan.kratochvil@redhat.com> - -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 <ralph@inputplus.co.uk> - - 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 - <mlichvar@redhat.com> - -builtins/printf.def - - getint: if garglist == 0, return whatever getintmax returns (0). - Fixes bug reported by Ralph Coredroy <ralph@inputplus.co.uk> - - 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 <gmargo@pacbell.net> - - 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 - <lhunath@lyndir.com> - - 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 <bash@tlinx.org>. - 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 - <ohnobinki@ohnopublishing.net> -- 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 <vince.sheffer@apisphere.com> - -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 <rrakus@redhat.com> - - 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 - <rrakus@redhat.com> - - 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 <diegoaugustomolina@gmail.com> - - 9/19 - ---- -expr.c - - exppower: replace the simple exponentiation algorithm with an - implementation of exponentiation by squaring. Inspired by report - from Nicolas ARGYROU <nargy@yahoo.com> - -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 <backuppc-users@whitleymott.net> - -doc/{bash.1,bashref.texi},lib/readline/doc/{hsuser,rluser}.texi - - minor editorial changes inspired by suggestions from - Roger Zauner <rogerx.oss@gmail.com> - - 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 - <bensberg@justemail.net> - - 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 <daysleeper@centrum.cz> - - 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 - <bugs@kayari.org> - - 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 <pto@linuxbog.dk> and Patrick Pfeifer - <patrick@pfeifer.de> - - 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 <patrick@pfeifer.de> - -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 <dearvoid@gmail.com> - -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 <davidparks21@yahoo.com> - - 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 <jreiser@bitwagon.com> - 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 <vapier@gentoo.org> 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 <vapier@gentoo.org> 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 <Len.Giambrone@intersystems.com> - - 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 - <wooledg@eeg.ccf.org> - - 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 <lolilolicon@gmail.com> - - 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 <michael@kalisz.homelinux.net> - - 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 <jaak.ristioja@cyber.ee> - - 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 <ormaaj@gmail.com> - - 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 <vapier@gentoo.org> - - 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 - <jens.schmidt35@arcor.de> - -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 <jan.ktratochvil@redhat.com> 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 - <stephane_chazelas@yahoo.fr> - -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 <eggert@cs.ucla.edu> - - 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 <schwab@linux-m68k.org> - -builtins/read.def - - skip over NUL bytes in input, as most modern shells seem to. Bug - report by Matthew Story <matt@tablethotels.com> - -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 - <pierre.gaston@gmail.com> - -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 - <g.clare@opengroup.org> 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 <yanegomi@gmail.com> - - 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 - <yanegomi@gmail.com> - - 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 <yanegomi@gmail.com> - - 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 - <panyongzhi@gmail.com> - - 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 <panyongzhi@gmail.com> - - 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 - <dearvoid@gmail.com> - - 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 <hanzl@noel.feld.cvut.cz> - - 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 - <kazikcz@gmail.com> - - 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 <dethrophes@motd005> - -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 <raphael.droz+floss@gmail.com> - - 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 - <ormaaj@gmail.com> - -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 <pengyu.ut@gmail.com> - - 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 - <bill@ycc.com> - - 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 <p@draigbrady.com> - - 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 - <raphael.droz+floss@gmail.com> - -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 <sungpae@gmail.com> - - 1/18 - ---- - -{configure,config.h}.in - - new check: check for AUDIT_USER_TTY defined in <linux/audit.h>, - 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 <mlichvar@redhat.com> - - 1/21 - ---- - -lib/readline/readline.c: - - _rl_dispatch_subseq: add an inter-character timeout for multi-char - key sequences. Suggested by <rogerx.oss@gmail.com>. 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 <ormaaj@gmail.com> - - - 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 - <pierre.muller@ics-cnrs.unistra.fr> - -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 <bash@tlinx.org> - - 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 <james_avera@yahoo.com> - - 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 <rogerx.oss@gmail.com> - - _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 - <rogerx.oss@gmail.com> - - 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 <schwab@linux-m68k.org> - -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 - <Ewan.Mellor@eu.citrix.com> - -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 - <ormaaj@gmail.com> - -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 <ormaaj@gmail.com> - - 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 <dethrophes@web.de> - -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 <dethrophes@web.de> - - 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 <dethrophes@web.de> - - 2/21 - ---- -doc/{bash,builtins}.1 - - minor changes from Bjarni Ingi Gislason <bjarniig@rhi.hi.is> - -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 <derflob@derflob.de> - - 2/22 - ---- -lib/sh/shquote.c - - sh_backslash_quote: quote tilde in places where it would be - expanded. From a report from John Kearney <dethrophes@web.de> - - 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 <rdkehn@yahoo.com> - - 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 <dethrophes@web.de> - - u32toutf16: function to convert unsigned 32-bit value (unicode) to - UTF-16. From John Kearney <dethrophes@web.de> - - 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 <dethrophes@web.de> - - 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 <sar@nec-labs.com> - - 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 <ormaaj@gmail.com> - -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 <sami.pietila@gmail.com> - - 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 - <werner@suse.de> 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 - <fabrizio.ge@tiscali.it> - - 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 <fabrizio.ge@tiscali.it> - -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 - <siddhesh@redhat.com> - -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 <medgar123@gmail.com> - -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 <jurij.mihelic@fri.uni-lj.si> - - 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 <bill@ycc.com> - - 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 - <rogerx.oss@gmail.com>; this prompted by report from Barry Downes - <barry.downes@gmail.com> - -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 - <wooledg@eeg.ccf.org> - - 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 <stdbool.h> 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 <petr.sumbera@sun.com> - - 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 <petr.sumbera@sun.com> - - 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 <arnold@skeeve.com> - - 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 <vapier@gentoo.org>, - fix from Andreas Schwab <schwab@linux-m68k.org> - -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 <wooledg@eeg.ccf.org> - - 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 <RKuhlmann@orga-systems.com> - - 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 <ormaaj@gmail.com> - -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 <ormaaj@gmail.com> - - 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 <ormaaj@gmail.com> - - 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 <backuppc-users@whitleymott.net> and - supplemented by Dan Douglas <ormaaj@gmail.com> - -doc/{bash.1,bashref.texi} - - changes to the description of substring expansion inspired by - suggestions from Bill Gradwohl <bill@ycc.com> - -doc/bashref.texi - - added substring expansion examples inspired by suggestions from - Bill Gradwohl <bill@ycc.com> - -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 <stddef.h>. Fix from - John E. Malmberg <wb8tyw@qsl.net> - - 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 - <levertond@googlemail.com> - - 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 - <scotty.mcmillan@gmail.com> - - 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" <dave_br@gmx.com> - - 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 <bash@tlinx.org> - -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 <schweikh@schweikhardt.net> - - 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 - <nshyrokovskiy@gmail.com> - - 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 <ormaaj@gmail.com> - - 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 <wb8tyw@qsl.net> - - 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 - <svdb@stack.nl>, fix from Andreas Schwab <schwab@linux-m68k.org> - - 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 <max@quendi.de> - - 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 <dennistwilliamson@gmail.com> - - 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 <dennistwilliamson@gmail.com>, fix from - Andreas Schwab <schwab@linux-m68k.org> - - 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 <rainer.blome@gmx.de> - -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 <pengyu.ut@gmail.com> - - 7/24 - ---- -configure.in - - interix: define RECYCLES_PIDS. Based on a report from Michael - Haubenwallner <michael.haubenwallner@salomon.at> - - 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 - <michael.haubenwallner@salomon.at> - -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 <michael.haubenwallner@salomon.at> - -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 - <michael.haubenwallner@salomon.at> - - 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 <lhunath@lyndir.com> - -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 - <lhunath@lyndir.com> - -{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 <sys/param.h> 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 <clark.wang@oracle.com> - - 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 - <dearvoid@gmail.com> - -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 <techlivezheng@gmail.com> - - 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 <ormaaj@gmail.com> - - 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 <armandsl@gmail.com> - -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 <vapier@gentoo.org> - - 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 <soltys@ziu.info> - -doc/bashref.texi - - some small formatting changes from Karl Berry <karl@freefriends.org> - - 8/27 - ---- -lib/readline/doc/{history,rlman,rluserman}.texi - - some small formatting changes from Karl Berry <karl@freefriends.org> - -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 <dennistwilliamson@gmail.com> - and Chris F. A. Johnson <chris@cfajohnson.com> - -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 <stefano.lattarini@gmail.com> - -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}<file - -redir.c - - redir_varassign: bind_var_to_int already handles array assignments, - so don't need to do anything more for things like {a[i]}<file - - redir_varvalue: changes to allow references to {a[i]} when - performing redirections using valid_array_reference and - get_array_value. Adds functionality requested most recently by - <unknown@vmw-les.eng.vmware.com> - -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 <mkoskar@gmail.com> and most recently by Jordan Michael - Ziegler <jziegler@bnl.gov> - -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 - <pierre.gaston@gmail.com> - - 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 <ormaaj@gmail.com> - - 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 <gerd.hofmann.nbg@googlemail.com> - -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 <vermaelen.wouter@gmail.com> - -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 <ormaaj@gmail.com> - - 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 <benoit.vaugon@gmail.com> - - 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 <rrakus@redhat.com> - -configure.ac - - HP NonStop (*-nsk*): compile --without-bash-malloc. Change from - Joachim Schmitz <jojo@schmitz-digital.de> - - 9/16 - ---- -subst.c,execute_cmd.c,lib/glob/sm_loop.c,lib/sh/shquote.c - - minor code cleanups from Joachim Schmitz <jojo@schmitz-digital.de> - -lib/readline/colors.h - - workaround for HP NonStop compiler issue with <stdbool.h> from - Joachim Schmitz <jojo@schmitz-digital.de> - - 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 <dualbus@gmail.com> - -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 <info@skeena.net> - - 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 <pclouds@gmail.com> - - 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 <hans1worst@gmail.com> - - 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 <baldiniebaldini@gmail.com> - - 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 <kaasen@nvg.ntnu.no> - - 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 - <zls.sogou@gmail.com> - -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 <zls.sogou@gmail.com> - - 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 <zls.sogou@gmail.com> - - 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 <nikolai.kondrashov@redhat.com> - -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 <zev@bewilderbeest.net> - - 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 <sgf.dma@gmail.com> - -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 <idfah@cs.colostate.edu> - -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 <idfah@cs.colostate.edu> - -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 <vmkari@cc.helsinki.fi> - -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 <sam@liddicott.com> - - 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 - <idfah@cs.colostate.edu> - -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 - <wb8tyw@qsl.net> - - 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 <me@timfriske.com> - -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 <me@timfriske.com> - - 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 <me@timfriske.com> - - 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 - <arvidjaar@gmail.com> - - 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 <ulfalizer@gmail.com> - - 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 <arvidjaar@gmail.com> - -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 <vapier@gentoo.org> - - 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 <raphael.droz@gmail.com> - - 12/13 - ----- -execute_cmd.c - - execute_coproc: handle the command's exit status being inverted - (an oversight). Fixes bug reported by DJ Mills - <danielmills1@gmail.com> and Andreas Schwab <schwab@linux-m68k.org> - - 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 - <pierre.muller@ics-cnrs.unistra.fr> - -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 <dearvoid@gmail.com> - -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 <vapier@gentoo.org> - -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 <Roman.Fiedler@ait.ac.at> - -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 <rschiele@gmail.com> - - 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 - <eggert@cs.ucla.edu> - - 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 <vituko@gmail.com>, 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 <wb8tyw@qsl.net> 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 - <raphael.droz@gmail.com> - - 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 <nagler@bivio.biz> - - 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<dualbus@gmail.com> and Dan Douglas <ormaaj@gmail.com> - -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 - <dualbus@gmail.com> - - 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 - <ormaaj@gmail.com> - - 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 - <ormaaj@gmail.com> - -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 <ormaaj@gmail.com> - - 1/15 - ---- -builtins/cd.def - - cd_builtin: make sure call to internal_getopt handles -e option. - Fixes bug reported by <mashimiao.fnst@cn.fujitsu.com> - - 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 <wq-doux@cn.fujitsu.com> - - 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 <ormaaj@gmail.com> [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 - <ormaaj@gmail.com> - -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 <rrakus@redhat.com> - - 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 - <konsolebox@gmail.com>; 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 - <ormaaj@gmail.com> - - 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 <egmont@gmail.com> - - 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 <vapier@gentoo.org> - - 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 <ormaaj@gmail.com> - -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 <vapier@gentoo.org> - -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 <ttrnka@mail.muni.cz> - - 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 <vapier@gentoo.org> - - 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" <dashing@hushmail.com> - - - 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 <bruce.korb@gmail.com> - - 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 <rich.tollerton@ni.com> - - 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 <p@draigbrady.com> 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 <egmont@gmail.com> - - 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 <stephane.chazelas@gmail.com> - - 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 <signal.h> 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 <gotmynick@gmail.com> - - 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 <info@skeena.net> - -[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 <mattdr@google.com> - - 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 - <jonathan.leffler@gmail.com> - - 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 <dualbus@gmail.com> - -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 - <ormaaj@gmail.com> - - 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 <watson_ian_a@lilly.com> - - 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 <schwab@linux-m68k.org> - -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 <ormaaj@gmail.com> - -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 <ormaaj@gmail.com> - - 4/13 - ---- -subst.c - - process_substitute: run the EXIT trap before exiting, as other - shells seem to. Fixes problem pointed out by Dan Douglas - <ormaaj@gmail.com> - -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 <watson_ian_a@lilly.com> - - 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 <schwab@linux-m68k.org> - -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 <rrakus@redhat.com> - - 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 <pengyu.ut@gmail.com> - -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 <jthomas@exosec.fr> - - 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 <flaviomotamedeiros@gmail.com> - - 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 <dan.mick@inktank.com> - -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 <ormaaj@gmail.com> - -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 <ormaaj@gmail.com> - - 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 <scx.mail@gmail.com> - - 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 - <gsliu.tju@gmail.com> - -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 <bash@tlinx.org> - -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 <jstcdr@gmail.com> - - 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 <mjackson220.list@gmail.com> - - 7/13 - ---- -doc/{bash.1,bashref.texi} - - slight change to add a description of `shopt -o' suggested by Bruce - Korb <bruce.korb@gmail.com> - - 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 <chris@chrisdown.name> - -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 <geir.hauge@gmail.com> - - 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 <geir.hauge@gmail.com> - - 8/3 - --- -Makefile.in - - pcomplete.o: add dependency on $(DEFDIR)/builtext.h. Suggested by - Curtis Doty <curtis@greenkey.net> - - 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 - <geir.hauge@gmail.com> - - 8/6 - --- -doc/{bash.1,bashref.texi},builtins/hash.def,lib/readline/doc/rluser.texi - - minor typo changes from Geir Hauge <geir.hauge@gmail.com> - -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 <geir.hauge@gmail.com> - - 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 <geir.hauge@gmail.com> - - 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 <micfied@gmail.com> - - 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 - <jdthood@gmail.com> - - 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 <schwab@linux-m68k.org> - -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 <stephane.chazelas@gmail.com> - -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 - <danielmills1@gmail.com> - -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 <mtmiller@ieee.org> - - 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 - <pierre.muller@ics-cnrs.unistra.fr> - - 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 <schwab@linux-m68k.org> - -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 - <cedric.blancher@gmail.com> - - 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 <bertsutherland@gmail.com> - -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 <yong.zhang@windriver.com> - -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 - <michael.haubenwallner@salomon.at> - -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 <qwertologe@googlemail.com> - - 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 - <joshhurst@gmail.com> - - 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 <admn.ombres@gmail.com> - - 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 <john.dawson@gmail.com> - -support/shobj-conf - - add support for Darwin 13 (Mac OS X 10.9, Mavericks). Based on a - report by Ludwig Schwardt <ludwig.schwardt@gmail.com> - - 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 - <nbah@sfr.fr> - - 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 <peter@cordes.ca> - - 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 <pankaj.s01@samsung.com> - - - 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 <mwesdorp@casema.nl> - - 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 <pierre.gaston@gmail.com> - - 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 - <pierre.gaston@gmail.com> - -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 <martin@kurahaupo.gen.nz> - - 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 <andrew.martin@gmail.com> - - 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 <ben@okopnik.com> - -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 - <jinesh@onelittlehope.com> - -Makefile.in - - install: make sure to use $(DESTDIR) when installing OTHER_DOCS. - Report and fix from Matthias Klose <doko@debian.org> - -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 <backuppc-users@whitleymott.net> - - 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 <parke.nexus@gmail.com> - -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 <prusselltechgroup@gmail.com> - - 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 <thkala@gmail.com> - - 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 <dualbus@gmail.com> - - 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 <bash@tlinx.org> - -Makefile.in - - variables.o: add dependency on builtins/builtext.h; helps with - parallel builds. Report from Linda Walsh <bash@tlinx.org> - -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 - <max@quendi.de> - - 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 <max@quendi.de> - - 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 <hiroo.hayashi@computer.org> - -general.c - - include trap.h for any_signals_trapped() prototype - -lib/sh/unicode.c - - include <stdio.h> 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 - <vapier@gentoo.org> - - 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 <chris@chrisdown.name> - - 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 <schwab@linux-m68k.org> - -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 <alexandru.damian@intel.com> - - 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 <jidanni@jidanni.org> - - 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 - <ilyushkeane@gmail.com> - - 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 <wooledg@eeg.ccf.org> - -[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 <dualbus@gmail.com> - - 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 <geir.hauge@gmail.com> - - 2/26 - ---- -[bash-4.3 released] - - 2/27 - ---- -aclocal.m4 - - broken wcwidth check: fix typo reported by David Michael - <fedora.dm0@gmail.com> - - 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 <moetunes42@gmail.com> - -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 <nbah@sfr.fr> - - 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 <dualbus@gmail.com> - - 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 <Albert.Shih@obspm.fr> - -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 <daan@flash.uchicago.edu> - -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 - <dave.gma@googlemail.com> - - 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 <felixonmars@gmail.com> 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 <anatol.pomozov@gmail.com> - - 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. <malsyned@malsyned.net> - -doc/bash.1 - - shell-kill-word and shell-backward-kill-word should be documented - as unbound by default. Report from Oliver Hartley - <ohartley@talktalk.net> - -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 <dualbus@gmail.com> - - 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 - <doug@cs.dartmouth.edu> - - 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 - <geir.hauge@gmail.com> - -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 - <stephane.chazelas@gmail.com> - - 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 <egmont@gmail.com> - - 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 <uwe@ibr.ch> - - 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 - <tataranovich@gmail.com> 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 <max@quendi.de> - - 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 - <dualbus@gmail.com> - - 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 <slovichon@gmail.com> - - {save,restore}_parser_state: save and restore need_here_doc flag. - Rest of fix for bug reported by Jared Yanovich <slovichon@gmail.com> - - 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 <wooledg@eeg.ccf.org> 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 - <g1pi@libero.it> 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 <Trond.Endrestol@ximalas.info> - - 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 - <dearvoid@gmail.com> - - 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 - <andre.holzhey@gmx.de> - - 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 <pierre.gaston@gmail.com> - - 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 <pierre.gaston@gmail.com> - -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 <pierre.gaston@gmail.com> - - 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 <pierre.gaston@gmail.com> - - 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 - <ormaaj@gmail.com> - - 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 - - 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 - <jeffrey.haemer@gmail.com> - -arrayfunc.c - - bind_array_var_internal: make sure ENTRY no longer has invisible - attribute before returning. Fixes bug reported by Geir Hauge - <geir.hauge@gmail.com> - - 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 <worley@alum.mit.edu> - - 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 <koenig@tat.physik.uni-tuebingen.de> - - - 6/16 - ---- -builtins/shopt.def - - compat42: make sure the `compat42' option sets the correct variable - for compatibility level. Fixes bug reported by Ondrej Oprala - <ooprala@redhat.com> - -support/bashbug.sh - - fix typo when echoing $USAGE. Report from Shantanu Kulkarni - <djbware@shantanukulkarni.org> - -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 <koenig@tat.physik.uni-tuebingen.de> - - 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 <me@timfriske.com> - -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 <scorp.dev.null@gmail.com> - -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 <ian@iankelling.org> - - 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 - <ian@iankelling.org> - -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 - <slovichon@gmail.com> - -subst.c - - command_substitute: other shells do not appear to inherit the -v - option when reading and executing command substitutions. Reported - by Ondrej Oprala <ooprala@redhat.com> - - 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 <gang.chen.5i5j@gmail.com> 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 <oliver.morais@gmail.com> - -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 - <prusselltechgroup@gmail.com> - - show_var_attributes: don't print assignment if array or assoc - attribute is set but variable marked as invisible diff --git a/CWRU/POSIX.NOTES.old b/CWRU/POSIX.NOTES.old deleted file mode 100644 index 1707ab10..00000000 --- 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 87b78d7c..00000000 --- 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 <stdio.h> -#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 998fd72b..00000000 --- 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/MANIFEST~ b/MANIFEST~ deleted file mode 100644 index 65e1ac8e..00000000 --- a/MANIFEST~ +++ /dev/null @@ -1,1290 +0,0 @@ -# -# Master distribution manifest for bash -# -# -# Filename type -# -CWRU d -CWRU/misc d -builtins d -cross-build d -doc d -examples d -#examples/obashdb d -examples/complete d -examples/functions d -examples/scripts d -#examples/scripts.v2 d -#examples/scripts.noah d -examples/startup-files d -#examples/startup-files/apple d -examples/misc d -examples/loadables d -examples/loadables/perl d -include d -lib d -lib/glob d -lib/glob/doc d -lib/intl d -lib/malloc d -lib/readline d -lib/readline/doc d -lib/readline/examples d -lib/sh d -lib/termcap d -lib/tilde d -m4 d -po d -support d -tests d -tests/misc d -ABOUT-NLS f -ChangeLog s CWRU/changelog -CHANGES f -COMPAT f -COPYING f -INSTALL f -MANIFEST f -NEWS f -NOTES f -POSIX f -README f -RBASH f -AUTHORS f -Y2K f -configure.ac f -configure f 755 -Makefile.in f -config-top.h f -config-bot.h f -config.h.in f -aclocal.m4 f -array.c f -arrayfunc.c f -assoc.c f -eval.c f -print_cmd.c f -general.c f -list.c f -locale.c f -stringlib.c f -variables.c f -make_cmd.c f -copy_cmd.c f -unwind_prot.c f -dispose_cmd.c f -bashhist.c f -hashcmd.c f -hashlib.c f -parse.y f -pathexp.c f -subst.c f -shell.c f -trap.c f -sig.c f -siglist.c f -version.c f -flags.c f -jobs.c f -input.c f -mailcheck.c f -test.c f -expr.c f -alias.c f -execute_cmd.c f -findcmd.c f -redir.c f -bashline.c f -braces.c f -bracecomp.c f -nojobs.c f -error.c f -xmalloc.c f -pcomplete.c f -pcomplib.c f -mksyntax.c f -alias.h f -builtins.h f -bashhist.h f -bashline.h f -conftypes.h f -patchlevel.h f -variables.h f -array.h f -arrayfunc.h f -assoc.h f -jobs.h f -findcmd.h f -hashlib.h f -quit.h f -flags.h f -shell.h f -syntax.h f -pathexp.h f -parser.h f -pcomplete.h f -sig.h f -test.h f -trap.h f -general.h f -unwind_prot.h f -input.h f -error.h f -command.h f -externs.h f -siglist.h f -subst.h f -dispose_cmd.h f -hashcmd.h f -bashansi.h f -bashjmp.h f -bashintl.h f -make_cmd.h f -execute_cmd.h f -redir.h f -bashtypes.h f -mailcheck.h f -xmalloc.h f -y.tab.c f -y.tab.h f -parser-built f -pathnames.h.in f -builtins/Makefile.in f -builtins/alias.def f -builtins/bind.def f -builtins/break.def f -builtins/builtin.def f -builtins/caller.def f -builtins/cd.def f -builtins/colon.def f -builtins/command.def f -builtins/complete.def f -builtins/common.c f -builtins/declare.def f -builtins/echo.def f -builtins/enable.def f -builtins/eval.def f -builtins/evalfile.c f -builtins/evalstring.c f -builtins/exec.def f -builtins/exit.def f -builtins/fc.def f -builtins/fg_bg.def f -builtins/gen-helpfiles.c f -builtins/getopt.c f -builtins/getopt.h f -builtins/getopts.def f -builtins/hash.def f -builtins/help.def f -builtins/let.def f -builtins/history.def f -builtins/jobs.def f -builtins/kill.def f -builtins/mapfile.def f -builtins/mkbuiltins.c f -builtins/printf.def f -builtins/pushd.def f -builtins/read.def f -builtins/reserved.def f -builtins/return.def f -builtins/set.def f -builtins/setattr.def f -builtins/shift.def f -builtins/shopt.def f -builtins/source.def f -builtins/suspend.def f -builtins/test.def f -builtins/times.def f -builtins/trap.def f -builtins/type.def f -builtins/ulimit.def f -builtins/umask.def f -builtins/wait.def f -builtins/psize.c f -builtins/psize.sh f -builtins/inlib.def f -builtins/bashgetopt.c f -builtins/common.h f -builtins/bashgetopt.h f -cross-build/cygwin32.cache f -cross-build/x86-beos.cache f -cross-build/opennt.cache f -include/ansi_stdlib.h f -include/chartypes.h f -include/filecntl.h f -include/gettext.h f -include/maxpath.h f -include/memalloc.h f -include/ocache.h f -include/posixdir.h f -include/posixjmp.h f -include/posixselect.h f -include/posixstat.h f -include/posixtime.h f -include/posixwait.h f -include/shmbchar.h f -include/shmbutil.h f -include/shtty.h f -include/stat-time.h f -include/stdc.h f -include/systimes.h f -include/typemax.h f -include/unionwait.h f -lib/glob/Makefile.in f -lib/glob/sm_loop.c f -lib/glob/smatch.c f -lib/glob/strmatch.c f -lib/glob/strmatch.h f -lib/glob/glob.c f -lib/glob/glob.h f -lib/glob/glob_loop.c f -lib/glob/gmisc.c f -lib/glob/xmbsrtowcs.c f -lib/glob/collsyms.h f -lib/glob/doc/Makefile f -lib/glob/doc/glob.texi f -lib/glob/ndir.h f -lib/intl/ChangeLog f -lib/intl/Makefile.in f -lib/intl/VERSION f -lib/intl/bindtextdom.c f -lib/intl/config.charset f -lib/intl/dcgettext.c f -lib/intl/dcigettext.c f -lib/intl/dcngettext.c f -lib/intl/dgettext.c f -lib/intl/dngettext.c f -lib/intl/eval-plural.h f -lib/intl/explodename.c f -lib/intl/finddomain.c f -lib/intl/gettext.c f -lib/intl/gettextP.h f -lib/intl/gmo.h f -lib/intl/hash-string.h f -lib/intl/intl-compat.c f -lib/intl/l10nflist.c f -lib/intl/libgnuintl.h.in f -lib/intl/loadinfo.h f -lib/intl/loadmsgcat.c f -lib/intl/localcharset.c f -lib/intl/localcharset.h f -lib/intl/locale.alias f -lib/intl/localealias.c f -lib/intl/localename.c f -lib/intl/log.c f -lib/intl/ngettext.c f -lib/intl/os2compat.c f -lib/intl/os2compat.h f -lib/intl/osdep.c f -lib/intl/plural-exp.c f -lib/intl/plural-exp.h f -lib/intl/plural.c f -lib/intl/plural.y f -lib/intl/ref-add.sin f -lib/intl/ref-del.sin f -lib/intl/relocatable.c f -lib/intl/relocatable.h f -lib/intl/textdomain.c f -lib/malloc/Makefile.in f -lib/malloc/getpagesize.h f -lib/malloc/imalloc.h f -lib/malloc/mstats.h f -lib/malloc/shmalloc.h f -lib/malloc/table.h f -lib/malloc/watch.h f -lib/malloc/alloca.c f -lib/malloc/malloc.c f -lib/malloc/stats.c f -lib/malloc/table.c f -lib/malloc/trace.c f -lib/malloc/watch.c f -lib/malloc/xmalloc.c f -lib/malloc/xleaktrace f 755 -lib/malloc/stub.c f -lib/malloc/i386-alloca.s f -lib/malloc/x386-alloca.s f -lib/readline/COPYING f -lib/readline/Makefile.in f -lib/readline/ChangeLog f -lib/readline/README f -lib/readline/STANDALONE f -lib/readline/readline.c f -lib/readline/vi_mode.c f -lib/readline/emacs_keymap.c f -lib/readline/vi_keymap.c f -lib/readline/history.c f -lib/readline/histexpand.c f -lib/readline/histsearch.c f -lib/readline/histfile.c f -lib/readline/funmap.c f -lib/readline/keymaps.c f -lib/readline/util.c f -lib/readline/terminal.c f -lib/readline/xfree.c f -lib/readline/xmalloc.c f -lib/readline/search.c f -lib/readline/isearch.c f -lib/readline/parens.c f -lib/readline/rltty.c f -lib/readline/compat.c f -lib/readline/complete.c f -lib/readline/bind.c f -lib/readline/display.c f -lib/readline/signals.c f -lib/readline/kill.c f -lib/readline/text.c f -lib/readline/undo.c f -lib/readline/macro.c f -lib/readline/input.c f -lib/readline/callback.c f -lib/readline/mbutil.c f -lib/readline/misc.c f -lib/readline/nls.c f -lib/readline/shell.c f -lib/readline/colors.c f -lib/readline/parse-colors.c f -lib/readline/savestring.c f -lib/readline/tilde.c f -lib/readline/tilde.h f -lib/readline/rldefs.h f -lib/readline/rlconf.h f -lib/readline/rlmbutil.h f -lib/readline/rlshell.h f -lib/readline/rltty.h f -lib/readline/rltypedefs.h f -lib/readline/rlwinsize.h f -lib/readline/readline.h f -lib/readline/tcap.h f -lib/readline/keymaps.h f -lib/readline/history.h f -lib/readline/histlib.h f -lib/readline/chardefs.h f -lib/readline/posixdir.h f -lib/readline/posixjmp.h f -lib/readline/posixselect.h f -lib/readline/posixstat.h f -lib/readline/ansi_stdlib.h f -lib/readline/rlstdc.h f -lib/readline/rlprivate.h f -lib/readline/colors.h f -lib/readline/parse-colors.h f -lib/readline/xmalloc.h f -lib/readline/doc/Makefile f -lib/readline/doc/version.texi f -lib/readline/doc/rlman.texi f -lib/readline/doc/rltech.texi f -lib/readline/doc/rluser.texi f -lib/readline/doc/rluserman.texi f -lib/readline/doc/history.texi f -lib/readline/doc/hstech.texi f -lib/readline/doc/hsuser.texi f -lib/readline/doc/fdl.texi f -lib/readline/examples/Makefile f -lib/readline/examples/excallback.c f -lib/readline/examples/fileman.c f -lib/readline/examples/manexamp.c f -lib/readline/examples/histexamp.c f -lib/readline/examples/rltest.c f -lib/readline/examples/rl-callbacktest.c f -lib/readline/examples/rl.c f -lib/readline/examples/rlcat.c f -lib/readline/examples/Inputrc f -lib/sh/Makefile.in f -lib/sh/casemod.c f -lib/sh/clktck.c f -lib/sh/clock.c f -lib/sh/dprintf.c f -lib/sh/eaccess.c f -lib/sh/fmtullong.c f -lib/sh/fmtulong.c f -lib/sh/fmtumax.c f -lib/sh/fnxform.c f -lib/sh/fpurge.c f -lib/sh/getcwd.c f -lib/sh/getenv.c f -lib/sh/inet_aton.c f -lib/sh/input_avail.c f -lib/sh/itos.c f -lib/sh/mailstat.c f -lib/sh/makepath.c f -lib/sh/mbscasecmp.c f -lib/sh/mbschr.c f -lib/sh/mbscmp.c f -lib/sh/memset.c f -lib/sh/mktime.c f -lib/sh/netconn.c f -lib/sh/netopen.c f -lib/sh/oslib.c f -lib/sh/pathcanon.c f -lib/sh/pathphys.c f -lib/sh/rename.c f -lib/sh/setlinebuf.c f -lib/sh/shmatch.c f -lib/sh/shmbchar.c f -lib/sh/shquote.c f -lib/sh/shtty.c f -lib/sh/snprintf.c f -lib/sh/spell.c f -lib/sh/strcasecmp.c f -lib/sh/strcasestr.c f -lib/sh/strchrnul.c f -lib/sh/strdup.c f -lib/sh/strerror.c f -lib/sh/strftime.c f -lib/sh/stringlist.c f -lib/sh/stringvec.c f -lib/sh/strnlen.c f -lib/sh/strpbrk.c f -lib/sh/strstr.c f -lib/sh/strtod.c f -lib/sh/strtoimax.c f -lib/sh/strtol.c f -lib/sh/strtoll.c f -lib/sh/strtoul.c f -lib/sh/strtoull.c f -lib/sh/strtoumax.c f -lib/sh/strtrans.c f -lib/sh/times.c f -lib/sh/timeval.c f -lib/sh/tmpfile.c f -lib/sh/uconvert.c f -lib/sh/ufuncs.c f -lib/sh/unicode.c f -lib/sh/vprint.c f -lib/sh/wcsdup.c f -lib/sh/wcsnwidth.c f -lib/sh/wcswidth.c f -lib/sh/winsize.c f -lib/sh/zcatfd.c f -lib/sh/zgetline.c f -lib/sh/zmapfd.c f -lib/sh/zread.c f -lib/sh/zwrite.c f -lib/termcap/Makefile.in f -lib/termcap/ltcap.h f -lib/termcap/termcap.c f -lib/termcap/termcap.h f -lib/termcap/tparam.c f -lib/termcap/version.c f -lib/tilde/README f -lib/tilde/Makefile.in f -lib/tilde/tilde.c f -lib/tilde/tilde.h f -lib/tilde/shell.c f -m4/stat-time.m4 f -m4/timespec.m4 f -po/LINGUAS f -po/Makefile.in.in f -po/Makevars f -po/POTFILES.in f -po/README f -po/Rules-builtins f -po/Rules-quot f -po/bash.pot f -po/boldquot.sed f -po/en@boldquot.gmo f -po/en@boldquot.header f -po/en@boldquot.po f -po/en@quot.gmo f -po/en@quot.header f -po/en@quot.po f -po/af.gmo f -po/af.po f -po/bg.gmo f -po/bg.po f -po/ca.gmo f -po/ca.po f -po/cs.gmo f -po/cs.po f -po/da.gmo f -po/da.po f -po/de.gmo f -po/de.po f -po/el.gmo f -po/el.po f -po/eo.gmo f -po/eo.po f -po/es.gmo f -po/es.po f -po/et.gmo f -po/et.po f -po/fi.gmo f -po/fi.po f -po/fr.gmo f -po/fr.po f -po/ga.gmo f -po/ga.po f -po/gl.gmo f -po/gl.po f -po/hr.gmo f -po/hr.po f -po/hu.gmo f -po/hu.po f -po/id.gmo f -po/id.po f -po/it.gmo f -po/it.po f -po/ja.gmo f -po/ja.po f -po/lt.gmo f -po/lt.po f -po/nl.gmo f -po/nl.po f -po/pl.gmo f -po/pl.po f -po/pt_BR.gmo f -po/pt_BR.po f -po/ro.gmo f -po/ro.po f -po/ru.gmo f -po/ru.po f -po/sk.gmo f -po/sk.po f -po/sl.gmo f -po/sr.po f -po/sr.gmo f -po/sl.po f -po/sv.gmo f -po/sv.po f -po/tr.gmo f -po/tr.po f -po/uk.gmo f -po/uk.po f -po/vi.gmo f -po/vi.po f -po/zh_CN.gmo f -po/zh_CN.po f -po/zh_TW.gmo f -po/zh_TW.po f -po/insert-header.sin f -po/quot.sed f -po/remove-potcdate.sin f -CWRU/misc/open-files.c f -CWRU/misc/sigs.c f -CWRU/misc/sigstat.c f -CWRU/misc/bison f -CWRU/misc/errlist.c f -CWRU/misc/hpux10-dlfcn.h f -CWRU/PLATFORMS f -CWRU/README f -CWRU/changelog f -CWRU/sh-redir-hack f -doc/FAQ f -doc/Makefile.in f -doc/bash.1 f -doc/bashbug.1 f -doc/builtins.1 f -doc/rbash.1 f -doc/README f -doc/INTRO f -doc/texinfo.tex f -doc/bashref.texi f -doc/version.texi f -doc/bashref.info f -doc/article.ms f -doc/htmlpost.sh f 755 -doc/infopost.sh f 755 -doc/fdl.texi f -doc/fdl.txt f -# -doc/article.ps f -doc/rose94.ps f -doc/bash.ps f -doc/bashbug.ps f -doc/builtins.ps f -doc/rbash.ps f -doc/bashref.ps f -doc/bashref.dvi f -doc/bash.0 f -doc/bashbug.0 f -doc/builtins.0 f -doc/rbash.0 f -doc/article.txt f -doc/bash.html f -doc/bashref.html f -doc/article.pdf f -doc/bash.pdf f -doc/bashref.pdf f -doc/rose94.pdf f -doc/aosa-bash.pdf f -# -support/Makefile.in f -support/bashversion.c f -support/checkbashisms f 755 -support/config.guess f -support/config.rpath f 755 -support/config.sub f -support/printenv.sh f 755 -support/printenv.c f -support/bash.xbm f -support/missing f 755 -support/mkclone f 755 -support/mkconffiles f 755 -support/mkdirs f 755 -support/mkinstalldirs f 755 -support/mkversion.sh f 755 -support/mksignames.c f -support/signames.c f -support/bashbug.sh f -support/man2html.c f -support/recho.c f -support/zecho.c f -support/xcase.c f -support/SYMLINKS f -support/fixlinks f 755 -support/install.sh f 755 -support/texi2dvi f 755 -support/texi2html f 755 -support/xenix-link.sh f 755 -support/shobj-conf f 755 -support/rlvers.sh f 755 -examples/INDEX.txt f -examples/INDEX.html f -#examples/obashdb/PERMISSION f -#examples/obashdb/README f -#examples/obashdb/bashdb f -#examples/obashdb/bashdb.el f -examples/complete/bash_completion f -examples/complete/cdfunc f -examples/complete/complete-examples f -#examples/complete/complete.ianmac f -#examples/complete/complete2.ianmac f -#examples/complete/complete.freebsd f -#examples/complete/complete.gnu-longopt f -examples/complete/bashcc-1.0.1.tar.gz f -examples/loadables/README f -examples/loadables/template.c f -examples/loadables/Makefile.in f -examples/loadables/necho.c f -examples/loadables/hello.c f -examples/loadables/print.c f -examples/loadables/realpath.c f -examples/loadables/sleep.c f -examples/loadables/strftime.c f -examples/loadables/truefalse.c f -#examples/loadables/getconf.h f -#examples/loadables/getconf.c f -examples/loadables/finfo.c f -examples/loadables/cat.c f -#examples/loadables/cut.c f -examples/loadables/logname.c f -examples/loadables/basename.c f -examples/loadables/dirname.c f -examples/loadables/tty.c f -examples/loadables/pathchk.c f -examples/loadables/tee.c f -examples/loadables/rmdir.c f -examples/loadables/head.c f -examples/loadables/printenv.c f -examples/loadables/push.c f -examples/loadables/id.c f -examples/loadables/whoami.c f -examples/loadables/uname.c f -examples/loadables/sync.c f -examples/loadables/mkdir.c f -examples/loadables/ln.c f -examples/loadables/mypid.c f -examples/loadables/unlink.c f -examples/loadables/perl/Makefile.in f -examples/loadables/perl/README f -examples/loadables/perl/bperl.c f -examples/loadables/perl/iperl.c f -#examples/loadables/sprintf.c f -#examples/loadables/xtitle.c f -examples/functions/array-stuff f -examples/functions/array-to-string f -examples/functions/autoload f -examples/functions/autoload.v2 f -examples/functions/autoload.v3 f -examples/functions/basename f -#examples/functions/basename2 f -#examples/functions/coproc.bash f -#examples/functions/coshell.README f -#examples/functions/coshell.bash f -examples/functions/csh-compat f -#examples/functions/dirfuncs f -examples/functions/dirname f -examples/functions/dirstack f -#examples/functions/emptydir f -examples/functions/exitstat f -examples/functions/external f -examples/functions/fact f -examples/functions/fstty f -examples/functions/func f -#examples/functions/gethtml f -#examples/functions/getoptx.bash f -examples/functions/inetaddr f -examples/functions/inpath f -#examples/functions/isnum.bash f -examples/functions/isnum2 f -examples/functions/isvalidip f -#examples/functions/jdate.bash f -#examples/functions/jj.bash f -#examples/functions/keep f -examples/functions/ksh-cd f -examples/functions/ksh-compat-test f -examples/functions/kshenv f -examples/functions/login f -#examples/functions/lowercase f -#examples/functions/manpage f -#examples/functions/mhfold f -#examples/functions/newdirstack.bsh f -examples/functions/notify.bash f -#examples/functions/pathfuncs f -#examples/functions/recurse f -#examples/functions/repeat2 f -#examples/functions/repeat3 f -examples/functions/seq f -examples/functions/seq2 f -examples/functions/shcat f -examples/functions/shcat2 f -examples/functions/sort-pos-params f -#examples/functions/sqroot f -examples/functions/substr f -examples/functions/substr2 f -#examples/functions/term f -examples/functions/whatis f -examples/functions/whence f -examples/functions/which f -#examples/functions/xalias.bash f -#examples/functions/xfind.bash f -#examples/scripts/adventure.sh f -#examples/scripts/bash-hexdump.sh f -#examples/scripts/bcsh.sh f -examples/scripts/cat.sh f -examples/scripts/center f -#examples/scripts/dd-ex.sh f -#examples/scripts/fixfiles.bash f -#examples/scripts/hanoi.bash f -examples/scripts/inpath f -#examples/scripts/krand.bash f -#examples/scripts/line-input.bash f -#examples/scripts/nohup.bash f -#examples/scripts/precedence f -#examples/scripts/randomcard.bash f -#examples/scripts/scrollbar f -#examples/scripts/scrollbar2 f -#examples/scripts/self-repro f -#examples/scripts/showperm.bash f -examples/scripts/shprompt f -examples/scripts/spin.bash f -#examples/scripts/timeout f -#examples/scripts/timeout2 f -#examples/scripts/timeout3 f -#examples/scripts/vtree2 f -#examples/scripts/vtree3 f -#examples/scripts/vtree3a f -#examples/scripts/websrv.sh f -examples/scripts/xterm_title f -examples/scripts/zprintf f -examples/startup-files/README f -examples/startup-files/Bashrc.bfox f -examples/startup-files/Bash_aliases f -examples/startup-files/Bash_profile f -examples/startup-files/bash-profile f -examples/startup-files/bashrc f -#examples/startup-files/apple/README f -#examples/startup-files/apple/aliases f -#examples/startup-files/apple/bash.defaults f -#examples/startup-files/apple/environment f -#examples/startup-files/apple/login f -#examples/startup-files/apple/logout f -#examples/startup-files/apple/rc f -#examples/misc/suncmd.termcap f -examples/misc/aliasconv.sh f -examples/misc/aliasconv.bash f -examples/misc/cshtobash f -tests/README f -tests/COPYRIGHT f -tests/alias.tests f -tests/alias1.sub f -tests/alias.right f -tests/appendop.tests f -tests/appendop1.sub f -tests/appendop2.sub f -tests/appendop.right f -tests/arith-for.tests f -tests/arith-for.right f -tests/arith.tests f -tests/arith.right f -tests/arith1.sub f -tests/arith2.sub f -tests/arith3.sub f -tests/arith4.sub f -tests/arith5.sub f -tests/arith6.sub f -tests/array.tests f -tests/array.right f -tests/array1.sub f -tests/array2.sub f -tests/array3.sub f -tests/array4.sub f -tests/array5.sub f -tests/array6.sub f -tests/array7.sub f -tests/array8.sub f -tests/array9.sub f -tests/array10.sub f -tests/array11.sub f -tests/array12.sub f -tests/array13.sub f -tests/array14.sub f -tests/array15.sub f -tests/array16.sub f -tests/array-at-star f -tests/array2.right f -tests/assoc.tests f -tests/assoc.right f -tests/assoc1.sub f -tests/assoc2.sub f -tests/assoc3.sub f -tests/assoc4.sub f -tests/assoc5.sub f -tests/assoc6.sub f -tests/assoc7.sub f -tests/braces.tests f -tests/braces.right f -tests/builtins.tests f -tests/builtins.right f -tests/builtins1.sub f -tests/builtins2.sub f -tests/builtins3.sub f -tests/builtins4.sub f -tests/source1.sub f -tests/source2.sub f -tests/source3.sub f -tests/source4.sub f -tests/source5.sub f -tests/source6.sub f -tests/source7.sub f -tests/case.tests f -tests/case.right f -tests/case1.sub f -tests/casemod.tests f -tests/casemod.right f -tests/comsub.tests f -tests/comsub.right f -tests/comsub1.sub f -tests/comsub-eof.tests f -tests/comsub-eof0.sub f -tests/comsub-eof1.sub f -tests/comsub-eof2.sub f -tests/comsub-eof3.sub f -tests/comsub-eof4.sub f -tests/comsub-eof5.sub f -tests/comsub-eof.right f -tests/comsub-posix.tests f -tests/comsub-posix.right f -tests/comsub-posix1.sub f -tests/comsub-posix2.sub f -tests/comsub-posix3.sub f -tests/cond.tests f -tests/cond.right f -tests/cond-regexp1.sub f -tests/cond-regexp2.sub f -tests/cond-regexp3.sub f -tests/coproc.tests f -tests/coproc.right f -tests/cprint.tests f -tests/cprint.right f -tests/dbg-support.right f -tests/dbg-support.sub f -tests/dbg-support.tests f -tests/dbg-support2.right f -tests/dbg-support2.tests f -tests/dbg-support3.sub f -tests/dollar-at-star f -tests/dollar-at-star1.sub f -tests/dollar-at-star2.sub f -tests/dollar-at1.sub f -tests/dollar-at2.sub f -tests/dollar-at3.sub f -tests/dollar-at4.sub f -tests/dollar-at5.sub f -tests/dollar-at6.sub f -tests/dollar-star1.sub f -tests/dollar-star2.sub f -tests/dollar-star3.sub f -tests/dollar-star4.sub f -tests/dollar-star5.sub f -tests/dollar-star6.sub f -tests/dollar-star7.sub f -tests/dollar.right f -tests/dstack.tests f -tests/dstack.right f -tests/dstack2.tests f -tests/dstack2.right f -tests/errors.tests f -tests/errors.right f -tests/errors1.sub f -tests/errors2.sub f -tests/errors3.sub f -tests/execscript f -tests/exec.right f -tests/exec1.sub f 755 -tests/exec2.sub f -tests/exec3.sub f -tests/exec4.sub f -tests/exec5.sub f -tests/exec6.sub f -tests/exec7.sub f -tests/exec8.sub f -tests/exec9.sub f -tests/exp.tests f -tests/exp.right f -tests/exp1.sub f -tests/exp2.sub f -tests/exp3.sub f -tests/exp4.sub f -tests/exp5.sub f -tests/exp6.sub f -tests/extglob.tests f -tests/extglob.right f -tests/extglob1.sub f -tests/extglob1a.sub f -tests/extglob3.sub f -tests/extglob2.tests f -tests/extglob2.right f -tests/extglob3.tests f -tests/extglob3.right f -tests/func.tests f -tests/func.right f -tests/func1.sub f -tests/func2.sub f -tests/func3.sub f -tests/func4.sub f -tests/getopts.tests f -tests/getopts.right f -tests/getopts1.sub f -tests/getopts2.sub f -tests/getopts3.sub f -tests/getopts4.sub f -tests/getopts5.sub f -tests/getopts6.sub f -tests/getopts7.sub f -tests/glob.tests f -tests/glob1.sub f -tests/glob.right f -tests/globstar.tests f -tests/globstar.right f -tests/globstar1.sub f -tests/globstar2.sub f -tests/heredoc.tests f -tests/heredoc.right f -tests/heredoc1.sub f -tests/heredoc2.sub f -tests/heredoc3.sub f -tests/herestr.tests f -tests/herestr.right f -tests/histexp.tests f -tests/histexp.right f -tests/history.tests f -tests/history.right f -tests/history.list f 444 -tests/history1.sub f -tests/history2.sub f -tests/ifs.tests f -tests/ifs.right f -tests/ifs-posix.tests f -tests/ifs-posix.right f -tests/input-line.sh f -tests/input-line.sub f -tests/input.right f -tests/intl.tests f -tests/intl1.sub f -tests/intl2.sub f -tests/intl.right f -tests/iquote.tests f -tests/iquote.right f -tests/iquote1.sub f -tests/invert.tests f -tests/invert.right f -tests/jobs.tests f -tests/jobs1.sub f -tests/jobs2.sub f -tests/jobs3.sub f -tests/jobs4.sub f -tests/jobs5.sub f -tests/jobs.right f -tests/lastpipe.right f -tests/lastpipe.tests f -tests/lastpipe1.sub f -tests/mapfile.data f -tests/mapfile.right f -tests/mapfile.tests f -tests/mapfile1.sub f -tests/more-exp.tests f -tests/more-exp.right f -tests/nameref.tests f -tests/nameref1.sub f -tests/nameref2.sub f -tests/nameref3.sub f -tests/nameref4.sub f -tests/nameref5.sub f -tests/nameref6.sub f -tests/nameref7.sub f -tests/nameref8.sub f -tests/nameref.right f -tests/new-exp.tests f -tests/new-exp1.sub f -tests/new-exp2.sub f -tests/new-exp3.sub f -tests/new-exp4.sub f -tests/new-exp5.sub f -tests/new-exp6.sub f -tests/new-exp7.sub f -tests/new-exp8.sub f -tests/new-exp9.sub f -tests/new-exp.right f -tests/nquote.tests f -tests/nquote.right f -tests/nquote1.sub f -tests/nquote2.sub f -tests/nquote1.tests f -tests/nquote1.right f -tests/nquote2.tests f -tests/nquote2.right f -tests/nquote3.tests f -tests/nquote3.right f -tests/nquote4.tests f -tests/nquote4.right f -tests/nquote5.tests f -tests/nquote5.right f -tests/posix2.tests f -tests/posix2.right f -tests/posixexp.tests f -tests/posixexp.right f -tests/posixexp1.sub f -tests/posixexp2.sub f -tests/posixexp2.tests f -tests/posixexp2.right f -tests/posixpat.tests f -tests/posixpat.right f -tests/posixpipe.tests f -tests/posixpipe.right f -tests/prec.right f -tests/precedence f -tests/printf.tests f -tests/printf.right f -tests/printf1.sub f -tests/printf2.sub f -tests/printf3.sub f -tests/printf4.sub f -tests/quote.tests f -tests/quote.right f -tests/quote1.sub f -tests/read.tests f -tests/read.right f -tests/read1.sub f -tests/read2.sub f -tests/read3.sub f -tests/read4.sub f -tests/read5.sub f -tests/read6.sub f -tests/redir.tests f -tests/redir.right f -tests/redir1.sub f -tests/redir2.sub f -tests/redir3.sub f -tests/redir3.in1 f -tests/redir3.in2 f -tests/redir4.sub f -tests/redir4.in1 f -tests/redir5.sub f -tests/redir6.sub f -tests/redir7.sub f -tests/redir8.sub f -tests/redir9.sub f -tests/redir10.sub f -tests/rhs-exp.tests f -tests/rhs-exp.right f -tests/rhs-exp1.sub f -tests/rsh.tests f -tests/rsh.right f -tests/run-all f -tests/run-minimal f -tests/run-alias f -tests/run-appendop f -tests/run-arith-for f -tests/run-arith f -tests/run-array f -tests/run-array2 f -tests/run-assoc f -tests/run-braces f -tests/run-builtins f -tests/run-case f -tests/run-casemod f -tests/run-comsub f -tests/run-comsub-eof f -tests/run-comsub-posix f -tests/run-cond f -tests/run-coproc f -tests/run-cprint f -tests/run-dbg-support f -tests/run-dbg-support2 f -tests/run-dirstack f -tests/run-dollars f -tests/run-errors f -tests/run-execscript f -tests/run-exp-tests f -tests/run-extglob f -tests/run-extglob2 f -tests/run-extglob3 f -tests/run-func f -tests/run-getopts f -tests/run-glob-test f -tests/run-globstar f -tests/run-heredoc f -tests/run-herestr f -tests/run-histexpand f -tests/run-history f -tests/run-ifs f -tests/run-ifs-posix f -tests/run-input-test f -tests/run-intl f -tests/run-iquote f -tests/run-invert f -tests/run-jobs f -tests/run-lastpipe f -tests/run-mapfile f -tests/run-more-exp f -tests/run-nameref f -tests/run-new-exp f -tests/run-nquote f -tests/run-nquote1 f -tests/run-nquote2 f -tests/run-nquote3 f -tests/run-nquote4 f -tests/run-nquote5 f -tests/run-posix2 f -tests/run-posixexp f -tests/run-posixexp2 f -tests/run-posixpat f -tests/run-posixpipe f -tests/run-precedence f -tests/run-printf f -tests/run-quote f -tests/run-read f -tests/run-redir f -tests/run-rhs-exp f -tests/run-rsh f -tests/run-set-e f -tests/run-set-x f -tests/run-shopt f -tests/run-strip f -tests/run-test f -tests/run-tilde f -tests/run-tilde2 f -tests/run-trap f -tests/run-type f -tests/run-varenv f -tests/run-vredir f -tests/set-e.tests f -tests/set-e1.sub f -tests/set-e2.sub f -tests/set-e3.sub f -tests/set-e3a.sub f -tests/set-e.right f -tests/set-x.tests f -tests/set-x1.sub f -tests/set-x.right f -tests/shopt.tests f -tests/shopt.right f -tests/strip.tests f -tests/strip.right f -tests/test.tests f -tests/test.right f -tests/tilde.tests f -tests/tilde.right f -tests/tilde2.tests f -tests/tilde2.right f -tests/trap.tests f -tests/trap.right f -tests/trap1.sub f 755 -tests/trap2.sub f 755 -tests/trap2a.sub f 755 -tests/trap3.sub f -tests/trap4.sub f -tests/trap5.sub f -tests/type.tests f -tests/type.right f -tests/type1.sub f -tests/type2.sub f -tests/type3.sub f -tests/type4.sub f -tests/unicode1.sub f -tests/unicode2.sub f -tests/unicode3.sub f -tests/varenv.right f -tests/varenv.sh f -tests/varenv1.sub f -tests/varenv2.sub f -tests/varenv3.sub f -tests/varenv4.sub f -tests/varenv5.sub f -tests/varenv6.sub f -tests/version f -tests/version.mini f -tests/vredir.tests f -tests/vredir.right f -tests/vredir1.sub f -tests/vredir2.sub f -tests/vredir3.sub f -tests/vredir4.sub f -tests/vredir5.sub f -tests/vredir6.sub f -tests/misc/dev-tcp.tests f -tests/misc/perf-script f -tests/misc/perftest f -tests/misc/read-nchars.tests f -tests/misc/redir-t2.sh f -tests/misc/run-r2.sh f -tests/misc/sigint-1.sh f -tests/misc/sigint-2.sh f -tests/misc/sigint-3.sh f -tests/misc/sigint-4.sh f -tests/misc/test-minus-e.1 f -tests/misc/test-minus-e.2 f -tests/misc/wait-bg.tests f -#examples/scripts.v2/PERMISSION f -#examples/scripts.v2/README f -#examples/scripts.v2/arc2tarz f -#examples/scripts.v2/bashrand f -#examples/scripts.v2/cal2day.bash f -#examples/scripts.v2/cdhist.bash f -#examples/scripts.v2/corename f -#examples/scripts.v2/fman f -#examples/scripts.v2/frcp f -#examples/scripts.v2/lowercase f -#examples/scripts.v2/ncp f -#examples/scripts.v2/newext f -#examples/scripts.v2/nmv f -#examples/scripts.v2/pages f -#examples/scripts.v2/pf f -#examples/scripts.v2/ren f -#examples/scripts.v2/rename f -#examples/scripts.v2/repeat f -#examples/scripts.v2/untar f -#examples/scripts.v2/uudec f -#examples/scripts.v2/uuenc f -#examples/scripts.v2/vtree f -#examples/scripts.v2/where f -#examples/scripts.v2/pmtop f -#examples/scripts.v2/shprof f -#examples/scripts.noah/PERMISSION f -#examples/scripts.noah/README f -#examples/scripts.noah/aref.bash f -#examples/scripts.noah/bash.sub.bash f -#examples/scripts.noah/bash_version.bash f -#examples/scripts.noah/meta.bash f -#examples/scripts.noah/mktmp.bash f -#examples/scripts.noah/number.bash f -#examples/scripts.noah/prompt.bash f -#examples/scripts.noah/remap_keys.bash f -#examples/scripts.noah/require.bash f -#examples/scripts.noah/send_mail.bash f -#examples/scripts.noah/shcat.bash f -#examples/scripts.noah/source.bash f -#examples/scripts.noah/string.bash f -#examples/scripts.noah/stty.bash f -#examples/scripts.noah/y_or_n_p.bash f diff --git a/builtins/mapfile.def~ b/builtins/mapfile.def~ deleted file mode 100644 index 7c980bc9..00000000 --- a/builtins/mapfile.def~ +++ /dev/null @@ -1,368 +0,0 @@ -This file is mapfile.def, from which is created mapfile.c. -It implements the builtin "mapfile" in Bash. - -Copyright (C) 2005-2006 Rocky Bernstein for Free Software Foundation, Inc. -Copyright (C) 2008-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 <http://www.gnu.org/licenses/>. - -$PRODUCES mapfile.c - -$BUILTIN mapfile -$FUNCTION mapfile_builtin -$SHORT_DOC mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array] -Read lines from the standard input into an indexed array variable. - -Read lines from the standard input into the indexed array variable ARRAY, or -from file descriptor FD if the -u option is supplied. The variable MAPFILE -is the default ARRAY. - -Options: - -n count Copy at most COUNT lines. If COUNT is 0, all lines are copied. - -O origin Begin assigning to ARRAY at index ORIGIN. The default index is 0. - -s count Discard the first COUNT lines read. - -t Remove a trailing newline from each line read. - -u fd Read lines from file descriptor FD instead of the standard input. - -C callback Evaluate CALLBACK each time QUANTUM lines are read. - -c quantum Specify the number of lines read between each call to CALLBACK. - -Arguments: - ARRAY Array variable name to use for file data. - -If -C is supplied without -c, the default quantum is 5000. When -CALLBACK is evaluated, it is supplied the index of the next array -element to be assigned and the line to be assigned to that element -as additional arguments. - -If not supplied with an explicit origin, mapfile will clear ARRAY before -assigning to it. - -Exit Status: -Returns success unless an invalid option is given or ARRAY is readonly or -not an indexed array. -$END - -$BUILTIN readarray -$FUNCTION mapfile_builtin -$SHORT_DOC readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array] -Read lines from a file into an array variable. - -A synonym for `mapfile'. -$END - -#include <config.h> - -#include "builtins.h" -#include "posixstat.h" - -#if defined (HAVE_UNISTD_H) -# include <unistd.h> -#endif - -#include "bashansi.h" -#include "bashintl.h" - -#include <stdio.h> -#include <errno.h> - -#include "../bashintl.h" -#include "../shell.h" -#include "common.h" -#include "bashgetopt.h" - -#if !defined (errno) -extern int errno; -#endif - -#if defined (ARRAY_VARS) - -static int run_callback __P((const char *, unsigned int, const char *)); - -#define DEFAULT_ARRAY_NAME "MAPFILE" -#define DEFAULT_VARIABLE_NAME "MAPLINE" /* not used right now */ - -/* The value specifying how frequently `mapfile' calls the callback. */ -#define DEFAULT_QUANTUM 5000 - -/* Values for FLAGS */ -#define MAPF_CLEARARRAY 0x01 -#define MAPF_CHOP 0x02 - -static int delim; - -static int -run_callback (callback, curindex, curline) - const char *callback; - unsigned int curindex; - const char *curline; -{ - unsigned int execlen; - char *execstr, *qline; - int flags; - - qline = sh_single_quote (curline); - execlen = strlen (callback) + strlen (qline) + 10; - /* 1 for each space between %s and %d, - another 1 for the last nul char for C string. */ - execlen += 3; - execstr = xmalloc (execlen); - - flags = SEVAL_NOHIST; -#if 0 - if (interactive) - flags |= SEVAL_INTERACT; -#endif - snprintf (execstr, execlen, "%s %d %s", callback, curindex, qline); - free (qline); - return evalstring (execstr, NULL, flags); -} - -static void -do_chop(line) - char * line; -{ - int length; - - length = strlen (line); - if (length && line[length-1] == '\n') - line[length-1] = '\0'; -} - -static int -mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_name, delim, flags) - int fd; - long line_count_goal, origin, nskip, callback_quantum; - char *callback, *array_name; - int delim; - int flags; -{ - char *line; - size_t line_length; - unsigned int array_index, line_count; - SHELL_VAR *entry; - int unbuffered_read; - - line = NULL; - line_length = 0; - unbuffered_read = 0; - - /* The following check should be done before reading any lines. Doing it - here allows us to call bind_array_element instead of bind_array_variable - and skip the variable lookup on every call. */ - entry = find_or_make_array_variable (array_name, 1); - if (entry == 0 || readonly_p (entry) || noassign_p (entry)) - { - if (entry && readonly_p (entry)) - err_readonly (array_name); - - return (EXECUTION_FAILURE); - } - else if (array_p (entry) == 0) - { - builtin_error (_("%s: not an indexed array"), array_name); - return (EXECUTION_FAILURE); - } - else if (invisible_p (entry)) - VUNSETATTR (entry, att_invisible); /* no longer invisible */ - - if (flags & MAPF_CLEARARRAY) - array_flush (array_cell (entry)); - -#ifndef __CYGWIN__ - unbuffered_read = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE); -#else - unbuffered_read = 1; -#endif - - zreset (); - - /* Skip any lines at beginning of file? */ - for (line_count = 0; line_count < nskip; line_count++) - if (zgetline (fd, &line, &line_length, delim, unbuffered_read) < 0) - break; - - line = 0; - line_length = 0; - - /* Reset the buffer for bash own stream */ - for (array_index = origin, line_count = 1; - zgetline (fd, &line, &line_length, delim, unbuffered_read) != -1; - array_index++) - { - /* Remove trailing newlines? */ - if (flags & MAPF_CHOP) - do_chop (line); - - /* Has a callback been registered and if so is it time to call it? */ - if (callback && line_count && (line_count % callback_quantum) == 0) - { - run_callback (callback, array_index, line); - - /* Reset the buffer for bash own stream. */ - if (unbuffered_read == 0) - zsyncfd (fd); - } - - /* XXX - bad things can happen if the callback modifies ENTRY, e.g., - unsetting it or changing it to a non-indexed-array type. */ - bind_array_element (entry, array_index, line, 0); - - /* Have we exceeded # of lines to store? */ - line_count++; - if (line_count_goal != 0 && line_count > line_count_goal) - break; - } - - xfree (line); - - if (unbuffered_read == 0) - zsyncfd (fd); - - return EXECUTION_SUCCESS; -} - -int -mapfile_builtin (list) - WORD_LIST *list; -{ - int opt, code, fd, clear_array, flags; - intmax_t intval; - long lines, origin, nskip, callback_quantum; - char *array_name, *callback; - - clear_array = 1; - fd = 0; - lines = origin = nskip = 0; - flags = MAPF_CLEARARRAY; - callback_quantum = DEFAULT_QUANTUM; - callback = 0; - delim = '\n'; - - reset_internal_getopt (); - while ((opt = internal_getopt (list, "d:u:n:O:tC:c:s:")) != -1) - { - switch (opt) - { - case 'd': - delim = *list_optarg; - break; - case 'u': - code = legal_number (list_optarg, &intval); - if (code == 0 || intval < 0 || intval != (int)intval) - { - builtin_error (_("%s: invalid file descriptor specification"), list_optarg); - return (EXECUTION_FAILURE); - } - else - fd = intval; - - if (sh_validfd (fd) == 0) - { - builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno)); - return (EXECUTION_FAILURE); - } - break; - - case 'n': - code = legal_number (list_optarg, &intval); - if (code == 0 || intval < 0 || intval != (unsigned)intval) - { - builtin_error (_("%s: invalid line count"), list_optarg); - return (EXECUTION_FAILURE); - } - else - lines = intval; - break; - - case 'O': - code = legal_number (list_optarg, &intval); - if (code == 0 || intval < 0 || intval != (unsigned)intval) - { - builtin_error (_("%s: invalid array origin"), list_optarg); - return (EXECUTION_FAILURE); - } - else - origin = intval; - flags &= ~MAPF_CLEARARRAY; - break; - case 't': - flags |= MAPF_CHOP; - break; - case 'C': - callback = list_optarg; - break; - case 'c': - code = legal_number (list_optarg, &intval); - if (code == 0 || intval <= 0 || intval != (unsigned)intval) - { - builtin_error (_("%s: invalid callback quantum"), list_optarg); - return (EXECUTION_FAILURE); - } - else - callback_quantum = intval; - break; - case 's': - code = legal_number (list_optarg, &intval); - if (code == 0 || intval < 0 || intval != (unsigned)intval) - { - builtin_error (_("%s: invalid line count"), list_optarg); - return (EXECUTION_FAILURE); - } - else - nskip = intval; - break; - default: - builtin_usage (); - return (EX_USAGE); - } - } - list = loptend; - - if (list == 0) - array_name = DEFAULT_ARRAY_NAME; - else if (list->word == 0 || list->word->word == 0) - { - builtin_error ("internal error: getting variable name"); - return (EXECUTION_FAILURE); - } - else if (list->word->word[0] == '\0') - { - builtin_error (_("empty array variable name")); - return (EX_USAGE); - } - else - array_name = list->word->word; - - if (legal_identifier (array_name) == 0 && valid_array_reference (array_name) == 0) - { - sh_invalidid (array_name); - return (EXECUTION_FAILURE); - } - - return mapfile (fd, lines, origin, nskip, callback_quantum, callback, array_name, delim, flags); -} - -#else - -int -mapfile_builtin (list) - WORD_LIST *list; -{ - builtin_error (_("array variable support required")); - return (EXECUTION_FAILURE); -} - -#endif /* ARRAY_VARS */ diff --git a/builtins/setattr.def~ b/builtins/setattr.def~ deleted file mode 100644 index 3506447a..00000000 --- a/builtins/setattr.def~ +++ /dev/null @@ -1,555 +0,0 @@ -This file is setattr.def, from which is created setattr.c. -It implements the builtins "export" and "readonly", in Bash. - -Copyright (C) 1987-2012 Free Software Foundation, Inc. - -This file is part of GNU Bash, the Bourne Again SHell. - -Bash is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Bash is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Bash. If not, see <http://www.gnu.org/licenses/>. - -$PRODUCES setattr.c - -#include <config.h> - -#if defined (HAVE_UNISTD_H) -# ifdef _MINIX -# include <sys/types.h> -# endif -# include <unistd.h> -#endif - -#include <stdio.h> -#include "../bashansi.h" -#include "../bashintl.h" - -#include "../shell.h" -#include "../flags.h" -#include "common.h" -#include "bashgetopt.h" - -extern int posixly_correct; -extern int array_needs_making; -extern char *this_command_name; -extern sh_builtin_func_t *this_shell_builtin; - -#ifdef ARRAY_VARS -extern int declare_builtin __P((WORD_LIST *)); -#endif - -#define READONLY_OR_EXPORT \ - (this_shell_builtin == readonly_builtin || this_shell_builtin == export_builtin) - -$BUILTIN export -$FUNCTION export_builtin -$SHORT_DOC export [-fn] [name[=value] ...] or export -p -Set export attribute for shell variables. - -Marks each NAME for automatic export to the environment of subsequently -executed commands. If VALUE is supplied, assign VALUE before exporting. - -Options: - -f refer to shell functions - -n remove the export property from each NAME - -p display a list of all exported variables and functions - -An argument of `--' disables further option processing. - -Exit Status: -Returns success unless an invalid option is given or NAME is invalid. -$END - -/* For each variable name in LIST, make that variable appear in the - environment passed to simple commands. If there is no LIST, then - print all such variables. An argument of `-n' says to remove the - exported attribute from variables named in LIST. An argument of - -f indicates that the names present in LIST refer to functions. */ -int -export_builtin (list) - register WORD_LIST *list; -{ - return (set_or_show_attributes (list, att_exported, 0)); -} - -$BUILTIN readonly -$FUNCTION readonly_builtin -$SHORT_DOC readonly [-aAf] [name[=value] ...] or readonly -p -Mark shell variables as unchangeable. - -Mark each NAME as read-only; the values of these NAMEs may not be -changed by subsequent assignment. If VALUE is supplied, assign VALUE -before marking as read-only. - -Options: - -a refer to indexed array variables - -A refer to associative array variables - -f refer to shell functions - -p display a list of all readonly variables or functions, depending on - whether or not the -f option is given - -An argument of `--' disables further option processing. - -Exit Status: -Returns success unless an invalid option is given or NAME is invalid. -$END - -/* For each variable name in LIST, make that variable readonly. Given an - empty LIST, print out all existing readonly variables. */ -int -readonly_builtin (list) - register WORD_LIST *list; -{ - return (set_or_show_attributes (list, att_readonly, 0)); -} - -#if defined (ARRAY_VARS) -# define ATTROPTS "aAfnp" -#else -# define ATTROPTS "fnp" -#endif - -/* For each variable name in LIST, make that variable have the specified - ATTRIBUTE. An arg of `-n' says to remove the attribute from the the - remaining names in LIST (doesn't work for readonly). */ -int -set_or_show_attributes (list, attribute, nodefs) - register WORD_LIST *list; - int attribute, nodefs; -{ - register SHELL_VAR *var; - int assign, undo, any_failed, assign_error, opt; - int functions_only, arrays_only, assoc_only; - int aflags; - char *name; -#if defined (ARRAY_VARS) - WORD_LIST *nlist, *tlist; - WORD_DESC *w; -#endif - - functions_only = arrays_only = assoc_only = 0; - undo = any_failed = assign_error = 0; - /* Read arguments from the front of the list. */ - reset_internal_getopt (); - while ((opt = internal_getopt (list, ATTROPTS)) != -1) - { - switch (opt) - { - case 'n': - undo = 1; - break; - case 'f': - functions_only = 1; - break; -#if defined (ARRAY_VARS) - case 'a': - arrays_only = 1; - break; - case 'A': - assoc_only = 1; - break; -#endif - case 'p': - break; - default: - builtin_usage (); - return (EX_USAGE); - } - } - list = loptend; - - if (list) - { - if (attribute & att_exported) - array_needs_making = 1; - - /* Cannot undo readonly status, silently disallowed. */ - if (undo && (attribute & att_readonly)) - attribute &= ~att_readonly; - - while (list) - { - name = list->word->word; - - if (functions_only) /* xxx -f name */ - { - var = find_function (name); - if (var == 0) - { - builtin_error (_("%s: not a function"), name); - any_failed++; - } - else - SETVARATTR (var, attribute, undo); - - list = list->next; - continue; - } - - /* xxx [-np] name[=value] */ - assign = assignment (name, 0); - - aflags = 0; - if (assign) - { - name[assign] = '\0'; - if (name[assign - 1] == '+') - { - aflags |= ASS_APPEND; - name[assign - 1] = '\0'; - } - } - - if (legal_identifier (name) == 0) - { - sh_invalidid (name); - if (assign) - assign_error++; - else - any_failed++; - list = list->next; - continue; - } - - if (assign) /* xxx [-np] name=value */ - { - name[assign] = '='; - if (aflags & ASS_APPEND) - name[assign - 1] = '+'; -#if defined (ARRAY_VARS) - /* Let's try something here. Turn readonly -a xxx=yyy into - declare -ra xxx=yyy and see what that gets us. */ - if (arrays_only || assoc_only) - { - tlist = list->next; - list->next = (WORD_LIST *)NULL; - w = arrays_only ? make_word ("-ra") : make_word ("-rA"); - nlist = make_word_list (w, list); - opt = declare_builtin (nlist); - if (opt != EXECUTION_SUCCESS) - assign_error++; - list->next = tlist; - dispose_word (w); - free (nlist); - } - else -#endif - /* This word has already been expanded once with command - and parameter expansion. Call do_assignment_no_expand (), - which does not do command or parameter substitution. If - the assignment is not performed correctly, flag an error. */ - if (do_assignment_no_expand (name) == 0) - assign_error++; - name[assign] = '\0'; - if (aflags & ASS_APPEND) - name[assign - 1] = '\0'; - } - - set_var_attribute (name, attribute, undo); - list = list->next; - } - } - else - { - SHELL_VAR **variable_list; - register int i; - - if ((attribute & att_function) || functions_only) - { - variable_list = all_shell_functions (); - if (attribute != att_function) - attribute &= ~att_function; /* so declare -xf works, for example */ - } - else - variable_list = all_shell_variables (); - -#if defined (ARRAY_VARS) - if (attribute & att_array) - { - arrays_only++; - if (attribute != att_array) - attribute &= ~att_array; - } - else if (attribute & att_assoc) - { - assoc_only++; - if (attribute != att_assoc) - attribute &= ~att_assoc; - } -#endif - - if (variable_list) - { - for (i = 0; var = variable_list[i]; i++) - { -#if defined (ARRAY_VARS) - if (arrays_only && array_p (var) == 0) - continue; - else if (assoc_only && assoc_p (var) == 0) - continue; -#endif - if ((var->attributes & attribute)) - { - show_var_attributes (var, READONLY_OR_EXPORT, nodefs); - if (any_failed = sh_chkwrite (any_failed)) - break; - } - } - free (variable_list); - } - } - - return (assign_error ? EX_BADASSIGN - : ((any_failed == 0) ? EXECUTION_SUCCESS - : EXECUTION_FAILURE)); -} - -/* Show all variable variables (v == 1) or functions (v == 0) with - attributes. */ -int -show_all_var_attributes (v, nodefs) - int v, nodefs; -{ - SHELL_VAR **variable_list, *var; - int any_failed; - register int i; - - variable_list = v ? all_shell_variables () : all_shell_functions (); - if (variable_list == 0) - return (EXECUTION_SUCCESS); - - for (i = any_failed = 0; var = variable_list[i]; i++) - { - show_var_attributes (var, READONLY_OR_EXPORT, nodefs); - if (any_failed = sh_chkwrite (any_failed)) - break; - } - free (variable_list); - return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE); -} - -/* Show the attributes for shell variable VAR. If NODEFS is non-zero, - don't show function definitions along with the name. If PATTR is - non-zero, it indicates we're being called from `export' or `readonly'. - In POSIX mode, this prints the name of the calling builtin (`export' - or `readonly') instead of `declare', and doesn't print function defs - when called by `export' or `readonly'. */ -int -show_var_attributes (var, pattr, nodefs) - SHELL_VAR *var; - int pattr, nodefs; -{ - char flags[16], *x; - int i; - - i = 0; - - /* pattr == 0 means we are called from `declare'. */ - if (pattr == 0 || posixly_correct == 0) - { -#if defined (ARRAY_VARS) - if (array_p (var)) - flags[i++] = 'a'; - - if (assoc_p (var)) - flags[i++] = 'A'; -#endif - - if (function_p (var)) - flags[i++] = 'f'; - - if (integer_p (var)) - flags[i++] = 'i'; - - if (nameref_p (var)) - flags[i++] = 'n'; - - if (readonly_p (var)) - flags[i++] = 'r'; - - if (trace_p (var)) - flags[i++] = 't'; - - if (exported_p (var)) - flags[i++] = 'x'; - - if (capcase_p (var)) - flags[i++] = 'c'; - - if (lowercase_p (var)) - flags[i++] = 'l'; - - if (uppercase_p (var)) - flags[i++] = 'u'; - } - else - { -#if defined (ARRAY_VARS) - if (array_p (var)) - flags[i++] = 'a'; - - if (assoc_p (var)) - flags[i++] = 'A'; -#endif - - if (function_p (var)) - flags[i++] = 'f'; - } - - flags[i] = '\0'; - - /* If we're printing functions with definitions, print the function def - first, then the attributes, instead of printing output that can't be - reused as input to recreate the current state. */ - if (function_p (var) && nodefs == 0 && (pattr == 0 || posixly_correct == 0)) - { - printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL)); - nodefs++; - if (pattr == 0 && i == 1 && flags[0] == 'f') - return 0; /* don't print `declare -f name' */ - } - - if (pattr == 0 || posixly_correct == 0) - printf ("declare -%s ", i ? flags : "-"); - else if (i) - printf ("%s -%s ", this_command_name, flags); - else - printf ("%s ", this_command_name); - -#if defined (ARRAY_VARS) - if (array_p (var)) - print_array_assignment (var, 1); - else if (assoc_p (var)) - print_assoc_assignment (var, 1); - else -#endif - /* force `readonly' and `export' to not print out function definitions - when in POSIX mode. */ - if (nodefs || (function_p (var) && pattr != 0 && posixly_correct)) - printf ("%s\n", var->name); - else if (function_p (var)) - printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL)); - else if (invisible_p (var) && (array_p (var) || assoc_p (var))) - printf ("%s\n", var->name); - else if (invisible_p (var) || var_isset (var) == 0) - printf ("%s\n", var->name); - else - { - x = sh_double_quote (value_cell (var)); - printf ("%s=%s\n", var->name, x); - free (x); - } - return (0); -} - -int -show_name_attributes (name, nodefs) - char *name; - int nodefs; -{ - SHELL_VAR *var; - -#if 0 - var = find_variable_tempenv (name); -#else - var = find_variable_noref (name); -#endif - - if (var /* && invisible_p (var) == 0 */) /* XXX bash-4.4/bash-5.0 */ - { - show_var_attributes (var, READONLY_OR_EXPORT, nodefs); - return (0); - } - else - return (1); -} - -int -show_func_attributes (name, nodefs) - char *name; - int nodefs; -{ - SHELL_VAR *var; - - var = find_function (name); - - if (var) - { - show_var_attributes (var, READONLY_OR_EXPORT, nodefs); - return (0); - } - else - return (1); -} - -void -set_var_attribute (name, attribute, undo) - char *name; - int attribute, undo; -{ - SHELL_VAR *var, *tv, *v; - char *tvalue; - - if (undo) - var = find_variable (name); - else - { - tv = find_tempenv_variable (name); - /* XXX -- need to handle case where tv is a temp variable in a - function-scope context, since function_env has been merged into - the local variables table. */ - if (tv && tempvar_p (tv)) - { - tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring (""); - - var = bind_variable (tv->name, tvalue, 0); - var->attributes |= tv->attributes & ~att_tempvar; - /* This avoids an error message when propagating a read-only var - later on. */ - if (var->context == 0 && (attribute & att_readonly)) - { - /* Don't bother to set the `propagate to the global variables - table' flag if we've just bound the variable in that table */ - v = find_global_variable (tv->name); - if (v != var) - VSETATTR (tv, att_propagate); - } - else - VSETATTR (tv, att_propagate); - if (var->context != 0) - VSETATTR (var, att_propagate); - SETVARATTR (tv, attribute, undo); /* XXX */ - - stupidly_hack_special_variables (tv->name); - - free (tvalue); - } - else - { - var = find_variable_notempenv (name); - if (var == 0) - { - var = bind_variable (name, (char *)NULL, 0); - if (no_invisible_vars == 0) - VSETATTR (var, att_invisible); - } - else if (var->context != 0) - VSETATTR (var, att_propagate); - } - } - - if (var) - SETVARATTR (var, attribute, undo); - - if (var && (exported_p (var) || (attribute & att_exported))) - array_needs_making++; /* XXX */ -} diff --git a/config-top.h~ b/config-top.h~ deleted file mode 100644 index c62e88f1..00000000 --- a/config-top.h~ +++ /dev/null @@ -1,141 +0,0 @@ -/* config-top.h - various user-settable options not under the control of autoconf. */ - -/* Copyright (C) 2002-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 <http://www.gnu.org/licenses/>. -*/ - -/* Define CONTINUE_AFTER_KILL_ERROR if you want the kill command to - continue processing arguments after one of them fails. This is - what POSIX.2 specifies. */ -#define CONTINUE_AFTER_KILL_ERROR - -/* Define BREAK_COMPLAINS if you want the non-standard, but useful - error messages about `break' and `continue' out of context. */ -#define BREAK_COMPLAINS - -/* Define BUFFERED_INPUT if you want the shell to do its own input - buffering, rather than using stdio. Do not undefine this; it's - required to preserve semantics required by POSIX. */ -#define BUFFERED_INPUT - -/* Define ONESHOT if you want sh -c 'command' to avoid forking to execute - `command' whenever possible. This is a big efficiency improvement. */ -#define ONESHOT - -/* Define V9_ECHO if you want to give the echo builtin backslash-escape - interpretation using the -e option, in the style of the Bell Labs 9th - Edition version of echo. You cannot emulate the System V echo behavior - without this option. */ -#define V9_ECHO - -/* Define DONT_REPORT_SIGPIPE if you don't want to see `Broken pipe' messages - when a job like `cat jobs.c | exit 1' terminates due to a SIGPIPE. */ -#define DONT_REPORT_SIGPIPE - -/* Define DONT_REPORT_SIGTERM if you don't want to see `Terminates' message - when a job exits due to SIGTERM, since that's the default signal sent - by the kill builtin. */ -/* #define DONT_REPORT_SIGTERM */ - -/* Define DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS if you don't want builtins - like `echo' and `printf' to report errors when output does not succeed - due to EPIPE. */ -/* #define DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS */ - -/* The default value of the PATH variable. */ -#ifndef DEFAULT_PATH_VALUE -#define DEFAULT_PATH_VALUE \ - "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:." -#endif - -/* The value for PATH when invoking `command -p'. This is only used when - the Posix.2 confstr () function, or CS_PATH define are not present. */ -#ifndef STANDARD_UTILS_PATH -#define STANDARD_UTILS_PATH \ - "/bin:/usr/bin:/sbin:/usr/sbin:/etc:/usr/etc" -#endif - -/* Default primary and secondary prompt strings. */ -#define PPROMPT "\\s-\\v\\$ " -#define SPROMPT "> " - -/* Undefine this if you don't want the ksh-compatible behavior of reprinting - the select menu after a valid choice is made only if REPLY is set to NULL - in the body of the select command. The menu is always reprinted if the - reply to the select query is an empty line. */ -#define KSH_COMPATIBLE_SELECT - -/* Default interactive shell startup file. */ -#define DEFAULT_BASHRC "~/.bashrc" - -/* System-wide .bashrc file for interactive shells. */ -/* #define SYS_BASHRC "/etc/bash.bashrc" */ - -/* System-wide .bash_logout for login shells. */ -/* #define SYS_BASH_LOGOUT "/etc/bash.bash_logout" */ - -/* Define this to make non-interactive shells begun with argv[0][0] == '-' - run the startup files when not in posix mode. */ -/* #define NON_INTERACTIVE_LOGIN_SHELLS */ - -/* Define this if you want bash to try to check whether it's being run by - sshd and source the .bashrc if so (like the rshd behavior). This checks - for the presence of SSH_CLIENT or SSH2_CLIENT in the initial environment, - which can be fooled under certain not-uncommon circumstances. */ -/* #define SSH_SOURCE_BASHRC */ - -/* Define if you want the case-capitalizing operators (~[~]) and the - `capcase' variable attribute (declare -c). */ -#define CASEMOD_CAPCASE - -/* This is used as the name of a shell function to call when a command - name is not found. If you want to name it something other than the - default ("command_not_found_handle"), change it here. */ -/* #define NOTFOUND_HOOK "command_not_found_handle" */ - -/* Define if you want each line saved to the history list in bashhist.c: - bash_add_history() to be sent to syslog(). */ -/* #define SYSLOG_HISTORY */ -#if defined (SYSLOG_HISTORY) -# define SYSLOG_FACILITY LOG_USER -# define SYSLOG_LEVEL LOG_INFO -#endif - -/* Define if you want to include code in shell.c to support wordexp(3) */ -/* #define WORDEXP_OPTION */ - -/* Define as 1 if you want to enable code that implements multiple coprocs */ -#ifndef MULTIPLE_COPROCS -# define MULTIPLE_COPROCS 0 -#endif - -/* Define to 0 if you want the checkwinsize option off by default, 1 if you - want it on. */ -#define CHECKWINSIZE_DEFAULT 0 - -/* Define to 1 if you want to optimize for sequential array assignment when - using indexed arrays, 0 if you want bash-4.2 behavior, which favors - random access but is O(N) for each array assignment. */ -#define OPTIMIZE_SEQUENTIAL_ARRAY_ASSIGNMENT 1 - -/* Define to 1 if you want to be able to export indexed arrays to processes - using the foo=([0]=one [1]=two) and so on */ -/* #define ARRAY_EXPORT 1 */ - -/* Defined to 1 if you want the shell to exit if it is running setuid and its - attempt to drop privilege using setuid(getuid()) fails with errno == EAGAIN */ -/* #define EXIT_ON_SETUID_FAILURE 1 */ diff --git a/cross-build/cygwin32.cache.old b/cross-build/cygwin32.cache.old deleted file mode 100644 index 640390fb..00000000 --- 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 1cff3c8e..00000000 --- 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 <snowball3@bigfoot.com> 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 $(<filename) command substitution, which is equivalent to - $(cat filename) -new tilde prefixes that expand to directories from the directory stack -new `**' arithmetic operator to do exponentiation -case-insensitive globbing (filename expansion) -menu completion a la tcsh -`magic-space' history expansion function like tcsh -the readline inputrc `language' has a new file inclusion directive ($include) - -Bash-2.01 contained only a few new features: - -new `GROUPS' builtin array variable containing the user's group list -new bindable readline commands: history-and-alias-expand-line and - alias-expand-line - -Bash-2.0 contained extensive changes and new features from bash-1.14.7. -Here's a short list: - -new `time' reserved word to time pipelines, shell builtins, and - shell functions -one-dimensional arrays with a new compound assignment statement, - appropriate expansion constructs and modifications to some - of the builtins (read, declare, etc.) to use them -new quoting syntaxes for ANSI-C string expansion and locale-specific - string translation -new expansions to do substring extraction, pattern replacement, and - indirect variable expansion -new builtins: `disown' and `shopt' -new variables: HISTIGNORE, SHELLOPTS, PIPESTATUS, DIRSTACK, GLOBIGNORE, - MACHTYPE, BASH_VERSINFO -special handling of many unused or redundant variables removed - (e.g., $notify, $glob_dot_filenames, $no_exit_on_failed_exec) -dynamic loading of new builtin commands; many loadable examples provided -new prompt expansions: \a, \e, \n, \H, \T, \@, \v, \V -history and aliases available in shell scripts -new readline variables: enable-keypad, mark-directories, input-meta, - visible-stats, disable-completion, comment-begin -new readline commands to manipulate the mark and operate on the region -new readline emacs mode commands and bindings for ksh-88 compatibility -updated and extended builtins -new DEBUG trap -expanded (and now documented) restricted shell mode - -implementation stuff: -autoconf-based configuration -nearly all of the bugs reported since version 1.14 have been fixed -most builtins converted to use builtin `getopt' for consistency -most builtins use -p option to display output in a reusable form - (for consistency) -grammar tighter and smaller (66 reduce-reduce conflicts gone) -lots of code now smaller and faster -test suite greatly expanded - -B2) Are there any user-visible incompatibilities between bash-2.05b and - bash-1.14.7? - -There are a few incompatibilities between version 1.14.7 and version 2.05b. -They are detailed in the file COMPAT in the bash distribution. That file -is not meant to be all-encompassing; send mail to bash-maintainers@gnu.org -if if you find something that's not mentioned there. - -Section C: Differences from other Unix shells - -C1) How does bash differ from sh, the Bourne shell? - -This is a non-comprehensive list of features that differentiate bash -from the SVR4.2 shell. The bash manual page explains these more -completely. - -Things bash has that sh does not: - long invocation options - [+-]O invocation option - -l invocation option - `!' reserved word to invert pipeline return value - `time' reserved word to time pipelines and shell builtins - the `function' reserved word - the `select' compound command and reserved word - arithmetic for command: for ((expr1 ; expr2; expr3 )); do list; done - new $'...' and $"..." quoting - the $(...) form of command substitution - the $(<filename) form of command substitution, equivalent to - $(cat filename) - the ${#param} parameter value length operator - 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 - expansions to perform substring removal (${p%[%]w}, ${p#[#]w}) - expansion of positional parameters beyond $9 with ${num} - variables: BASH, BASH_VERSION, BASH_VERSINFO, UID, EUID, REPLY, - TIMEFORMAT, PPID, PWD, OLDPWD, SHLVL, RANDOM, SECONDS, - LINENO, HISTCMD, HOSTTYPE, OSTYPE, MACHTYPE, HOSTNAME, - ENV, PS3, PS4, DIRSTACK, PIPESTATUS, HISTSIZE, HISTFILE, - HISTFILESIZE, HISTCONTROL, HISTIGNORE, GLOBIGNORE, GROUPS, - PROMPT_COMMAND, FCEDIT, FIGNORE, IGNOREEOF, INPUTRC, - SHELLOPTS, OPTERR, HOSTFILE, TMOUT, FUNCNAME, histchars, - auto_resume - DEBUG trap - ERR trap - variable arrays with new compound assignment syntax - redirections: <>, &>, >|, <<<, [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/bash.1~ b/doc/bash.1~ deleted file mode 100644 index 45dc80fd..00000000 --- a/doc/bash.1~ +++ /dev/null @@ -1,10345 +0,0 @@ -.\" -.\" MAN PAGE COMMENTS to -.\" -.\" Chet Ramey -.\" Case Western Reserve University -.\" chet.ramey@case.edu -.\" -.\" Last Change: Tue Jul 1 15:51:28 PDT 2014 -.\" -.\" bash_builtins, strip all but Built-Ins section -.if \n(zZ=1 .ig zZ -.if \n(zY=1 .ig zY -.TH BASH 1 "2014 July 1" "GNU Bash 4.3" -.\" -.\" There's some problem with having a `@' -.\" in a tagged paragraph with the BSD man macros. -.\" It has to do with `@' appearing in the }1 macro. -.\" This is a problem on 4.3 BSD and Ultrix, but Sun -.\" appears to have fixed it. -.\" If you're seeing the characters -.\" `@u-3p' appearing before the lines reading -.\" `possible-hostname-completions -.\" and `complete-hostname' down in READLINE, -.\" then uncomment this redefinition. -.\" -.de }1 -.ds ]X \&\\*(]B\\ -.nr )E 0 -.if !"\\$1"" .nr )I \\$1n -.}f -.ll \\n(LLu -.in \\n()Ru+\\n(INu+\\n()Iu -.ti \\n(INu -.ie !\\n()Iu+\\n()Ru-\w\\*(]Xu-3p \{\\*(]X -.br\} -.el \\*(]X\h|\\n()Iu+\\n()Ru\c -.}f -.. -.\" -.\" File Name macro. This used to be `.PN', for Path Name, -.\" but Sun doesn't seem to like that very much. -.\" -.de FN -\fI\|\\$1\|\fP -.. -.SH NAME -bash \- GNU Bourne-Again SHell -.SH SYNOPSIS -.B bash -[options] -[command_string | file] -.SH COPYRIGHT -.if n Bash is Copyright (C) 1989-2013 by the Free Software Foundation, Inc. -.if t Bash is Copyright \(co 1989-2013 by the Free Software Foundation, Inc. -.SH DESCRIPTION -.B Bash -is an \fBsh\fR-compatible command language interpreter that -executes commands read from the standard input or from a file. -.B Bash -also incorporates useful features from the \fIKorn\fP and \fIC\fP -shells (\fBksh\fP and \fBcsh\fP). -.PP -.B Bash -is intended to be a conformant implementation of the -Shell and Utilities portion of the IEEE POSIX specification -(IEEE Standard 1003.1). -.B Bash -can be configured to be POSIX-conformant by default. -.SH OPTIONS -All of the single-character shell options documented in the -description of the \fBset\fR builtin command can be used as options -when the shell is invoked. -In addition, \fBbash\fR -interprets the following options when it is invoked: -.PP -.PD 0 -.TP 10 -.B \-c -If the -.B \-c -option is present, then commands are read from the first non-option argument -.IR command_string . -If there are arguments after the -.IR command_string , -they are assigned to the positional parameters, starting with -.BR $0 . -.TP -.B \-i -If the -.B \-i -option is present, the shell is -.IR interactive . -.TP -.B \-l -Make -.B bash -act as if it had been invoked as a login shell (see -.SM -.B INVOCATION -below). -.TP -.B \-r -If the -.B \-r -option is present, the shell becomes -.I restricted -(see -.SM -.B "RESTRICTED SHELL" -below). -.TP -.B \-s -If the -.B \-s -option is present, or if no arguments remain after option -processing, then commands are read from the standard input. -This option allows the positional parameters to be set -when invoking an interactive shell. -.TP -.B \-D -A list of all double-quoted strings preceded by \fB$\fP -is printed on the standard output. -These are the strings that -are subject to language translation when the current locale -is not \fBC\fP or \fBPOSIX\fP. -This implies the \fB\-n\fP option; no commands will be executed. -.TP -.B [\-+]O [\fIshopt_option\fP] -\fIshopt_option\fP is one of the shell options accepted by the -\fBshopt\fP builtin (see -.SM -.B SHELL BUILTIN COMMANDS -below). -If \fIshopt_option\fP is present, \fB\-O\fP sets the value of that option; -\fB+O\fP unsets it. -If \fIshopt_option\fP is not supplied, the names and values of the shell -options accepted by \fBshopt\fP are printed on the standard output. -If the invocation option is \fB+O\fP, the output is displayed in a format -that may be reused as input. -.TP -.B \-\- -A -.B \-\- -signals the end of options and disables further option processing. -Any arguments after the -.B \-\- -are treated as filenames and arguments. An argument of -.B \- -is equivalent to \fB\-\-\fP. -.PD -.PP -.B Bash -also interprets a number of multi-character options. -These options must appear on the command line before the -single-character options to be recognized. -.PP -.PD 0 -.TP -.B \-\-debugger -Arrange for the debugger profile to be executed before the shell -starts. -Turns on extended debugging mode (see the description of the -.B extdebug -option to the -.B shopt -builtin below). -.TP -.B \-\-dump\-po\-strings -Equivalent to \fB\-D\fP, but the output is in the GNU \fIgettext\fP -\fBpo\fP (portable object) file format. -.TP -.B \-\-dump\-strings -Equivalent to \fB\-D\fP. -.TP -.B \-\-help -Display a usage message on standard output and exit successfully. -.TP -\fB\-\-init\-file\fP \fIfile\fP -.PD 0 -.TP -\fB\-\-rcfile\fP \fIfile\fP -.PD -Execute commands from -.I file -instead of the standard personal initialization file -.I ~/.bashrc -if the shell is interactive (see -.SM -.B INVOCATION -below). -.TP -.B \-\-login -Equivalent to \fB\-l\fP. -.TP -.B \-\-noediting -Do not use the GNU -.B readline -library to read command lines when the shell is interactive. -.TP -.B \-\-noprofile -Do not read either the system-wide startup file -.FN /etc/profile -or any of the personal initialization files -.IR ~/.bash_profile , -.IR ~/.bash_login , -or -.IR ~/.profile . -By default, -.B bash -reads these files when it is invoked as a login shell (see -.SM -.B INVOCATION -below). -.TP -.B \-\-norc -Do not read and execute the personal initialization file -.I ~/.bashrc -if the shell is interactive. -This option is on by default if the shell is invoked as -.BR sh . -.TP -.B \-\-posix -Change the behavior of \fBbash\fP where the default operation differs -from the POSIX standard to match the standard (\fIposix mode\fP). -See -.SM -.B "SEE ALSO" -below for a reference to a document that details how posix mode affects -bash's behavior. -.TP -.B \-\-restricted -The shell becomes restricted (see -.SM -.B "RESTRICTED SHELL" -below). -.TP -.B \-\-verbose -Equivalent to \fB\-v\fP. -.TP -.B \-\-version -Show version information for this instance of -.B bash -on the standard output and exit successfully. -.PD -.SH ARGUMENTS -If arguments remain after option processing, and neither the -.B \-c -nor the -.B \-s -option has been supplied, the first argument is assumed to -be the name of a file containing shell commands. -If -.B bash -is invoked in this fashion, -.B $0 -is set to the name of the file, and the positional parameters -are set to the remaining arguments. -.B Bash -reads and executes commands from this file, then exits. -\fBBash\fP's exit status is the exit status of the last command -executed in the script. -If no commands are executed, the exit status is 0. -An attempt is first made to open the file in the current directory, and, -if no file is found, then the shell searches the directories in -.SM -.B PATH -for the script. -.SH INVOCATION -A \fIlogin shell\fP is one whose first character of argument zero is a -.BR \- , -or one started with the -.B \-\-login -option. -.PP -An \fIinteractive\fP shell is one started without non-option arguments -and without the -.B \-c -option -whose standard input and error are -both connected to terminals (as determined by -.IR isatty (3)), -or one started with the -.B \-i -option. -.SM -.B PS1 -is set and -.B $\- -includes -.B i -if -.B bash -is interactive, -allowing a shell script or a startup file to test this state. -.PP -The following paragraphs describe how -.B bash -executes its startup files. -If any of the files exist but cannot be read, -.B bash -reports an error. -Tildes are expanded in filenames as described below under -.B "Tilde Expansion" -in the -.SM -.B EXPANSION -section. -.PP -When -.B bash -is invoked as an interactive login shell, or as a non-interactive shell -with the \fB\-\-login\fP option, it first reads and -executes commands from the file \fI/etc/profile\fP, if that -file exists. -After reading that file, it looks for \fI~/.bash_profile\fP, -\fI~/.bash_login\fP, and \fI~/.profile\fP, in that order, and reads -and executes commands from the first one that exists and is readable. -The -.B \-\-noprofile -option may be used when the shell is started to inhibit this behavior. -.PP -When a login shell exits, -.B bash -reads and executes commands from the file \fI~/.bash_logout\fP, if it -exists. -.PP -When an interactive shell that is not a login shell is started, -.B bash -reads and executes commands from \fI~/.bashrc\fP, if that file exists. -This may be inhibited by using the -.B \-\-norc -option. -The \fB\-\-rcfile\fP \fIfile\fP option will force -.B bash -to read and execute commands from \fIfile\fP instead of \fI~/.bashrc\fP. -.PP -When -.B bash -is started non-interactively, to run a shell script, for example, it -looks for the variable -.SM -.B BASH_ENV -in the environment, expands its value if it appears there, and uses the -expanded value as the name of a file to read and execute. -.B Bash -behaves as if the following command were executed: -.sp .5 -.RS -.if t \f(CWif [ \-n "$BASH_ENV" ]; then . "$BASH_ENV"; fi\fP -.if n if [ \-n "$BASH_ENV" ]; then . "$BASH_ENV"; fi -.RE -.sp .5 -but the value of the -.SM -.B PATH -variable is not used to search for the filename. -.PP -If -.B bash -is invoked with the name -.BR sh , -it tries to mimic the startup behavior of historical versions of -.B sh -as closely as possible, -while conforming to the POSIX standard as well. -When invoked as an interactive login shell, or a non-interactive -shell with the \fB\-\-login\fP option, it first attempts to -read and execute commands from -.I /etc/profile -and -.IR ~/.profile , -in that order. -The -.B \-\-noprofile -option may be used to inhibit this behavior. -When invoked as an interactive shell with the name -.BR sh , -.B bash -looks for the variable -.SM -.BR ENV , -expands its value if it is defined, and uses the -expanded value as the name of a file to read and execute. -Since a shell invoked as -.B sh -does not attempt to read and execute commands from any other startup -files, the -.B \-\-rcfile -option has no effect. -A non-interactive shell invoked with the name -.B sh -does not attempt to read any other startup files. -When invoked as -.BR sh , -.B bash -enters -.I posix -mode after the startup files are read. -.PP -When -.B bash -is started in -.I posix -mode, as with the -.B \-\-posix -command line option, it follows the POSIX standard for startup files. -In this mode, interactive shells expand the -.SM -.B ENV -variable and commands are read and executed from the file -whose name is the expanded value. -No other startup files are read. -.PP -.B Bash -attempts to determine when it is being run with its standard input -connected to a network connection, as when executed by the remote shell -daemon, usually \fIrshd\fP, or the secure shell daemon \fIsshd\fP. -If -.B bash -determines it is being run in this fashion, it reads and executes -commands from \fI~/.bashrc\fP, if that file exists and is readable. -It will not do this if invoked as \fBsh\fP. -The -.B \-\-norc -option may be used to inhibit this behavior, and the -.B \-\-rcfile -option may be used to force another file to be read, but neither -\fIrshd\fP nor \fIsshd\fP generally invoke the shell with those options -or allow them to be specified. -.PP -If the shell is started with the effective user (group) id not equal to the -real user (group) id, and the \fB\-p\fP option is not supplied, no startup -files are read, shell functions are not inherited from the environment, the -.SM -.BR SHELLOPTS , -.SM -.BR BASHOPTS , -.SM -.BR CDPATH , -and -.SM -.B GLOBIGNORE -variables, if they appear in the environment, are ignored, -and the effective user id is set to the real user id. -If the \fB\-p\fP option is supplied at invocation, the startup behavior is -the same, but the effective user id is not reset. -.SH DEFINITIONS -.PP -The following definitions are used throughout the rest of this -document. -.PD 0 -.TP -.B blank -A space or tab. -.TP -.B word -A sequence of characters considered as a single unit by the shell. -Also known as a -.BR token . -.TP -.B name -A -.I word -consisting only of alphanumeric characters and underscores, and -beginning with an alphabetic character or an underscore. Also -referred to as an -.BR identifier . -.TP -.B metacharacter -A character that, when unquoted, separates words. One of the following: -.br -.RS -.PP -.if t \fB| & ; ( ) < > space tab\fP -.if n \fB| & ; ( ) < > space tab\fP -.RE -.PP -.TP -.B control operator -A \fItoken\fP that performs a control function. It is one of the following -symbols: -.RS -.PP -.if t \fB|| & && ; ;; ( ) | |& <newline>\fP -.if n \fB|| & && ; ;; ( ) | |& <newline>\fP -.RE -.PD -.SH "RESERVED WORDS" -\fIReserved words\fP are words that have a special meaning to the shell. -The following words are recognized as reserved when unquoted and either -the first word of a simple command (see -.SM -.B SHELL GRAMMAR -below) or the third word of a -.B case -or -.B for -command: -.if t .RS -.PP -.B -.if n ! case coproc do done elif else esac fi for function if in select then until while { } time [[ ]] -.if t ! case coproc do done elif else esac fi for function if in select then until while { } time [[ ]] -.if t .RE -.SH "SHELL GRAMMAR" -.SS Simple Commands -.PP -A \fIsimple command\fP is a sequence of optional variable assignments -followed by \fBblank\fP-separated words and redirections, and -terminated by a \fIcontrol operator\fP. The first word -specifies the command to be executed, and is passed as argument zero. -The remaining words are passed as arguments to the invoked command. -.PP -The return value of a \fIsimple command\fP is its exit status, or -128+\fIn\^\fP if the command is terminated by signal -.IR n . -.SS Pipelines -.PP -A \fIpipeline\fP is a sequence of one or more commands separated by -one of the control operators -.B | -or \fB|&\fP. -The format for a pipeline is: -.RS -.PP -[\fBtime\fP [\fB\-p\fP]] [ ! ] \fIcommand\fP [ [\fB|\fP\(bv\fB|&\fP] \fIcommand2\fP ... ] -.RE -.PP -The standard output of -.I command -is connected via a pipe to the standard input of -.IR command2 . -This connection is performed before any redirections specified by the -command (see -.SM -.B REDIRECTION -below). -If \fB|&\fP is used, \fIcommand\fP's standard error, in addition to its -standard output, is connected to -\fIcommand2\fP's standard input through the pipe; -it is shorthand for \fB2>&1 |\fP. -This implicit redirection of the standard error to the standard output is -performed after any redirections specified by the command. -.PP -The return status of a pipeline is the exit status of the last -command, unless the \fBpipefail\fP option is enabled. -If \fBpipefail\fP is enabled, the pipeline's return status is the -value of the last (rightmost) command to exit with a non-zero status, -or zero if all commands exit successfully. -If the reserved word -.B ! -precedes a pipeline, the exit status of that pipeline is the logical -negation of the exit status as described above. -The shell waits for all commands in the pipeline to -terminate before returning a value. -.PP -If the -.B time -reserved word precedes a pipeline, the elapsed as well as user and -system time consumed by its execution are reported when the pipeline -terminates. -The \fB\-p\fP option changes the output format to that specified by POSIX. -When the shell is in \fIposix mode\fP, it does not recognize -\fBtime\fP as a reserved word if the next token begins with a `-'. -The -.SM -.B TIMEFORMAT -variable may be set to a format string that specifies how the timing -information should be displayed; see the description of -.SM -.B TIMEFORMAT -under -.B "Shell Variables" -below. -.PP -When the shell is in \fIposix mode\fP, \fBtime\fP -may be followed by a newline. In this case, the shell displays the -total user and system time consumed by the shell and its children. -The -.SM -.B TIMEFORMAT -variable may be used to specify the format of -the time information. -.PP -Each command in a pipeline is executed as a separate process (i.e., in a -subshell). -.SS Lists -.PP -A \fIlist\fP is a sequence of one or more pipelines separated by one -of the operators -.BR ; , -.BR & , -.BR && , -or -.BR || , -and optionally terminated by one of -.BR ; , -.BR & , -or -.BR <newline> . -.PP -Of these list operators, -.B && -and -.B || -have equal precedence, followed by -.B ; -and -.BR & , -which have equal precedence. -.PP -A sequence of one or more newlines may appear in a \fIlist\fP instead -of a semicolon to delimit commands. -.PP -If a command is terminated by the control operator -.BR & , -the shell executes the command in the \fIbackground\fP -in a subshell. The shell does not wait for the command to -finish, and the return status is 0. Commands separated by a -.B ; -are executed sequentially; the shell waits for each -command to terminate in turn. The return status is the -exit status of the last command executed. -.PP -AND and OR lists are sequences of one of more pipelines separated by the -\fB&&\fP and \fB||\fP control operators, respectively. -AND and OR lists are executed with left associativity. -An AND list has the form -.RS -.PP -\fIcommand1\fP \fB&&\fP \fIcommand2\fP -.RE -.PP -.I command2 -is executed if, and only if, -.I command1 -returns an exit status of zero. -.PP -An OR list has the form -.RS -.PP -\fIcommand1\fP \fB||\fP \fIcommand2\fP -.PP -.RE -.PP -.I command2 -is executed if and only if -.I command1 -returns a non-zero exit status. -The return status of -AND and OR lists is the exit status of the last command -executed in the list. -.SS Compound Commands -.PP -A \fIcompound command\fP is one of the following. -In most cases a \fIlist\fP in a command's description may be separated from -the rest of the command by one or more newlines, and may be followed by a -newline in place of a semicolon. -.TP -(\fIlist\fP) -\fIlist\fP is executed in a subshell environment (see -.SM -\fBCOMMAND EXECUTION ENVIRONMENT\fP -below). -Variable assignments and builtin -commands that affect the shell's environment do not remain in effect -after the command completes. The return status is the exit status of -\fIlist\fP. -.TP -{ \fIlist\fP; } -\fIlist\fP is simply executed in the current shell environment. -\fIlist\fP must be terminated with a newline or semicolon. -This is known as a \fIgroup command\fP. -The return status is the exit status of -\fIlist\fP. -Note that unlike the metacharacters \fB(\fP and \fB)\fP, \fB{\fP and -\fB}\fP are \fIreserved words\fP and must occur where a reserved -word is permitted to be recognized. Since they do not cause a word -break, they must be separated from \fIlist\fP by whitespace or another -shell metacharacter. -.TP -((\fIexpression\fP)) -The \fIexpression\fP is evaluated according to the rules described -below under -.SM -.BR "ARITHMETIC EVALUATION" . -If the value of the expression is non-zero, the return status is 0; -otherwise the return status is 1. This is exactly equivalent to -\fBlet "\fIexpression\fP"\fR. -.TP -\fB[[\fP \fIexpression\fP \fB]]\fP -Return a status of 0 or 1 depending on the evaluation of -the conditional expression \fIexpression\fP. -Expressions are composed of the primaries described below under -.SM -.BR "CONDITIONAL EXPRESSIONS" . -Word splitting and pathname expansion are not performed on the words -between the \fB[[\fP and \fB]]\fP; tilde expansion, -parameter and variable expansion, -arithmetic expansion, command substitution, process -substitution, and quote removal are performed. -Conditional operators such as \fB\-f\fP must be unquoted to be recognized -as primaries. -.if t .sp 0.5 -.if n .sp 1 -When used with \fB[[\fP, the \fB<\fP and \fB>\fP operators sort -lexicographically using the current locale. -.if t .sp 0.5 -.if n .sp 1 -When the \fB==\fP and \fB!=\fP operators are used, the string to the -right of the operator is considered a pattern and matched according -to the rules described below under \fBPattern Matching\fP, -as if the \fBextglob\fP shell option were enabled. -The \fB=\fP operator is equivalent to \fB==\fP. -If the shell option -.B nocasematch -is enabled, the match is performed without regard to the case -of alphabetic characters. -The return value is 0 if the string matches (\fB==\fP) or does not match -(\fB!=\fP) the pattern, and 1 otherwise. -Any part of the pattern may be quoted to force the quoted portion -to be matched as a string. -.if t .sp 0.5 -.if n .sp 1 -An additional binary operator, \fB=~\fP, is available, with the same -precedence as \fB==\fP and \fB!=\fP. -When it is used, the string to the right of the operator is considered -an extended regular expression and matched accordingly (as in \fIregex\fP(3)). -The return value is 0 if the string matches -the pattern, and 1 otherwise. -If the regular expression is syntactically incorrect, the conditional -expression's return value is 2. -If the shell option -.B nocasematch -is enabled, the match is performed without regard to the case -of alphabetic characters. -Any part of the pattern may be quoted to force the quoted portion -to be matched as a string. -Bracket expressions in regular expressions must be treated carefully, -since normal quoting characters lose their meanings between brackets. -If the pattern is stored in a shell variable, quoting the variable -expansion forces the entire pattern to be matched as a string. -Substrings matched by parenthesized subexpressions within the regular -expression are saved in the array variable -.SM -.BR BASH_REMATCH . -The element of -.SM -.B BASH_REMATCH -with index 0 is the portion of the string -matching the entire regular expression. -The element of -.SM -.B BASH_REMATCH -with index \fIn\fP is the portion of the -string matching the \fIn\fPth parenthesized subexpression. -.if t .sp 0.5 -.if n .sp 1 -Expressions may be combined using the following operators, listed -in decreasing order of precedence: -.if t .sp 0.5 -.if n .sp 1 -.RS -.PD 0 -.TP -.B ( \fIexpression\fP ) -Returns the value of \fIexpression\fP. -This may be used to override the normal precedence of operators. -.TP -.B ! \fIexpression\fP -True if -.I expression -is false. -.TP -\fIexpression1\fP \fB&&\fP \fIexpression2\fP -True if both -.I expression1 -and -.I expression2 -are true. -.TP -\fIexpression1\fP \fB||\fP \fIexpression2\fP -True if either -.I expression1 -or -.I expression2 -is true. -.PD -.LP -The \fB&&\fP and \fB||\fP -operators do not evaluate \fIexpression2\fP if the value of -\fIexpression1\fP is sufficient to determine the return value of -the entire conditional expression. -.RE -.TP -\fBfor\fP \fIname\fP [ [ \fBin\fP [ \fIword ...\fP ] ] ; ] \fBdo\fP \fIlist\fP ; \fBdone\fP -The list of words following \fBin\fP is expanded, generating a list -of items. -The variable \fIname\fP is set to each element of this list -in turn, and \fIlist\fP is executed each time. -If the \fBin\fP \fIword\fP is omitted, the \fBfor\fP command executes -\fIlist\fP once for each positional parameter that is set (see -.SM -.B PARAMETERS -below). -The return status is the exit status of the last command that executes. -If the expansion of the items following \fBin\fP results in an empty -list, no commands are executed, and the return status is 0. -.TP -\fBfor\fP (( \fIexpr1\fP ; \fIexpr2\fP ; \fIexpr3\fP )) ; \fBdo\fP \fIlist\fP ; \fBdone\fP -First, the arithmetic expression \fIexpr1\fP is evaluated according -to the rules described below under -.SM -.BR "ARITHMETIC EVALUATION" . -The arithmetic expression \fIexpr2\fP is then evaluated repeatedly -until it evaluates to zero. -Each time \fIexpr2\fP evaluates to a non-zero value, \fIlist\fP is -executed and the arithmetic expression \fIexpr3\fP is evaluated. -If any expression is omitted, it behaves as if it evaluates to 1. -The return value is the exit status of the last command in \fIlist\fP -that is executed, or false if any of the expressions is invalid. -.TP -\fBselect\fP \fIname\fP [ \fBin\fP \fIword\fP ] ; \fBdo\fP \fIlist\fP ; \fBdone\fP -The list of words following \fBin\fP is expanded, generating a list -of items. The set of expanded words is printed on the standard -error, each preceded by a number. If the \fBin\fP -\fIword\fP is omitted, the positional parameters are printed (see -.SM -.B PARAMETERS -below). The -.SM -.B PS3 -prompt is then displayed and a line read from the standard input. -If the line consists of a number corresponding to one of -the displayed words, then the value of -.I name -is set to that word. If the line is empty, the words and prompt -are displayed again. If EOF is read, the command completes. Any -other value read causes -.I name -to be set to null. The line read is saved in the variable -.SM -.BR REPLY . -The -.I list -is executed after each selection until a -.B break -command is executed. -The exit status of -.B select -is the exit status of the last command executed in -.IR list , -or zero if no commands were executed. -.TP -\fBcase\fP \fIword\fP \fBin\fP [ [(] \fIpattern\fP [ \fB|\fP \fIpattern\fP ] \ -... ) \fIlist\fP ;; ] ... \fBesac\fP -A \fBcase\fP command first expands \fIword\fP, and tries to match -it against each \fIpattern\fP in turn, using the same matching rules -as for pathname expansion (see -.B Pathname Expansion -below). -The \fIword\fP is expanded using tilde -expansion, parameter and variable expansion, arithmetic substitution, -command substitution, process substitution and quote removal. -Each \fIpattern\fP examined is expanded using tilde -expansion, parameter and variable expansion, arithmetic substitution, -command substitution, and process substitution. -If the shell option -.B nocasematch -is enabled, the match is performed without regard to the case -of alphabetic characters. -When a match is found, the corresponding \fIlist\fP is executed. -If the \fB;;\fP operator is used, no subsequent matches are attempted after -the first pattern match. -Using \fB;&\fP in place of \fB;;\fP causes execution to continue with -the \fIlist\fP associated with the next set of patterns. -Using \fB;;&\fP in place of \fB;;\fP causes the shell to test the next -pattern list in the statement, if any, and execute any associated \fIlist\fP -on a successful match. -The exit status is zero if no -pattern matches. Otherwise, it is the exit status of the -last command executed in \fIlist\fP. -.TP -\fBif\fP \fIlist\fP; \fBthen\fP \fIlist\fP; \ -[ \fBelif\fP \fIlist\fP; \fBthen\fP \fIlist\fP; ] ... \ -[ \fBelse\fP \fIlist\fP; ] \fBfi\fP -The -.B if -.I list -is executed. If its exit status is zero, the -\fBthen\fP \fIlist\fP is executed. Otherwise, each \fBelif\fP -\fIlist\fP is executed in turn, and if its exit status is zero, -the corresponding \fBthen\fP \fIlist\fP is executed and the -command completes. Otherwise, the \fBelse\fP \fIlist\fP is -executed, if present. The exit status is the exit status of the -last command executed, or zero if no condition tested true. -.TP -\fBwhile\fP \fIlist-1\fP; \fBdo\fP \fIlist-2\fP; \fBdone\fP -.PD 0 -.TP -\fBuntil\fP \fIlist-1\fP; \fBdo\fP \fIlist-2\fP; \fBdone\fP -.PD -The \fBwhile\fP command continuously executes the list -\fIlist-2\fP as long as the last command in the list \fIlist-1\fP returns -an exit status of zero. The \fBuntil\fP command is identical -to the \fBwhile\fP command, except that the test is negated; -.I list-2 -is executed as long as the last command in -.I list-1 -returns a non-zero exit status. -The exit status of the \fBwhile\fP and \fBuntil\fP commands -is the exit status -of the last command executed in \fIlist-2\fP, or zero if -none was executed. -.SS Coprocesses -.PP -A \fIcoprocess\fP is a shell command preceded by the \fBcoproc\fP reserved -word. -A coprocess is executed asynchronously in a subshell, as if the command -had been terminated with the \fB&\fP control operator, with a two-way pipe -established between the executing shell and the coprocess. -.PP -The format for a coprocess is: -.RS -.PP -\fBcoproc\fP [\fINAME\fP] \fIcommand\fP [\fIredirections\fP] -.RE -.PP -This creates a coprocess named \fINAME\fP. -If \fINAME\fP is not supplied, the default name is \fBCOPROC\fP. -\fINAME\fP must not be supplied if \fIcommand\fP is a \fIsimple -command\fP (see above); otherwise, it is interpreted as the first word -of the simple command. -When the coprocess is executed, the shell creates an array variable (see -.B Arrays -below) named \fINAME\fP in the context of the executing shell. -The standard output of -.I command -is connected via a pipe to a file descriptor in the executing shell, -and that file descriptor is assigned to \fINAME\fP[0]. -The standard input of -.I command -is connected via a pipe to a file descriptor in the executing shell, -and that file descriptor is assigned to \fINAME\fP[1]. -This pipe is established before any redirections specified by the -command (see -.SM -.B REDIRECTION -below). -The file descriptors can be utilized as arguments to shell commands -and redirections using standard word expansions. -The file descriptors are not available in subshells. -The process ID of the shell spawned to execute the coprocess is -available as the value of the variable \fINAME\fP_PID. -The \fBwait\fP -builtin command may be used to wait for the coprocess to terminate. -.PP -Since the coprocess is created as an asynchronous command, -the \fBcoproc\fP command always returns success. -The return status of a coprocess is the exit status of \fIcommand\fP. -.SS Shell Function Definitions -.PP -A shell function is an object that is called like a simple command and -executes a compound command with a new set of positional parameters. -Shell functions are declared as follows: -.TP -\fIname\fP () \fIcompound\-command\fP [\fIredirection\fP] -.PD 0 -.TP -\fBfunction\fP \fIname\fP [()] \fIcompound\-command\fP [\fIredirection\fP] -.PD -This defines a function named \fIname\fP. -The reserved word \fBfunction\fP is optional. -If the \fBfunction\fP reserved word is supplied, the parentheses are optional. -The \fIbody\fP of the function is the compound command -.I compound\-command -(see \fBCompound Commands\fP above). -That command is usually a \fIlist\fP of commands between { and }, but -may be any command listed under \fBCompound Commands\fP above, -with one exception: If the \fBfunction\fP reserved word is used, but the -parentheses are not supplied, the braces are required. -\fIcompound\-command\fP is executed whenever \fIname\fP is specified as the -name of a simple command. -When in \fIposix mode\fP, \fIname\fP may not be the name of one of the -POSIX \fIspecial builtins\fP. -Any redirections (see -.SM -.B REDIRECTION -below) specified when a function is defined are performed -when the function is executed. -The exit status of a function definition is zero unless a syntax error -occurs or a readonly function with the same name already exists. -When executed, the exit status of a function is the exit status of the -last command executed in the body. (See -.SM -.B FUNCTIONS -below.) -.SH COMMENTS -In a non-interactive shell, or an interactive shell in which the -.B interactive_comments -option to the -.B shopt -builtin is enabled (see -.SM -.B "SHELL BUILTIN COMMANDS" -below), a word beginning with -.B # -causes that word and all remaining characters on that line to -be ignored. An interactive shell without the -.B interactive_comments -option enabled does not allow comments. The -.B interactive_comments -option is on by default in interactive shells. -.SH QUOTING -\fIQuoting\fP is used to remove the special meaning of certain -characters or words to the shell. Quoting can be used to -disable special treatment for special characters, to prevent -reserved words from being recognized as such, and to prevent -parameter expansion. -.PP -Each of the \fImetacharacters\fP listed above under -.SM -.B DEFINITIONS -has special meaning to the shell and must be quoted if it is to -represent itself. -.PP -When the command history expansion facilities are being used -(see -.SM -.B HISTORY EXPANSION -below), the -\fIhistory expansion\fP character, usually \fB!\fP, must be quoted -to prevent history expansion. -.PP -There are three quoting mechanisms: the -.IR "escape character" , -single quotes, and double quotes. -.PP -A non-quoted backslash (\fB\e\fP) is the -.IR "escape character" . -It preserves the literal value of the next character that follows, -with the exception of <newline>. If a \fB\e\fP<newline> pair -appears, and the backslash is not itself quoted, the \fB\e\fP<newline> -is treated as a line continuation (that is, it is removed from the -input stream and effectively ignored). -.PP -Enclosing characters in single quotes preserves the literal value -of each character within the quotes. A single quote may not occur -between single quotes, even when preceded by a backslash. -.PP -Enclosing characters in double quotes preserves the literal value -of all characters within the quotes, with the exception of -.BR $ , -.BR \` , -.BR \e , -and, when history expansion is enabled, -.BR ! . -The characters -.B $ -and -.B \` -retain their special meaning within double quotes. The backslash -retains its special meaning only when followed by one of the following -characters: -.BR $ , -.BR \` , -\^\fB"\fP\^, -.BR \e , -or -.BR <newline> . -A double quote may be quoted within double quotes by preceding it with -a backslash. -If enabled, history expansion will be performed unless an -.B ! -appearing in double quotes is escaped using a backslash. -The backslash preceding the -.B ! -is not removed. -.PP -The special parameters -.B * -and -.B @ -have special meaning when in double -quotes (see -.SM -.B PARAMETERS -below). -.PP -Words of the form \fB$\fP\(aq\fIstring\fP\(aq are treated specially. The -word expands to \fIstring\fP, with backslash-escaped characters replaced -as specified by the ANSI C standard. Backslash escape sequences, if -present, are decoded as follows: -.RS -.PD 0 -.TP -.B \ea -alert (bell) -.TP -.B \eb -backspace -.TP -.B \ee -.TP -.B \eE -an escape character -.TP -.B \ef -form feed -.TP -.B \en -new line -.TP -.B \er -carriage return -.TP -.B \et -horizontal tab -.TP -.B \ev -vertical tab -.TP -.B \e\e -backslash -.TP -.B \e\(aq -single quote -.TP -.B \e\(dq -double quote -.TP -.B \e\fInnn\fP -the eight-bit character whose value is the octal value \fInnn\fP -(one to three digits) -.TP -.B \ex\fIHH\fP -the eight-bit character whose value is the hexadecimal value \fIHH\fP -(one or two hex digits) -.TP -.B \eu\fIHHHH\fP -the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value -\fIHHHH\fP (one to four hex digits) -.TP -.B \eU\fIHHHHHHHH\fP -the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value -\fIHHHHHHHH\fP (one to eight hex digits) -.TP -.B \ec\fIx\fP -a control-\fIx\fP character -.PD -.RE -.LP -The expanded result is single-quoted, as if the dollar sign had -not been present. -.PP -A double-quoted string preceded by a dollar sign (\fB$\fP\(dq\fIstring\fP\(dq) -will cause the string to be translated according to the current locale. -If the current locale is \fBC\fP or \fBPOSIX\fP, the dollar sign -is ignored. -If the string is translated and replaced, the replacement is -double-quoted. -.SH PARAMETERS -A -.I parameter -is an entity that stores values. -It can be a -.IR name , -a number, or one of the special characters listed below under -.BR "Special Parameters" . -A -.I variable -is a parameter denoted by a -.IR name . -A variable has a \fIvalue\fP and zero or more \fIattributes\fP. -Attributes are assigned using the -.B declare -builtin command (see -.B declare -below in -.SM -.BR "SHELL BUILTIN COMMANDS" ). -.PP -A parameter is set if it has been assigned a value. The null string is -a valid value. Once a variable is set, it may be unset only by using -the -.B unset -builtin command (see -.SM -.B SHELL BUILTIN COMMANDS -below). -.PP -A -.I variable -may be assigned to by a statement of the form -.RS -.PP -\fIname\fP=[\fIvalue\fP] -.RE -.PP -If -.I value -is not given, the variable is assigned the null string. All -.I values -undergo tilde expansion, parameter and variable expansion, -command substitution, arithmetic expansion, and quote -removal (see -.SM -.B EXPANSION -below). If the variable has its -.B integer -attribute set, then -.I value -is evaluated as an arithmetic expression even if the $((...)) expansion is -not used (see -.B "Arithmetic Expansion" -below). -Word splitting is not performed, with the exception -of \fB"$@"\fP as explained below under -.BR "Special Parameters" . -Pathname expansion is not performed. -Assignment statements may also appear as arguments to the -.BR alias , -.BR declare , -.BR typeset , -.BR export , -.BR readonly , -and -.B local -builtin commands (\fIdeclaration\fP commands). -When in \fIposix mode\fP, these builtins may appear in a command after -one or more instances of the \fBcommand\fP builtin and retain these -assignment statement properties. -.PP -In the context where an assignment statement is assigning a value -to a shell variable or array index, the += operator can be used to -append to or add to the variable's previous value. -This includes arguments to builtin commands such as \fBdeclare\fP that -accept assignment statements (\fIdeclaration\fP commands). -When += is applied to a variable for which the \fIinteger\fP attribute has been -set, \fIvalue\fP is evaluated as an arithmetic expression and added to the -variable's current value, which is also evaluated. -When += is applied to an array variable using compound assignment (see -.B Arrays -below), the -variable's value is not unset (as it is when using =), and new values are -appended to the array beginning at one greater than the array's maximum index -(for indexed arrays) or added as additional key\-value pairs in an -associative array. -When applied to a string-valued variable, \fIvalue\fP is expanded and -appended to the variable's value. -.PP -A variable can be assigned the \fInameref\fP attribute using the -\fB\-n\fP option to the \fBdeclare\fP or \fBlocal\fP builtin commands -(see the descriptions of \fBdeclare\fP and \fBlocal\fP below) -to create a \fInameref\fP, or a reference to another variable. -This allows variables to be manipulated indirectly. -Whenever the nameref variable is referenced, assigned to, unset, or has -its attributes modified (other than the \fInameref\P attribute itself), the -operation is actually performed on the variable specified by the nameref -variable's value. -A nameref is commonly used within shell functions to refer to a variable -whose name is passed as an argument to the function. -For instance, if a variable name is passed to a shell function as its first -argument, running -.sp .5 -.RS -.if t \f(CWdeclare -n ref=$1\fP -.if n declare -n ref=$1 -.RE -.sp .5 -inside the function creates a nameref variable \fBref\fP whose value is -the variable name passed as the first argument. -References and assignments to \fBref\fP, and changes to its attributes, -are treated as references, assignments, and attribute modifications -to the variable whose name was passed as \fB$1\fP. -If the control variable in a \fBfor\fP loop has the nameref attribute, -the list of words can be a list of shell variables, and a name reference -will be established for each word in the list, in turn, when the loop is -executed. -Array variables cannot be given the \fB\nameref\fP attribute. -However, nameref variables can reference array variables and subscripted -array variables. -Namerefs can be unset using the \fB\-n\fP option to the \fBunset\fP builtin. -Otherwise, if \fBunset\fP is executed with the name of a nameref variable -as an argument, the variable referenced by the nameref variable will be unset. -.SS Positional Parameters -.PP -A -.I positional parameter -is a parameter denoted by one or more -digits, other than the single digit 0. Positional parameters are -assigned from the shell's arguments when it is invoked, -and may be reassigned using the -.B set -builtin command. Positional parameters may not be assigned to -with assignment statements. The positional parameters are -temporarily replaced when a shell function is executed (see -.SM -.B FUNCTIONS -below). -.PP -When a positional parameter consisting of more than a single -digit is expanded, it must be enclosed in braces (see -.SM -.B EXPANSION -below). -.SS Special Parameters -.PP -The shell treats several parameters specially. These parameters may -only be referenced; assignment to them is not allowed. -.PD 0 -.TP -.B * -Expands to the positional parameters, starting from one. -When the expansion is not within double quotes, each positional parameter -expands to a separate word. -In contexts where it is performed, those words -are subject to further word splitting and pathname expansion. -When the expansion occurs within double quotes, it expands to a single word -with the value of each parameter separated by the first character -of the -.SM -.B IFS -special variable. That is, "\fB$*\fP" is equivalent -to "\fB$1\fP\fIc\fP\fB$2\fP\fIc\fP\fB...\fP", where -.I c -is the first character of the value of the -.SM -.B IFS -variable. If -.SM -.B IFS -is unset, the parameters are separated by spaces. -If -.SM -.B IFS -is null, the parameters are joined without intervening separators. -.TP -.B @ -Expands to the positional parameters, starting from one. When the -expansion occurs within double quotes, each parameter expands to a -separate word. That is, "\fB$@\fP" is equivalent to -"\fB$1\fP" "\fB$2\fP" ... -If the double-quoted expansion occurs within a word, the expansion of -the first parameter is joined with the beginning part of the original -word, and the expansion of the last parameter is joined with the last -part of the original word. -When there are no positional parameters, "\fB$@\fP" and -.B $@ -expand to nothing (i.e., they are removed). -.TP -.B # -Expands to the number of positional parameters in decimal. -.TP -.B ? -Expands to the exit status of the most recently executed foreground -pipeline. -.TP -.B \- -Expands to the current option flags as specified upon invocation, -by the -.B set -builtin command, or those set by the shell itself -(such as the -.B \-i -option). -.TP -.B $ -Expands to the process ID of the shell. In a () subshell, it -expands to the process ID of the current shell, not the -subshell. -.TP -.B ! -Expands to the process ID of the job most recently placed into the -background, whether executed as an asynchronous command or using -the \fBbg\fP builtin (see -.SM -.B "JOB CONTROL" -below). -.TP -.B 0 -Expands to the name of the shell or shell script. This is set at -shell initialization. If -.B bash -is invoked with a file of commands, -.B $0 -is set to the name of that file. If -.B bash -is started with the -.B \-c -option, then -.B $0 -is set to the first argument after the string to be -executed, if one is present. Otherwise, it is set -to the filename used to invoke -.BR bash , -as given by argument zero. -.TP -.B _ -At shell startup, set to the absolute pathname used to invoke the -shell or shell script being executed as passed in the environment -or argument list. -Subsequently, expands to the last argument to the previous command, -after expansion. -Also set to the full pathname used to invoke each command executed -and placed in the environment exported to that command. -When checking mail, this parameter holds the name of the mail file -currently being checked. -.PD -.SS Shell Variables -.PP -The following variables are set by the shell: -.PP -.PD 0 -.TP -.B BASH -Expands to the full filename used to invoke this instance of -.BR bash . -.TP -.B BASHOPTS -A colon-separated list of enabled shell options. Each word in -the list is a valid argument for the -.B \-s -option to the -.B shopt -builtin command (see -.SM -.B "SHELL BUILTIN COMMANDS" -below). The options appearing in -.SM -.B BASHOPTS -are those reported as -.I on -by \fBshopt\fP. -If this variable is in the environment when -.B bash -starts up, each shell option in the list will be enabled before -reading any startup files. -This variable is read-only. -.TP -.B BASHPID -Expands to the process ID of the current \fBbash\fP process. -This differs from \fB$$\fP under certain circumstances, such as subshells -that do not require \fBbash\fP to be re-initialized. -.TP -.B BASH_ALIASES -An associative array variable whose members correspond to the internal -list of aliases as maintained by the \fBalias\fP builtin. -Elements added to this array appear in the alias list; unsetting array -elements cause aliases to be removed from the alias list. -.TP -.B BASH_ARGC -An array variable whose values are the number of parameters in each -frame of the current \fBbash\fP execution call stack. -The number of -parameters to the current subroutine (shell function or script executed -with \fB.\fP or \fBsource\fP) is at the top of the stack. -When a subroutine is executed, the number of parameters passed is pushed onto -.SM -.BR BASH_ARGC . -The shell sets -.SM -.B BASH_ARGC -only when in extended debugging mode (see the description of the -.B extdebug -option to the -.B shopt -builtin below) -.TP -.B BASH_ARGV -An array variable containing all of the parameters in the current \fBbash\fP -execution call stack. The final parameter of the last subroutine call -is at the top of the stack; the first parameter of the initial call is -at the bottom. When a subroutine is executed, the parameters supplied -are pushed onto -.SM -.BR BASH_ARGV . -The shell sets -.SM -.B BASH_ARGV -only when in extended debugging mode -(see the description of the -.B extdebug -option to the -.B shopt -builtin below) -.TP -.B BASH_CMDS -An associative array variable whose members correspond to the internal -hash table of commands as maintained by the \fBhash\fP builtin. -Elements added to this array appear in the hash table; unsetting array -elements cause commands to be removed from the hash table. -.TP -.B BASH_COMMAND -The command currently being executed or about to be executed, unless the -shell is executing a command as the result of a trap, -in which case it is the command executing at the time of the trap. -.TP -.B BASH_EXECUTION_STRING -The command argument to the \fB\-c\fP invocation option. -.TP -.B BASH_LINENO -An array variable whose members are the line numbers in source files -where each corresponding member of -.SM -.B FUNCNAME -was invoked. -\fB${BASH_LINENO[\fP\fI$i\fP\fB]}\fP is the line number in the source -file (\fB${BASH_SOURCE[\fP\fI$i+1\fP\fB]}\fP) where -\fB${FUNCNAME[\fP\fI$i\fP\fB]}\fP was called -(or \fB${BASH_LINENO[\fP\fI$i-1\fP\fB]}\fP if referenced within another -shell function). -Use -.SM -.B LINENO -to obtain the current line number. -.TP -.B BASH_REMATCH -An array variable whose members are assigned by the \fB=~\fP binary -operator to the \fB[[\fP conditional command. -The element with index 0 is the portion of the string -matching the entire regular expression. -The element with index \fIn\fP is the portion of the -string matching the \fIn\fPth parenthesized subexpression. -This variable is read-only. -.TP -.B BASH_SOURCE -An array variable whose members are the source filenames -where the corresponding shell function names in the -.SM -.B FUNCNAME -array variable are defined. -The shell function -\fB${FUNCNAME[\fP\fI$i\fP\fB]}\fP is defined in the file -\fB${BASH_SOURCE[\fP\fI$i\fP\fB]}\fP and called from -\fB${BASH_SOURCE[\fP\fI$i+1\fP\fB]}\fP. -.TP -.B BASH_SUBSHELL -Incremented by one within each subshell or subshell environment when -the shell begins executing in that environment. -The initial value is 0. -.TP -.B BASH_VERSINFO -A readonly array variable whose members hold version information for -this instance of -.BR bash . -The values assigned to the array members are as follows: -.sp .5 -.RS -.TP 24 -.B BASH_VERSINFO[\fR0\fP] -The major version number (the \fIrelease\fP). -.TP -.B BASH_VERSINFO[\fR1\fP] -The minor version number (the \fIversion\fP). -.TP -.B BASH_VERSINFO[\fR2\fP] -The patch level. -.TP -.B BASH_VERSINFO[\fR3\fP] -The build version. -.TP -.B BASH_VERSINFO[\fR4\fP] -The release status (e.g., \fIbeta1\fP). -.TP -.B BASH_VERSINFO[\fR5\fP] -The value of -.SM -.BR MACHTYPE . -.RE -.TP -.B BASH_VERSION -Expands to a string describing the version of this instance of -.BR bash . -.TP -.B COMP_CWORD -An index into \fB${COMP_WORDS}\fP of the word containing the current -cursor position. -This variable is available only in shell functions invoked by the -programmable completion facilities (see \fBProgrammable Completion\fP -below). -.TP -.B COMP_KEY -The key (or final key of a key sequence) used to invoke the current -completion function. -.TP -.B COMP_LINE -The current command line. -This variable is available only in shell functions and external -commands invoked by the -programmable completion facilities (see \fBProgrammable Completion\fP -below). -.TP -.B COMP_POINT -The index of the current cursor position relative to the beginning of -the current command. -If the current cursor position is at the end of the current command, -the value of this variable is equal to \fB${#COMP_LINE}\fP. -This variable is available only in shell functions and external -commands invoked by the -programmable completion facilities (see \fBProgrammable Completion\fP -below). -.TP -.B COMP_TYPE -Set to an integer value corresponding to the type of completion attempted -that caused a completion function to be called: -\fITAB\fP, for normal completion, -\fI?\fP, for listing completions after successive tabs, -\fI!\fP, for listing alternatives on partial word completion, -\fI@\fP, to list completions if the word is not unmodified, -or -\fI%\fP, for menu completion. -This variable is available only in shell functions and external -commands invoked by the -programmable completion facilities (see \fBProgrammable Completion\fP -below). -.TP -.B COMP_WORDBREAKS -The set of characters that the \fBreadline\fP library treats as word -separators when performing word completion. -If -.SM -.B COMP_WORDBREAKS -is unset, it loses its special properties, even if it is -subsequently reset. -.TP -.B COMP_WORDS -An array variable (see \fBArrays\fP below) consisting of the individual -words in the current command line. -The line is split into words as \fBreadline\fP would split it, using -.SM -.B COMP_WORDBREAKS -as described above. -This variable is available only in shell functions invoked by the -programmable completion facilities (see \fBProgrammable Completion\fP -below). -.TP -.B COPROC -An array variable (see \fBArrays\fP below) created to hold the file descriptors -for output from and input to an unnamed coprocess (see \fBCoprocesses\fP -above). -.TP -.B DIRSTACK -An array variable (see -.B Arrays -below) containing the current contents of the directory stack. -Directories appear in the stack in the order they are displayed by the -.B dirs -builtin. -Assigning to members of this array variable may be used to modify -directories already in the stack, but the -.B pushd -and -.B popd -builtins must be used to add and remove directories. -Assignment to this variable will not change the current directory. -If -.SM -.B DIRSTACK -is unset, it loses its special properties, even if it is -subsequently reset. -.TP -.B EUID -Expands to the effective user ID of the current user, initialized at -shell startup. This variable is readonly. -.TP -.B FUNCNAME -An array variable containing the names of all shell functions -currently in the execution call stack. -The element with index 0 is the name of any currently-executing -shell function. -The bottom-most element (the one with the highest index) is -.if t \f(CW"main"\fP. -.if n "main". -This variable exists only when a shell function is executing. -Assignments to -.SM -.B FUNCNAME -have no effect and return an error status. -If -.SM -.B FUNCNAME -is unset, it loses its special properties, even if it is -subsequently reset. -.if t .sp 0.5 -.if n .sp 1 -This variable can be used with \fBBASH_LINENO\fP and \fBBASH_SOURCE\fP. -Each element of \fBFUNCNAME\fP has corresponding elements in -\fBBASH_LINENO\fP and \fBBASH_SOURCE\fP to describe the call stack. -For instance, \fB${FUNCNAME[\fP\fI$i\fP\fB]}\fP was called from the file -\fB${BASH_SOURCE[\fP\fI$i+1\fP\fB]}\fP at line number -\fB${BASH_LINENO[\fP\fI$i\fP\fB]}\fP. -The \fBcaller\fP builtin displays the current call stack using this -information. -.TP -.B GROUPS -An array variable containing the list of groups of which the current -user is a member. -Assignments to -.SM -.B GROUPS -have no effect and return an error status. -If -.SM -.B GROUPS -is unset, it loses its special properties, even if it is -subsequently reset. -.TP -.B HISTCMD -The history number, or index in the history list, of the current -command. -If -.SM -.B HISTCMD -is unset, it loses its special properties, even if it is -subsequently reset. -.TP -.B HOSTNAME -Automatically set to the name of the current host. -.TP -.B HOSTTYPE -Automatically set to a string that uniquely -describes the type of machine on which -.B bash -is executing. -The default is system-dependent. -.TP -.B LINENO -Each time this parameter is referenced, the shell substitutes -a decimal number representing the current sequential line number -(starting with 1) within a script or function. When not in a -script or function, the value substituted is not guaranteed to -be meaningful. -If -.SM -.B LINENO -is unset, it loses its special properties, even if it is -subsequently reset. -.TP -.B MACHTYPE -Automatically set to a string that fully describes the system -type on which -.B bash -is executing, in the standard GNU \fIcpu-company-system\fP format. -The default is system-dependent. -.TP -.B MAPFILE -An array variable (see \fBArrays\fP below) created to hold the text -read by the \fBmapfile\fP builtin when no variable name is supplied. -.TP -.B OLDPWD -The previous working directory as set by the -.B cd -command. -.TP -.B OPTARG -The value of the last option argument processed by the -.B getopts -builtin command (see -.SM -.B SHELL BUILTIN COMMANDS -below). -.TP -.B OPTIND -The index of the next argument to be processed by the -.B getopts -builtin command (see -.SM -.B SHELL BUILTIN COMMANDS -below). -.TP -.B OSTYPE -Automatically set to a string that -describes the operating system on which -.B bash -is executing. -The default is system-dependent. -.TP -.B PIPESTATUS -An array variable (see -.B Arrays -below) containing a list of exit status values from the processes -in the most-recently-executed foreground pipeline (which may -contain only a single command). -.TP -.B PPID -The process ID of the shell's parent. This variable is readonly. -.TP -.B PWD -The current working directory as set by the -.B cd -command. -.TP -.B RANDOM -Each time this parameter is referenced, a random integer between -0 and 32767 is -generated. The sequence of random numbers may be initialized by assigning -a value to -.SM -.BR RANDOM . -If -.SM -.B RANDOM -is unset, it loses its special properties, even if it is -subsequently reset. -.TP -.B READLINE_LINE -The contents of the -.B readline -line buffer, for use with -.if t \f(CWbind -x\fP -.if n "bind -x" -(see -.SM -.B "SHELL BUILTIN COMMANDS" -below). -.TP -.B READLINE_POINT -The position of the insertion point in the -.B readline -line buffer, for use with -.if t \f(CWbind -x\fP -.if n "bind -x" -(see -.SM -.B "SHELL BUILTIN COMMANDS" -below). -.TP -.B REPLY -Set to the line of input read by the -.B read -builtin command when no arguments are supplied. -.TP -.B SECONDS -Each time this parameter is -referenced, the number of seconds since shell invocation is returned. If a -value is assigned to -.SM -.BR SECONDS , -the value returned upon subsequent -references is -the number of seconds since the assignment plus the value assigned. -If -.SM -.B SECONDS -is unset, it loses its special properties, even if it is -subsequently reset. -.TP -.B SHELLOPTS -A colon-separated list of enabled shell options. Each word in -the list is a valid argument for the -.B \-o -option to the -.B set -builtin command (see -.SM -.B "SHELL BUILTIN COMMANDS" -below). The options appearing in -.SM -.B SHELLOPTS -are those reported as -.I on -by \fBset \-o\fP. -If this variable is in the environment when -.B bash -starts up, each shell option in the list will be enabled before -reading any startup files. -This variable is read-only. -.TP -.B SHLVL -Incremented by one each time an instance of -.B bash -is started. -.TP -.B UID -Expands to the user ID of the current user, initialized at shell startup. -This variable is readonly. -.PD -.PP -The following variables are used by the shell. In some cases, -.B bash -assigns a default value to a variable; these cases are noted -below. -.PP -.PD 0 -.TP -.B BASH_COMPAT -The value is used to set the shell's compatibility level. -See the description of the \fBshopt\fP builtin below under -\fBSHELL BUILTIN COMMANDS\fP -for a description of the various compatibility -levels and their effects. -The value may be a decimal number (e.g., 4.2) or an integer (e.g., 42) -corresponding to the desired compatibility level. -If \fBBASH_COMPAT\fP is unset or set to the empty string, the compatibility -level is set to the default for the current version. -If \fBBASH_COMPAT\fP is set to a value that is not one of the valid -compatibility levels, the shell prints an error message and sets the -compatibility level to the default for the current version. -The valid compatibility levels correspond to the compatibility options -accepted by the \fBshopt\fP builtin described below (for example, -\fBcompat42\fP means that 4.2 and 42 are valid values). -The current version is also a valid value. -.TP -.B BASH_ENV -If this parameter is set when \fBbash\fP is executing a shell script, -its value is interpreted as a filename containing commands to -initialize the shell, as in -.IR ~/.bashrc . -The value of -.SM -.B BASH_ENV -is subjected to parameter expansion, command substitution, and arithmetic -expansion before being interpreted as a filename. -.SM -.B PATH -is not used to search for the resultant filename. -.TP -.B BASH_XTRACEFD -If set to an integer corresponding to a valid file descriptor, \fBbash\fP -will write the trace output generated when -.if t \f(CWset -x\fP -.if n \fIset -x\fP -is enabled to that file descriptor. -The file descriptor is closed when -.SM -.B BASH_XTRACEFD -is unset or assigned a new value. -Unsetting -.SM -.B BASH_XTRACEFD -or assigning it the empty string causes the -trace output to be sent to the standard error. -Note that setting -.SM -.B BASH_XTRACEFD -to 2 (the standard error file -descriptor) and then unsetting it will result in the standard error -being closed. -.TP -.B CDPATH -The search path for the -.B cd -command. -This is a colon-separated list of directories in which the shell looks -for destination directories specified by the -.B cd -command. -A sample value is -.if t \f(CW".:~:/usr"\fP. -.if n ".:~:/usr". -.TP -.B CHILD_MAX -Set the number of exited child status values for the shell to remember. -Bash will not allow this value to be decreased below a POSIX-mandated -minimum, and there is a maximum value (currently 8192) that this may -not exceed. -The minimum value is system-dependent. -.TP -.B COLUMNS -Used by the \fBselect\fP compound command to determine the terminal width -when printing selection lists. -Automatically set if the -.B checkwinsize -option is enabled or in an interactive shell upon receipt of a -.SM -.BR SIGWINCH . -.TP -.B COMPREPLY -An array variable from which \fBbash\fP reads the possible completions -generated by a shell function invoked by the programmable completion -facility (see \fBProgrammable Completion\fP below). -Each array element contains one possible completion. -.TP -.B EMACS -If \fBbash\fP finds this variable in the environment when the shell starts -with value -.if t \f(CWt\fP, -.if n "t", -it assumes that the shell is running in an Emacs shell buffer and disables -line editing. -.TP -.B ENV -Similar to -.SM -.BR BASH_ENV ; -used when the shell is invoked in POSIX mode. -.TP -.B FCEDIT -The default editor for the -.B fc -builtin command. -.TP -.B FIGNORE -A colon-separated list of suffixes to ignore when performing -filename completion (see -.SM -.B READLINE -below). -A filename whose suffix matches one of the entries in -.SM -.B FIGNORE -is excluded from the list of matched filenames. -A sample value is -.if t \f(CW".o:~"\fP. -.if n ".o:~". -.TP -.B FUNCNEST -If set to a numeric value greater than 0, defines a maximum function -nesting level. Function invocations that exceed this nesting level -will cause the current command to abort. -.TP -.B GLOBIGNORE -A colon-separated list of patterns defining the set of filenames to -be ignored by pathname expansion. -If a filename matched by a pathname expansion pattern also matches one -of the patterns in -.SM -.BR GLOBIGNORE , -it is removed from the list of matches. -.TP -.B HISTCONTROL -A colon-separated list of values controlling how commands are saved on -the history list. -If the list of values includes -.IR ignorespace , -lines which begin with a -.B space -character are not saved in the history list. -A value of -.I ignoredups -causes lines matching the previous history entry to not be saved. -A value of -.I ignoreboth -is shorthand for \fIignorespace\fP and \fIignoredups\fP. -A value of -.IR erasedups -causes all previous lines matching the current line to be removed from -the history list before that line is saved. -Any value not in the above list is ignored. -If -.SM -.B HISTCONTROL -is unset, or does not include a valid value, -all lines read by the shell parser are saved on the history list, -subject to the value of -.SM -.BR HISTIGNORE . -The second and subsequent lines of a multi-line compound command are -not tested, and are added to the history regardless of the value of -.SM -.BR HISTCONTROL . -.TP -.B HISTFILE -The name of the file in which command history is saved (see -.SM -.B HISTORY -below). The default value is \fI~/.bash_history\fP. If unset, the -command history is not saved when a shell exits. -.TP -.B HISTFILESIZE -The maximum number of lines contained in the history file. When this -variable is assigned a value, the history file is truncated, if -necessary, -to contain no more than that number of lines by removing the oldest entries. -The history file is also truncated to this size after -writing it when a shell exits. -If the value is 0, the history file is truncated to zero size. -Non-numeric values and numeric values less than zero inhibit truncation. -The shell sets the default value to the value of \fBHISTSIZE\fP -after reading any startup files. -.TP -.B HISTIGNORE -A colon-separated list of patterns used to decide which command lines -should be saved on the history list. Each pattern is anchored at the -beginning of the line and must match the complete line (no implicit -`\fB*\fP' is appended). Each pattern is tested against the line -after the checks specified by -.SM -.B HISTCONTROL -are applied. -In addition to the normal shell pattern matching characters, `\fB&\fP' -matches the previous history line. `\fB&\fP' may be escaped using a -backslash; the backslash is removed before attempting a match. -The second and subsequent lines of a multi-line compound command are -not tested, and are added to the history regardless of the value of -.SM -.BR HISTIGNORE . -.TP -.B HISTSIZE -The number of commands to remember in the command history (see -.SM -.B HISTORY -below). -If the value is 0, commands are not saved in the history list. -Numeric values less than zero result in every command being saved -on the history list (there is no limit). -The shell sets the default value to 500 after reading any startup files. -.TP -.B HISTTIMEFORMAT -If this variable is set and not null, its value is used as a format string -for \fIstrftime\fP(3) to print the time stamp associated with each history -entry displayed by the \fBhistory\fP builtin. -If this variable is set, time stamps are written to the history file so -they may be preserved across shell sessions. -This uses the history comment character to distinguish timestamps from -other history lines. -.TP -.B HOME -The home directory of the current user; the default argument for the -\fBcd\fP builtin command. -The value of this variable is also used when performing tilde expansion. -.TP -.B HOSTFILE -Contains the name of a file in the same format as -.FN /etc/hosts -that should be read when the shell needs to complete a -hostname. -The list of possible hostname completions may be changed while the -shell is running; -the next time hostname completion is attempted after the -value is changed, -.B bash -adds the contents of the new file to the existing list. -If -.SM -.B HOSTFILE -is set, but has no value, or does not name a readable file, -\fBbash\fP attempts to read -.FN /etc/hosts -to obtain the list of possible hostname completions. -When -.SM -.B HOSTFILE -is unset, the hostname list is cleared. -.TP -.B IFS -The -.I Internal Field Separator -that is used -for word splitting after expansion and to -split lines into words with the -.B read -builtin command. The default value is -``<space><tab><newline>''. -.TP -.B IGNOREEOF -Controls the -action of an interactive shell on receipt of an -.SM -.B EOF -character as the sole input. If set, the value is the number of -consecutive -.SM -.B EOF -characters which must be -typed as the first characters on an input line before -.B bash -exits. If the variable exists but does not have a numeric value, or -has no value, the default value is 10. If it does not exist, -.SM -.B EOF -signifies the end of input to the shell. -.TP -.B INPUTRC -The filename for the -.B readline -startup file, overriding the default of -.FN ~/.inputrc -(see -.SM -.B READLINE -below). -.TP -.B LANG -Used to determine the locale category for any category not specifically -selected with a variable starting with \fBLC_\fP. -.TP -.B LC_ALL -This variable overrides the value of -.SM -.B LANG -and any other -\fBLC_\fP variable specifying a locale category. -.TP -.B LC_COLLATE -This variable determines the collation order used when sorting the -results of pathname expansion, and determines the behavior of range -expressions, equivalence classes, and collating sequences within -pathname expansion and pattern matching. -.TP -.B LC_CTYPE -This variable determines the interpretation of characters and the -behavior of character classes within pathname expansion and pattern -matching. -.TP -.B LC_MESSAGES -This variable determines the locale used to translate double-quoted -strings preceded by a \fB$\fP. -.TP -.B LC_NUMERIC -This variable determines the locale category used for number formatting. -.TP -.B LINES -Used by the \fBselect\fP compound command to determine the column length -for printing selection lists. -Automatically set if the -.B checkwinsize -option is enabled or in an interactive shell upon receipt of a -.SM -.BR SIGWINCH . -.TP -.B MAIL -If this parameter is set to a file or directory name and the -.SM -.B MAILPATH -variable is not set, -.B bash -informs the user of the arrival of mail in the specified file or -Maildir-format directory. -.TP -.B MAILCHECK -Specifies how -often (in seconds) -.B bash -checks for mail. The default is 60 seconds. When it is time to check -for mail, the shell does so before displaying the primary prompt. -If this variable is unset, or set to a value that is not a number -greater than or equal to zero, the shell disables mail checking. -.TP -.B MAILPATH -A colon-separated list of filenames to be checked for mail. -The message to be printed when mail arrives in a particular file -may be specified by separating the filename from the message with a `?'. -When used in the text of the message, \fB$_\fP expands to the name of -the current mailfile. -Example: -.RS -.PP -\fBMAILPATH\fP=\(aq/var/mail/bfox?"You have mail":~/shell\-mail?"$_ has mail!"\(aq -.PP -.B Bash -supplies a default value for this variable, but the location of the user -mail files that it uses is system dependent (e.g., /var/mail/\fB$USER\fP). -.RE -.TP -.B OPTERR -If set to the value 1, -.B bash -displays error messages generated by the -.B getopts -builtin command (see -.SM -.B SHELL BUILTIN COMMANDS -below). -.SM -.B OPTERR -is initialized to 1 each time the shell is invoked or a shell -script is executed. -.TP -.B PATH -The search path for commands. It -is a colon-separated list of directories in which -the shell looks for commands (see -.SM -.B COMMAND EXECUTION -below). -A zero-length (null) directory name in the value of -.SM -.B PATH -indicates the current directory. -A null directory name may appear as two adjacent colons, or as an initial -or trailing colon. -The default path is system-dependent, -and is set by the administrator who installs -.BR bash . -A common value is -.if t \f(CW/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin\fP. -.if n ``/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin''. -.TP -.B POSIXLY_CORRECT -If this variable is in the environment when \fBbash\fP starts, the shell -enters \fIposix mode\fP before reading the startup files, as if the -.B \-\-posix -invocation option had been supplied. If it is set while the shell is -running, \fBbash\fP enables \fIposix mode\fP, as if the command -.if t \f(CWset -o posix\fP -.if n \fIset -o posix\fP -had been executed. -.TP -.B PROMPT_COMMAND -If set, the value is executed as a command prior to issuing each primary -prompt. -.TP -.B PROMPT_DIRTRIM -If set to a number greater than zero, the value is used as the number of -trailing directory components to retain when expanding the \fB\ew\fP and -\fB\eW\fP prompt string escapes (see -.SM -.B PROMPTING -below). Characters removed are replaced with an ellipsis. -.TP -.B PS1 -The value of this parameter is expanded (see -.SM -.B PROMPTING -below) and used as the primary prompt string. The default value is -``\fB\es\-\ev\e$ \fP''. -.TP -.B PS2 -The value of this parameter is expanded as with -.SM -.B PS1 -and used as the secondary prompt string. The default is -``\fB> \fP''. -.TP -.B PS3 -The value of this parameter is used as the prompt for the -.B select -command (see -.SM -.B SHELL GRAMMAR -above). -.TP -.B PS4 -The value of this parameter is expanded as with -.SM -.B PS1 -and the value is printed before each command -.B bash -displays during an execution trace. The first character of -.SM -.B PS4 -is replicated multiple times, as necessary, to indicate multiple -levels of indirection. The default is ``\fB+ \fP''. -.TP -.B SHELL -The full pathname to the shell is kept in this environment variable. -If it is not set when the shell starts, -.B bash -assigns to it the full pathname of the current user's login shell. -.TP -.B TIMEFORMAT -The value of this parameter is used as a format string specifying -how the timing information for pipelines prefixed with the -.B time -reserved word should be displayed. -The \fB%\fP character introduces an escape sequence that is -expanded to a time value or other information. -The escape sequences and their meanings are as follows; the -braces denote optional portions. -.sp .5 -.RS -.PD 0 -.TP 10 -.B %% -A literal \fB%\fP. -.TP -.B %[\fIp\fP][l]R -The elapsed time in seconds. -.TP -.B %[\fIp\fP][l]U -The number of CPU seconds spent in user mode. -.TP -.B %[\fIp\fP][l]S -The number of CPU seconds spent in system mode. -.TP -.B %P -The CPU percentage, computed as (%U + %S) / %R. -.PD -.RE -.IP -The optional \fIp\fP is a digit specifying the \fIprecision\fP, -the number of fractional digits after a decimal point. -A value of 0 causes no decimal point or fraction to be output. -At most three places after the decimal point may be specified; -values of \fIp\fP greater than 3 are changed to 3. -If \fIp\fP is not specified, the value 3 is used. -.IP -The optional \fBl\fP specifies a longer format, including -minutes, of the form \fIMM\fPm\fISS\fP.\fIFF\fPs. -The value of \fIp\fP determines whether or not the fraction is -included. -.IP -If this variable is not set, \fBbash\fP acts as if it had the -value \fB$\(aq\enreal\et%3lR\enuser\et%3lU\ensys\et%3lS\(aq\fP. -If the value is null, no timing information is displayed. -A trailing newline is added when the format string is displayed. -.PD 0 -.TP -.B TMOUT -If set to a value greater than zero, -.SM -.B TMOUT -is treated as the -default timeout for the \fBread\fP builtin. -The \fBselect\fP command terminates if input does not arrive -after -.SM -.B TMOUT -seconds when input is coming from a terminal. -In an interactive shell, the value is interpreted as the -number of seconds to wait for a line of input after issuing the -primary prompt. -.B Bash -terminates after waiting for that number of seconds if a complete -line of input does not arrive. -.TP -.B TMPDIR -If set, \fBbash\fP uses its value as the name of a directory in which -\fBbash\fP creates temporary files for the shell's use. -.TP -.B auto_resume -This variable controls how the shell interacts with the user and -job control. If this variable is set, single word simple -commands without redirections are treated as candidates for resumption -of an existing stopped job. There is no ambiguity allowed; if there is -more than one job beginning with the string typed, the job most recently -accessed is selected. The -.I name -of a stopped job, in this context, is the command line used to -start it. -If set to the value -.IR exact , -the string supplied must match the name of a stopped job exactly; -if set to -.IR substring , -the string supplied needs to match a substring of the name of a -stopped job. The -.I substring -value provides functionality analogous to the -.B %? -job identifier (see -.SM -.B JOB CONTROL -below). If set to any other value, the supplied string must -be a prefix of a stopped job's name; this provides functionality -analogous to the \fB%\fP\fIstring\fP job identifier. -.TP -.B histchars -The two or three characters which control history expansion -and tokenization (see -.SM -.B HISTORY EXPANSION -below). The first character is the \fIhistory expansion\fP character, -the character which signals the start of a history -expansion, normally `\fB!\fP'. -The second character is the \fIquick substitution\fP -character, which is used as shorthand for re-running the previous -command entered, substituting one string for another in the command. -The default is `\fB^\fP'. -The optional third character is the character -which indicates that the remainder of the line is a comment when found -as the first character of a word, normally `\fB#\fP'. The history -comment character causes history substitution to be skipped for the -remaining words on the line. It does not necessarily cause the shell -parser to treat the rest of the line as a comment. -.PD -.SS Arrays -.B Bash -provides one-dimensional indexed and associative array variables. -Any variable may be used as an indexed array; the -.B declare -builtin will explicitly declare an array. -There is no maximum -limit on the size of an array, nor any requirement that members -be indexed or assigned contiguously. -Indexed arrays are referenced using integers (including arithmetic -expressions) and are zero-based; associative arrays are referenced -using arbitrary strings. -Unless otherwise noted, indexed array indices must be non-negative integers. -.PP -An indexed array is created automatically if any variable is assigned to -using the syntax \fIname\fP[\fIsubscript\fP]=\fIvalue\fP. The -.I subscript -is treated as an arithmetic expression that must evaluate to a number. -To explicitly declare an indexed array, use -.B declare \-a \fIname\fP -(see -.SM -.B SHELL BUILTIN COMMANDS -below). -.B declare \-a \fIname\fP[\fIsubscript\fP] -is also accepted; the \fIsubscript\fP is ignored. -.PP -Associative arrays are created using -.BR "declare \-A \fIname\fP" . -.PP -Attributes may be -specified for an array variable using the -.B declare -and -.B readonly -builtins. Each attribute applies to all members of an array. -.PP -Arrays are assigned to using compound assignments of the form -\fIname\fP=\fB(\fPvalue\fI1\fP ... value\fIn\fP\fB)\fP, where each -\fIvalue\fP is of the form [\fIsubscript\fP]=\fIstring\fP. -Indexed array assignments do not require anything but \fIstring\fP. -When assigning to indexed arrays, if the optional brackets and subscript -are supplied, that index is assigned to; -otherwise the index of the element assigned is the last index assigned -to by the statement plus one. Indexing starts at zero. -.PP -When assigning to an associative array, the subscript is required. -.PP -This syntax is also accepted by the -.B declare -builtin. Individual array elements may be assigned to using the -\fIname\fP[\fIsubscript\fP]=\fIvalue\fP syntax introduced above. -When assigning to an indexed array, if -.I name -is subscripted by a negative number, that number is -interpreted as relative to one greater than the maximum index of -\fIname\fP, so negative indices count back from the end of the -array, and an index of \-1 references the last element. -.PP -Any element of an array may be referenced using -${\fIname\fP[\fIsubscript\fP]}. The braces are required to avoid -conflicts with pathname expansion. If -\fIsubscript\fP is \fB@\fP or \fB*\fP, the word expands to -all members of \fIname\fP. These subscripts differ only when the -word appears within double quotes. If the word is double-quoted, -${\fIname\fP[*]} expands to a single -word with the value of each array member separated by the first -character of the -.SM -.B IFS -special variable, and ${\fIname\fP[@]} expands each element of -\fIname\fP to a separate word. When there are no array members, -${\fIname\fP[@]} expands to nothing. -If the double-quoted expansion occurs within a word, the expansion of -the first parameter is joined with the beginning part of the original -word, and the expansion of the last parameter is joined with the last -part of the original word. -This is analogous to the expansion -of the special parameters \fB*\fP and \fB@\fP (see -.B Special Parameters -above). ${#\fIname\fP[\fIsubscript\fP]} expands to the length of -${\fIname\fP[\fIsubscript\fP]}. If \fIsubscript\fP is \fB*\fP or -\fB@\fP, the expansion is the number of elements in the array. -Referencing an array variable without a subscript is equivalent to -referencing the array with a subscript of 0. -If the -.I subscript -used to reference an element of an indexed array -evaluates to a number less than zero, it is -interpreted as relative to one greater than the maximum index of the array, -so negative indices count back from the end of the -array, and an index of \-1 references the last element. -.PP -An array variable is considered set if a subscript has been assigned a -value. The null string is a valid value. -.PP -It is possible to obtain the keys (indices) of an array as well as the values. -${\fB!\fP\fIname\fP[\fI@\fP]} and ${\fB!\fP\fIname\fP[\fI*\fP]} -expand to the indices assigned in array variable \fIname\fP. -The treatment when in double quotes is similar to the expansion of the -special parameters \fI@\fP and \fI*\fP within double quotes. -.PP -The -.B unset -builtin is used to destroy arrays. \fBunset\fP \fIname\fP[\fIsubscript\fP] -destroys the array element at index \fIsubscript\fP. -Negative subscripts to indexed arrays are interpreted as described above. -Care must be taken to avoid unwanted side effects caused by pathname -expansion. -\fBunset\fP \fIname\fP, where \fIname\fP is an array, or -\fBunset\fP \fIname\fP[\fIsubscript\fP], where -\fIsubscript\fP is \fB*\fP or \fB@\fP, removes the entire array. -.PP -The -.BR declare , -.BR local , -and -.B readonly -builtins each accept a -.B \-a -option to specify an indexed array and a -.B \-A -option to specify an associative array. -If both options are supplied, -.B \-A -takes precedence. -The -.B read -builtin accepts a -.B \-a -option to assign a list of words read from the standard input -to an array. The -.B set -and -.B declare -builtins display array values in a way that allows them to be -reused as assignments. -.SH EXPANSION -Expansion is performed on the command line after it has been split into -words. There are seven kinds of expansion performed: -.IR "brace expansion" , -.IR "tilde expansion" , -.IR "parameter and variable expansion" , -.IR "command substitution" , -.IR "arithmetic expansion" , -.IR "word splitting" , -and -.IR "pathname expansion" . -.PP -The order of expansions is: -brace expansion; -tilde expansion, parameter and variable expansion, arithmetic expansion, -and command substitution (done in a left-to-right fashion); -word splitting; -and pathname expansion. -.PP -On systems that can support it, there is an additional expansion -available: \fIprocess substitution\fP. -This is performed at the -same time as tilde, parameter, variable, and arithmetic expansion and -command substitution. -.PP -Only brace expansion, word splitting, and pathname expansion -can change the number of words of the expansion; other expansions -expand a single word to a single word. -The only exceptions to this are the expansions of -"\fB$@\fP" and "\fB${\fP\fIname\fP\fB[@]}\fP" -as explained above (see -.SM -.BR PARAMETERS ). -.SS Brace Expansion -.PP -.I "Brace expansion" -is a mechanism by which arbitrary strings -may be generated. This mechanism is similar to -\fIpathname expansion\fP, but the filenames generated -need not exist. Patterns to be brace expanded take -the form of an optional -.IR preamble , -followed by either a series of comma-separated strings or -a sequence expression between a pair of braces, followed by -an optional -.IR postscript . -The preamble is prefixed to each string contained -within the braces, and the postscript is then appended -to each resulting string, expanding left to right. -.PP -Brace expansions may be nested. The results of each expanded -string are not sorted; left to right order is preserved. -For example, a\fB{\fPd,c,b\fB}\fPe expands into `ade ace abe'. -.PP -A sequence expression takes the form -\fB{\fP\fIx\fP\fB..\fP\fIy\fP\fB[..\fP\fIincr\fP\fB]}\fP, -where \fIx\fP and \fIy\fP are either integers or single characters, -and \fIincr\fP, an optional increment, is an integer. -When integers are supplied, the expression expands to each number between -\fIx\fP and \fIy\fP, inclusive. -Supplied integers may be prefixed with \fI0\fP to force each term to have the -same width. -When either \fIx\fP or \fPy\fP begins with a zero, the shell -attempts to force all generated terms to contain the same number of digits, -zero-padding where necessary. -When characters are supplied, the expression expands to each character -lexicographically between \fIx\fP and \fIy\fP, inclusive, -using the default C locale. -Note that both \fIx\fP and \fIy\fP must be of the same type. -When the increment is supplied, it is used as the difference between -each term. The default increment is 1 or -1 as appropriate. -.PP -Brace expansion is performed before any other expansions, -and any characters special to other expansions are preserved -in the result. It is strictly textual. -.B Bash -does not apply any syntactic interpretation to the context of the -expansion or the text between the braces. -.PP -A correctly-formed brace expansion must contain unquoted opening -and closing braces, and at least one unquoted comma or a valid -sequence expression. -Any incorrectly formed brace expansion is left unchanged. -A \fB{\fP or \fB,\fP may be quoted with a backslash to prevent its -being considered part of a brace expression. -To avoid conflicts with parameter expansion, the string \fB${\fP -is not considered eligible for brace expansion. -.PP -This construct is typically used as shorthand when the common -prefix of the strings to be generated is longer than in the -above example: -.RS -.PP -mkdir /usr/local/src/bash/{old,new,dist,bugs} -.RE -or -.RS -chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}} -.RE -.PP -Brace expansion introduces a slight incompatibility with -historical versions of -.BR sh . -.B sh -does not treat opening or closing braces specially when they -appear as part of a word, and preserves them in the output. -.B Bash -removes braces from words as a consequence of brace -expansion. For example, a word entered to -.B sh -as \fIfile{1,2}\fP -appears identically in the output. The same word is -output as -.I file1 file2 -after expansion by -.BR bash . -If strict compatibility with -.B sh -is desired, start -.B bash -with the -.B +B -option or disable brace expansion with the -.B +B -option to the -.B set -command (see -.SM -.B SHELL BUILTIN COMMANDS -below). -.SS Tilde Expansion -.PP -If a word begins with an unquoted tilde character (`\fB~\fP'), all of -the characters preceding the first unquoted slash (or all characters, -if there is no unquoted slash) are considered a \fItilde-prefix\fP. -If none of the characters in the tilde-prefix are quoted, the -characters in the tilde-prefix following the tilde are treated as a -possible \fIlogin name\fP. -If this login name is the null string, the tilde is replaced with the -value of the shell parameter -.SM -.BR HOME . -If -.SM -.B HOME -is unset, the home directory of the user executing the shell is -substituted instead. -Otherwise, the tilde-prefix is replaced with the home directory -associated with the specified login name. -.PP -If the tilde-prefix is a `~+', the value of the shell variable -.SM -.B PWD -replaces the tilde-prefix. -If the tilde-prefix is a `~\-', the value of the shell variable -.SM -.BR OLDPWD , -if it is set, is substituted. -If the characters following the tilde in the tilde-prefix consist -of a number \fIN\fP, optionally prefixed -by a `+' or a `\-', the tilde-prefix is replaced with the corresponding -element from the directory stack, as it would be displayed by the -.B dirs -builtin invoked with the tilde-prefix as an argument. -If the characters following the tilde in the tilde-prefix consist of a -number without a leading `+' or `\-', `+' is assumed. -.PP -If the login name is invalid, or the tilde expansion fails, the word -is unchanged. -.PP -Each variable assignment is checked for unquoted tilde-prefixes immediately -following a -.B : -or the first -.BR = . -In these cases, tilde expansion is also performed. -Consequently, one may use filenames with tildes in assignments to -.SM -.BR PATH , -.SM -.BR MAILPATH , -and -.SM -.BR CDPATH , -and the shell assigns the expanded value. -.SS Parameter Expansion -.PP -The `\fB$\fP' character introduces parameter expansion, -command substitution, or arithmetic expansion. The parameter name -or symbol to be expanded may be enclosed in braces, which -are optional but serve to protect the variable to be expanded from -characters immediately following it which could be -interpreted as part of the name. -.PP -When braces are used, the matching ending brace is the first `\fB}\fP' -not escaped by a backslash or within a quoted string, and not within an -embedded arithmetic expansion, command substitution, or parameter -expansion. -.PP -.PD 0 -.TP -${\fIparameter\fP} -The value of \fIparameter\fP is substituted. The braces are required -when -.I parameter -is a positional parameter with more than one digit, -or when -.I parameter -is followed by a character which is not to be -interpreted as part of its name. -The \fIparameter\fP is a shell parameter as described above -\fBPARAMETERS\fP) or an array reference (\fBArrays\fP). -.PD -.PP -If the first character of \fIparameter\fP is an exclamation point (\fB!\fP), -it introduces a level of variable indirection. -\fBBash\fP uses the value of the variable formed from the rest of -\fIparameter\fP as the name of the variable; this variable is then -expanded and that value is used in the rest of the substitution, rather -than the value of \fIparameter\fP itself. -This is known as \fIindirect expansion\fP. -The exceptions to this are the expansions of ${\fB!\fP\fIprefix\fP\fB*\fP} and -${\fB!\fP\fIname\fP[\fI@\fP]} described below. -The exclamation point must immediately follow the left brace in order to -introduce indirection. -.PP -In each of the cases below, \fIword\fP is subject to tilde expansion, -parameter expansion, command substitution, and arithmetic expansion. -.PP -When not performing substring expansion, using the forms documented below -(e.g., \fB:-\fP), -\fBbash\fP tests for a parameter that is unset or null. Omitting the colon -results in a test only for a parameter that is unset. -.PP -.PD 0 -.TP -${\fIparameter\fP\fB:\-\fP\fIword\fP} -\fBUse Default Values\fP. If -.I parameter -is unset or null, the expansion of -.I word -is substituted. Otherwise, the value of -.I parameter -is substituted. -.TP -${\fIparameter\fP\fB:=\fP\fIword\fP} -\fBAssign Default Values\fP. -If -.I parameter -is unset or null, the expansion of -.I word -is assigned to -.IR parameter . -The value of -.I parameter -is then substituted. Positional parameters and special parameters may -not be assigned to in this way. -.TP -${\fIparameter\fP\fB:?\fP\fIword\fP} -\fBDisplay Error if Null or Unset\fP. -If -.I parameter -is null or unset, the expansion of \fIword\fP (or a message to that effect -if -.I word -is not present) is written to the standard error and the shell, if it -is not interactive, exits. Otherwise, the value of \fIparameter\fP is -substituted. -.TP -${\fIparameter\fP\fB:+\fP\fIword\fP} -\fBUse Alternate Value\fP. -If -.I parameter -is null or unset, nothing is substituted, otherwise the expansion of -.I word -is substituted. -.TP -${\fIparameter\fP\fB:\fP\fIoffset\fP} -.PD 0 -.TP -${\fIparameter\fP\fB:\fP\fIoffset\fP\fB:\fP\fIlength\fP} -.PD -\fBSubstring Expansion\fP. -Expands to up to \fIlength\fP characters of the value of \fIparameter\fP -starting at the character specified by \fIoffset\fP. -If \fIparameter\fP is \fB@\fP, an indexed array subscripted by -\fB@\fP or \fB*\fP, or an associative array name, the results differ as -described below. -If \fIlength\fP is omitted, expands to the substring of the value of -\fIparameter\fP starting at the character specified by \fIoffset\fP -and extending to the end of the value. -\fIlength\fP and \fIoffset\fP are arithmetic expressions (see -.SM -.B -ARITHMETIC EVALUATION -below). -.sp 1 -If \fIoffset\fP evaluates to a number less than zero, the value -is used as an offset in characters -from the end of the value of \fIparameter\fP. -If \fIlength\fP evaluates to a number less than zero, -it is interpreted as an offset in characters -from the end of the value of \fIparameter\fP rather than -a number of characters, and the expansion is the characters between -\fIoffset\fP and that result. -Note that a negative offset must be separated from the colon by at least -one space to avoid being confused with the \fB:-\fP expansion. -.sp 1 -If \fIparameter\fP is \fB@\fP, the result is \fIlength\fP positional -parameters beginning at \fIoffset\fP. -A negative \fIoffset\fP is taken relative to one greater than the greatest -positional parameter, so an offset of -1 evaluates to the last positional -parameter. -It is an expansion error if \fIlength\fP evaluates to a number less than -zero. -.sp 1 -If \fIparameter\fP is an indexed array name subscripted by @ or *, -the result is the \fIlength\fP -members of the array beginning with ${\fIparameter\fP[\fIoffset\fP]}. -A negative \fIoffset\fP is taken relative to one greater than the maximum -index of the specified array. -It is an expansion error if \fIlength\fP evaluates to a number less than -zero. -.sp 1 -Substring expansion applied to an associative array produces undefined -results. -.sp 1 -Substring indexing is zero-based unless the positional parameters -are used, in which case the indexing starts at 1 by default. -If \fIoffset\fP is 0, and the positional parameters are used, \fB$0\fP is -prefixed to the list. -.TP -${\fB!\fP\fIprefix\fP\fB*\fP} -.PD 0 -.TP -${\fB!\fP\fIprefix\fP\fB@\fP} -.PD -\fBNames matching prefix\fP. -Expands to the names of variables whose names begin with \fIprefix\fP, -separated by the first character of the -.SM -.B IFS -special variable. -When \fI@\fP is used and the expansion appears within double quotes, each -variable name expands to a separate word. -.TP -${\fB!\fP\fIname\fP[\fI@\fP]} -.PD 0 -.TP -${\fB!\fP\fIname\fP[\fI*\fP]} -.PD -\fBList of array keys\fP. -If \fIname\fP is an array variable, expands to the list of array indices -(keys) assigned in \fIname\fP. -If \fIname\fP is not an array, expands to 0 if \fIname\fP is set and null -otherwise. -When \fI@\fP is used and the expansion appears within double quotes, each -key expands to a separate word. -.TP -${\fB#\fP\fIparameter\fP} -\fBParameter length\fP. -The length in characters of the value of \fIparameter\fP is substituted. -If -.I parameter -is -.B * -or -.BR @ , -the value substituted is the number of positional parameters. -If -.I parameter -is an array name subscripted by -.B * -or -.BR @ , -the value substituted is the number of elements in the array. -If -.I parameter -is an indexed array name subscripted by a negative number, that number is -interpreted as relative to one greater than the maximum index of -\fIparameter\fP, so negative indices count back from the end of the -array, and an index of \-1 references the last element. -.TP -${\fIparameter\fP\fB#\fP\fIword\fP} -.PD 0 -.TP -${\fIparameter\fP\fB##\fP\fIword\fP} -.PD -\fBRemove matching prefix pattern\fP. -The -.I word -is expanded to produce a pattern just as in pathname -expansion. If the pattern matches the beginning of -the value of -.IR parameter , -then the result of the expansion is the expanded value of -.I parameter -with the shortest matching pattern (the ``\fB#\fP'' case) or the -longest matching pattern (the ``\fB##\fP'' case) deleted. -If -.I parameter -is -.B @ -or -.BR * , -the pattern removal operation is applied to each positional -parameter in turn, and the expansion is the resultant list. -If -.I parameter -is an array variable subscripted with -.B @ -or -.BR * , -the pattern removal operation is applied to each member of the -array in turn, and the expansion is the resultant list. -.TP -${\fIparameter\fP\fB%\fP\fIword\fP} -.PD 0 -.TP -${\fIparameter\fP\fB%%\fP\fIword\fP} -.PD -\fBRemove matching suffix pattern\fP. -The \fIword\fP is expanded to produce a pattern just as in -pathname expansion. -If the pattern matches a trailing portion of the expanded value of -.IR parameter , -then the result of the expansion is the expanded value of -.I parameter -with the shortest matching pattern (the ``\fB%\fP'' case) or the -longest matching pattern (the ``\fB%%\fP'' case) deleted. -If -.I parameter -is -.B @ -or -.BR * , -the pattern removal operation is applied to each positional -parameter in turn, and the expansion is the resultant list. -If -.I parameter -is an array variable subscripted with -.B @ -or -.BR * , -the pattern removal operation is applied to each member of the -array in turn, and the expansion is the resultant list. -.TP -${\fIparameter\fP\fB/\fP\fIpattern\fP\fB/\fP\fIstring\fP} -\fBPattern substitution\fP. -The \fIpattern\fP is expanded to produce a pattern just as in -pathname expansion. -\fIParameter\fP is expanded and the longest match of \fIpattern\fP -against its value is replaced with \fIstring\fP. -If \fIpattern\fP begins with \fB/\fP, all matches of \fIpattern\fP are -replaced with \fIstring\fP. Normally only the first match is replaced. -If \fIpattern\fP begins with \fB#\fP, it must match at the beginning -of the expanded value of \fIparameter\fP. -If \fIpattern\fP begins with \fB%\fP, it must match at the end -of the expanded value of \fIparameter\fP. -If \fIstring\fP is null, matches of \fIpattern\fP are deleted -and the \fB/\fP following \fIpattern\fP may be omitted. -If -.I parameter -is -.B @ -or -.BR * , -the substitution operation is applied to each positional -parameter in turn, and the expansion is the resultant list. -If -.I parameter -is an array variable subscripted with -.B @ -or -.BR * , -the substitution operation is applied to each member of the -array in turn, and the expansion is the resultant list. -.TP -${\fIparameter\fP\fB^\fP\fIpattern\fP} -.PD 0 -.TP -${\fIparameter\fP\fB^^\fP\fIpattern\fP} -.TP -${\fIparameter\fP\fB,\fP\fIpattern\fP} -.TP -${\fIparameter\fP\fB,,\fP\fIpattern\fP} -.PD -\fBCase modification\fP. -This expansion modifies the case of alphabetic characters in \fIparameter\fP. -The \fIpattern\fP is expanded to produce a pattern just as in -pathname expansion. -Each character in the expanded value of \fIparameter\fP is tested against -\fIpattern\fP, and, if it matches the pattern, its case is converted. -The pattern should not attempt to match more than one character. -The \fB^\fP operator converts lowercase letters matching \fIpattern\fP -to uppercase; the \fB,\fP operator converts matching uppercase letters -to lowercase. -The \fB^^\fP and \fB,,\fP expansions convert each matched character in the -expanded value; the \fB^\fP and \fB,\fP expansions match and convert only -the first character in the expanded value. -If \fIpattern\fP is omitted, it is treated like a \fB?\fP, which matches -every character. -If -.I parameter -is -.B @ -or -.BR * , -the case modification operation is applied to each positional -parameter in turn, and the expansion is the resultant list. -If -.I parameter -is an array variable subscripted with -.B @ -or -.BR * , -the case modification operation is applied to each member of the -array in turn, and the expansion is the resultant list. -.SS Command Substitution -.PP -\fICommand substitution\fP allows the output of a command to replace -the command name. There are two forms: -.RS -.PP -\fB$(\fP\fIcommand\fP\|\fB)\fP -.RE -or -.RS -\fB\`\fP\fIcommand\fP\fB\`\fP -.RE -.PP -.B Bash -performs the expansion by executing \fIcommand\fP and -replacing the command substitution with the standard output of the -command, with any trailing newlines deleted. -Embedded newlines are not deleted, but they may be removed during -word splitting. -The command substitution \fB$(cat \fIfile\fP)\fR can be replaced by -the equivalent but faster \fB$(< \fIfile\fP)\fR. -.PP -When the old-style backquote form of substitution is used, -backslash retains its literal meaning except when followed by -.BR $ , -.BR \` , -or -.BR \e . -The first backquote not preceded by a backslash terminates the -command substitution. -When using the $(\^\fIcommand\fP\|) form, all characters between the -parentheses make up the command; none are treated specially. -.PP -Command substitutions may be nested. To nest when using the backquoted form, -escape the inner backquotes with backslashes. -.PP -If the substitution appears within double quotes, word splitting and -pathname expansion are not performed on the results. -.SS Arithmetic Expansion -.PP -Arithmetic expansion allows the evaluation of an arithmetic expression -and the substitution of the result. The format for arithmetic expansion is: -.RS -.PP -\fB$((\fP\fIexpression\fP\fB))\fP -.RE -.PP -The -.I expression -is treated as if it were within double quotes, but a double quote -inside the parentheses is not treated specially. -All tokens in the expression undergo parameter and variable expansion, -command substitution, and quote removal. -The result is treated as the arithmetic expression to be evaluated. -Arithmetic expansions may be nested. -.PP -The evaluation is performed according to the rules listed below under -.SM -.BR "ARITHMETIC EVALUATION" . -If -.I expression -is invalid, -.B bash -prints a message indicating failure and no substitution occurs. -.SS Process Substitution -.PP -\fIProcess substitution\fP is supported on systems that support named -pipes (\fIFIFOs\fP) or the \fB/dev/fd\fP method of naming open files. -It takes the form of -\fB<(\fP\fIlist\^\fP\fB)\fP -or -\fB>(\fP\fIlist\^\fP\fB)\fP. -The process \fIlist\fP is run with its input or output connected to a -\fIFIFO\fP or some file in \fB/dev/fd\fP. The name of this file is -passed as an argument to the current command as the result of the -expansion. If the \fB>(\fP\fIlist\^\fP\fB)\fP form is used, writing to -the file will provide input for \fIlist\fP. If the -\fB<(\fP\fIlist\^\fP\fB)\fP form is used, the file passed as an -argument should be read to obtain the output of \fIlist\fP. -.PP -When available, process substitution is performed -simultaneously with parameter and variable expansion, -command substitution, -and arithmetic expansion. -.SS Word Splitting -.PP -The shell scans the results of -parameter expansion, -command substitution, -and -arithmetic expansion -that did not occur within double quotes for -.IR "word splitting" . -.PP -The shell treats each character of -.SM -.B IFS -as a delimiter, and splits the results of the other -expansions into words using these characters as field terminators. -If -.SM -.B IFS -is unset, or its -value is exactly -.BR <space><tab><newline> , -the default, then -sequences of -.BR <space> , -.BR <tab> , -and -.B <newline> -at the beginning and end of the results of the previous -expansions are ignored, and -any sequence of -.SM -.B IFS -characters not at the beginning or end serves to delimit words. -If -.SM -.B IFS -has a value other than the default, then sequences of -the whitespace characters -.B space -and -.B tab -are ignored at the beginning and end of the -word, as long as the whitespace character is in the -value of -.SM -.BR IFS -(an -.SM -.B IFS -whitespace character). -Any character in -.SM -.B IFS -that is not -.SM -.B IFS -whitespace, along with any adjacent -.SM -.B IFS -whitespace characters, delimits a field. -A sequence of -.SM -.B IFS -whitespace characters is also treated as a delimiter. -If the value of -.SM -.B IFS -is null, no word splitting occurs. -.PP -Explicit null arguments (\^\f3"\^"\fP or \^\f3\(aq\^\(aq\fP\^) are retained. -Unquoted implicit null arguments, resulting from the expansion of -parameters that have no values, are removed. -If a parameter with no value is expanded within double quotes, a -null argument results and is retained. -.PP -Note that if no expansion occurs, no splitting -is performed. -.SS Pathname Expansion -.PP -After word splitting, -unless the -.B \-f -option has been set, -.B bash -scans each word for the characters -.BR * , -.BR ? , -and -.BR [ . -If one of these characters appears, then the word is -regarded as a -.IR pattern , -and replaced with an alphabetically sorted list of -filenames matching the pattern -(see -.SM -.B "Pattern Matching" -below). -If no matching filenames are found, -and the shell option -.B nullglob -is not enabled, the word is left unchanged. -If the -.B nullglob -option is set, and no matches are found, -the word is removed. -If the -.B failglob -shell option is set, and no matches are found, an error message -is printed and the command is not executed. -If the shell option -.B nocaseglob -is enabled, the match is performed without regard to the case -of alphabetic characters. -When a pattern is used for pathname expansion, -the character -.B ``.'' -at the start of a name or immediately following a slash -must be matched explicitly, unless the shell option -.B dotglob -is set. -When matching a pathname, the slash character must always be -matched explicitly. -In other cases, the -.B ``.'' -character is not treated specially. -See the description of -.B shopt -below under -.SM -.B SHELL BUILTIN COMMANDS -for a description of the -.BR nocaseglob , -.BR nullglob , -.BR failglob , -and -.B dotglob -shell options. -.PP -The -.SM -.B GLOBIGNORE -shell variable may be used to restrict the set of filenames matching a -.IR pattern . -If -.SM -.B GLOBIGNORE -is set, each matching filename that also matches one of the patterns in -.SM -.B GLOBIGNORE -is removed from the list of matches. -The filenames -.B ``.'' -and -.B ``..'' -are always ignored when -.SM -.B GLOBIGNORE -is set and not null. However, setting -.SM -.B GLOBIGNORE -to a non-null value has the effect of enabling the -.B dotglob -shell option, so all other filenames beginning with a -.B ``.'' -will match. -To get the old behavior of ignoring filenames beginning with a -.BR ``.'' , -make -.B ``.*'' -one of the patterns in -.SM -.BR GLOBIGNORE . -The -.B dotglob -option is disabled when -.SM -.B GLOBIGNORE -is unset. -.PP -\fBPattern Matching\fP -.PP -Any character that appears in a pattern, other than the special pattern -characters described below, matches itself. The NUL character may not -occur in a pattern. A backslash escapes the following character; the -escaping backslash is discarded when matching. -The special pattern characters must be quoted if -they are to be matched literally. -.PP -The special pattern characters have the following meanings: -.PP -.PD 0 -.RS -.TP -.B * -Matches any string, including the null string. -When the \fBglobstar\fP shell option is enabled, and \fB*\fP is used in -a pathname expansion context, two adjacent \fB*\fPs used as a single -pattern will match all files and zero or more directories and -subdirectories. -If followed by a \fB/\fP, two adjacent \fB*\fPs will match only directories -and subdirectories. -.TP -.B ? -Matches any single character. -.TP -.B [...] -Matches any one of the enclosed characters. A pair of characters -separated by a hyphen denotes a -\fIrange expression\fP; -any character that falls between those two characters, inclusive, -using the current locale's collating sequence and character set, -is matched. If the first character following the -.B [ -is a -.B ! -or a -.B ^ -then any character not enclosed is matched. -The sorting order of characters in range expressions is determined by -the current locale and the values of the -.SM -.B LC_COLLATE -or -.SM -.B LC_ALL -shell variables, if set. -To obtain the traditional interpretation of range expressions, where -.B [a\-d] -is equivalent to -.BR [abcd] , -set value of the -.B LC_ALL -shell variable to -.BR C , -or enable the -.B globasciiranges -shell option. -A -.B \- -may be matched by including it as the first or last character -in the set. -A -.B ] -may be matched by including it as the first character -in the set. -.br -.if t .sp 0.5 -.if n .sp 1 -Within -.B [ -and -.BR ] , -\fIcharacter classes\fP can be specified using the syntax -\fB[:\fP\fIclass\fP\fB:]\fP, where \fIclass\fP is one of the -following classes defined in the POSIX standard: -.PP -.RS -.B -.if n alnum alpha ascii blank cntrl digit graph lower print punct space upper word xdigit -.if t alnum alpha ascii blank cntrl digit graph lower print punct space upper word xdigit -.br -A character class matches any character belonging to that class. -The \fBword\fP character class matches letters, digits, and the character _. -.br -.if t .sp 0.5 -.if n .sp 1 -Within -.B [ -and -.BR ] , -an \fIequivalence class\fP can be specified using the syntax -\fB[=\fP\fIc\fP\fB=]\fP, which matches all characters with the -same collation weight (as defined by the current locale) as -the character \fIc\fP. -.br -.if t .sp 0.5 -.if n .sp 1 -Within -.B [ -and -.BR ] , -the syntax \fB[.\fP\fIsymbol\fP\fB.]\fP matches the collating symbol -\fIsymbol\fP. -.RE -.RE -.PD -.PP -If the \fBextglob\fP shell option is enabled using the \fBshopt\fP -builtin, several extended pattern matching operators are recognized. -In the following description, a \fIpattern-list\fP is a list of one -or more patterns separated by a \fB|\fP. -Composite patterns may be formed using one or more of the following -sub-patterns: -.sp 1 -.PD 0 -.RS -.TP -\fB?(\fP\^\fIpattern-list\^\fP\fB)\fP -Matches zero or one occurrence of the given patterns -.TP -\fB*(\fP\^\fIpattern-list\^\fP\fB)\fP -Matches zero or more occurrences of the given patterns -.TP -\fB+(\fP\^\fIpattern-list\^\fP\fB)\fP -Matches one or more occurrences of the given patterns -.TP -\fB@(\fP\^\fIpattern-list\^\fP\fB)\fP -Matches one of the given patterns -.TP -\fB!(\fP\^\fIpattern-list\^\fP\fB)\fP -Matches anything except one of the given patterns -.RE -.PD -.SS Quote Removal -.PP -After the preceding expansions, all unquoted occurrences of the -characters -.BR \e , -.BR \(aq , -and \^\f3"\fP\^ that did not result from one of the above -expansions are removed. -.SH REDIRECTION -Before a command is executed, its input and output -may be -.I redirected -using a special notation interpreted by the shell. -Redirection allows commands' file handles to be -duplicated, opened, closed, -made to refer to different files, -and can change the files the command reads from and writes to. -Redirection may also be used to modify file handles in the -current shell execution environment. -The following redirection -operators may precede or appear anywhere within a -.I simple command -or may follow a -.IR command . -Redirections are processed in the order they appear, from -left to right. -.PP -Each redirection that may be preceded by a file descriptor number -may instead be preceded by a word of the form {\fIvarname\fP}. -In this case, for each redirection operator except ->&- and <&-, the shell will allocate a file descriptor greater -than or equal to 10 and assign it to \fIvarname\fP. -If >&- or <&- is preceded -by {\fIvarname\fP}, the value of \fIvarname\fP defines the file -descriptor to close. -.PP -In the following descriptions, if the file descriptor number is -omitted, and the first character of the redirection operator is -.BR < , -the redirection refers to the standard input (file descriptor -0). If the first character of the redirection operator is -.BR > , -the redirection refers to the standard output (file descriptor -1). -.PP -The word following the redirection operator in the following -descriptions, unless otherwise noted, is subjected to -brace expansion, tilde expansion, parameter and variable expansion, -command substitution, arithmetic expansion, quote removal, -pathname expansion, and word splitting. -If it expands to more than one word, -.B bash -reports an error. -.PP -Note that the order of redirections is significant. For example, -the command -.RS -.PP -ls \fB>\fP dirlist 2\fB>&\fP1 -.RE -.PP -directs both standard output and standard error to the file -.IR dirlist , -while the command -.RS -.PP -ls 2\fB>&\fP1 \fB>\fP dirlist -.RE -.PP -directs only the standard output to file -.IR dirlist , -because the standard error was duplicated from the standard output -before the standard output was redirected to -.IR dirlist . -.PP -\fBBash\fP handles several filenames specially when they are used in -redirections, as described in the following table: -.RS -.PP -.PD 0 -.TP -.B /dev/fd/\fIfd\fP -If \fIfd\fP is a valid integer, file descriptor \fIfd\fP is duplicated. -.TP -.B /dev/stdin -File descriptor 0 is duplicated. -.TP -.B /dev/stdout -File descriptor 1 is duplicated. -.TP -.B /dev/stderr -File descriptor 2 is duplicated. -.TP -.B /dev/tcp/\fIhost\fP/\fIport\fP -If \fIhost\fP is a valid hostname or Internet address, and \fIport\fP -is an integer port number or service name, \fBbash\fP attempts to open -the corresponding TCP socket. -.TP -.B /dev/udp/\fIhost\fP/\fIport\fP -If \fIhost\fP is a valid hostname or Internet address, and \fIport\fP -is an integer port number or service name, \fBbash\fP attempts to open -the corresponding UDP socket. -.PD -.RE -.PP -A failure to open or create a file causes the redirection to fail. -.PP -Redirections using file descriptors greater than 9 should be used with -care, as they may conflict with file descriptors the shell uses -internally. -.SS Redirecting Input -.PP -Redirection of input causes the file whose name results from -the expansion of -.I word -to be opened for reading on file descriptor -.IR n , -or the standard input (file descriptor 0) if -.I n -is not specified. -.PP -The general format for redirecting input is: -.RS -.PP -[\fIn\fP]\fB<\fP\fIword\fP -.RE -.SS Redirecting Output -.PP -Redirection of output causes the file whose name results from -the expansion of -.I word -to be opened for writing on file descriptor -.IR n , -or the standard output (file descriptor 1) if -.I n -is not specified. If the file does not exist it is created; -if it does exist it is truncated to zero size. -.PP -The general format for redirecting output is: -.RS -.PP -[\fIn\fP]\fB>\fP\fIword\fP -.RE -.PP -If the redirection operator is -.BR > , -and the -.B noclobber -option to the -.B set -builtin has been enabled, the redirection will fail if the file -whose name results from the expansion of \fIword\fP exists and is -a regular file. -If the redirection operator is -.BR >| , -or the redirection operator is -.B > -and the -.B noclobber -option to the -.B set -builtin command is not enabled, the redirection is attempted even -if the file named by \fIword\fP exists. -.SS Appending Redirected Output -.PP -Redirection of output in this fashion -causes the file whose name results from -the expansion of -.I word -to be opened for appending on file descriptor -.IR n , -or the standard output (file descriptor 1) if -.I n -is not specified. If the file does not exist it is created. -.PP -The general format for appending output is: -.RS -.PP -[\fIn\fP]\fB>>\fP\fIword\fP -.RE -.PP -.SS Redirecting Standard Output and Standard Error -.PP -This construct allows both the -standard output (file descriptor 1) and -the standard error output (file descriptor 2) -to be redirected to the file whose name is the -expansion of -.IR word . -.PP -There are two formats for redirecting standard output and -standard error: -.RS -.PP -\fB&>\fP\fIword\fP -.RE -and -.RS -\fB>&\fP\fIword\fP -.RE -.PP -Of the two forms, the first is preferred. -This is semantically equivalent to -.RS -.PP -\fB>\fP\fIword\fP 2\fB>&\fP1 -.RE -.PP -When using the second form, \fIword\fP may not expand to a number or -\fB\-\fP. If it does, other redirection operators apply -(see \fBDuplicating File Descriptors\fP below) for compatibility -reasons. -.SS Appending Standard Output and Standard Error -.PP -This construct allows both the -standard output (file descriptor 1) and -the standard error output (file descriptor 2) -to be appended to the file whose name is the -expansion of -.IR word . -.PP -The format for appending standard output and standard error is: -.RS -.PP -\fB&>>\fP\fIword\fP -.RE -.PP -This is semantically equivalent to -.RS -.PP -\fB>>\fP\fIword\fP 2\fB>&\fP1 -.RE -.PP -(see \fBDuplicating File Descriptors\fP below). -.SS Here Documents -.PP -This type of redirection instructs the shell to read input from the -current source until a line containing only -.I delimiter -(with no trailing blanks) -is seen. All of -the lines read up to that point are then used as the standard -input for a command. -.PP -The format of here-documents is: -.RS -.PP -.nf -\fB<<\fP[\fB\-\fP]\fIword\fP - \fIhere-document\fP -\fIdelimiter\fP -.fi -.RE -.PP -No parameter and variable expansion, command substitution, -arithmetic expansion, or pathname expansion is performed on -.IR word . -If any characters in -.I word -are quoted, the -.I delimiter -is the result of quote removal on -.IR word , -and the lines in the here-document are not expanded. -If \fIword\fP is unquoted, -all lines of the here-document are subjected to -parameter expansion, command substitution, and arithmetic expansion, -the character sequence -.B \e<newline> -is ignored, and -.B \e -must be used to quote the characters -.BR \e , -.BR $ , -and -.BR \` . -.PP -If the redirection operator is -.BR <<\- , -then all leading tab characters are stripped from input lines and the -line containing -.IR delimiter . -This allows -here-documents within shell scripts to be indented in a -natural fashion. -.SS "Here Strings" -A variant of here documents, the format is: -.RS -.PP -.nf -\fB<<<\fP\fIword\fP -.fi -.RE -.PP -The \fIword\fP undergoes -brace expansion, tilde expansion, parameter and variable expansion, -command substitution, arithmetic expansion, and quote removal. -Pathname expansion and word splitting are not performed. -The result is supplied as a single string to the command on its -standard input. -.SS "Duplicating File Descriptors" -.PP -The redirection operator -.RS -.PP -[\fIn\fP]\fB<&\fP\fIword\fP -.RE -.PP -is used to duplicate input file descriptors. -If -.I word -expands to one or more digits, the file descriptor denoted by -.I n -is made to be a copy of that file descriptor. -If the digits in -.I word -do not specify a file descriptor open for input, a redirection error occurs. -If -.I word -evaluates to -.BR \- , -file descriptor -.I n -is closed. If -.I n -is not specified, the standard input (file descriptor 0) is used. -.PP -The operator -.RS -.PP -[\fIn\fP]\fB>&\fP\fIword\fP -.RE -.PP -is used similarly to duplicate output file descriptors. If -.I n -is not specified, the standard output (file descriptor 1) is used. -If the digits in -.I word -do not specify a file descriptor open for output, a redirection error occurs. -If -.I word -evaluates to -.BR \- , -file descriptor -.I n -is closed. -As a special case, if \fIn\fP is omitted, and \fIword\fP does not -expand to one or more digits or \fB\-\fP, the standard output and standard -error are redirected as described previously. -.SS "Moving File Descriptors" -.PP -The redirection operator -.RS -.PP -[\fIn\fP]\fB<&\fP\fIdigit\fP\fB\-\fP -.RE -.PP -moves the file descriptor \fIdigit\fP to file descriptor -.IR n , -or the standard input (file descriptor 0) if \fIn\fP is not specified. -\fIdigit\fP is closed after being duplicated to \fIn\fP. -.PP -Similarly, the redirection operator -.RS -.PP -[\fIn\fP]\fB>&\fP\fIdigit\fP\fB\-\fP -.RE -.PP -moves the file descriptor \fIdigit\fP to file descriptor -.IR n , -or the standard output (file descriptor 1) if \fIn\fP is not specified. -.SS "Opening File Descriptors for Reading and Writing" -.PP -The redirection operator -.RS -.PP -[\fIn\fP]\fB<>\fP\fIword\fP -.RE -.PP -causes the file whose name is the expansion of -.I word -to be opened for both reading and writing on file descriptor -.IR n , -or on file descriptor 0 if -.I n -is not specified. If the file does not exist, it is created. -.SH ALIASES -\fIAliases\fP allow a string to be substituted for a word when it is used -as the first word of a simple command. -The shell maintains a list of aliases that may be set and unset with the -.B alias -and -.B unalias -builtin commands (see -.SM -.B SHELL BUILTIN COMMANDS -below). -The first word of each simple command, if unquoted, -is checked to see if it has an -alias. If so, that word is replaced by the text of the alias. -The characters \fB/\fP, \fB$\fP, \fB\`\fP, and \fB=\fP and -any of the shell \fImetacharacters\fP or quoting characters -listed above may not appear in an alias name. -The replacement text may contain any valid shell input, -including shell metacharacters. -The first word of the replacement text is tested -for aliases, but a word that is identical to an alias being expanded -is not expanded a second time. -This means that one may alias -.B ls -to -.BR "ls \-F" , -for instance, and -.B bash -does not try to recursively expand the replacement text. -If the last character of the alias value is a -.IR blank , -then the next command -word following the alias is also checked for alias expansion. -.PP -Aliases are created and listed with the -.B alias -command, and removed with the -.B unalias -command. -.PP -There is no mechanism for using arguments in the replacement text. -If arguments are needed, a shell function should be used (see -.SM -.B FUNCTIONS -below). -.PP -Aliases are not expanded when the shell is not interactive, unless -the -.B expand_aliases -shell option is set using -.B shopt -(see the description of -.B shopt -under -.SM -\fBSHELL BUILTIN COMMANDS\fP -below). -.PP -The rules concerning the definition and use of aliases are -somewhat confusing. -.B Bash -always reads at least one complete line -of input before executing any -of the commands on that line. Aliases are expanded when a -command is read, not when it is executed. Therefore, an -alias definition appearing on the same line as another -command does not take effect until the next line of input is read. -The commands following the alias definition -on that line are not affected by the new alias. -This behavior is also an issue when functions are executed. -Aliases are expanded when a function definition is read, -not when the function is executed, because a function definition -is itself a command. As a consequence, aliases -defined in a function are not available until after that -function is executed. To be safe, always put -alias definitions on a separate line, and do not use -.B alias -in compound commands. -.PP -For almost every purpose, aliases are superseded by -shell functions. -.SH FUNCTIONS -A shell function, defined as described above under -.SM -.BR "SHELL GRAMMAR" , -stores a series of commands for later execution. -When the name of a shell function is used as a simple command name, -the list of commands associated with that function name is executed. -Functions are executed in the context of the -current shell; no new process is created to interpret -them (contrast this with the execution of a shell script). -When a function is executed, the arguments to the -function become the positional parameters -during its execution. -The special parameter -.B # -is updated to reflect the change. Special parameter \fB0\fP -is unchanged. -The first element of the -.SM -.B FUNCNAME -variable is set to the name of the function while the function -is executing. -.PP -All other aspects of the shell execution -environment are identical between a function and its caller -with these exceptions: the -.SM -.B DEBUG -and -.B RETURN -traps (see the description of the -.B trap -builtin under -.SM -.B SHELL BUILTIN COMMANDS -below) are not inherited unless the function has been given the -\fBtrace\fP attribute (see the description of the -.SM -.B declare -builtin below) or the -\fB\-o functrace\fP shell option has been enabled with -the \fBset\fP builtin -(in which case all functions inherit the \fBDEBUG\fP and \fBRETURN\fP traps), -and the -.SM -.B ERR -trap is not inherited unless the \fB\-o errtrace\fP shell option has -been enabled. -.PP -Variables local to the function may be declared with the -.B local -builtin command. Ordinarily, variables and their values -are shared between the function and its caller. -.PP -The \fBFUNCNEST\fP variable, if set to a numeric value greater -than 0, defines a maximum function nesting level. Function -invocations that exceed the limit cause the entire command to -abort. -.PP -If the builtin command -.B return -is executed in a function, the function completes and -execution resumes with the next command after the function -call. -Any command associated with the \fBRETURN\fP trap is executed -before execution resumes. -When a function completes, the values of the -positional parameters and the special parameter -.B # -are restored to the values they had prior to the function's -execution. -.PP -Function names and definitions may be listed with the -.B \-f -option to the -.B declare -or -.B typeset -builtin commands. The -.B \-F -option to -.B declare -or -.B typeset -will list the function names only -(and optionally the source file and line number, if the \fBextdebug\fP -shell option is enabled). -Functions may be exported so that subshells -automatically have them defined with the -.B \-f -option to the -.B export -builtin. -A function definition may be deleted using the \fB\-f\fP option to -the -.B unset -builtin. -Note that shell functions and variables with the same name may result -in multiple identically-named entries in the environment passed to the -shell's children. -Care should be taken in cases where this may cause a problem. -.PP -Functions may be recursive. -The \fBFUNCNEST\fP variable may be used to limit the depth of the -function call stack and restrict the number of function invocations. -By default, no limit is imposed on the number of recursive calls. -.SH "ARITHMETIC EVALUATION" -The shell allows arithmetic expressions to be evaluated, under -certain circumstances (see the \fBlet\fP and \fBdeclare\fP builtin -commands and \fBArithmetic Expansion\fP). -Evaluation is done in fixed-width integers with no check for overflow, -though division by 0 is trapped and flagged as an error. -The operators and their precedence, associativity, and values -are the same as in the C language. -The following list of operators is grouped into levels of -equal-precedence operators. -The levels are listed in order of decreasing precedence. -.PP -.PD 0 -.TP -.B \fIid\fP++ \fIid\fP\-\- -variable post-increment and post-decrement -.TP -.B ++\fIid\fP \-\-\fIid\fP -variable pre-increment and pre-decrement -.TP -.B \- + -unary minus and plus -.TP -.B ! ~ -logical and bitwise negation -.TP -.B ** -exponentiation -.TP -.B * / % -multiplication, division, remainder -.TP -.B + \- -addition, subtraction -.TP -.B << >> -left and right bitwise shifts -.TP -.B <= >= < > -comparison -.TP -.B == != -equality and inequality -.TP -.B & -bitwise AND -.TP -.B ^ -bitwise exclusive OR -.TP -.B | -bitwise OR -.TP -.B && -logical AND -.TP -.B || -logical OR -.TP -.B \fIexpr\fP?\fIexpr\fP:\fIexpr\fP -conditional operator -.TP -.B = *= /= %= += \-= <<= >>= &= ^= |= -assignment -.TP -.B \fIexpr1\fP , \fIexpr2\fP -comma -.PD -.PP -Shell variables are allowed as operands; parameter expansion is -performed before the expression is evaluated. -Within an expression, shell variables may also be referenced by name -without using the parameter expansion syntax. -A shell variable that is null or unset evaluates to 0 when referenced -by name without using the parameter expansion syntax. -The value of a variable is evaluated as an arithmetic expression -when it is referenced, or when a variable which has been given the -\fIinteger\fP attribute using \fBdeclare -i\fP is assigned a value. -A null value evaluates to 0. -A shell variable need not have its \fIinteger\fP attribute -turned on to be used in an expression. -.PP -Constants with a leading 0 are interpreted as octal numbers. -A leading 0x or 0X denotes hexadecimal. -Otherwise, numbers take the form [\fIbase#\fP]n, where the optional \fIbase\fP -is a decimal number between 2 and 64 representing the arithmetic -base, and \fIn\fP is a number in that base. -If \fIbase#\fP is omitted, then base 10 is used. -When specifying \fIn\fP, -the digits greater< than 9 are represented by the lowercase letters, -the uppercase letters, @, and _, in that order. -If \fIbase\fP is less than or equal to 36, lowercase and uppercase -letters may be used interchangeably to represent numbers between 10 -and 35. -.PP -Operators are evaluated in order of precedence. Sub-expressions in -parentheses are evaluated first and may override the precedence -rules above. -.SH "CONDITIONAL EXPRESSIONS" -Conditional expressions are used by the \fB[[\fP compound command and -the \fBtest\fP and \fB[\fP builtin commands to test file attributes -and perform string and arithmetic comparisons. -Expressions are formed from the following unary or binary primaries. -If any \fIfile\fP argument to one of the primaries is of the form -\fI/dev/fd/n\fP, then file descriptor \fIn\fP is checked. -If the \fIfile\fP argument to one of the primaries is one of -\fI/dev/stdin\fP, \fI/dev/stdout\fP, or \fI/dev/stderr\fP, file -descriptor 0, 1, or 2, respectively, is checked. -.PP -Unless otherwise specified, primaries that operate on files follow symbolic -links and operate on the target of the link, rather than the link itself. -.if t .sp 0.5 -.if n .sp 1 -When used with \fB[[\fP, the \fB<\fP and \fB>\fP operators sort -lexicographically using the current locale. -The \fBtest\fP command sorts using ASCII ordering. -.sp 1 -.PD 0 -.TP -.B \-a \fIfile\fP -True if \fIfile\fP exists. -.TP -.B \-b \fIfile\fP -True if \fIfile\fP exists and is a block special file. -.TP -.B \-c \fIfile\fP -True if \fIfile\fP exists and is a character special file. -.TP -.B \-d \fIfile\fP -True if \fIfile\fP exists and is a directory. -.TP -.B \-e \fIfile\fP -True if \fIfile\fP exists. -.TP -.B \-f \fIfile\fP -True if \fIfile\fP exists and is a regular file. -.TP -.B \-g \fIfile\fP -True if \fIfile\fP exists and is set-group-id. -.TP -.B \-h \fIfile\fP -True if \fIfile\fP exists and is a symbolic link. -.TP -.B \-k \fIfile\fP -True if \fIfile\fP exists and its ``sticky'' bit is set. -.TP -.B \-p \fIfile\fP -True if \fIfile\fP exists and is a named pipe (FIFO). -.TP -.B \-r \fIfile\fP -True if \fIfile\fP exists and is readable. -.TP -.B \-s \fIfile\fP -True if \fIfile\fP exists and has a size greater than zero. -.TP -.B \-t \fIfd\fP -True if file descriptor -.I fd -is open and refers to a terminal. -.TP -.B \-u \fIfile\fP -True if \fIfile\fP exists and its set-user-id bit is set. -.TP -.B \-w \fIfile\fP -True if \fIfile\fP exists and is writable. -.TP -.B \-x \fIfile\fP -True if \fIfile\fP exists and is executable. -.TP -.B \-G \fIfile\fP -True if \fIfile\fP exists and is owned by the effective group id. -.TP -.B \-L \fIfile\fP -True if \fIfile\fP exists and is a symbolic link. -.TP -.B \-N \fIfile\fP -True if \fIfile\fP exists and has been modified since it was last read. -.TP -.B \-O \fIfile\fP -True if \fIfile\fP exists and is owned by the effective user id. -.TP -.B \-S \fIfile\fP -True if \fIfile\fP exists and is a socket. -.TP -\fIfile1\fP \fB\-ef\fP \fIfile2\fP -True if \fIfile1\fP and \fIfile2\fP refer to the same device and -inode numbers. -.TP -\fIfile1\fP \-\fBnt\fP \fIfile2\fP -True if \fIfile1\fP is newer (according to modification date) than \fIfile2\fP, -or if \fIfile1\fP exists and \fPfile2\fP does not. -.TP -\fIfile1\fP \-\fBot\fP \fIfile2\fP -True if \fIfile1\fP is older than \fIfile2\fP, or if \fIfile2\fP exists -and \fIfile1\fP does not. -.TP -.B \-o \fIoptname\fP -True if the shell option -.I optname -is enabled. -See the list of options under the description of the -.B \-o -option to the -.B set -builtin below. -.TP -.B \-v \fIvarname\fP -True if the shell variable -.I varname -is set (has been assigned a value). -.TP -.B \-R \fIvarname\fP -True if the shell variable -.I varname -is set and is a name reference. -.TP -.B \-z \fIstring\fP -True if the length of \fIstring\fP is zero. -.TP -\fIstring\fP -.PD 0 -.TP -.B \-n \fIstring\fP -.PD -True if the length of -.I string -is non-zero. -.TP -\fIstring1\fP \fB==\fP \fIstring2\fP -.PD 0 -.TP -\fIstring1\fP \fB=\fP \fIstring2\fP -.PD -True if the strings are equal. \fB=\fP should be used -with the \fBtest\fP command for POSIX conformance. -When used with the \fB[[\fP command, this performs pattern matching as -described above (\fBCompound Commands\fP). -.TP -\fIstring1\fP \fB!=\fP \fIstring2\fP -True if the strings are not equal. -.TP -\fIstring1\fP \fB<\fP \fIstring2\fP -True if \fIstring1\fP sorts before \fIstring2\fP lexicographically. -.TP -\fIstring1\fP \fB>\fP \fIstring2\fP -True if \fIstring1\fP sorts after \fIstring2\fP lexicographically. -.TP -.I \fIarg1\fP \fBOP\fP \fIarg2\fP -.SM -.B OP -is one of -.BR \-eq , -.BR \-ne , -.BR \-lt , -.BR \-le , -.BR \-gt , -or -.BR \-ge . -These arithmetic binary operators return true if \fIarg1\fP -is equal to, not equal to, less than, less than or equal to, -greater than, or greater than or equal to \fIarg2\fP, respectively. -.I Arg1 -and -.I arg2 -may be positive or negative integers. -.PD -.SH "SIMPLE COMMAND EXPANSION" -When a simple command is executed, the shell performs the following -expansions, assignments, and redirections, from left to right. -.IP 1. -The words that the parser has marked as variable assignments (those -preceding the command name) and redirections are saved for later -processing. -.IP 2. -The words that are not variable assignments or redirections are -expanded. If any words remain after expansion, the first word -is taken to be the name of the command and the remaining words are -the arguments. -.IP 3. -Redirections are performed as described above under -.SM -.BR REDIRECTION . -.IP 4. -The text after the \fB=\fP in each variable assignment undergoes tilde -expansion, parameter expansion, command substitution, arithmetic expansion, -and quote removal before being assigned to the variable. -.PP -If no command name results, the variable assignments affect the current -shell environment. Otherwise, the variables are added to the environment -of the executed command and do not affect the current shell environment. -If any of the assignments attempts to assign a value to a readonly variable, -an error occurs, and the command exits with a non-zero status. -.PP -If no command name results, redirections are performed, but do not -affect the current shell environment. A redirection error causes the -command to exit with a non-zero status. -.PP -If there is a command name left after expansion, execution proceeds as -described below. Otherwise, the command exits. If one of the expansions -contained a command substitution, the exit status of the command is -the exit status of the last command substitution performed. If there -were no command substitutions, the command exits with a status of zero. -.SH "COMMAND EXECUTION" -After a command has been split into words, if it results in a -simple command and an optional list of arguments, the following -actions are taken. -.PP -If the command name contains no slashes, the shell attempts to -locate it. If there exists a shell function by that name, that -function is invoked as described above in -.SM -.BR FUNCTIONS . -If the name does not match a function, the shell searches for -it in the list of shell builtins. If a match is found, that -builtin is invoked. -.PP -If the name is neither a shell function nor a builtin, -and contains no slashes, -.B bash -searches each element of the -.SM -.B PATH -for a directory containing an executable file by that name. -.B Bash -uses a hash table to remember the full pathnames of executable -files (see -.B hash -under -.SM -.B "SHELL BUILTIN COMMANDS" -below). -A full search of the directories in -.SM -.B PATH -is performed only if the command is not found in the hash table. -If the search is unsuccessful, the shell searches for a defined shell -function named \fBcommand_not_found_handle\fP. -If that function exists, it is invoked with the original command and -the original command's arguments as its arguments, and the function's -exit status becomes the exit status of the shell. -If that function is not defined, the shell prints an error -message and returns an exit status of 127. -.PP -If the search is successful, or if the command name contains -one or more slashes, the shell executes the named program in a -separate execution environment. -Argument 0 is set to the name given, and the remaining arguments -to the command are set to the arguments given, if any. -.PP -If this execution fails because the file is not in executable -format, and the file is not a directory, it is assumed to be -a \fIshell script\fP, a file -containing shell commands. A subshell is spawned to execute -it. This subshell reinitializes itself, so -that the effect is as if a new shell had been invoked -to handle the script, with the exception that the locations of -commands remembered by the parent (see -.B hash -below under -.SM -\fBSHELL BUILTIN COMMANDS\fP) -are retained by the child. -.PP -If the program is a file beginning with -.BR #! , -the remainder of the first line specifies an interpreter -for the program. The shell executes the -specified interpreter on operating systems that do not -handle this executable format themselves. The arguments to the -interpreter consist of a single optional argument following the -interpreter name on the first line of the program, followed -by the name of the program, followed by the command -arguments, if any. -.SH COMMAND EXECUTION ENVIRONMENT -The shell has an \fIexecution environment\fP, which consists of the -following: -.IP \(bu -open files inherited by the shell at invocation, as modified by -redirections supplied to the \fBexec\fP builtin -.IP \(bu -the current working directory as set by \fBcd\fP, \fBpushd\fP, or -\fBpopd\fP, or inherited by the shell at invocation -.IP \(bu -the file creation mode mask as set by \fBumask\fP or inherited from -the shell's parent -.IP \(bu -current traps set by \fBtrap\fP -.IP \(bu -shell parameters that are set by variable assignment or with \fBset\fP -or inherited from the shell's parent in the environment -.IP \(bu -shell functions defined during execution or inherited from the shell's -parent in the environment -.IP \(bu -options enabled at invocation (either by default or with command-line -arguments) or by \fBset\fP -.IP \(bu -options enabled by \fBshopt\fP -.IP \(bu -shell aliases defined with \fBalias\fP -.IP \(bu -various process IDs, including those of background jobs, the value -of \fB$$\fP, and the value of -.SM -.B PPID -.PP -When a simple command other than a builtin or shell function -is to be executed, it -is invoked in a separate execution environment that consists of -the following. Unless otherwise noted, the values are inherited -from the shell. -.if n .sp 1 -.IP \(bu -the shell's open files, plus any modifications and additions specified -by redirections to the command -.IP \(bu -the current working directory -.IP \(bu -the file creation mode mask -.IP \(bu -shell variables and functions marked for export, along with variables -exported for the command, passed in the environment -.IP \(bu -traps caught by the shell are reset to the values inherited from the -shell's parent, and traps ignored by the shell are ignored -.PP -A command invoked in this separate environment cannot affect the -shell's execution environment. -.PP -Command substitution, commands grouped with parentheses, -and asynchronous commands are invoked in a -subshell environment that is a duplicate of the shell environment, -except that traps caught by the shell are reset to the values -that the shell inherited from its parent at invocation. Builtin -commands that are invoked as part of a pipeline are also executed in a -subshell environment. Changes made to the subshell environment -cannot affect the shell's execution environment. -.PP -Subshells spawned to execute command substitutions inherit the value of -the \fB\-e\fP option from the parent shell. When not in \fIposix\fP mode, -\fBbash\fP clears the \fB\-e\fP option in such subshells. -.PP -If a command is followed by a \fB&\fP and job control is not active, the -default standard input for the command is the empty file \fI/dev/null\fP. -Otherwise, the invoked command inherits the file descriptors of the calling -shell as modified by redirections. -.SH ENVIRONMENT -When a program is invoked it is given an array of strings -called the -.IR environment . -This is a list of -\fIname\fP\-\fIvalue\fP pairs, of the form -.IR "name\fR=\fPvalue" . -.PP -The shell provides several ways to manipulate the environment. -On invocation, the shell scans its own environment and -creates a parameter for each name found, automatically marking -it for -.I export -to child processes. Executed commands inherit the environment. -The -.B export -and -.B declare \-x -commands allow parameters and functions to be added to and -deleted from the environment. If the value of a parameter -in the environment is modified, the new value becomes part -of the environment, replacing the old. The environment -inherited by any executed command consists of the shell's -initial environment, whose values may be modified in the shell, -less any pairs removed by the -.B unset -command, plus any additions via the -.B export -and -.B declare \-x -commands. -.PP -The environment for any -.I simple command -or function may be augmented temporarily by prefixing it with -parameter assignments, as described above in -.SM -.BR PARAMETERS . -These assignment statements affect only the environment seen -by that command. -.PP -If the -.B \-k -option is set (see the -.B set -builtin command below), then -.I all -parameter assignments are placed in the environment for a command, -not just those that precede the command name. -.PP -When -.B bash -invokes an external command, the variable -.B _ -is set to the full filename of the command and passed to that -command in its environment. -.SH "EXIT STATUS" -.PP -The exit status of an executed command is the value returned by the -\fIwaitpid\fP system call or equivalent function. Exit statuses -fall between 0 and 255, though, as explained below, the shell may -use values above 125 specially. Exit statuses from shell builtins and -compound commands are also limited to this range. Under certain -circumstances, the shell will use special values to indicate specific -failure modes. -.PP -For the shell's purposes, a command which exits with a -zero exit status has succeeded. An exit status of zero -indicates success. A non-zero exit status indicates failure. -When a command terminates on a fatal signal \fIN\fP, \fBbash\fP uses -the value of 128+\fIN\fP as the exit status. -.PP -If a command is not found, the child process created to -execute it returns a status of 127. If a command is found -but is not executable, the return status is 126. -.PP -If a command fails because of an error during expansion or redirection, -the exit status is greater than zero. -.PP -Shell builtin commands return a status of 0 (\fItrue\fP) if -successful, and non-zero (\fIfalse\fP) if an error occurs -while they execute. -All builtins return an exit status of 2 to indicate incorrect usage, -generally invalid options or missing arguments. -.PP -\fBBash\fP itself returns the exit status of the last command -executed, unless a syntax error occurs, in which case it exits -with a non-zero value. See also the \fBexit\fP builtin -command below. -.SH SIGNALS -When \fBbash\fP is interactive, in the absence of any traps, it ignores -.SM -.B SIGTERM -(so that \fBkill 0\fP does not kill an interactive shell), -and -.SM -.B SIGINT -is caught and handled (so that the \fBwait\fP builtin is interruptible). -In all cases, \fBbash\fP ignores -.SM -.BR SIGQUIT . -If job control is in effect, -.B bash -ignores -.SM -.BR SIGTTIN , -.SM -.BR SIGTTOU , -and -.SM -.BR SIGTSTP . -.PP -Non-builtin commands run by \fBbash\fP have signal handlers -set to the values inherited by the shell from its parent. -When job control is not in effect, asynchronous commands -ignore -.SM -.B SIGINT -and -.SM -.B SIGQUIT -in addition to these inherited handlers. -Commands run as a result of command substitution ignore the -keyboard-generated job control signals -.SM -.BR SIGTTIN , -.SM -.BR SIGTTOU , -and -.SM -.BR SIGTSTP . -.PP -The shell exits by default upon receipt of a -.SM -.BR SIGHUP . -Before exiting, an interactive shell resends the -.SM -.B SIGHUP -to all jobs, running or stopped. -Stopped jobs are sent -.SM -.B SIGCONT -to ensure that they receive the -.SM -.BR SIGHUP . -To prevent the shell from -sending the signal to a particular job, it should be removed from the -jobs table with the -.B disown -builtin (see -.SM -.B "SHELL BUILTIN COMMANDS" -below) or marked -to not receive -.SM -.B SIGHUP -using -.BR "disown \-h" . -.PP -If the -.B huponexit -shell option has been set with -.BR shopt , -.B bash -sends a -.SM -.B SIGHUP -to all jobs when an interactive login shell exits. -.PP -If \fBbash\fP is waiting for a command to complete and receives a signal -for which a trap has been set, the trap will not be executed until -the command completes. -When \fBbash\fP is waiting for an asynchronous command via the \fBwait\fP -builtin, the reception of a signal for which a trap has been set will -cause the \fBwait\fP builtin to return immediately with an exit status -greater than 128, immediately after which the trap is executed. -.SH "JOB CONTROL" -.I Job control -refers to the ability to selectively stop (\fIsuspend\fP) -the execution of processes and continue (\fIresume\fP) -their execution at a later point. A user typically employs -this facility via an interactive interface supplied jointly -by the operating system kernel's terminal driver and -.BR bash . -.PP -The shell associates a -.I job -with each pipeline. It keeps a table of currently executing -jobs, which may be listed with the -.B jobs -command. When -.B bash -starts a job asynchronously (in the -.IR background ), -it prints a line that looks like: -.RS -.PP -[1] 25647 -.RE -.PP -indicating that this job is job number 1 and that the process ID -of the last process in the pipeline associated with this job is 25647. -All of the processes in a single pipeline are members of the same job. -.B Bash -uses the -.I job -abstraction as the basis for job control. -.PP -To facilitate the implementation of the user interface to job -control, the operating system maintains the notion of a \fIcurrent terminal -process group ID\fP. Members of this process group (processes whose -process group ID is equal to the current terminal process group ID) -receive keyboard-generated signals such as -.SM -.BR SIGINT . -These processes are said to be in the -.IR foreground . -.I Background -processes are those whose process group ID differs from the terminal's; -such processes are immune to keyboard-generated signals. -Only foreground processes are allowed to read from or, if the -user so specifies with \f(CWstty tostop\fP, write to the -terminal. -Background processes which attempt to read from (write to when -\f(CWstty tostop\fP is in effect) the -terminal are sent a -.SM -.B SIGTTIN (SIGTTOU) -signal by the kernel's terminal driver, -which, unless caught, suspends the process. -.PP -If the operating system on which -.B bash -is running supports -job control, -.B bash -contains facilities to use it. -Typing the -.I suspend -character (typically -.BR ^Z , -Control-Z) while a process is running -causes that process to be stopped and returns control to -.BR bash . -Typing the -.I "delayed suspend" -character (typically -.BR ^Y , -Control-Y) causes the process to be stopped when it -attempts to read input from the terminal, and control to -be returned to -.BR bash . -The user may then manipulate the state of this job, using the -.B bg -command to continue it in the background, the -.B fg -command to continue it in the foreground, or -the -.B kill -command to kill it. A \fB^Z\fP takes effect immediately, -and has the additional side effect of causing pending output -and typeahead to be discarded. -.PP -There are a number of ways to refer to a job in the shell. -The character -.B % -introduces a job specification (\fIjobspec\fP). Job number -.I n -may be referred to as -.BR %n . -A job may also be referred to using a prefix of the name used to -start it, or using a substring that appears in its command line. -For example, -.B %ce -refers to a stopped -.B ce -job. If a prefix matches more than one job, -.B bash -reports an error. Using -.BR %?ce , -on the other hand, refers to any job containing the string -.B ce -in its command line. If the substring matches more than one job, -.B bash -reports an error. The symbols -.B %% -and -.B %+ -refer to the shell's notion of the -.IR "current job" , -which is the last job stopped while it was in -the foreground or started in the background. -The -.I "previous job" -may be referenced using -.BR %\- . -If there is only a single job, \fB%+\fP and \fB%\-\fP can both be used -to refer to that job. -In output pertaining to jobs (e.g., the output of the -.B jobs -command), the current job is always flagged with a -.BR + , -and the previous job with a -.BR \- . -A single % (with no accompanying job specification) also refers to the -current job. -.PP -Simply naming a job can be used to bring it into the -foreground: -.B %1 -is a synonym for -\fB``fg %1''\fP, -bringing job 1 from the background into the foreground. -Similarly, -.B ``%1 &'' -resumes job 1 in the background, equivalent to -\fB``bg %1''\fP. -.PP -The shell learns immediately whenever a job changes state. -Normally, -.B bash -waits until it is about to print a prompt before reporting -changes in a job's status so as to not interrupt -any other output. If the -.B \-b -option to the -.B set -builtin command -is enabled, -.B bash -reports such changes immediately. -Any trap on -.SM -.B SIGCHLD -is executed for each child that exits. -.PP -If an attempt to exit -.B bash -is made while jobs are stopped (or, if the \fBcheckjobs\fP shell option has -been enabled using the \fBshopt\fP builtin, running), the shell prints a -warning message, and, if the \fBcheckjobs\fP option is enabled, lists the -jobs and their statuses. -The -.B jobs -command may then be used to inspect their status. -If a second attempt to exit is made without an intervening command, -the shell does not print another warning, and any stopped -jobs are terminated. -.SH PROMPTING -When executing interactively, -.B bash -displays the primary prompt -.SM -.B PS1 -when it is ready to read a command, and the secondary prompt -.SM -.B PS2 -when it needs more input to complete a command. -.B Bash -allows these prompt strings to be customized by inserting a number of -backslash-escaped special characters that are decoded as follows: -.RS -.PD 0 -.TP -.B \ea -an ASCII bell character (07) -.TP -.B \ed -the date in "Weekday Month Date" format (e.g., "Tue May 26") -.TP -.B \eD{\fIformat\fP} -the \fIformat\fP is passed to \fIstrftime\fP(3) and the result is inserted -into the prompt string; an empty \fIformat\fP results in a locale-specific -time representation. The braces are required -.TP -.B \ee -an ASCII escape character (033) -.TP -.B \eh -the hostname up to the first `.' -.TP -.B \eH -the hostname -.TP -.B \ej -the number of jobs currently managed by the shell -.TP -.B \el -the basename of the shell's terminal device name -.TP -.B \en -newline -.TP -.B \er -carriage return -.TP -.B \es -the name of the shell, the basename of -.B $0 -(the portion following the final slash) -.TP -.B \et -the current time in 24-hour HH:MM:SS format -.TP -.B \eT -the current time in 12-hour HH:MM:SS format -.TP -.B \e@ -the current time in 12-hour am/pm format -.TP -.B \eA -the current time in 24-hour HH:MM format -.TP -.B \eu -the username of the current user -.TP -.B \ev -the version of \fBbash\fP (e.g., 2.00) -.TP -.B \eV -the release of \fBbash\fP, version + patch level (e.g., 2.00.0) -.TP -.B \ew -the current working directory, with -.SM -.B $HOME -abbreviated with a tilde -(uses the value of the -.SM -.B PROMPT_DIRTRIM -variable) -.TP -.B \eW -the basename of the current working directory, with -.SM -.B $HOME -abbreviated with a tilde -.TP -.B \e! -the history number of this command -.TP -.B \e# -the command number of this command -.TP -.B \e$ -if the effective UID is 0, a -.BR # , -otherwise a -.B $ -.TP -.B \e\fInnn\fP -the character corresponding to the octal number \fInnn\fP -.TP -.B \e\e -a backslash -.TP -.B \e[ -begin a sequence of non-printing characters, which could be used to -embed a terminal control sequence into the prompt -.TP -.B \e] -end a sequence of non-printing characters -.PD -.RE -.PP -The command number and the history number are usually different: -the history number of a command is its position in the history -list, which may include commands restored from the history file -(see -.SM -.B HISTORY -below), while the command number is the position in the sequence -of commands executed during the current shell session. -After the string is decoded, it is expanded via -parameter expansion, command substitution, arithmetic -expansion, and quote removal, subject to the value of the -.B promptvars -shell option (see the description of the -.B shopt -command under -.SM -.B "SHELL BUILTIN COMMANDS" -below). -.SH READLINE -This is the library that handles reading input when using an interactive -shell, unless the -.B \-\-noediting -option is given at shell invocation. -Line editing is also used when using the \fB\-e\fP option to the -\fBread\fP builtin. -By default, the line editing commands are similar to those of Emacs. -A vi-style line editing interface is also available. -Line editing can be enabled at any time using the -.B \-o emacs -or -.B \-o vi -options to the -.B set -builtin (see -.SM -.B SHELL BUILTIN COMMANDS -below). -To turn off line editing after the shell is running, use the -.B +o emacs -or -.B +o vi -options to the -.B set -builtin. -.SS "Readline Notation" -.PP -In this section, the Emacs-style notation is used to denote -keystrokes. Control keys are denoted by C\-\fIkey\fR, e.g., C\-n -means Control\-N. Similarly, -.I meta -keys are denoted by M\-\fIkey\fR, so M\-x means Meta\-X. (On keyboards -without a -.I meta -key, M\-\fIx\fP means ESC \fIx\fP, i.e., press the Escape key -then the -.I x -key. This makes ESC the \fImeta prefix\fP. -The combination M\-C\-\fIx\fP means ESC\-Control\-\fIx\fP, -or press the Escape key -then hold the Control key while pressing the -.I x -key.) -.PP -Readline commands may be given numeric -.IR arguments , -which normally act as a repeat count. -Sometimes, however, it is the sign of the argument that is significant. -Passing a negative argument to a command that acts in the forward -direction (e.g., \fBkill\-line\fP) causes that command to act in a -backward direction. -Commands whose behavior with arguments deviates from this are noted -below. -.PP -When a command is described as \fIkilling\fP text, the text -deleted is saved for possible future retrieval -(\fIyanking\fP). The killed text is saved in a -\fIkill ring\fP. Consecutive kills cause the text to be -accumulated into one unit, which can be yanked all at once. -Commands which do not kill text separate the chunks of text -on the kill ring. -.SS "Readline Initialization" -.PP -Readline is customized by putting commands in an initialization -file (the \fIinputrc\fP file). -The name of this file is taken from the value of the -.SM -.B INPUTRC -variable. If that variable is unset, the default is -.IR ~/.inputrc . -When a program which uses the readline library starts up, the -initialization file is read, and the key bindings and variables -are set. -There are only a few basic constructs allowed in the -readline initialization file. -Blank lines are ignored. -Lines beginning with a \fB#\fP are comments. -Lines beginning with a \fB$\fP indicate conditional constructs. -Other lines denote key bindings and variable settings. -.PP -The default key-bindings may be changed with an -.I inputrc -file. -Other programs that use this library may add their own commands -and bindings. -.PP -For example, placing -.RS -.PP -M\-Control\-u: universal\-argument -.RE -or -.RS -C\-Meta\-u: universal\-argument -.RE -into the -.I inputrc -would make M\-C\-u execute the readline command -.IR universal\-argument . -.PP -The following symbolic character names are recognized: -.IR RUBOUT , -.IR DEL , -.IR ESC , -.IR LFD , -.IR NEWLINE , -.IR RET , -.IR RETURN , -.IR SPC , -.IR SPACE , -and -.IR TAB . -.PP -In addition to command names, readline allows keys to be bound -to a string that is inserted when the key is pressed (a \fImacro\fP). -.SS "Readline Key Bindings" -.PP -The syntax for controlling key bindings in the -.I inputrc -file is simple. All that is required is the name of the -command or the text of a macro and a key sequence to which -it should be bound. The name may be specified in one of two ways: -as a symbolic key name, possibly with \fIMeta\-\fP or \fIControl\-\fP -prefixes, or as a key sequence. -.PP -When using the form \fBkeyname\fP:\^\fIfunction\-name\fP or \fImacro\fP, -.I keyname -is the name of a key spelled out in English. For example: -.sp -.RS -Control-u: universal\-argument -.br -Meta-Rubout: backward-kill-word -.br -Control-o: "> output" -.RE -.LP -In the above example, -.I C\-u -is bound to the function -.BR universal\-argument , -.I M\-DEL -is bound to the function -.BR backward\-kill\-word , -and -.I C\-o -is bound to run the macro -expressed on the right hand side (that is, to insert the text -.if t \f(CW> output\fP -.if n ``> output'' -into the line). -.PP -In the second form, \fB"keyseq"\fP:\^\fIfunction\-name\fP or \fImacro\fP, -.B keyseq -differs from -.B keyname -above in that strings denoting -an entire key sequence may be specified by placing the sequence -within double quotes. Some GNU Emacs style key escapes can be -used, as in the following example, but the symbolic character names -are not recognized. -.sp -.RS -"\eC\-u": universal\-argument -.br -"\eC\-x\eC\-r": re\-read\-init\-file -.br -"\ee[11~": "Function Key 1" -.RE -.PP -In this example, -.I C\-u -is again bound to the function -.BR universal\-argument . -.I "C\-x C\-r" -is bound to the function -.BR re\-read\-init\-file , -and -.I "ESC [ 1 1 ~" -is bound to insert the text -.if t \f(CWFunction Key 1\fP. -.if n ``Function Key 1''. -.PP -The full set of GNU Emacs style escape sequences is -.RS -.PD 0 -.TP -.B \eC\- -control prefix -.TP -.B \eM\- -meta prefix -.TP -.B \ee -an escape character -.TP -.B \e\e -backslash -.TP -.B \e" -literal " -.TP -.B \e\(aq -literal \(aq -.RE -.PD -.PP -In addition to the GNU Emacs style escape sequences, a second -set of backslash escapes is available: -.RS -.PD 0 -.TP -.B \ea -alert (bell) -.TP -.B \eb -backspace -.TP -.B \ed -delete -.TP -.B \ef -form feed -.TP -.B \en -newline -.TP -.B \er -carriage return -.TP -.B \et -horizontal tab -.TP -.B \ev -vertical tab -.TP -.B \e\fInnn\fP -the eight-bit character whose value is the octal value \fInnn\fP -(one to three digits) -.TP -.B \ex\fIHH\fP -the eight-bit character whose value is the hexadecimal value \fIHH\fP -(one or two hex digits) -.RE -.PD -.PP -When entering the text of a macro, single or double quotes must -be used to indicate a macro definition. -Unquoted text is assumed to be a function name. -In the macro body, the backslash escapes described above are expanded. -Backslash will quote any other character in the macro text, -including " and \(aq. -.PP -.B Bash -allows the current readline key bindings to be displayed or modified -with the -.B bind -builtin command. The editing mode may be switched during interactive -use by using the -.B \-o -option to the -.B set -builtin command (see -.SM -.B SHELL BUILTIN COMMANDS -below). -.SS "Readline Variables" -.PP -Readline has variables that can be used to further customize its -behavior. A variable may be set in the -.I inputrc -file with a statement of the form -.RS -.PP -\fBset\fP \fIvariable\-name\fP \fIvalue\fP -.RE -.PP -Except where noted, readline variables can take the values -.B On -or -.B Off -(without regard to case). -Unrecognized variable names are ignored. -When a variable value is read, empty or null values, "on" (case-insensitive), -and "1" are equivalent to \fBOn\fP. All other values are equivalent to -\fBOff\fP. -The variables and their default values are: -.PP -.PD 0 -.TP -.B bell\-style (audible) -Controls what happens when readline wants to ring the terminal bell. -If set to \fBnone\fP, readline never rings the bell. If set to -\fBvisible\fP, readline uses a visible bell if one is available. -If set to \fBaudible\fP, readline attempts to ring the terminal's bell. -.TP -.B bind\-tty\-special\-chars (On) -If set to \fBOn\fP, readline attempts to bind the control characters -treated specially by the kernel's terminal driver to their readline -equivalents. -.TP -.B colored\-stats (Off) -If set to \fBOn\fP, readline displays possible completions using different -colors to indicate their file type. -The color definitions are taken from the value of the \fBLS_COLORS\fP -environment variable. -.TP -.B comment\-begin (``#'') -The string that is inserted when the readline -.B insert\-comment -command is executed. -This command is bound to -.B M\-# -in emacs mode and to -.B # -in vi command mode. -.TP -.B completion\-ignore\-case (Off) -If set to \fBOn\fP, readline performs filename matching and completion -in a case\-insensitive fashion. -.TP -.B completion\-prefix\-display\-length (0) -The length in characters of the common prefix of a list of possible -completions that is displayed without modification. When set to a -value greater than zero, common prefixes longer than this value are -replaced with an ellipsis when displaying possible completions. -.TP -.B completion\-query\-items (100) -This determines when the user is queried about viewing -the number of possible completions -generated by the \fBpossible\-completions\fP command. -It may be set to any integer value greater than or equal to -zero. If the number of possible completions is greater than -or equal to the value of this variable, the user is asked whether -or not he wishes to view them; otherwise they are simply listed -on the terminal. -.TP -.B convert\-meta (On) -If set to \fBOn\fP, readline will convert characters with the -eighth bit set to an ASCII key sequence -by stripping the eighth bit and prefixing an -escape character (in effect, using escape as the \fImeta prefix\fP). -.TP -.B disable\-completion (Off) -If set to \fBOn\fP, readline will inhibit word completion. Completion -characters will be inserted into the line as if they had been -mapped to \fBself-insert\fP. -.TP -.B editing\-mode (emacs) -Controls whether readline begins with a set of key bindings similar -to \fIEmacs\fP or \fIvi\fP. -.B editing\-mode -can be set to either -.B emacs -or -.BR vi . -.TP -.B echo\-control\-characters (On) -When set to \fBOn\fP, on operating systems that indicate they support it, -readline echoes a character corresponding to a signal generated from the -keyboard. -.TP -.B enable\-keypad (Off) -When set to \fBOn\fP, readline will try to enable the application -keypad when it is called. Some systems need this to enable the -arrow keys. -.TP -.B enable\-meta\-key (On) -When set to \fBOn\fP, readline will try to enable any meta modifier -key the terminal claims to support when it is called. On many terminals, -the meta key is used to send eight-bit characters. -.TP -.B expand\-tilde (Off) -If set to \fBOn\fP, tilde expansion is performed when readline -attempts word completion. -.TP -.B history\-preserve\-point (Off) -If set to \fBOn\fP, the history code attempts to place point at the -same location on each history line retrieved with \fBprevious-history\fP -or \fBnext-history\fP. -.TP -.B history\-size (0) -Set the maximum number of history entries saved in the history list. -If set to zero, any existing history entries are deleted and no new entries -are saved. -If set to a value less than zero, the number of history entries is not -limited. -By default, the number of history entries is not limited. -.TP -.B horizontal\-scroll\-mode (Off) -When set to \fBOn\fP, makes readline use a single line for display, -scrolling the input horizontally on a single screen line when it -becomes longer than the screen width rather than wrapping to a new line. -.TP -.B input\-meta (Off) -If set to \fBOn\fP, readline will enable eight-bit input (that is, -it will not strip the high bit from the characters it reads), -regardless of what the terminal claims it can support. The name -.B meta\-flag -is a synonym for this variable. -.TP -.B isearch\-terminators (``C\-[C\-J'') -The string of characters that should terminate an incremental -search without subsequently executing the character as a command. -If this variable has not been given a value, the characters -\fIESC\fP and \fIC\-J\fP will terminate an incremental search. -.TP -.B keymap (emacs) -Set the current readline keymap. The set of valid keymap names is -\fIemacs, emacs\-standard, emacs\-meta, emacs\-ctlx, vi, -vi\-command\fP, and -.IR vi\-insert . -\fIvi\fP is equivalent to \fIvi\-command\fP; \fIemacs\fP is -equivalent to \fIemacs\-standard\fP. The default value is -.IR emacs ; -the value of -.B editing\-mode -also affects the default keymap. -.TP -.B keyseq\-timeout (500) -Specifies the duration \fIreadline\fP will wait for a character when reading an -ambiguous key sequence (one that can form a complete key sequence using -the input read so far, or can take additional input to complete a longer -key sequence). -If no input is received within the timeout, \fIreadline\fP will use the shorter -but complete key sequence. -The value is specified in milliseconds, so a value of 1000 means that -\fIreadline\fP will wait one second for additional input. -If this variable is set to a value less than or equal to zero, or to a -non-numeric value, \fIreadline\fP will wait until another key is pressed to -decide which key sequence to complete. -.TP -.B mark\-directories (On) -If set to \fBOn\fP, completed directory names have a slash -appended. -.TP -.B mark\-modified\-lines (Off) -If set to \fBOn\fP, history lines that have been modified are displayed -with a preceding asterisk (\fB*\fP). -.TP -.B mark\-symlinked\-directories (Off) -If set to \fBOn\fP, completed names which are symbolic links to directories -have a slash appended (subject to the value of -\fBmark\-directories\fP). -.TP -.B match\-hidden\-files (On) -This variable, when set to \fBOn\fP, causes readline to match files whose -names begin with a `.' (hidden files) when performing filename -completion. -If set to \fBOff\fP, the leading `.' must be -supplied by the user in the filename to be completed. -.TP -.B menu\-complete\-display\-prefix (Off) -If set to \fBOn\fP, menu completion displays the common prefix of the -list of possible completions (which may be empty) before cycling through -the list. -.TP -.B output\-meta (Off) -If set to \fBOn\fP, readline will display characters with the -eighth bit set directly rather than as a meta-prefixed escape -sequence. -.TP -.B page\-completions (On) -If set to \fBOn\fP, readline uses an internal \fImore\fP-like pager -to display a screenful of possible completions at a time. -.TP -.B print\-completions\-horizontally (Off) -If set to \fBOn\fP, readline will display completions with matches -sorted horizontally in alphabetical order, rather than down the screen. -.TP -.B revert\-all\-at\-newline (Off) -If set to \fBOn\fP, readline will undo all changes to history lines -before returning when \fBaccept\-line\fP is executed. By default, -history lines may be modified and retain individual undo lists across -calls to \fBreadline\fP. -.TP -.B show\-all\-if\-ambiguous (Off) -This alters the default behavior of the completion functions. If -set to -.BR On , -words which have more than one possible completion cause the -matches to be listed immediately instead of ringing the bell. -.TP -.B show\-all\-if\-unmodified (Off) -This alters the default behavior of the completion functions in -a fashion similar to \fBshow\-all\-if\-ambiguous\fP. -If set to -.BR On , -words which have more than one possible completion without any -possible partial completion (the possible completions don't share -a common prefix) cause the matches to be listed immediately instead -of ringing the bell. -.TP -.B show\-mode\-in\-prompt (Off) -If set to \fBOn\fP, add a character to the beginning of the prompt -indicating the editing mode: emacs (@), vi command (:) or vi -insertion (+). -.TP -.B skip\-completed\-text (Off) -If set to \fBOn\fP, this alters the default completion behavior when -inserting a single match into the line. It's only active when -performing completion in the middle of a word. If enabled, readline -does not insert characters from the completion that match characters -after point in the word being completed, so portions of the word -following the cursor are not duplicated. -.TP -.B visible\-stats (Off) -If set to \fBOn\fP, a character denoting a file's type as reported -by \fIstat\fP(2) is appended to the filename when listing possible -completions. -.PD -.SS "Readline Conditional Constructs" -.PP -Readline implements a facility similar in spirit to the conditional -compilation features of the C preprocessor which allows key -bindings and variable settings to be performed as the result -of tests. There are four parser directives used. -.IP \fB$if\fP -The -.B $if -construct allows bindings to be made based on the -editing mode, the terminal being used, or the application using -readline. The text of the test extends to the end of the line; -no characters are required to isolate it. -.RS -.IP \fBmode\fP -The \fBmode=\fP form of the \fB$if\fP directive is used to test -whether readline is in emacs or vi mode. -This may be used in conjunction -with the \fBset keymap\fP command, for instance, to set bindings in -the \fIemacs\-standard\fP and \fIemacs\-ctlx\fP keymaps only if -readline is starting out in emacs mode. -.IP \fBterm\fP -The \fBterm=\fP form may be used to include terminal-specific -key bindings, perhaps to bind the key sequences output by the -terminal's function keys. The word on the right side of the -.B = -is tested against the both full name of the terminal and the portion -of the terminal name before the first \fB\-\fP. This allows -.I sun -to match both -.I sun -and -.IR sun\-cmd , -for instance. -.IP \fBapplication\fP -The \fBapplication\fP construct is used to include -application-specific settings. Each program using the readline -library sets the \fIapplication name\fP, and an initialization -file can test for a particular value. -This could be used to bind key sequences to functions useful for -a specific program. For instance, the following command adds a -key sequence that quotes the current or previous word in \fBbash\fP: -.sp 1 -.RS -.nf -\fB$if\fP Bash -# Quote the current or previous word -"\eC\-xq": "\eeb\e"\eef\e"" -\fB$endif\fP -.fi -.RE -.RE -.IP \fB$endif\fP -This command, as seen in the previous example, terminates an -\fB$if\fP command. -.IP \fB$else\fP -Commands in this branch of the \fB$if\fP directive are executed if -the test fails. -.IP \fB$include\fP -This directive takes a single filename as an argument and reads commands -and bindings from that file. For example, the following directive -would read \fI/etc/inputrc\fP: -.sp 1 -.RS -.nf -\fB$include\fP \^ \fI/etc/inputrc\fP -.fi -.RE -.SS Searching -.PP -Readline provides commands for searching through the command history -(see -.SM -.B HISTORY -below) for lines containing a specified string. -There are two search modes: -.I incremental -and -.IR non-incremental . -.PP -Incremental searches begin before the user has finished typing the -search string. -As each character of the search string is typed, readline displays -the next entry from the history matching the string typed so far. -An incremental search requires only as many characters as needed to -find the desired history entry. -The characters present in the value of the \fBisearch-terminators\fP -variable are used to terminate an incremental search. -If that variable has not been assigned a value the Escape and -Control-J characters will terminate an incremental search. -Control-G will abort an incremental search and restore the original -line. -When the search is terminated, the history entry containing the -search string becomes the current line. -.PP -To find other matching entries in the history list, type Control-S or -Control-R as appropriate. -This will search backward or forward in the history for the next -entry matching the search string typed so far. -Any other key sequence bound to a readline command will terminate -the search and execute that command. -For instance, a \fInewline\fP will terminate the search and accept -the line, thereby executing the command from the history list. -.PP -Readline remembers the last incremental search string. If two -Control-Rs are typed without any intervening characters defining a -new search string, any remembered search string is used. -.PP -Non-incremental searches read the entire search string before starting -to search for matching history lines. The search string may be -typed by the user or be part of the contents of the current line. -.SS "Readline Command Names" -.PP -The following is a list of the names of the commands and the default -key sequences to which they are bound. -Command names without an accompanying key sequence are unbound by default. -In the following descriptions, \fIpoint\fP refers to the current cursor -position, and \fImark\fP refers to a cursor position saved by the -\fBset\-mark\fP command. -The text between the point and mark is referred to as the \fIregion\fP. -.SS Commands for Moving -.PP -.PD 0 -.TP -.B beginning\-of\-line (C\-a) -Move to the start of the current line. -.TP -.B end\-of\-line (C\-e) -Move to the end of the line. -.TP -.B forward\-char (C\-f) -Move forward a character. -.TP -.B backward\-char (C\-b) -Move back a character. -.TP -.B forward\-word (M\-f) -Move forward to the end of the next word. Words are composed of -alphanumeric characters (letters and digits). -.TP -.B backward\-word (M\-b) -Move back to the start of the current or previous word. -Words are composed of alphanumeric characters (letters and digits). -.TP -.B shell\-forward\-word -Move forward to the end of the next word. -Words are delimited by non-quoted shell metacharacters. -.TP -.B shell\-backward\-word -Move back to the start of the current or previous word. -Words are delimited by non-quoted shell metacharacters. -.TP -.B clear\-screen (C\-l) -Clear the screen leaving the current line at the top of the screen. -With an argument, refresh the current line without clearing the -screen. -.TP -.B redraw\-current\-line -Refresh the current line. -.PD -.SS Commands for Manipulating the History -.PP -.PD 0 -.TP -.B accept\-line (Newline, Return) -Accept the line regardless of where the cursor is. If this line is -non-empty, add it to the history list according to the state of the -.SM -.B HISTCONTROL -variable. If the line is a modified history -line, then restore the history line to its original state. -.TP -.B previous\-history (C\-p) -Fetch the previous command from the history list, moving back in -the list. -.TP -.B next\-history (C\-n) -Fetch the next command from the history list, moving forward in the -list. -.TP -.B beginning\-of\-history (M\-<) -Move to the first line in the history. -.TP -.B end\-of\-history (M\->) -Move to the end of the input history, i.e., the line currently being -entered. -.TP -.B reverse\-search\-history (C\-r) -Search backward starting at the current line and moving `up' through -the history as necessary. This is an incremental search. -.TP -.B forward\-search\-history (C\-s) -Search forward starting at the current line and moving `down' through -the history as necessary. This is an incremental search. -.TP -.B non\-incremental\-reverse\-search\-history (M\-p) -Search backward through the history starting at the current line -using a non-incremental search for a string supplied by the user. -.TP -.B non\-incremental\-forward\-search\-history (M\-n) -Search forward through the history using a non-incremental search for -a string supplied by the user. -.TP -.B history\-search\-forward -Search forward through the history for the string of characters -between the start of the current line and the point. -This is a non-incremental search. -.TP -.B history\-search\-backward -Search backward through the history for the string of characters -between the start of the current line and the point. -This is a non-incremental search. -.TP -.B yank\-nth\-arg (M\-C\-y) -Insert the first argument to the previous command (usually -the second word on the previous line) at point. -With an argument -.IR n , -insert the \fIn\fPth word from the previous command (the words -in the previous command begin with word 0). A negative argument -inserts the \fIn\fPth word from the end of the previous command. -Once the argument \fIn\fP is computed, the argument is extracted -as if the "!\fIn\fP" history expansion had been specified. -.TP -.B -yank\-last\-arg (M\-.\^, M\-_\^) -Insert the last argument to the previous command (the last word of -the previous history entry). -With a numeric argument, behave exactly like \fByank\-nth\-arg\fP. -Successive calls to \fByank\-last\-arg\fP move back through the history -list, inserting the last word (or the word specified by the argument to -the first call) of each line in turn. -Any numeric argument supplied to these successive calls determines -the direction to move through the history. A negative argument switches -the direction through the history (back or forward). -The history expansion facilities are used to extract the last word, -as if the "!$" history expansion had been specified. -.TP -.B shell\-expand\-line (M\-C\-e) -Expand the line as the shell does. This -performs alias and history expansion as well as all of the shell -word expansions. See -.SM -.B HISTORY EXPANSION -below for a description of history expansion. -.TP -.B history\-expand\-line (M\-^) -Perform history expansion on the current line. -See -.SM -.B HISTORY EXPANSION -below for a description of history expansion. -.TP -.B magic\-space -Perform history expansion on the current line and insert a space. -See -.SM -.B HISTORY EXPANSION -below for a description of history expansion. -.TP -.B alias\-expand\-line -Perform alias expansion on the current line. -See -.SM -.B ALIASES -above for a description of alias expansion. -.TP -.B history\-and\-alias\-expand\-line -Perform history and alias expansion on the current line. -.TP -.B insert\-last\-argument (M\-.\^, M\-_\^) -A synonym for \fByank\-last\-arg\fP. -.TP -.B operate\-and\-get\-next (C\-o) -Accept the current line for execution and fetch the next line -relative to the current line from the history for editing. Any -argument is ignored. -.TP -.B edit\-and\-execute\-command (C\-xC\-e) -Invoke an editor on the current command line, and execute the result as shell -commands. -\fBBash\fP attempts to invoke -.SM -.BR $VISUAL , -.SM -.BR $EDITOR , -and \fIemacs\fP as the editor, in that order. -.PD -.SS Commands for Changing Text -.PP -.PD 0 -.TP -.B \fIend\-of\-file\fP (usually C\-d) -The character indicating end-of-file as set, for example, by -.if t \f(CWstty\fP. -.if n ``stty''. -If this character is read when there are no characters -on the line, and point is at the beginning of the line, Readline -interprets it as the end of input and returns -.SM -.BR EOF . -.TP -.B delete\-char (C\-d) -Delete the character at point. -If this function is bound to the -same character as the tty \fBEOF\fP character, as \fBC\-d\fP -commonly is, see above for the effects. -.TP -.B backward\-delete\-char (Rubout) -Delete the character behind the cursor. When given a numeric argument, -save the deleted text on the kill ring. -.TP -.B forward\-backward\-delete\-char -Delete the character under the cursor, unless the cursor is at the -end of the line, in which case the character behind the cursor is -deleted. -.TP -.B quoted\-insert (C\-q, C\-v) -Add the next character typed to the line verbatim. This is -how to insert characters like \fBC\-q\fP, for example. -.TP -.B tab\-insert (C\-v TAB) -Insert a tab character. -.TP -.B self\-insert (a,\ b,\ A,\ 1,\ !,\ ...) -Insert the character typed. -.TP -.B transpose\-chars (C\-t) -Drag the character before point forward over the character at point, -moving point forward as well. -If point is at the end of the line, then this transposes -the two characters before point. -Negative arguments have no effect. -.TP -.B transpose\-words (M\-t) -Drag the word before point past the word after point, -moving point over that word as well. -If point is at the end of the line, this transposes -the last two words on the line. -.TP -.B upcase\-word (M\-u) -Uppercase the current (or following) word. With a negative argument, -uppercase the previous word, but do not move point. -.TP -.B downcase\-word (M\-l) -Lowercase the current (or following) word. With a negative argument, -lowercase the previous word, but do not move point. -.TP -.B capitalize\-word (M\-c) -Capitalize the current (or following) word. With a negative argument, -capitalize the previous word, but do not move point. -.TP -.B overwrite\-mode -Toggle overwrite mode. With an explicit positive numeric argument, -switches to overwrite mode. With an explicit non-positive numeric -argument, switches to insert mode. This command affects only -\fBemacs\fP mode; \fBvi\fP mode does overwrite differently. -Each call to \fIreadline()\fP starts in insert mode. -In overwrite mode, characters bound to \fBself\-insert\fP replace -the text at point rather than pushing the text to the right. -Characters bound to \fBbackward\-delete\-char\fP replace the character -before point with a space. By default, this command is unbound. -.PD -.SS Killing and Yanking -.PP -.PD 0 -.TP -.B kill\-line (C\-k) -Kill the text from point to the end of the line. -.TP -.B backward\-kill\-line (C\-x Rubout) -Kill backward to the beginning of the line. -.TP -.B unix\-line\-discard (C\-u) -Kill backward from point to the beginning of the line. -The killed text is saved on the kill-ring. -.\" There is no real difference between this and backward-kill-line -.TP -.B kill\-whole\-line -Kill all characters on the current line, no matter where point is. -.TP -.B kill\-word (M\-d) -Kill from point to the end of the current word, or if between -words, to the end of the next word. -Word boundaries are the same as those used by \fBforward\-word\fP. -.TP -.B backward\-kill\-word (M\-Rubout) -Kill the word behind point. -Word boundaries are the same as those used by \fBbackward\-word\fP. -.TP -.B shell\-kill\-word -Kill from point to the end of the current word, or if between -words, to the end of the next word. -Word boundaries are the same as those used by \fBshell\-forward\-word\fP. -.TP -.B shell\-backward\-kill\-word -Kill the word behind point. -Word boundaries are the same as those used by \fBshell\-backward\-word\fP. -.TP -.B unix\-word\-rubout (C\-w) -Kill the word behind point, using white space as a word boundary. -The killed text is saved on the kill-ring. -.TP -.B unix\-filename\-rubout -Kill the word behind point, using white space and the slash character -as the word boundaries. -The killed text is saved on the kill-ring. -.TP -.B delete\-horizontal\-space (M\-\e) -Delete all spaces and tabs around point. -.TP -.B kill\-region -Kill the text in the current region. -.TP -.B copy\-region\-as\-kill -Copy the text in the region to the kill buffer. -.TP -.B copy\-backward\-word -Copy the word before point to the kill buffer. -The word boundaries are the same as \fBbackward\-word\fP. -.TP -.B copy\-forward\-word -Copy the word following point to the kill buffer. -The word boundaries are the same as \fBforward\-word\fP. -.TP -.B yank (C\-y) -Yank the top of the kill ring into the buffer at point. -.TP -.B yank\-pop (M\-y) -Rotate the kill ring, and yank the new top. Only works following -.B yank -or -.BR yank\-pop . -.PD -.SS Numeric Arguments -.PP -.PD 0 -.TP -.B digit\-argument (M\-0, M\-1, ..., M\-\-) -Add this digit to the argument already accumulating, or start a new -argument. M\-\- starts a negative argument. -.TP -.B universal\-argument -This is another way to specify an argument. -If this command is followed by one or more digits, optionally with a -leading minus sign, those digits define the argument. -If the command is followed by digits, executing -.B universal\-argument -again ends the numeric argument, but is otherwise ignored. -As a special case, if this command is immediately followed by a -character that is neither a digit or minus sign, the argument count -for the next command is multiplied by four. -The argument count is initially one, so executing this function the -first time makes the argument count four, a second time makes the -argument count sixteen, and so on. -.PD -.SS Completing -.PP -.PD 0 -.TP -.B complete (TAB) -Attempt to perform completion on the text before point. -.B Bash -attempts completion treating the text as a variable (if the -text begins with \fB$\fP), username (if the text begins with -\fB~\fP), hostname (if the text begins with \fB@\fP), or -command (including aliases and functions) in turn. If none -of these produces a match, filename completion is attempted. -.TP -.B possible\-completions (M\-?) -List the possible completions of the text before point. -.TP -.B insert\-completions (M\-*) -Insert all completions of the text before point -that would have been generated by -\fBpossible\-completions\fP. -.TP -.B menu\-complete -Similar to \fBcomplete\fP, but replaces the word to be completed -with a single match from the list of possible completions. -Repeated execution of \fBmenu\-complete\fP steps through the list -of possible completions, inserting each match in turn. -At the end of the list of completions, the bell is rung -(subject to the setting of \fBbell\-style\fP) -and the original text is restored. -An argument of \fIn\fP moves \fIn\fP positions forward in the list -of matches; a negative argument may be used to move backward -through the list. -This command is intended to be bound to \fBTAB\fP, but is unbound -by default. -.TP -.B menu\-complete\-backward -Identical to \fBmenu\-complete\fP, but moves backward through the list -of possible completions, as if \fBmenu\-complete\fP had been given a -negative argument. This command is unbound by default. -.TP -.B delete\-char\-or\-list -Deletes the character under the cursor if not at the beginning or -end of the line (like \fBdelete\-char\fP). -If at the end of the line, behaves identically to -\fBpossible\-completions\fP. -This command is unbound by default. -.TP -.B complete\-filename (M\-/) -Attempt filename completion on the text before point. -.TP -.B possible\-filename\-completions (C\-x /) -List the possible completions of the text before point, -treating it as a filename. -.TP -.B complete\-username (M\-~) -Attempt completion on the text before point, treating -it as a username. -.TP -.B possible\-username\-completions (C\-x ~) -List the possible completions of the text before point, -treating it as a username. -.TP -.B complete\-variable (M\-$) -Attempt completion on the text before point, treating -it as a shell variable. -.TP -.B possible\-variable\-completions (C\-x $) -List the possible completions of the text before point, -treating it as a shell variable. -.TP -.B complete\-hostname (M\-@) -Attempt completion on the text before point, treating -it as a hostname. -.TP -.B possible\-hostname\-completions (C\-x @) -List the possible completions of the text before point, -treating it as a hostname. -.TP -.B complete\-command (M\-!) -Attempt completion on the text before point, treating -it as a command name. Command completion attempts to -match the text against aliases, reserved words, shell -functions, shell builtins, and finally executable filenames, -in that order. -.TP -.B possible\-command\-completions (C\-x !) -List the possible completions of the text before point, -treating it as a command name. -.TP -.B dynamic\-complete\-history (M\-TAB) -Attempt completion on the text before point, comparing -the text against lines from the history list for possible -completion matches. -.TP -.B dabbrev\-expand -Attempt menu completion on the text before point, comparing -the text against lines from the history list for possible -completion matches. -.TP -.B complete\-into\-braces (M\-{) -Perform filename completion and insert the list of possible completions -enclosed within braces so the list is available to the shell (see -.B Brace Expansion -above). -.PD -.SS Keyboard Macros -.PP -.PD 0 -.TP -.B start\-kbd\-macro (C\-x (\^) -Begin saving the characters typed into the current keyboard macro. -.TP -.B end\-kbd\-macro (C\-x )\^) -Stop saving the characters typed into the current keyboard macro -and store the definition. -.TP -.B call\-last\-kbd\-macro (C\-x e) -Re-execute the last keyboard macro defined, by making the characters -in the macro appear as if typed at the keyboard. -.TP -.B print\-last\-kbd\-macro () -Print the last keyboard macro defined in a format suitable for the -\fIinputrc\fP file. -.PD -.SS Miscellaneous -.PP -.PD 0 -.TP -.B re\-read\-init\-file (C\-x C\-r) -Read in the contents of the \fIinputrc\fP file, and incorporate -any bindings or variable assignments found there. -.TP -.B abort (C\-g) -Abort the current editing command and -ring the terminal's bell (subject to the setting of -.BR bell\-style ). -.TP -.B do\-uppercase\-version (M\-a, M\-b, M\-\fIx\fP, ...) -If the metafied character \fIx\fP is lowercase, run the command -that is bound to the corresponding uppercase character. -.TP -.B prefix\-meta (ESC) -Metafy the next character typed. -.SM -.B ESC -.B f -is equivalent to -.BR Meta\-f . -.TP -.B undo (C\-_, C\-x C\-u) -Incremental undo, separately remembered for each line. -.TP -.B revert\-line (M\-r) -Undo all changes made to this line. This is like executing the -.B undo -command enough times to return the line to its initial state. -.TP -.B tilde\-expand (M\-&) -Perform tilde expansion on the current word. -.TP -.B set\-mark (C\-@, M\-<space>) -Set the mark to the point. If a -numeric argument is supplied, the mark is set to that position. -.TP -.B exchange\-point\-and\-mark (C\-x C\-x) -Swap the point with the mark. The current cursor position is set to -the saved position, and the old cursor position is saved as the mark. -.TP -.B character\-search (C\-]) -A character is read and point is moved to the next occurrence of that -character. A negative count searches for previous occurrences. -.TP -.B character\-search\-backward (M\-C\-]) -A character is read and point is moved to the previous occurrence of that -character. A negative count searches for subsequent occurrences. -.TP -.B skip\-csi\-sequence -Read enough characters to consume a multi-key sequence such as those -defined for keys like Home and End. Such sequences begin with a -Control Sequence Indicator (CSI), usually ESC\-[. If this sequence is -bound to "\e[", keys producing such sequences will have no effect -unless explicitly bound to a readline command, instead of inserting -stray characters into the editing buffer. This is unbound by default, -but usually bound to ESC\-[. -.TP -.B insert\-comment (M\-#) -Without a numeric argument, the value of the readline -.B comment\-begin -variable is inserted at the beginning of the current line. -If a numeric argument is supplied, this command acts as a toggle: if -the characters at the beginning of the line do not match the value -of \fBcomment\-begin\fP, the value is inserted, otherwise -the characters in \fBcomment\-begin\fP are deleted from the beginning of -the line. -In either case, the line is accepted as if a newline had been typed. -The default value of -\fBcomment\-begin\fP causes this command to make the current line -a shell comment. -If a numeric argument causes the comment character to be removed, the line -will be executed by the shell. -.TP -.B glob\-complete\-word (M\-g) -The word before point is treated as a pattern for pathname expansion, -with an asterisk implicitly appended. This pattern is used to -generate a list of matching filenames for possible completions. -.TP -.B glob\-expand\-word (C\-x *) -The word before point is treated as a pattern for pathname expansion, -and the list of matching filenames is inserted, replacing the word. -If a numeric argument is supplied, an asterisk is appended before -pathname expansion. -.TP -.B glob\-list\-expansions (C\-x g) -The list of expansions that would have been generated by -.B glob\-expand\-word -is displayed, and the line is redrawn. -If a numeric argument is supplied, an asterisk is appended before -pathname expansion. -.TP -.B dump\-functions -Print all of the functions and their key bindings to the -readline output stream. If a numeric argument is supplied, -the output is formatted in such a way that it can be made part -of an \fIinputrc\fP file. -.TP -.B dump\-variables -Print all of the settable readline variables and their values to the -readline output stream. If a numeric argument is supplied, -the output is formatted in such a way that it can be made part -of an \fIinputrc\fP file. -.TP -.B dump\-macros -Print all of the readline key sequences bound to macros and the -strings they output. If a numeric argument is supplied, -the output is formatted in such a way that it can be made part -of an \fIinputrc\fP file. -.TP -.B display\-shell\-version (C\-x C\-v) -Display version information about the current instance of -.BR bash . -.PD -.SS Programmable Completion -.PP -When word completion is attempted for an argument to a command for -which a completion specification (a \fIcompspec\fP) has been defined -using the \fBcomplete\fP builtin (see -.SM -.B "SHELL BUILTIN COMMANDS" -below), the programmable completion facilities are invoked. -.PP -First, the command name is identified. -If the command word is the empty string (completion attempted at the -beginning of an empty line), any compspec defined with -the \fB\-E\fP option to \fBcomplete\fP is used. -If a compspec has been defined for that command, the -compspec is used to generate the list of possible completions for the word. -If the command word is a full pathname, a compspec for the full -pathname is searched for first. -If no compspec is found for the full pathname, an attempt is made to -find a compspec for the portion following the final slash. -If those searches do not result in a compspec, any compspec defined with -the \fB\-D\fP option to \fBcomplete\fP is used as the default. -.PP -Once a compspec has been found, it is used to generate the list of -matching words. -If a compspec is not found, the default \fBbash\fP completion as -described above under \fBCompleting\fP is performed. -.PP -First, the actions specified by the compspec are used. -Only matches which are prefixed by the word being completed are -returned. -When the -.B \-f -or -.B \-d -option is used for filename or directory name completion, the shell -variable -.SM -.B FIGNORE -is used to filter the matches. -.PP -Any completions specified by a pathname expansion pattern to the -\fB\-G\fP option are generated next. -The words generated by the pattern need not match the word -being completed. -The -.SM -.B GLOBIGNORE -shell variable is not used to filter the matches, but the -.SM -.B FIGNORE -variable is used. -.PP -Next, the string specified as the argument to the \fB\-W\fP option -is considered. -The string is first split using the characters in the -.SM -.B IFS -special variable as delimiters. -Shell quoting is honored. -Each word is then expanded using -brace expansion, tilde expansion, parameter and variable expansion, -command substitution, and arithmetic expansion, -as described above under -.SM -.BR EXPANSION . -The results are split using the rules described above under -\fBWord Splitting\fP. -The results of the expansion are prefix-matched against the word being -completed, and the matching words become the possible completions. -.PP -After these matches have been generated, any shell function or command -specified with the \fB\-F\fP and \fB\-C\fP options is invoked. -When the command or function is invoked, the -.SM -.BR COMP_LINE , -.SM -.BR COMP_POINT , -.SM -.BR COMP_KEY , -and -.SM -.B COMP_TYPE -variables are assigned values as described above under -\fBShell Variables\fP. -If a shell function is being invoked, the -.SM -.B COMP_WORDS -and -.SM -.B COMP_CWORD -variables are also set. -When the function or command is invoked, -the first argument (\fB$1\fP) is the name of the command whose arguments are -being completed, -the second argument (\fB$2\fP) is the word being completed, -and the third argument (\fB$3\fP) is the word preceding the word being -completed on the current command line. -No filtering of the generated completions against the word being completed -is performed; the function or command has complete freedom in generating -the matches. -.PP -Any function specified with \fB\-F\fP is invoked first. -The function may use any of the shell facilities, including the -\fBcompgen\fP builtin described below, to generate the matches. -It must put the possible completions in the -.SM -.B COMPREPLY -array variable, one per array element. -.PP -Next, any command specified with the \fB\-C\fP option is invoked -in an environment equivalent to command substitution. -It should print a list of completions, one per line, to the -standard output. -Backslash may be used to escape a newline, if necessary. -.PP -After all of the possible completions are generated, any filter -specified with the \fB\-X\fP option is applied to the list. -The filter is a pattern as used for pathname expansion; a \fB&\fP -in the pattern is replaced with the text of the word being completed. -A literal \fB&\fP may be escaped with a backslash; the backslash -is removed before attempting a match. -Any completion that matches the pattern will be removed from the list. -A leading \fB!\fP negates the pattern; in this case any completion -not matching the pattern will be removed. -.PP -Finally, any prefix and suffix specified with the \fB\-P\fP and \fB\-S\fP -options are added to each member of the completion list, and the result is -returned to the readline completion code as the list of possible -completions. -.PP -If the previously-applied actions do not generate any matches, and the -\fB\-o dirnames\fP option was supplied to \fBcomplete\fP when the -compspec was defined, directory name completion is attempted. -.PP -If the \fB\-o plusdirs\fP option was supplied to \fBcomplete\fP when the -compspec was defined, directory name completion is attempted and any -matches are added to the results of the other actions. -.PP -By default, if a compspec is found, whatever it generates is returned -to the completion code as the full set of possible completions. -The default \fBbash\fP completions are not attempted, and the readline -default of filename completion is disabled. -If the \fB\-o bashdefault\fP option was supplied to \fBcomplete\fP when -the compspec was defined, the \fBbash\fP default completions are attempted -if the compspec generates no matches. -If the \fB\-o default\fP option was supplied to \fBcomplete\fP when the -compspec was defined, readline's default completion will be performed -if the compspec (and, if attempted, the default \fBbash\fP completions) -generate no matches. -.PP -When a compspec indicates that directory name completion is desired, -the programmable completion functions force readline to append a slash -to completed names which are symbolic links to directories, subject to -the value of the \fBmark\-directories\fP readline variable, regardless -of the setting of the \fBmark-symlinked\-directories\fP readline variable. -.PP -There is some support for dynamically modifying completions. This is -most useful when used in combination with a default completion specified -with \fBcomplete -D\fP. -It's possible for shell functions executed as completion -handlers to indicate that completion should be retried by returning an -exit status of 124. If a shell function returns 124, and changes -the compspec associated with the command on which completion is being -attempted (supplied as the first argument when the function is executed), -programmable completion restarts from the beginning, with an -attempt to find a new compspec for that command. This allows a set of -completions to be built dynamically as completion is attempted, rather than -being loaded all at once. -.PP -For instance, assuming that there is a library of compspecs, each kept in a -file corresponding to the name of the command, the following default -completion function would load completions dynamically: -.PP -\f(CW_completion_loader() -.br -{ -.br - . "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124 -.br -} -.br -complete -D -F _completion_loader -o bashdefault -o default -.br -\fP -.SH HISTORY -When the -.B \-o history -option to the -.B set -builtin is enabled, the shell provides access to the -\fIcommand history\fP, -the list of commands previously typed. -The value of the -.SM -.B HISTSIZE -variable is used as the -number of commands to save in a history list. -The text of the last -.SM -.B HISTSIZE -commands (default 500) is saved. The shell -stores each command in the history list prior to parameter and -variable expansion (see -.SM -.B EXPANSION -above) but after history expansion is performed, subject to the -values of the shell variables -.SM -.B HISTIGNORE -and -.SM -.BR HISTCONTROL . -.PP -On startup, the history is initialized from the file named by -the variable -.SM -.B HISTFILE -(default \fI~/.bash_history\fP). -The file named by the value of -.SM -.B HISTFILE -is truncated, if necessary, to contain no more than -the number of lines specified by the value of -.SM -.BR HISTFILESIZE . -If \fBHISTFILESIZE\fP is unset, or set to null, a non-numeric value, -or a numeric value less than zero, the history file is not truncated. -When the history file is read, -lines beginning with the history comment character followed immediately -by a digit are interpreted as timestamps for the preceding history line. -These timestamps are optionally displayed depending on the value of the -.SM -.B HISTTIMEFORMAT -variable. -When a shell with history enabled exits, the last -.SM -.B $HISTSIZE -lines are copied from the history list to -.SM -.BR $HISTFILE . -If the -.B histappend -shell option is enabled -(see the description of -.B shopt -under -.SM -.B "SHELL BUILTIN COMMANDS" -below), the lines are appended to the history file, -otherwise the history file is overwritten. -If -.SM -.B HISTFILE -is unset, or if the history file is unwritable, the history is -not saved. -If the -.SM -.B HISTTIMEFORMAT -variable is set, time stamps are written to the history file, marked -with the history comment character, so -they may be preserved across shell sessions. -This uses the history comment character to distinguish timestamps from -other history lines. -After saving the history, the history file is truncated -to contain no more than -.SM -.B HISTFILESIZE -lines. If -.SM -.B HISTFILESIZE -is unset, or set to null, a non-numeric value, -or a numeric value less than zero, the history file is not truncated. -.PP -The builtin command -.B fc -(see -.SM -.B SHELL BUILTIN COMMANDS -below) may be used to list or edit and re-execute a portion of -the history list. -The -.B history -builtin may be used to display or modify the history list and -manipulate the history file. -When using command-line editing, search commands -are available in each editing mode that provide access to the -history list. -.PP -The shell allows control over which commands are saved on the history -list. The -.SM -.B HISTCONTROL -and -.SM -.B HISTIGNORE -variables may be set to cause the shell to save only a subset of the -commands entered. -The -.B cmdhist -shell option, if enabled, causes the shell to attempt to save each -line of a multi-line command in the same history entry, adding -semicolons where necessary to preserve syntactic correctness. -The -.B lithist -shell option causes the shell to save the command with embedded newlines -instead of semicolons. See the description of the -.B shopt -builtin below under -.SM -.B "SHELL BUILTIN COMMANDS" -for information on setting and unsetting shell options. -.SH "HISTORY EXPANSION" -.PP -The shell supports a history expansion feature that -is similar to the history expansion in -.BR csh. -This section describes what syntax features are available. This -feature is enabled by default for interactive shells, and can be -disabled using the -.B +H -option to the -.B set -builtin command (see -.SM -.B SHELL BUILTIN COMMANDS -below). Non-interactive shells do not perform history expansion -by default. -.PP -History expansions introduce words from the history list into -the input stream, making it easy to repeat commands, insert the -arguments to a previous command into the current input line, or -fix errors in previous commands quickly. -.PP -History expansion is performed immediately after a complete line -is read, before the shell breaks it into words. -It takes place in two parts. -The first is to determine which line from the history list -to use during substitution. -The second is to select portions of that line for inclusion into -the current one. -The line selected from the history is the \fIevent\fP, -and the portions of that line that are acted upon are \fIwords\fP. -Various \fImodifiers\fP are available to manipulate the selected words. -The line is broken into words in the same fashion as when reading input, -so that several \fImetacharacter\fP-separated words surrounded by -quotes are considered one word. -History expansions are introduced by the appearance of the -history expansion character, which is \^\fB!\fP\^ by default. -Only backslash (\^\fB\e\fP\^) and single quotes can quote -the history expansion character. -.PP -Several characters inhibit history expansion if found immediately -following the history expansion character, even if it is unquoted: -space, tab, newline, carriage return, and \fB=\fP. -If the \fBextglob\fP shell option is enabled, \fB(\fP will also -inhibit expansion. -.PP -Several shell options settable with the -.B shopt -builtin may be used to tailor the behavior of history expansion. -If the -.B histverify -shell option is enabled (see the description of the -.B shopt -builtin below), and -.B readline -is being used, history substitutions are not immediately passed to -the shell parser. -Instead, the expanded line is reloaded into the -.B readline -editing buffer for further modification. -If -.B readline -is being used, and the -.B histreedit -shell option is enabled, a failed history substitution will be reloaded -into the -.B readline -editing buffer for correction. -The -.B \-p -option to the -.B history -builtin command may be used to see what a history expansion will -do before using it. -The -.B \-s -option to the -.B history -builtin may be used to add commands to the end of the history list -without actually executing them, so that they are available for -subsequent recall. -.PP -The shell allows control of the various characters used by the -history expansion mechanism (see the description of -.B histchars -above under -.BR "Shell Variables" ). -The shell uses -the history comment character to mark history timestamps when -writing the history file. -.SS Event Designators -.PP -An event designator is a reference to a command line entry in the -history list. -Unless the reference is absolute, events are relative to the current -position in the history list. -.PP -.PD 0 -.TP -.B ! -Start a history substitution, except when followed by a -.BR blank , -newline, carriage return, = -or ( (when the \fBextglob\fP shell option is enabled using -the \fBshopt\fP builtin). -.TP -.B !\fIn\fR -Refer to command line -.IR n . -.TP -.B !\-\fIn\fR -Refer to the current command minus -.IR n . -.TP -.B !! -Refer to the previous command. This is a synonym for `!\-1'. -.TP -.B !\fIstring\fR -Refer to the most recent command preceding the current position in the -history list starting with -.IR string . -.TP -.B !?\fIstring\fR\fB[?]\fR -Refer to the most recent command preceding the current position in the -history list containing -.IR string . -The trailing \fB?\fP may be omitted if -.I string -is followed immediately by a newline. -.TP -.B \d\s+2^\s-2\u\fIstring1\fP\d\s+2^\s-2\u\fIstring2\fP\d\s+2^\s-2\u -Quick substitution. Repeat the previous command, replacing -.I string1 -with -.IR string2 . -Equivalent to -``!!:s/\fIstring1\fP/\fIstring2\fP/'' -(see \fBModifiers\fP below). -.TP -.B !# -The entire command line typed so far. -.PD -.SS Word Designators -.PP -Word designators are used to select desired words from the event. -A -.B : -separates the event specification from the word designator. -It may be omitted if the word designator begins with a -.BR ^ , -.BR $ , -.BR * , -.BR \- , -or -.BR % . -Words are numbered from the beginning of the line, -with the first word being denoted by 0 (zero). -Words are inserted into the current line separated by single spaces. -.PP -.PD 0 -.TP -.B 0 (zero) -The zeroth word. For the shell, this is the command -word. -.TP -.I n -The \fIn\fRth word. -.TP -.B ^ -The first argument. That is, word 1. -.TP -.B $ -The last word. This is usually the last argument, but will expand to the -zeroth word if there is only one word in the line. -.TP -.B % -The word matched by the most recent `?\fIstring\fR?' search. -.TP -.I x\fB\-\fPy -A range of words; `\-\fIy\fR' abbreviates `0\-\fIy\fR'. -.TP -.B * -All of the words but the zeroth. This is a synonym -for `\fI1\-$\fP'. It is not an error to use -.B * -if there is just one -word in the event; the empty string is returned in that case. -.TP -.B x* -Abbreviates \fIx\-$\fP. -.TP -.B x\- -Abbreviates \fIx\-$\fP like \fBx*\fP, but omits the last word. -.PD -.PP -If a word designator is supplied without an event specification, the -previous command is used as the event. -.SS Modifiers -.PP -After the optional word designator, there may appear a sequence of -one or more of the following modifiers, each preceded by a `:'. -.PP -.PD 0 -.PP -.TP -.B h -Remove a trailing filename component, leaving only the head. -.TP -.B t -Remove all leading filename components, leaving the tail. -.TP -.B r -Remove a trailing suffix of the form \fI.xxx\fP, leaving the -basename. -.TP -.B e -Remove all but the trailing suffix. -.TP -.B p -Print the new command but do not execute it. -.TP -.B q -Quote the substituted words, escaping further substitutions. -.TP -.B x -Quote the substituted words as with -.BR q , -but break into words at -.B blanks -and newlines. -.TP -.B s/\fIold\fP/\fInew\fP/ -Substitute -.I new -for the first occurrence of -.I old -in the event line. Any delimiter can be used in place of /. The -final delimiter is optional if it is the last character of the -event line. The delimiter may be quoted in -.I old -and -.I new -with a single backslash. If & appears in -.IR new , -it is replaced by -.IR old . -A single backslash will quote the &. If -.I old -is null, it is set to the last -.I old -substituted, or, if no previous history substitutions took place, -the last -.I string -in a -.B !?\fIstring\fR\fB[?]\fR -search. -.TP -.B & -Repeat the previous substitution. -.TP -.B g -Cause changes to be applied over the entire event line. This is -used in conjunction with `\fB:s\fP' (e.g., `\fB:gs/\fIold\fP/\fInew\fP/\fR') -or `\fB:&\fP'. If used with -`\fB:s\fP', any delimiter can be used -in place of /, and the final delimiter is optional -if it is the last character of the event line. -An \fBa\fP may be used as a synonym for \fBg\fP. -.TP -.B G -Apply the following `\fBs\fP' modifier once to each word in the event line. -.PD -.SH "SHELL BUILTIN COMMANDS" -.\" start of bash_builtins -.zZ -.PP -Unless otherwise noted, each builtin command documented in this -section as accepting options preceded by -.B \- -accepts -.B \-\- -to signify the end of the options. -The \fB:\fP, \fBtrue\fP, \fBfalse\fP, and \fBtest\fP builtins -do not accept options and do not treat \fB\-\-\fP specially. -The \fBexit\fP, \fBlogout\fP, \fBbreak\fP, \fBcontinue\fP, \fBlet\fP, -and \fBshift\fP builtins accept and process arguments beginning with -\fB\-\fP without requiring \fB\-\-\fP. -Other builtins that accept arguments but are not specified as accepting -options interpret arguments beginning with \fB\-\fP as invalid options and -require \fB\-\-\fP to prevent this interpretation. -.sp .5 -.PD 0 -.TP -\fB:\fP [\fIarguments\fP] -.PD -No effect; the command does nothing beyond expanding -.I arguments -and performing any specified -redirections. A zero exit code is returned. -.TP -\fB .\| \fP \fIfilename\fP [\fIarguments\fP] -.PD 0 -.TP -\fBsource\fP \fIfilename\fP [\fIarguments\fP] -.PD -Read and execute commands from -.I filename -in the current -shell environment and return the exit status of the last command -executed from -.IR filename . -If -.I filename -does not contain a slash, filenames in -.SM -.B PATH -are used to find the directory containing -.IR filename . -The file searched for in -.SM -.B PATH -need not be executable. -When \fBbash\fP is not in \fIposix mode\fP, the current directory is -searched if no file is found in -.SM -.BR PATH . -If the -.B sourcepath -option to the -.B shopt -builtin command is turned off, the -.SM -.B PATH -is not searched. -If any \fIarguments\fP are supplied, they become the positional -parameters when \fIfilename\fP is executed. Otherwise the positional -parameters are unchanged. -The return status is the status of the last command exited within -the script (0 if no commands are executed), and false if -.I filename -is not found or cannot be read. -.TP -\fBalias\fP [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] -\fBAlias\fP with no arguments or with the -.B \-p -option prints the list of aliases in the form -\fBalias\fP \fIname\fP=\fIvalue\fP on standard output. -When arguments are supplied, an alias is defined for -each \fIname\fP whose \fIvalue\fP is given. -A trailing space in \fIvalue\fP causes the next word to be -checked for alias substitution when the alias is expanded. -For each \fIname\fP in the argument list for which no \fIvalue\fP -is supplied, the name and value of the alias is printed. -\fBAlias\fP returns true unless a \fIname\fP is given for which -no alias has been defined. -.TP -\fBbg\fP [\fIjobspec\fP ...] -Resume each suspended job \fIjobspec\fP in the background, as if it -had been started with -.BR & . -If -.I jobspec -is not present, the shell's notion of the \fIcurrent job\fP is used. -.B bg -.I jobspec -returns 0 unless run when job control is disabled or, when run with -job control enabled, any specified \fIjobspec\fP was not found -or was started without job control. -.TP -\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSVX\fP] -.PD 0 -.TP -\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-q\fP \fIfunction\fP] [\fB\-u\fP \fIfunction\fP] [\fB\-r\fP \fIkeyseq\fP] -.TP -\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fB\-f\fP \fIfilename\fP -.TP -\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fB\-x\fP \fIkeyseq\fP:\fIshell\-command\fP -.TP -\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fIkeyseq\fP:\fIfunction\-name\fP -.TP -\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fIkeyseq\fP:\fIreadline\-command\fP -.PD -Display current -.B readline -key and function bindings, bind a key sequence to a -.B readline -function or macro, or set a -.B readline -variable. -Each non-option argument is a command as it would appear in -.IR .inputrc , -but each binding or command must be passed as a separate argument; -e.g., '"\eC\-x\eC\-r": re\-read\-init\-file'. -Options, if supplied, have the following meanings: -.RS -.PD 0 -.TP -.B \-m \fIkeymap\fP -Use -.I keymap -as the keymap to be affected by the subsequent bindings. -Acceptable -.I keymap -names are -\fIemacs, emacs\-standard, emacs\-meta, emacs\-ctlx, vi, -vi\-move, vi\-command\fP, and -.IR vi\-insert . -\fIvi\fP is equivalent to \fIvi\-command\fP; \fIemacs\fP is -equivalent to \fIemacs\-standard\fP. -.TP -.B \-l -List the names of all \fBreadline\fP functions. -.TP -.B \-p -Display \fBreadline\fP function names and bindings in such a way -that they can be re-read. -.TP -.B \-P -List current \fBreadline\fP function names and bindings. -.TP -.B \-s -Display \fBreadline\fP key sequences bound to macros and the strings -they output in such a way that they can be re-read. -.TP -.B \-S -Display \fBreadline\fP key sequences bound to macros and the strings -they output. -.TP -.B \-v -Display \fBreadline\fP variable names and values in such a way that they -can be re-read. -.TP -.B \-V -List current \fBreadline\fP variable names and values. -.TP -.B \-f \fIfilename\fP -Read key bindings from \fIfilename\fP. -.TP -.B \-q \fIfunction\fP -Query about which keys invoke the named \fIfunction\fP. -.TP -.B \-u \fIfunction\fP -Unbind all keys bound to the named \fIfunction\fP. -.TP -.B \-r \fIkeyseq\fP -Remove any current binding for \fIkeyseq\fP. -.TP -.B \-x \fIkeyseq\fP:\fIshell\-command\fP -Cause \fIshell\-command\fP to be executed whenever \fIkeyseq\fP is -entered. -When \fIshell\-command\fP is executed, the shell sets the -.SM -.B READLINE_LINE -variable to the contents of the \fBreadline\fP line buffer and the -.SM -.B READLINE_POINT -variable to the current location of the insertion point. -If the executed command changes the value of -.SM -.B READLINE_LINE -or -.SM -.BR READLINE_POINT , -those new values will be reflected in the editing state. -.TP -.B \-X -List all key sequences bound to shell commands and the associated commands -in a format that can be reused as input. -.PD -.PP -The return value is 0 unless an unrecognized option is given or an -error occurred. -.RE -.TP -\fBbreak\fP [\fIn\fP] -Exit from within a -.BR for , -.BR while , -.BR until , -or -.B select -loop. If \fIn\fP is specified, break \fIn\fP levels. -.I n -must be \(>= 1. If -.I n -is greater than the number of enclosing loops, all enclosing loops -are exited. -The return value is 0 unless \fIn\fP is not greater than or equal to 1. -.TP -\fBbuiltin\fP \fIshell\-builtin\fP [\fIarguments\fP] -Execute the specified shell builtin, passing it -.IR arguments , -and return its exit status. -This is useful when defining a -function whose name is the same as a shell builtin, -retaining the functionality of the builtin within the function. -The \fBcd\fP builtin is commonly redefined this way. -The return status is false if -.I shell\-builtin -is not a shell builtin command. -.TP -\fBcaller\fP [\fIexpr\fP] -Returns the context of any active subroutine call (a shell function or -a script executed with the \fB.\fP or \fBsource\fP builtins). -Without \fIexpr\fP, \fBcaller\fP displays the line number and source -filename of the current subroutine call. -If a non-negative integer is supplied as \fIexpr\fP, \fBcaller\fP -displays the line number, subroutine name, and source file corresponding -to that position in the current execution call stack. This extra -information may be used, for example, to print a stack trace. The -current frame is frame 0. -The return value is 0 unless the shell is not executing a subroutine -call or \fIexpr\fP does not correspond to a valid position in the -call stack. -.TP -\fBcd\fP [\fB\-L\fP|[\fB\-P\fP [\fB\-e\fP]] [\-@]] [\fIdir\fP] -Change the current directory to \fIdir\fP. -if \fIdir\fP is not supplied, the value of the -.SM -.B HOME -shell variable is the default. -Any additional arguments following \fIdir\fP are ignored. -The variable -.SM -.B CDPATH -defines the search path for the directory containing -.IR dir : -each directory name in -.SM -.B CDPATH -is searched for \fIdir\fP. -Alternative directory names in -.SM -.B CDPATH -are separated by a colon (:). A null directory name in -.SM -.B CDPATH -is the same as the current directory, i.e., ``\fB.\fP''. If -.I dir -begins with a slash (/), -then -.SM -.B CDPATH -is not used. The -.B \-P -option causes \fBcd\fP to use the physical directory structure -by resolving symbolic links while traversing \fIdir\fP and -before processing instances of \fI..\fP in \fIdir\fP (see also the -.B \-P -option to the -.B set -builtin command); the -.B \-L -option forces symbolic links to be followed by resolving the link -after processing instances of \fI..\fP in \fIdir\fP. -If \fI..\fP appears in \fIdir\fP, it is processed by removing the -immediately previous pathname component from \fIdir\fP, back to a slash -or the beginning of \fIdir\fP. -If the -.B \-e -option is supplied with -.BR \-P , -and the current working directory cannot be successfully determined -after a successful directory change, \fBcd\fP will return an unsuccessful -status. -On systems that support it, the \fB\-@\fP option presents the extended -attributes associated with a file as a directory. -An argument of -.B \- -is converted to -.SM -.B $OLDPWD -before the directory change is attempted. -If a non-empty directory name from -.SM -.B CDPATH -is used, or if -\fB\-\fP is the first argument, and the directory change is -successful, the absolute pathname of the new working directory is -written to the standard output. -The return value is true if the directory was successfully changed; -false otherwise. -.TP -\fBcommand\fP [\fB\-pVv\fP] \fIcommand\fP [\fIarg\fP ...] -Run -.I command -with -.I args -suppressing the normal shell function lookup. Only builtin -commands or commands found in the -.SM -.B PATH -are executed. If the -.B \-p -option is given, the search for -.I command -is performed using a default value for -.SM -.B PATH -that is guaranteed to find all of the standard utilities. -If either the -.B \-V -or -.B \-v -option is supplied, a description of -.I command -is printed. The -.B \-v -option causes a single word indicating the command or filename -used to invoke -.I command -to be displayed; the -.B \-V -option produces a more verbose description. -If the -.B \-V -or -.B \-v -option is supplied, the exit status is 0 if -.I command -was found, and 1 if not. If neither option is supplied and -an error occurred or -.I command -cannot be found, the exit status is 127. Otherwise, the exit status of the -.B command -builtin is the exit status of -.IR command . -.TP -\fBcompgen\fP [\fIoption\fP] [\fIword\fP] -Generate possible completion matches for \fIword\fP according to -the \fIoption\fPs, which may be any option accepted by the -.B complete -builtin with the exception of \fB\-p\fP and \fB\-r\fP, and write -the matches to the standard output. -When using the \fB\-F\fP or \fB\-C\fP options, the various shell variables -set by the programmable completion facilities, while available, will not -have useful values. -.sp 1 -The matches will be generated in the same way as if the programmable -completion code had generated them directly from a completion specification -with the same flags. -If \fIword\fP is specified, only those completions matching \fIword\fP -will be displayed. -.sp 1 -The return value is true unless an invalid option is supplied, or no -matches were generated. -.TP -\fBcomplete\fP [\fB\-abcdefgjksuv\fP] [\fB\-o\fP \fIcomp-option\fP] [\fB\-DE\fP] [\fB\-A\fP \fIaction\fP] [\fB\-G\fP \fIglobpat\fP] [\fB\-W\fP \fIwordlist\fP] [\fB\-F\fP \fIfunction\fP] [\fB\-C\fP \fIcommand\fP] -.br -[\fB\-X\fP \fIfilterpat\fP] [\fB\-P\fP \fIprefix\fP] [\fB\-S\fP \fIsuffix\fP] \fIname\fP [\fIname ...\fP] -.PD 0 -.TP -\fBcomplete\fP \fB\-pr\fP [\fB\-DE\fP] [\fIname\fP ...] -.PD -Specify how arguments to each \fIname\fP should be completed. -If the \fB\-p\fP option is supplied, or if no options are supplied, -existing completion specifications are printed in a way that allows -them to be reused as input. -The \fB\-r\fP option removes a completion specification for -each \fIname\fP, or, if no \fIname\fPs are supplied, all -completion specifications. -The \fB\-D\fP option indicates that the remaining options and actions should -apply to the ``default'' command completion; that is, completion attempted -on a command for which no completion has previously been defined. -The \fB\-E\fP option indicates that the remaining options and actions should -apply to ``empty'' command completion; that is, completion attempted on a -blank line. -.sp 1 -The process of applying these completion specifications when word completion -is attempted is described above under \fBProgrammable Completion\fP. -.sp 1 -Other options, if specified, have the following meanings. -The arguments to the \fB\-G\fP, \fB\-W\fP, and \fB\-X\fP options -(and, if necessary, the \fB\-P\fP and \fB\-S\fP options) -should be quoted to protect them from expansion before the -.B complete -builtin is invoked. -.RS -.PD 0 -.TP 8 -\fB\-o\fP \fIcomp-option\fP -The \fIcomp-option\fP controls several aspects of the compspec's behavior -beyond the simple generation of completions. -\fIcomp-option\fP may be one of: -.RS -.TP 8 -.B bashdefault -Perform the rest of the default \fBbash\fP completions if the compspec -generates no matches. -.TP 8 -.B default -Use readline's default filename completion if the compspec generates -no matches. -.TP 8 -.B dirnames -Perform directory name completion if the compspec generates no matches. -.TP 8 -.B filenames -Tell readline that the compspec generates filenames, so it can perform any -filename\-specific processing (like adding a slash to directory names, -quoting special characters, or suppressing trailing spaces). -Intended to be used with shell functions. -.TP 8 -.B noquote -Tell readline not to quote the completed words if they are filenames -(quoting filenames is the default). -.TP 8 -.B nospace -Tell readline not to append a space (the default) to words completed at -the end of the line. -.TP 8 -.B plusdirs -After any matches defined by the compspec are generated, -directory name completion is attempted and any -matches are added to the results of the other actions. -.RE -.TP 8 -\fB\-A\fP \fIaction\fP -The \fIaction\fP may be one of the following to generate a list of possible -completions: -.RS -.TP 8 -.B alias -Alias names. May also be specified as \fB\-a\fP. -.TP 8 -.B arrayvar -Array variable names. -.TP 8 -.B binding -\fBReadline\fP key binding names. -.TP 8 -.B builtin -Names of shell builtin commands. May also be specified as \fB\-b\fP. -.TP 8 -.B command -Command names. May also be specified as \fB\-c\fP. -.TP 8 -.B directory -Directory names. May also be specified as \fB\-d\fP. -.TP 8 -.B disabled -Names of disabled shell builtins. -.TP 8 -.B enabled -Names of enabled shell builtins. -.TP 8 -.B export -Names of exported shell variables. May also be specified as \fB\-e\fP. -.TP 8 -.B file -File names. May also be specified as \fB\-f\fP. -.TP 8 -.B function -Names of shell functions. -.TP 8 -.B group -Group names. May also be specified as \fB\-g\fP. -.TP 8 -.B helptopic -Help topics as accepted by the \fBhelp\fP builtin. -.TP 8 -.B hostname -Hostnames, as taken from the file specified by the -.SM -.B HOSTFILE -shell variable. -.TP 8 -.B job -Job names, if job control is active. May also be specified as \fB\-j\fP. -.TP 8 -.B keyword -Shell reserved words. May also be specified as \fB\-k\fP. -.TP 8 -.B running -Names of running jobs, if job control is active. -.TP 8 -.B service -Service names. May also be specified as \fB\-s\fP. -.TP 8 -.B setopt -Valid arguments for the \fB\-o\fP option to the \fBset\fP builtin. -.TP 8 -.B shopt -Shell option names as accepted by the \fBshopt\fP builtin. -.TP 8 -.B signal -Signal names. -.TP 8 -.B stopped -Names of stopped jobs, if job control is active. -.TP 8 -.B user -User names. May also be specified as \fB\-u\fP. -.TP 8 -.B variable -Names of all shell variables. May also be specified as \fB\-v\fP. -.RE -.TP 8 -\fB\-C\fP \fIcommand\fP -\fIcommand\fP is executed in a subshell environment, and its output is -used as the possible completions. -.TP 8 -\fB\-F\fP \fIfunction\fP -The shell function \fIfunction\fP is executed in the current shell -environment. -When the function is executed, -the first argument (\fB$1\fP) is the name of the command whose arguments are -being completed, -the second argument (\fB$2\fP) is the word being completed, -and the third argument (\fB$3\fP) is the word preceding the word being -completed on the current command line. -When it finishes, the possible completions are retrieved from the value -of the -.SM -.B COMPREPLY -array variable. -.TP 8 -\fB\-G\fP \fIglobpat\fP -The pathname expansion pattern \fIglobpat\fP is expanded to generate -the possible completions. -.TP 8 -\fB\-P\fP \fIprefix\fP -\fIprefix\fP is added at the beginning of each possible completion -after all other options have been applied. -.TP 8 -\fB\-S\fP \fIsuffix\fP -\fIsuffix\fP is appended to each possible completion -after all other options have been applied. -.TP 8 -\fB\-W\fP \fIwordlist\fP -The \fIwordlist\fP is split using the characters in the -.SM -.B IFS -special variable as delimiters, and each resultant word is expanded. -The possible completions are the members of the resultant list which -match the word being completed. -.TP 8 -\fB\-X\fP \fIfilterpat\fP -\fIfilterpat\fP is a pattern as used for pathname expansion. -It is applied to the list of possible completions generated by the -preceding options and arguments, and each completion matching -\fIfilterpat\fP is removed from the list. -A leading \fB!\fP in \fIfilterpat\fP negates the pattern; in this -case, any completion not matching \fIfilterpat\fP is removed. -.PD -.PP -The return value is true unless an invalid option is supplied, an option -other than \fB\-p\fP or \fB\-r\fP is supplied without a \fIname\fP -argument, an attempt is made to remove a completion specification for -a \fIname\fP for which no specification exists, or -an error occurs adding a completion specification. -.RE -.TP -\fBcompopt\fP [\fB\-o\fP \fIoption\fP] [\fB\-DE\fP] [\fB+o\fP \fIoption\fP] [\fIname\fP] -Modify completion options for each \fIname\fP according to the -\fIoption\fPs, or for the -currently-executing completion if no \fIname\fPs are supplied. -If no \fIoption\fPs are given, display the completion options for each -\fIname\fP or the current completion. -The possible values of \fIoption\fP are those valid for the \fBcomplete\fP -builtin described above. -The \fB\-D\fP option indicates that the remaining options should -apply to the ``default'' command completion; that is, completion attempted -on a command for which no completion has previously been defined. -The \fB\-E\fP option indicates that the remaining options should -apply to ``empty'' command completion; that is, completion attempted on a -blank line. -.sp 1 -The return value is true unless an invalid option is supplied, an attempt -is made to modify the options for a \fIname\fP for which no completion -specification exists, or an output error occurs. -.TP -\fBcontinue\fP [\fIn\fP] -Resume the next iteration of the enclosing -.BR for , -.BR while , -.BR until , -or -.B select -loop. -If -.I n -is specified, resume at the \fIn\fPth enclosing loop. -.I n -must be \(>= 1. If -.I n -is greater than the number of enclosing loops, the last enclosing loop -(the ``top-level'' loop) is resumed. -The return value is 0 unless \fIn\fP is not greater than or equal to 1. -.TP -\fBdeclare\fP [\fB\-aAfFgilnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] -.PD 0 -.TP -\fBtypeset\fP [\fB\-aAfFgilnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] -.PD -Declare variables and/or give them attributes. -If no \fIname\fPs are given then display the values of variables. -The -.B \-p -option will display the attributes and values of each -.IR name . -When -.B \-p -is used with \fIname\fP arguments, additional options, -other than \fB\-f\fP and \fB\-F\fP, are ignored. -When -.B \-p -is supplied without \fIname\fP arguments, it will display the attributes -and values of all variables having the attributes specified by the -additional options. -If no other options are supplied with \fB\-p\fP, \fBdeclare\fP will display -the attributes and values of all shell variables. The \fB\-f\fP option -will restrict the display to shell functions. -The -.B \-F -option inhibits the display of function definitions; only the -function name and attributes are printed. -If the \fBextdebug\fP shell option is enabled using \fBshopt\fP, -the source file name and line number where the function is defined -are displayed as well. The -.B \-F -option implies -.BR \-f . -The -.B \-g -option forces variables to be created or modified at the global scope, -even when \fBdeclare\fP is executed in a shell function. -It is ignored in all other cases. -The following options can -be used to restrict output to variables with the specified attribute or -to give variables attributes: -.RS -.PD 0 -.TP -.B \-a -Each \fIname\fP is an indexed array variable (see -.B Arrays -above). -.TP -.B \-A -Each \fIname\fP is an associative array variable (see -.B Arrays -above). -.TP -.B \-f -Use function names only. -.TP -.B \-i -The variable is treated as an integer; arithmetic evaluation (see -.SM -.B "ARITHMETIC EVALUATION" -above) is performed when the variable is assigned a value. -.TP -.B \-l -When the variable is assigned a value, all upper-case characters are -converted to lower-case. -The upper-case attribute is disabled. -.TP -.B \-n -Give each \fIname\fP the \fInameref\fP attribute, making -it a name reference to another variable. -That other variable is defined by the value of \fIname\fP. -All references, assignments, and attribute modifications -to \fIname\fP, except for changing the -\fB\-n\fP attribute itself, are performed on the variable referenced by -\fIname\fP's value. -The nameref attribute cannot be applied to array variables. -.TP -.B \-r -Make \fIname\fPs readonly. These names cannot then be assigned values -by subsequent assignment statements or unset. -.TP -.B \-t -Give each \fIname\fP the \fItrace\fP attribute. -Traced functions inherit the \fBDEBUG\fP and \fBRETURN\fP traps from -the calling shell. -The trace attribute has no special meaning for variables. -.TP -.B \-u -When the variable is assigned a value, all lower-case characters are -converted to upper-case. -The lower-case attribute is disabled. -.TP -.B \-x -Mark \fIname\fPs for export to subsequent commands via the environment. -.PD -.PP -Using `+' instead of `\-' -turns off the attribute instead, -with the exceptions that \fB+a\fP -may not be used to destroy an array variable and \fB+r\fP will not -remove the readonly attribute. -When used in a function, -.B declare -and -.B typeset -make each -\fIname\fP local, as with the -.B local -command, -unless the \fB\-g\fP option is supplied. -If a variable name is followed by =\fIvalue\fP, the value of -the variable is set to \fIvalue\fP. -When using \fB\-a\fP or \fB\-A\fP and the compound assignment syntax to -create array variables, additional attributes do not take effect until -subsequent assignments. -The return value is 0 unless an invalid option is encountered, -an attempt is made to define a function using -.if n ``\-f foo=bar'', -.if t \f(CW\-f foo=bar\fP, -an attempt is made to assign a value to a readonly variable, -an attempt is made to assign a value to an array variable without -using the compound assignment syntax (see -.B Arrays -above), one of the \fInames\fP is not a valid shell variable name, -an attempt is made to turn off readonly status for a readonly variable, -an attempt is made to turn off array status for an array variable, -or an attempt is made to display a non-existent function with \fB\-f\fP. -.RE -.TP -.B dirs [\fB\-clpv\fP] [+\fIn\fP] [\-\fIn\fP] -Without options, displays the list of currently remembered directories. -The default display is on a single line with directory names separated -by spaces. -Directories are added to the list with the -.B pushd -command; the -.B popd -command removes entries from the list. -.RS -.PD 0 -.TP -.B \-c -Clears the directory stack by deleting all of the entries. -.TP -.B \-l -Produces a listing using full pathnames; -the default listing format uses a tilde to denote the home directory. -.TP -.B \-p -Print the directory stack with one entry per line. -.TP -.B \-v -Print the directory stack with one entry per line, -prefixing each entry with its index in the stack. -.TP -\fB+\fP\fIn\fP -Displays the \fIn\fPth entry counting from the left of the list -shown by -.B dirs -when invoked without options, starting with zero. -.TP -\fB\-\fP\fIn\fP -Displays the \fIn\fPth entry counting from the right of the list -shown by -.B dirs -when invoked without options, starting with zero. -.PD -.PP -The return value is 0 unless an -invalid option is supplied or \fIn\fP indexes beyond the end -of the directory stack. -.RE -.TP -\fBdisown\fP [\fB\-ar\fP] [\fB\-h\fP] [\fIjobspec\fP ...] -Without options, remove each -.I jobspec -from the table of active jobs. -If -.I jobspec -is not present, and neither the \fB\-a\fP nor the \fB\-r\fP option -is supplied, the \fIcurrent job\fP is used. -If the \fB\-h\fP option is given, each -.I jobspec -is not removed from the table, but is marked so that -.SM -.B SIGHUP -is not sent to the job if the shell receives a -.SM -.BR SIGHUP . -If no -.I jobspec -is supplied, the -.B \-a -option means to remove or mark all jobs; the -.B \-r -option without a -.I jobspec -argument restricts operation to running jobs. -The return value is 0 unless a -.I jobspec -does not specify a valid job. -.TP -\fBecho\fP [\fB\-neE\fP] [\fIarg\fP ...] -Output the \fIarg\fPs, separated by spaces, followed by a newline. -The return status is 0 unless a write error occurs. -If \fB\-n\fP is specified, the trailing newline is -suppressed. If the \fB\-e\fP option is given, interpretation of -the following backslash-escaped characters is enabled. The -.B \-E -option disables the interpretation of these escape characters, -even on systems where they are interpreted by default. -The \fBxpg_echo\fP shell option may be used to -dynamically determine whether or not \fBecho\fP expands these -escape characters by default. -.B echo -does not interpret \fB\-\-\fP to mean the end of options. -.B echo -interprets the following escape sequences: -.RS -.PD 0 -.TP -.B \ea -alert (bell) -.TP -.B \eb -backspace -.TP -.B \ec -suppress further output -.TP -.B \ee -.TP -.B \eE -an escape character -.TP -.B \ef -form feed -.TP -.B \en -new line -.TP -.B \er -carriage return -.TP -.B \et -horizontal tab -.TP -.B \ev -vertical tab -.TP -.B \e\e -backslash -.TP -.B \e0\fInnn\fP -the eight-bit character whose value is the octal value \fInnn\fP -(zero to three octal digits) -.TP -.B \ex\fIHH\fP -the eight-bit character whose value is the hexadecimal value \fIHH\fP -(one or two hex digits) -.TP -.B \eu\fIHHHH\fP -the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value -\fIHHHH\fP (one to four hex digits) -.TP -.B \eU\fIHHHHHHHH\fP -the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value -\fIHHHHHHHH\fP (one to eight hex digits) -.PD -.RE -.TP -\fBenable\fP [\fB\-a\fP] [\fB\-dnps\fP] [\fB\-f\fP \fIfilename\fP] [\fIname\fP ...] -Enable and disable builtin shell commands. -Disabling a builtin allows a disk command which has the same name -as a shell builtin to be executed without specifying a full pathname, -even though the shell normally searches for builtins before disk commands. -If \fB\-n\fP is used, each \fIname\fP -is disabled; otherwise, -\fInames\fP are enabled. For example, to use the -.B test -binary found via the -.SM -.B PATH -instead of the shell builtin version, run -.if t \f(CWenable -n test\fP. -.if n ``enable -n test''. -The -.B \-f -option means to load the new builtin command -.I name -from shared object -.IR filename , -on systems that support dynamic loading. The -.B \-d -option will delete a builtin previously loaded with -.BR \-f . -If no \fIname\fP arguments are given, or if the -.B \-p -option is supplied, a list of shell builtins is printed. -With no other option arguments, the list consists of all enabled -shell builtins. -If \fB\-n\fP is supplied, only disabled builtins are printed. -If \fB\-a\fP is supplied, the list printed includes all builtins, with an -indication of whether or not each is enabled. -If \fB\-s\fP is supplied, the output is restricted to the POSIX -\fIspecial\fP builtins. -The return value is 0 unless a -.I name -is not a shell builtin or there is an error loading a new builtin -from a shared object. -.TP -\fBeval\fP [\fIarg\fP ...] -The \fIarg\fPs are read and concatenated together into a single -command. This command is then read and executed by the shell, and -its exit status is returned as the value of -.BR eval . -If there are no -.IR args , -or only null arguments, -.B eval -returns 0. -.TP -\fBexec\fP [\fB\-cl\fP] [\fB\-a\fP \fIname\fP] [\fIcommand\fP [\fIarguments\fP]] -If -.I command -is specified, it replaces the shell. -No new process is created. The -.I arguments -become the arguments to \fIcommand\fP. -If the -.B \-l -option is supplied, -the shell places a dash at the beginning of the zeroth argument passed to -.IR command . -This is what -.IR login (1) -does. The -.B \-c -option causes -.I command -to be executed with an empty environment. If -.B \-a -is supplied, the shell passes -.I name -as the zeroth argument to the executed command. -If -.I command -cannot be executed for some reason, a non-interactive shell exits, -unless the -.B execfail -shell option -is enabled. In that case, it returns failure. -An interactive shell returns failure if the file cannot be executed. -If -.I command -is not specified, any redirections take effect in the current shell, -and the return status is 0. If there is a redirection error, the -return status is 1. -.TP -\fBexit\fP [\fIn\fP] -Cause the shell to exit -with a status of \fIn\fP. If -.I n -is omitted, the exit status -is that of the last command executed. -A trap on -.SM -.B EXIT -is executed before the shell terminates. -.TP -\fBexport\fP [\fB\-fn\fP\^] [\fIname\fP[=\fIword\fP]] ... -.PD 0 -.TP -.B export \-p -.PD -The supplied -.I names -are marked for automatic export to the environment of -subsequently executed commands. If the -.B \-f -option is given, -the -.I names -refer to functions. -If no -.I names -are given, or if the -.B \-p -option is supplied, a list -of names of all exported variables is printed. -The -.B \-n -option causes the export property to be removed from each -\fIname\fP. -If a variable name is followed by =\fIword\fP, the value of -the variable is set to \fIword\fP. -.B export -returns an exit status of 0 unless an invalid option is -encountered, -one of the \fInames\fP is not a valid shell variable name, or -.B \-f -is supplied with a -.I name -that is not a function. -.TP -\fBfc\fP [\fB\-e\fP \fIename\fP] [\fB\-lnr\fP] [\fIfirst\fP] [\fIlast\fP] -.PD 0 -.TP -\fBfc\fP \fB\-s\fP [\fIpat\fP=\fIrep\fP] [\fIcmd\fP] -.PD -The first form selects a range of commands from -.I first -to -.I last -from the history list and displays or edits and re-executes them. -.I First -and -.I last -may be specified as a string (to locate the last command beginning -with that string) or as a number (an index into the history list, -where a negative number is used as an offset from the current -command number). If -.I last -is not specified it is set to -the current command for listing (so that -.if n ``fc \-l \-10'' -.if t \f(CWfc \-l \-10\fP -prints the last 10 commands) and to -.I first -otherwise. -If -.I first -is not specified it is set to the previous -command for editing and \-16 for listing. -.sp 1 -The -.B \-n -option suppresses -the command numbers when listing. The -.B \-r -option reverses the order of -the commands. If the -.B \-l -option is given, -the commands are listed on -standard output. Otherwise, the editor given by -.I ename -is invoked -on a file containing those commands. If -.I ename -is not given, the -value of the -.SM -.B FCEDIT -variable is used, and -the value of -.SM -.B EDITOR -if -.SM -.B FCEDIT -is not set. If neither variable is set, -.FN vi -is used. When editing is complete, the edited commands are -echoed and executed. -.sp 1 -In the second form, \fIcommand\fP is re-executed after each instance -of \fIpat\fP is replaced by \fIrep\fP. -\fICommand\fP is intepreted the same as \fIfirst\fP above. -A useful alias to use with this is -.if n ``r="fc -s"'', -.if t \f(CWr='fc \-s'\fP, -so that typing -.if n ``r cc'' -.if t \f(CWr cc\fP -runs the last command beginning with -.if n ``cc'' -.if t \f(CWcc\fP -and typing -.if n ``r'' -.if t \f(CWr\fP -re-executes the last command. -.sp 1 -If the first form is used, the return value is 0 unless an invalid -option is encountered or -.I first -or -.I last -specify history lines out of range. -If the -.B \-e -option is supplied, the return value is the value of the last -command executed or failure if an error occurs with the temporary -file of commands. If the second form is used, the return status -is that of the command re-executed, unless -.I cmd -does not specify a valid history line, in which case -.B fc -returns failure. -.TP -\fBfg\fP [\fIjobspec\fP] -Resume -.I jobspec -in the foreground, and make it the current job. -If -.I jobspec -is not present, the shell's notion of the \fIcurrent job\fP is used. -The return value is that of the command placed into the foreground, -or failure if run when job control is disabled or, when run with -job control enabled, if -.I jobspec -does not specify a valid job or -.I jobspec -specifies a job that was started without job control. -.TP -\fBgetopts\fP \fIoptstring\fP \fIname\fP [\fIargs\fP] -.B getopts -is used by shell procedures to parse positional parameters. -.I optstring -contains the option characters to be recognized; if a character -is followed by a colon, the option is expected to have an -argument, which should be separated from it by white space. -The colon and question mark characters may not be used as -option characters. -Each time it is invoked, -.B getopts -places the next option in the shell variable -.IR name , -initializing -.I name -if it does not exist, -and the index of the next argument to be processed into the -variable -.SM -.BR OPTIND . -.SM -.B OPTIND -is initialized to 1 each time the shell or a shell script -is invoked. When an option requires an argument, -.B getopts -places that argument into the variable -.SM -.BR OPTARG . -The shell does not reset -.SM -.B OPTIND -automatically; it must be manually reset between multiple -calls to -.B getopts -within the same shell invocation if a new set of parameters -is to be used. -.sp 1 -When the end of options is encountered, \fBgetopts\fP exits with a -return value greater than zero. -.SM -.B OPTIND -is set to the index of the first non-option argument, -and \fIname\fP is set to ?. -.sp 1 -.B getopts -normally parses the positional parameters, but if more arguments are -given in -.IR args , -.B getopts -parses those instead. -.sp 1 -.B getopts -can report errors in two ways. If the first character of -.I optstring -is a colon, -.I silent -error reporting is used. In normal operation, diagnostic messages -are printed when invalid options or missing option arguments are -encountered. -If the variable -.SM -.B OPTERR -is set to 0, no error messages will be displayed, even if the first -character of -.I optstring -is not a colon. -.sp 1 -If an invalid option is seen, -.B getopts -places ? into -.I name -and, if not silent, -prints an error message and unsets -.SM -.BR OPTARG . -If -.B getopts -is silent, -the option character found is placed in -.SM -.B OPTARG -and no diagnostic message is printed. -.sp 1 -If a required argument is not found, and -.B getopts -is not silent, -a question mark (\^\fB?\fP\^) is placed in -.IR name , -.SM -.B OPTARG -is unset, and a diagnostic message is printed. -If -.B getopts -is silent, then a colon (\^\fB:\fP\^) is placed in -.I name -and -.SM -.B OPTARG -is set to the option character found. -.sp 1 -.B getopts -returns true if an option, specified or unspecified, is found. -It returns false if the end of options is encountered or an -error occurs. -.TP -\fBhash\fP [\fB\-lr\fP] [\fB\-p\fP \fIfilename\fP] [\fB\-dt\fP] [\fIname\fP] -Each time \fBhash\fP is invoked, -the full pathname of the command -.I name -is determined by searching -the directories in -.B $PATH -and remembered. Any previously-remembered pathname is discarded. -If the -.B \-p -option is supplied, no path search is performed, and -.I filename -is used as the full filename of the command. -The -.B \-r -option causes the shell to forget all -remembered locations. -The -.B \-d -option causes the shell to forget the remembered location of each \fIname\fP. -If the -.B \-t -option is supplied, the full pathname to which each \fIname\fP corresponds -is printed. If multiple \fIname\fP arguments are supplied with \fB\-t\fP, -the \fIname\fP is printed before the hashed full pathname. -The -.B \-l -option causes output to be displayed in a format that may be reused as input. -If no arguments are given, or if only \fB\-l\fP is supplied, -information about remembered commands is printed. -The return status is true unless a -.I name -is not found or an invalid option is supplied. -.TP -\fBhelp\fP [\fB\-dms\fP] [\fIpattern\fP] -Display helpful information about builtin commands. If -.I pattern -is specified, -.B help -gives detailed help on all commands matching -.IR pattern ; -otherwise help for all the builtins and shell control structures -is printed. -.RS -.PD 0 -.TP -.B \-d -Display a short description of each \fIpattern\fP -.TP -.B \-m -Display the description of each \fIpattern\fP in a manpage-like format -.TP -.B \-s -Display only a short usage synopsis for each \fIpattern\fP -.PD -.PP -The return status is 0 unless no command matches -.IR pattern . -.RE -.TP -\fBhistory [\fIn\fP] -.PD 0 -.TP -\fBhistory\fP \fB\-c\fP -.TP -\fBhistory \-d\fP \fIoffset\fP -.TP -\fBhistory\fP \fB\-anrw\fP [\fIfilename\fP] -.TP -\fBhistory\fP \fB\-p\fP \fIarg\fP [\fIarg ...\fP] -.TP -\fBhistory\fP \fB\-s\fP \fIarg\fP [\fIarg ...\fP] -.PD -With no options, display the command -history list with line numbers. Lines listed -with a -.B * -have been modified. An argument of -.I n -lists only the last -.I n -lines. -If the shell variable -.SM -.B HISTTIMEFORMAT -is set and not null, -it is used as a format string for \fIstrftime\fP(3) to display -the time stamp associated with each displayed history entry. -No intervening blank is printed between the formatted time stamp -and the history line. -If \fIfilename\fP is supplied, it is used as the -name of the history file; if not, the value of -.SM -.B HISTFILE -is used. Options, if supplied, have the following meanings: -.RS -.PD 0 -.TP -.B \-c -Clear the history list by deleting all the entries. -.TP -\fB\-d\fP \fIoffset\fP -Delete the history entry at position \fIoffset\fP. -.TP -.B \-a -Append the ``new'' history lines (history lines entered since the -beginning of the current \fBbash\fP session) to the history file. -.TP -.B \-n -Read the history lines not already read from the history -file into the current history list. These are lines -appended to the history file since the beginning of the -current \fBbash\fP session. -.TP -.B \-r -Read the contents of the history file -and append them to the current history list. -.TP -.B \-w -Write the current history list to the history file, overwriting the -history file's contents. -.TP -.B \-p -Perform history substitution on the following \fIargs\fP and display -the result on the standard output. -Does not store the results in the history list. -Each \fIarg\fP must be quoted to disable normal history expansion. -.TP -.B \-s -Store the -.I args -in the history list as a single entry. The last command in the -history list is removed before the -.I args -are added. -.PD -.PP -If the -.SM -.B HISTTIMEFORMAT -variable is set, the time stamp information -associated with each history entry is written to the history file, -marked with the history comment character. -When the history file is read, lines beginning with the history -comment character followed immediately by a digit are interpreted -as timestamps for the previous history line. -The return value is 0 unless an invalid option is encountered, an -error occurs while reading or writing the history file, an invalid -\fIoffset\fP is supplied as an argument to \fB\-d\fP, or the -history expansion supplied as an argument to \fB\-p\fP fails. -.RE -.TP -\fBjobs\fP [\fB\-lnprs\fP] [ \fIjobspec\fP ... ] -.PD 0 -.TP -\fBjobs\fP \fB\-x\fP \fIcommand\fP [ \fIargs\fP ... ] -.PD -The first form lists the active jobs. The options have the following -meanings: -.RS -.PD 0 -.TP -.B \-l -List process IDs -in addition to the normal information. -.TP -.B \-n -Display information only about jobs that have changed status since -the user was last notified of their status. -.TP -.B \-p -List only the process ID of the job's process group -leader. -.TP -.B \-r -Display only running jobs. -.TP -.B \-s -Display only stopped jobs. -.PD -.PP -If -.I jobspec -is given, output is restricted to information about that job. -The return status is 0 unless an invalid option is encountered -or an invalid -.I jobspec -is supplied. -.PP -If the -.B \-x -option is supplied, -.B jobs -replaces any -.I jobspec -found in -.I command -or -.I args -with the corresponding process group ID, and executes -.I command -passing it -.IR args , -returning its exit status. -.RE -.TP -\fBkill\fP [\fB\-s\fP \fIsigspec\fP | \fB\-n\fP \fIsignum\fP | \fB\-\fP\fIsigspec\fP] [\fIpid\fP | \fIjobspec\fP] ... -.PD 0 -.TP -\fBkill\fP \fB\-l\fP [\fIsigspec\fP | \fIexit_status\fP] -.PD -Send the signal named by -.I sigspec -or -.I signum -to the processes named by -.I pid -or -.IR jobspec . -.I sigspec -is either a case-insensitive signal name such as -.SM -.B SIGKILL -(with or without the -.SM -.B SIG -prefix) or a signal number; -.I signum -is a signal number. -If -.I sigspec -is not present, then -.SM -.B SIGTERM -is assumed. -An argument of -.B \-l -lists the signal names. -If any arguments are supplied when -.B \-l -is given, the names of the signals corresponding to the arguments are -listed, and the return status is 0. -The \fIexit_status\fP argument to -.B \-l -is a number specifying either a signal number or the exit status of -a process terminated by a signal. -.B kill -returns true if at least one signal was successfully sent, or false -if an error occurs or an invalid option is encountered. -.TP -\fBlet\fP \fIarg\fP [\fIarg\fP ...] -Each -.I arg -is an arithmetic expression to be evaluated (see -.SM -.B "ARITHMETIC EVALUATION" -above). -If the last -.I arg -evaluates to 0, -.B let -returns 1; 0 is returned otherwise. -.TP -\fBlocal\fP [\fIoption\fP] [\fIname\fP[=\fIvalue\fP] ...] -For each argument, a local variable named -.I name -is created, and assigned -.IR value . -The \fIoption\fP can be any of the options accepted by \fBdeclare\fP. -When -.B local -is used within a function, it causes the variable -.I name -to have a visible scope restricted to that function and its children. -With no operands, -.B local -writes a list of local variables to the standard output. It is -an error to use -.B local -when not within a function. The return status is 0 unless -.B local -is used outside a function, an invalid -.I name -is supplied, or -\fIname\fP is a readonly variable. -.TP -.B logout -Exit a login shell. -.TP -\fBmapfile\fP [\fB\-n\fP \fIcount\fP] [\fB\-O\fP \fIorigin\fP] [\fB\-s\fP \fIcount\fP] [\fB\-t\fP] [\fB\-u\fP \fIfd\fP] [\fB\-C\fP \fIcallback\fP] [\fB\-c\fP \fIquantum\fP] [\fIarray\fP] -.PD 0 -.TP -\fBreadarray\fP [\fB\-n\fP \fIcount\fP] [\fB\-O\fP \fIorigin\fP] [\fB\-s\fP \fIcount\fP] [\fB\-t\fP] [\fB\-u\fP \fIfd\fP] [\fB\-C\fP \fIcallback\fP] [\fB\-c\fP \fIquantum\fP] [\fIarray\fP] -.PD -Read lines from the standard input into the indexed array variable -.IR array , -or from file descriptor -.IR fd -if the -.B \-u -option is supplied. -The variable -.SM -.B MAPFILE -is the default \fIarray\fP. -Options, if supplied, have the following meanings: -.RS -.PD 0 -.TP -.B \-n -Copy at most -.I count -lines. If \fIcount\fP is 0, all lines are copied. -.TP -.B \-O -Begin assigning to -.I array -at index -.IR origin . -The default index is 0. -.TP -.B \-s -Discard the first \fIcount\fP lines read. -.TP -.B \-t -Remove a trailing newline from each line read. -.TP -.B \-u -Read lines from file descriptor \fIfd\fP instead of the standard input. -.TP -.B \-C -Evaluate -.I callback -each time \fIquantum\fP lines are read. The \fB\-c\fP option specifies -.IR quantum . -.TP -.B \-c -Specify the number of lines read between each call to -.IR callback . -.PD -.PP -If -.B \-C -is specified without -.BR \-c , -the default quantum is 5000. -When \fIcallback\fP is evaluated, it is supplied the index of the next -array element to be assigned and the line to be assigned to that element -as additional arguments. -\fIcallback\fP is evaluated after the line is read but before the -array element is assigned. -.PP -If not supplied with an explicit origin, \fBmapfile\fP will clear \fIarray\fP -before assigning to it. -.PP -\fBmapfile\fP returns successfully unless an invalid option or option -argument is supplied, \fIarray\fP is invalid or unassignable, or if -\fIarray\fP is not an indexed array. -.RE -.TP -\fBpopd\fP [\-\fBn\fP] [+\fIn\fP] [\-\fIn\fP] -Removes entries from the directory stack. With no arguments, -removes the top directory from the stack, and performs a -.B cd -to the new top directory. -Arguments, if supplied, have the following meanings: -.RS -.PD 0 -.TP -.B \-n -Suppresses the normal change of directory when removing directories -from the stack, so that only the stack is manipulated. -.TP -\fB+\fP\fIn\fP -Removes the \fIn\fPth entry counting from the left of the list -shown by -.BR dirs , -starting with zero. For example: -.if n ``popd +0'' -.if t \f(CWpopd +0\fP -removes the first directory, -.if n ``popd +1'' -.if t \f(CWpopd +1\fP -the second. -.TP -\fB\-\fP\fIn\fP -Removes the \fIn\fPth entry counting from the right of the list -shown by -.BR dirs , -starting with zero. For example: -.if n ``popd -0'' -.if t \f(CWpopd -0\fP -removes the last directory, -.if n ``popd -1'' -.if t \f(CWpopd -1\fP -the next to last. -.PD -.PP -If the -.B popd -command is successful, a -.B dirs -is performed as well, and the return status is 0. -.B popd -returns false if an invalid option is encountered, the directory stack -is empty, a non-existent directory stack entry is specified, or the -directory change fails. -.RE -.TP -\fBprintf\fP [\fB\-v\fP \fIvar\fP] \fIformat\fP [\fIarguments\fP] -Write the formatted \fIarguments\fP to the standard output under the -control of the \fIformat\fP. -The \fB\-v\fP option causes the output to be assigned to the variable -\fIvar\fP rather than being printed to the standard output. -.sp 1 -The \fIformat\fP is a character string which contains three types of objects: -plain characters, which are simply copied to standard output, character -escape sequences, which are converted and copied to the standard output, and -format specifications, each of which causes printing of the next successive -\fIargument\fP. -In addition to the standard \fIprintf\fP(1) format specifications, -\fBprintf\fP interprets the following extensions: -.RS -.PD 0 -.TP -.B %b -causes -\fBprintf\fP to expand backslash escape sequences in the corresponding -\fIargument\fP (except that \fB\ec\fP terminates output, backslashes in -\fB\e\(aq\fP, \fB\e"\fP, and \fB\e?\fP are not removed, and octal escapes -beginning with \fB\e0\fP may contain up to four digits). -.TP -.B %q -causes \fBprintf\fP to output the corresponding -\fIargument\fP in a format that can be reused as shell input. -.TP -.B %(\fIdatefmt\fP)T -causes \fBprintf\fP to output the date-time string resulting from using -\fIdatefmt\fP as a format string for \fIstrftime\fP(3). -The corresponding \fIargument\fP is an integer representing the number of -seconds since the epoch. -Two special argument values may be used: -1 represents the current -time, and -2 represents the time the shell was invoked. -If no argument is specified, conversion behaves as if -1 had been given. -This is an exception to the usual \fBprintf\fP behavior. -.PD -.PP -Arguments to non-string format specifiers are treated as C constants, -except that a leading plus or minus sign is allowed, and if the leading -character is a single or double quote, the value is the ASCII value of -the following character. -.PP -The \fIformat\fP is reused as necessary to consume all of the \fIarguments\fP. -If the \fIformat\fP requires more \fIarguments\fP than are supplied, the -extra format specifications behave as if a zero value or null string, as -appropriate, had been supplied. -The return value is zero on success, non-zero on failure. -.RE -.TP -\fBpushd\fP [\fB\-n\fP] [+\fIn\fP] [\-\fIn\fP] -.PD 0 -.TP -\fBpushd\fP [\fB\-n\fP] [\fIdir\fP] -.PD -Adds a directory to the top of the directory stack, or rotates -the stack, making the new top of the stack the current working -directory. With no arguments, exchanges the top two directories -and returns 0, unless the directory stack is empty. -Arguments, if supplied, have the following meanings: -.RS -.PD 0 -.TP -.B \-n -Suppresses the normal change of directory when adding directories -to the stack, so that only the stack is manipulated. -.TP -\fB+\fP\fIn\fP -Rotates the stack so that the \fIn\fPth directory -(counting from the left of the list shown by -.BR dirs , -starting with zero) -is at the top. -.TP -\fB\-\fP\fIn\fP -Rotates the stack so that the \fIn\fPth directory -(counting from the right of the list shown by -.BR dirs , -starting with zero) is at the top. -.TP -.I dir -Adds -.I dir -to the directory stack at the top, making it the -new current working directory as if it had been supplied as the argument -to the \fBcd\fP builtin. -.PD -.PP -If the -.B pushd -command is successful, a -.B dirs -is performed as well. -If the first form is used, -.B pushd -returns 0 unless the cd to -.I dir -fails. With the second form, -.B pushd -returns 0 unless the directory stack is empty, -a non-existent directory stack element is specified, -or the directory change to the specified new current directory -fails. -.RE -.TP -\fBpwd\fP [\fB\-LP\fP] -Print the absolute pathname of the current working directory. -The pathname printed contains no symbolic links if the -.B \-P -option is supplied or the -.B \-o physical -option to the -.B set -builtin command is enabled. -If the -.B \-L -option is used, the pathname printed may contain symbolic links. -The return status is 0 unless an error occurs while -reading the name of the current directory or an -invalid option is supplied. -.TP -\fBread\fP [\fB\-ers\fP] [\fB\-a\fP \fIaname\fP] [\fB\-d\fP \fIdelim\fP] [\fB\-i\fP \fItext\fP] [\fB\-n\fP \fInchars\fP] [\fB\-N\fP \fInchars\fP] [\fB\-p\fP \fIprompt\fP] [\fB\-t\fP \fItimeout\fP] [\fB\-u\fP \fIfd\fP] [\fIname\fP ...] -One line is read from the standard input, or from the file descriptor -\fIfd\fP supplied as an argument to the \fB\-u\fP option, and the first word -is assigned to the first -.IR name , -the second word to the second -.IR name , -and so on, with leftover words and their intervening separators assigned -to the last -.IR name . -If there are fewer words read from the input stream than names, -the remaining names are assigned empty values. -The characters in -.SM -.B IFS -are used to split the line into words using the same rules the shell -uses for expansion (described above under \fBWord Splitting\fP). -The backslash character (\fB\e\fP) may be used to remove any special -meaning for the next character read and for line continuation. -Options, if supplied, have the following meanings: -.RS -.PD 0 -.TP -.B \-a \fIaname\fP -The words are assigned to sequential indices -of the array variable -.IR aname , -starting at 0. -.I aname -is unset before any new values are assigned. -Other \fIname\fP arguments are ignored. -.TP -.B \-d \fIdelim\fP -The first character of \fIdelim\fP is used to terminate the input line, -rather than newline. -.TP -.B \-e -If the standard input -is coming from a terminal, -.B readline -(see -.SM -.B READLINE -above) is used to obtain the line. -Readline uses the current (or default, if line editing was not previously -active) editing settings. -.TP -.B \-i \fItext\fP -If -.B readline -is being used to read the line, \fItext\fP is placed into the editing -buffer before editing begins. -.TP -.B \-n \fInchars\fP -\fBread\fP returns after reading \fInchars\fP characters rather than -waiting for a complete line of input, but honor a delimiter if fewer -than \fInchars\fP characters are read before the delimiter. -.TP -.B \-N \fInchars\fP -\fBread\fP returns after reading exactly \fInchars\fP characters rather -than waiting for a complete line of input, unless EOF is encountered or -\fBread\fP times out. -Delimiter characters encountered in the input are -not treated specially and do not cause \fBread\fP to return until -\fInchars\fP characters are read. -.TP -.B \-p \fIprompt\fP -Display \fIprompt\fP on standard error, without a -trailing newline, before attempting to read any input. The prompt -is displayed only if input is coming from a terminal. -.TP -.B \-r -Backslash does not act as an escape character. -The backslash is considered to be part of the line. -In particular, a backslash-newline pair may not be used as a line -continuation. -.TP -.B \-s -Silent mode. If input is coming from a terminal, characters are -not echoed. -.TP -.B \-t \fItimeout\fP -Cause \fBread\fP to time out and return failure if a complete line of -input (or a specified number of characters) -is not read within \fItimeout\fP seconds. -\fItimeout\fP may be a decimal number with a fractional portion following -the decimal point. -This option is only effective if \fBread\fP is reading input from a -terminal, pipe, or other special file; it has no effect when reading -from regular files. -If \fBread\fP times out, \fBread\fP saves any partial input read into -the specified variable \fIname\fP. -If \fItimeout\fP is 0, \fBread\fP returns immediately, without trying to -read any data. The exit status is 0 if input is available on -the specified file descriptor, non-zero otherwise. -The exit status is greater than 128 if the timeout is exceeded. -.TP -.B \-u \fIfd\fP -Read input from file descriptor \fIfd\fP. -.PD -.PP -If no -.I names -are supplied, the line read is assigned to the variable -.SM -.BR REPLY . -The return code is zero, unless end-of-file is encountered, \fBread\fP -times out (in which case the return code is greater than 128), -a variable assignment error (such as assigning to a readonly variable) occurs, -or an invalid file descriptor is supplied as the argument to \fB\-u\fP. -.RE -.TP -\fBreadonly\fP [\fB\-aAf\fP] [\fB\-p\fP] [\fIname\fP[=\fIword\fP] ...] -.PD -The given -\fInames\fP are marked readonly; the values of these -.I names -may not be changed by subsequent assignment. -If the -.B \-f -option is supplied, the functions corresponding to the -\fInames\fP are so -marked. -The -.B \-a -option restricts the variables to indexed arrays; the -.B \-A -option restricts the variables to associative arrays. -If both options are supplied, -.B \-A -takes precedence. -If no -.I name -arguments are given, or if the -.B \-p -option is supplied, a list of all readonly names is printed. -The other options may be used to restrict the output to a subset of -the set of readonly names. -The -.B \-p -option causes output to be displayed in a format that -may be reused as input. -If a variable name is followed by =\fIword\fP, the value of -the variable is set to \fIword\fP. -The return status is 0 unless an invalid option is encountered, -one of the -.I names -is not a valid shell variable name, or -.B \-f -is supplied with a -.I name -that is not a function. -.TP -\fBreturn\fP [\fIn\fP] -Causes a function to stop executing and return the value specified by -.I n -to its caller. -If -.I n -is omitted, the return status is that of the last command -executed in the function body. -If \fBreturn\fP is executed by a trap handler, the last command used to -determine the status is the last command executed before the trap handler. -if \fBreturn\fP is executed during a \fBDEBUG\fP trap, the last command -used to determine the status is the last command executed by the trap -handler before \fBreturn\fP was invoked. -If -.B return -is used outside a function, -but during execution of a script by the -.B . -(\fBsource\fP) command, it causes the shell to stop executing -that script and return either -.I n -or the exit status of the last command executed within the -script as the exit status of the script. -If \fIn\fP is supplied, the return value is its least significant -8 bits. -The return status is non-zero if -.B return -is supplied a non-numeric argument, or -is used outside a -function and not during execution of a script by \fB.\fP\^ or \fBsource\fP. -Any command associated with the \fBRETURN\fP trap is executed -before execution resumes after the function or script. -.TP -\fBset\fP [\fB\-\-abefhkmnptuvxBCEHPT\fP] [\fB\-o\fP \fIoption\-name\fP] [\fIarg\fP ...] -.PD 0 -.TP -\fBset\fP [\fB+abefhkmnptuvxBCEHPT\fP] [\fB+o\fP \fIoption\-name\fP] [\fIarg\fP ...] -.PD -Without options, the name and value of each shell variable are displayed -in a format that can be reused as input -for setting or resetting the currently-set variables. -Read-only variables cannot be reset. -In \fIposix\fP mode, only shell variables are listed. -The output is sorted according to the current locale. -When options are specified, they set or unset shell attributes. -Any arguments remaining after option processing are treated -as values for the positional parameters and are assigned, in order, to -.BR $1 , -.BR $2 , -.B ... -.BR $\fIn\fP . -Options, if specified, have the following meanings: -.RS -.PD 0 -.TP 8 -.B \-a -Automatically mark variables and functions which are modified or -created for export to the environment of subsequent commands. -.TP 8 -.B \-b -Report the status of terminated background jobs -immediately, rather than before the next primary prompt. This is -effective only when job control is enabled. -.TP 8 -.B \-e -Exit immediately if a -\fIpipeline\fP (which may consist of a single \fIsimple command\fP), -a \fIlist\fP, -or a \fIcompound command\fP -(see -.SM -.B SHELL GRAMMAR -above), exits with a non-zero status. -The shell does not exit if the -command that fails is part of the command list immediately following a -.B while -or -.B until -keyword, -part of the test following the -.B if -or -.B elif -reserved words, part of any command executed in a -.B && -or -.B || -list except the command following the final \fB&&\fP or \fB||\fP, -any command in a pipeline but the last, -or if the command's return value is -being inverted with -.BR ! . -If a compound command other than a subshell -returns a non-zero status because a command failed -while \fB\-e\fP was being ignored, the shell does not exit. -A trap on \fBERR\fP, if set, is executed before the shell exits. -This option applies to the shell environment and each subshell environment -separately (see -.SM -.B "COMMAND EXECUTION ENVIRONMENT" -above), and may cause -subshells to exit before executing all the commands in the subshell. -.if t .sp 0.5 -.if n .sp 1 -If a compound command or shell function executes in a context -where \fB\-e\fP is being ignored, -none of the commands executed within the compound command or function body -will be affected by the \fB\-e\fP setting, even if \fB\-e\fP is set -and a command returns a failure status. -If a compound command or shell function sets \fB\-e\fP while executing in -a context where \fB\-e\fP is ignored, that setting will not have any -effect until the compound command or the command containing the function -call completes. -.TP 8 -.B \-f -Disable pathname expansion. -.TP 8 -.B \-h -Remember the location of commands as they are looked up for execution. -This is enabled by default. -.TP 8 -.B \-k -All arguments in the form of assignment statements -are placed in the environment for a command, not just -those that precede the command name. -.TP 8 -.B \-m -Monitor mode. Job control is enabled. This option is on -by default for interactive shells on systems that support -it (see -.SM -.B JOB CONTROL -above). -All processes run in a separate process group. -When a background job completes, the shell prints a line -containing its exit status. -.TP 8 -.B \-n -Read commands but do not execute them. This may be used to -check a shell script for syntax errors. This is ignored by -interactive shells. -.TP 8 -.B \-o \fIoption\-name\fP -The \fIoption\-name\fP can be one of the following: -.RS -.TP 8 -.B allexport -Same as -.BR \-a . -.TP 8 -.B braceexpand -Same as -.BR \-B . -.TP 8 -.B emacs -Use an emacs-style command line editing interface. This is enabled -by default when the shell is interactive, unless the shell is started -with the -.B \-\-noediting -option. -This also affects the editing interface used for \fBread \-e\fP. -.TP 8 -.B errexit -Same as -.BR \-e . -.TP 8 -.B errtrace -Same as -.BR \-E . -.TP 8 -.B functrace -Same as -.BR \-T . -.TP 8 -.B hashall -Same as -.BR \-h . -.TP 8 -.B histexpand -Same as -.BR \-H . -.TP 8 -.B history -Enable command history, as described above under -.SM -.BR HISTORY . -This option is on by default in interactive shells. -.TP 8 -.B ignoreeof -The effect is as if the shell command -.if t \f(CWIGNOREEOF=10\fP -.if n ``IGNOREEOF=10'' -had been executed -(see -.B Shell Variables -above). -.TP 8 -.B keyword -Same as -.BR \-k . -.TP 8 -.B monitor -Same as -.BR \-m . -.TP 8 -.B noclobber -Same as -.BR \-C . -.TP 8 -.B noexec -Same as -.BR \-n . -.TP 8 -.B noglob -Same as -.BR \-f . -.TP 8 -.B nolog -Currently ignored. -.TP 8 -.B notify -Same as -.BR \-b . -.TP 8 -.B nounset -Same as -.BR \-u . -.TP 8 -.B onecmd -Same as -.BR \-t . -.TP 8 -.B physical -Same as -.BR \-P . -.TP 8 -.B pipefail -If set, the return value of a pipeline is the value of the last -(rightmost) command to exit with a non-zero status, or zero if all -commands in the pipeline exit successfully. -This option is disabled by default. -.TP 8 -.B posix -Change the behavior of -.B bash -where the default operation differs -from the POSIX standard to match the standard (\fIposix mode\fP). -See -.SM -.B "SEE ALSO" -below for a reference to a document that details how posix mode affects -bash's behavior. -.TP 8 -.B privileged -Same as -.BR \-p . -.TP 8 -.B verbose -Same as -.BR \-v . -.TP 8 -.B vi -Use a vi-style command line editing interface. -This also affects the editing interface used for \fBread \-e\fP. -.TP 8 -.B xtrace -Same as -.BR \-x . -.sp .5 -.PP -If -.B \-o -is supplied with no \fIoption\-name\fP, the values of the current options are -printed. -If -.B +o -is supplied with no \fIoption\-name\fP, a series of -.B set -commands to recreate the current option settings is displayed on -the standard output. -.RE -.TP 8 -.B \-p -Turn on -.I privileged -mode. In this mode, the -.SM -.B $ENV -and -.SM -.B $BASH_ENV -files are not processed, shell functions are not inherited from the -environment, and the -.SM -.BR SHELLOPTS , -.SM -.BR BASHOPTS , -.SM -.BR CDPATH , -and -.SM -.B GLOBIGNORE -variables, if they appear in the environment, are ignored. -If the shell is started with the effective user (group) id not equal to the -real user (group) id, and the \fB\-p\fP option is not supplied, these actions -are taken and the effective user id is set to the real user id. -If the \fB\-p\fP option is supplied at startup, the effective user id is -not reset. -Turning this option off causes the effective user -and group ids to be set to the real user and group ids. -.TP 8 -.B \-t -Exit after reading and executing one command. -.TP 8 -.B \-u -Treat unset variables and parameters other than the special -parameters "@" and "*" as an error when performing -parameter expansion. If expansion is attempted on an -unset variable or parameter, the shell prints an error message, and, -if not interactive, exits with a non-zero status. -.TP 8 -.B \-v -Print shell input lines as they are read. -.TP 8 -.B \-x -After expanding each \fIsimple command\fP, -\fBfor\fP command, \fBcase\fP command, \fBselect\fP command, or -arithmetic \fBfor\fP command, display the expanded value of -.SM -.BR PS4 , -followed by the command and its expanded arguments -or associated word list. -.TP 8 -.B \-B -The shell performs brace expansion (see -.B Brace Expansion -above). This is on by default. -.TP 8 -.B \-C -If set, -.B bash -does not overwrite an existing file with the -.BR > , -.BR >& , -and -.B <> -redirection operators. This may be overridden when -creating output files by using the redirection operator -.B >| -instead of -.BR > . -.TP 8 -.B \-E -If set, any trap on \fBERR\fP is inherited by shell functions, command -substitutions, and commands executed in a subshell environment. -The \fBERR\fP trap is normally not inherited in such cases. -.TP 8 -.B \-H -Enable -.B ! -style history substitution. This option is on by -default when the shell is interactive. -.TP 8 -.B \-P -If set, the shell does not resolve symbolic links when executing -commands such as -.B cd -that change the current working directory. It uses the -physical directory structure instead. By default, -.B bash -follows the logical chain of directories when performing commands -which change the current directory. -.TP 8 -.B \-T -If set, any traps on \fBDEBUG\fP and \fBRETURN\fP are inherited by shell -functions, command substitutions, and commands executed in a -subshell environment. -The \fBDEBUG\fP and \fBRETURN\fP traps are normally not inherited -in such cases. -.TP 8 -.B \-\- -If no arguments follow this option, then the positional parameters are -unset. Otherwise, the positional parameters are set to the -\fIarg\fPs, even if some of them begin with a -.BR \- . -.TP 8 -.B \- -Signal the end of options, cause all remaining \fIarg\fPs to be -assigned to the positional parameters. The -.B \-x -and -.B \-v -options are turned off. -If there are no \fIarg\fPs, -the positional parameters remain unchanged. -.PD -.PP -The options are off by default unless otherwise noted. -Using + rather than \- causes these options to be turned off. -The options can also be specified as arguments to an invocation of -the shell. -The current set of options may be found in -.BR $\- . -The return status is always true unless an invalid option is encountered. -.RE -.TP -\fBshift\fP [\fIn\fP] -The positional parameters from \fIn\fP+1 ... are renamed to -.B $1 -.B .... -Parameters represented by the numbers \fB$#\fP -down to \fB$#\fP\-\fIn\fP+1 are unset. -.I n -must be a non-negative number less than or equal to \fB$#\fP. -If -.I n -is 0, no parameters are changed. -If -.I n -is not given, it is assumed to be 1. -If -.I n -is greater than \fB$#\fP, the positional parameters are not changed. -The return status is greater than zero if -.I n -is greater than -.B $# -or less than zero; otherwise 0. -.TP -\fBshopt\fP [\fB\-pqsu\fP] [\fB\-o\fP] [\fIoptname\fP ...] -Toggle the values of settings controlling optional shell behavior. -The settings can be either those listed below, or, if the -.B \-o -option is used, those available with the -.B \-o -option to the \fBset\fP builtin command. -With no options, or with the -.B \-p -option, a list of all settable options is displayed, with -an indication of whether or not each is set. -The \fB\-p\fP option causes output to be displayed in a form that -may be reused as input. -Other options have the following meanings: -.RS -.PD 0 -.TP -.B \-s -Enable (set) each \fIoptname\fP. -.TP -.B \-u -Disable (unset) each \fIoptname\fP. -.TP -.B \-q -Suppresses normal output (quiet mode); the return status indicates -whether the \fIoptname\fP is set or unset. -If multiple \fIoptname\fP arguments are given with -.BR \-q , -the return status is zero if all \fIoptnames\fP are enabled; non-zero -otherwise. -.TP -.B \-o -Restricts the values of \fIoptname\fP to be those defined for the -.B \-o -option to the -.B set -builtin. -.PD -.PP -If either -.B \-s -or -.B \-u -is used with no \fIoptname\fP arguments, -.B shopt -shows only those options which are set or unset, respectively. -Unless otherwise noted, the \fBshopt\fP options are disabled (unset) -by default. -.PP -The return status when listing options is zero if all \fIoptnames\fP -are enabled, non-zero otherwise. When setting or unsetting options, -the return status is zero unless an \fIoptname\fP is not a valid shell -option. -.PP -The list of \fBshopt\fP options is: -.if t .sp .5v -.if n .sp 1v -.PD 0 -.TP 8 -.B autocd -If set, a command name that is the name of a directory is executed as if -it were the argument to the \fBcd\fP command. -This option is only used by interactive shells. -.TP 8 -.B cdable_vars -If set, an argument to the -.B cd -builtin command that -is not a directory is assumed to be the name of a variable whose -value is the directory to change to. -.TP 8 -.B cdspell -If set, minor errors in the spelling of a directory component in a -.B cd -command will be corrected. -The errors checked for are transposed characters, -a missing character, and one character too many. -If a correction is found, the corrected filename is printed, -and the command proceeds. -This option is only used by interactive shells. -.TP 8 -.B checkhash -If set, \fBbash\fP checks that a command found in the hash -table exists before trying to execute it. If a hashed command no -longer exists, a normal path search is performed. -.TP 8 -.B checkjobs -If set, \fBbash\fP lists the status of any stopped and running jobs before -exiting an interactive shell. If any jobs are running, this causes -the exit to be deferred until a second exit is attempted without an -intervening command (see -.SM -.B "JOB CONTROL" -above). The shell always -postpones exiting if any jobs are stopped. -.TP 8 -.B checkwinsize -If set, \fBbash\fP checks the window size after each command -and, if necessary, updates the values of -.SM -.B LINES -and -.SM -.BR COLUMNS . -.TP 8 -.B cmdhist -If set, -.B bash -attempts to save all lines of a multiple-line -command in the same history entry. This allows -easy re-editing of multi-line commands. -.TP 8 -.B compat31 -If set, -.B bash -changes its behavior to that of version 3.1 with respect to quoted -arguments to the \fB[[\fP conditional command's \fB=~\fP operator -and locale-specific string comparison when using the \fB[[\fP -conditional command's \fB<\fP and \fB>\fP operators. -Bash versions prior to bash-4.1 use ASCII collation and -.IR strcmp (3); -bash-4.1 and later use the current locale's collation sequence and -.IR strcoll (3). -.TP 8 -.B compat32 -If set, -.B bash -changes its behavior to that of version 3.2 with respect to -locale-specific string comparison when using the \fB[[\fP -conditional command's \fB<\fP and \fB>\fP operators (see previous item). -.TP 8 -.B compat40 -If set, -.B bash -changes its behavior to that of version 4.0 with respect to locale-specific -string comparison when using the \fB[[\fP -conditional command's \fB<\fP and \fB>\fP operators (see description of -\fBcompat31\fP) -and the effect of interrupting a command list. -Bash versions 4.0 and later interrupt the list as if the shell received the -interrupt; previous versions continue with the next command in the list. -.TP 8 -.B compat41 -If set, -.BR bash , -when in \fIposix\fP mode, treats a single quote in a double-quoted -parameter expansion as a special character. The single quotes must match -(an even number) and the characters between the single quotes are considered -quoted. This is the behavior of posix mode through version 4.1. -The default bash behavior remains as in previous versions. -.TP 8 -.B compat42 -If set, -.B bash -does not process the replacement string in the pattern substitution word -expansion using quote removal. -.TP 8 -.B complete_fullquote -If set, -.B bash -quotes all shell metacharacters in filenames and directory names when -performing completion. -If not set, -.B bash -removes metacharacters such as the dollar sign from the set of -characters that will be quoted in completed filenames -when these metacharacters appear in shell variable references in words to be -completed. -This means that dollar signs in variable names that expand to directories -will not be quoted; -however, any dollar signs appearing in filenames will not be quoted, either. -This is active only when bash is using backslashes to quote completed -filenames. -This variable is set by default, which is the default bash behavior in -versions through 4.2. -.TP 8 -.B direxpand -If set, -.B bash -replaces directory names with the results of word expansion when performing -filename completion. This changes the contents of the readline editing -buffer. -If not set, -.B bash -attempts to preserve what the user typed. -.TP 8 -.B dirspell -If set, -.B bash -attempts spelling correction on directory names during word completion -if the directory name initially supplied does not exist. -.TP 8 -.B dotglob -If set, -.B bash -includes filenames beginning with a `.' in the results of pathname -expansion. -.TP 8 -.B execfail -If set, a non-interactive shell will not exit if -it cannot execute the file specified as an argument to the -.B exec -builtin command. An interactive shell does not exit if -.B exec -fails. -.TP 8 -.B expand_aliases -If set, aliases are expanded as described above under -.SM -.BR ALIASES . -This option is enabled by default for interactive shells. -.TP 8 -.B extdebug -If set, behavior intended for use by debuggers is enabled: -.RS -.TP -.B 1. -The \fB\-F\fP option to the \fBdeclare\fP builtin displays the source -file name and line number corresponding to each function name supplied -as an argument. -.TP -.B 2. -If the command run by the \fBDEBUG\fP trap returns a non-zero value, the -next command is skipped and not executed. -.TP -.B 3. -If the command run by the \fBDEBUG\fP trap returns a value of 2, and the -shell is executing in a subroutine (a shell function or a shell script -executed by the \fB.\fP or \fBsource\fP builtins), the shell simulates -a call to \fBreturn\fP. -.TP -.B 4. -.SM -.B BASH_ARGC -and -.SM -.B BASH_ARGV -are updated as described in their descriptions above. -.TP -.B 5. -Function tracing is enabled: command substitution, shell functions, and -subshells invoked with \fB(\fP \fIcommand\fP \fB)\fP inherit the -\fBDEBUG\fP and \fBRETURN\fP traps. -.TP -.B 6. -Error tracing is enabled: command substitution, shell functions, and -subshells invoked with \fB(\fP \fIcommand\fP \fB)\fP inherit the -\fBERR\fP trap. -.RE -.TP 8 -.B extglob -If set, the extended pattern matching features described above under -\fBPathname Expansion\fP are enabled. -.TP 8 -.B extquote -If set, \fB$\fP\(aq\fIstring\fP\(aq and \fB$\fP"\fIstring\fP" quoting is -performed within \fB${\fP\fIparameter\fP\fB}\fP expansions -enclosed in double quotes. This option is enabled by default. -.TP 8 -.B failglob -If set, patterns which fail to match filenames during pathname expansion -result in an expansion error. -.TP 8 -.B force_fignore -If set, the suffixes specified by the -.SM -.B FIGNORE -shell variable -cause words to be ignored when performing word completion even if -the ignored words are the only possible completions. -See -.SM -\fBSHELL VARIABLES\fP -above for a description of -.SM -.BR FIGNORE . -This option is enabled by default. -.TP 8 -.B globasciiranges -If set, range expressions used in pattern matching bracket expressions (see -.SM -.B Pattern Matching -above) behave as if in the traditional C locale when performing -comparisons. That is, the current locale's collating sequence -is not taken into account, so -.B b -will not collate between -.B A -and -.BR B , -and upper-case and lower-case ASCII characters will collate together. -.TP 8 -.B globstar -If set, the pattern \fB**\fP used in a pathname expansion context will -match all files and zero or more directories and subdirectories. -If the pattern is followed by a \fB/\fP, only directories and -subdirectories match. -.TP 8 -.B gnu_errfmt -If set, shell error messages are written in the standard GNU error -message format. -.TP 8 -.B histappend -If set, the history list is appended to the file named by the value -of the -.SM -.B HISTFILE -variable when the shell exits, rather than overwriting the file. -.TP 8 -.B histreedit -If set, and -.B readline -is being used, a user is given the opportunity to re-edit a -failed history substitution. -.TP 8 -.B histverify -If set, and -.B readline -is being used, the results of history substitution are not immediately -passed to the shell parser. Instead, the resulting line is loaded into -the \fBreadline\fP editing buffer, allowing further modification. -.TP 8 -.B hostcomplete -If set, and -.B readline -is being used, \fBbash\fP will attempt to perform hostname completion when a -word containing a \fB@\fP is being completed (see -.B Completing -under -.SM -.B READLINE -above). -This is enabled by default. -.TP 8 -.B huponexit -If set, \fBbash\fP will send -.SM -.B SIGHUP -to all jobs when an interactive login shell exits. -.TP 8 -.B interactive_comments -If set, allow a word beginning with -.B # -to cause that word and all remaining characters on that -line to be ignored in an interactive shell (see -.SM -.B COMMENTS -above). This option is enabled by default. -.TP 8 -.B lastpipe -If set, and job control is not active, the shell runs the last command of -a pipeline not executed in the background in the current shell environment. -.TP 8 -.B lithist -If set, and the -.B cmdhist -option is enabled, multi-line commands are saved to the history with -embedded newlines rather than using semicolon separators where possible. -.TP 8 -.B login_shell -The shell sets this option if it is started as a login shell (see -.SM -.B "INVOCATION" -above). -The value may not be changed. -.TP 8 -.B mailwarn -If set, and a file that \fBbash\fP is checking for mail has been -accessed since the last time it was checked, the message ``The mail in -\fImailfile\fP has been read'' is displayed. -.TP 8 -.B no_empty_cmd_completion -If set, and -.B readline -is being used, -.B bash -will not attempt to search the -.SM -.B PATH -for possible completions when -completion is attempted on an empty line. -.TP 8 -.B nocaseglob -If set, -.B bash -matches filenames in a case\-insensitive fashion when performing pathname -expansion (see -.B Pathname Expansion -above). -.TP 8 -.B nocasematch -If set, -.B bash -matches patterns in a case\-insensitive fashion when performing matching -while executing \fBcase\fP or \fB[[\fP conditional commands. -.TP 8 -.B nullglob -If set, -.B bash -allows patterns which match no -files (see -.B Pathname Expansion -above) -to expand to a null string, rather than themselves. -.TP 8 -.B progcomp -If set, the programmable completion facilities (see -\fBProgrammable Completion\fP above) are enabled. -This option is enabled by default. -.TP 8 -.B promptvars -If set, prompt strings undergo -parameter expansion, command substitution, arithmetic -expansion, and quote removal after being expanded as described in -.SM -.B PROMPTING -above. This option is enabled by default. -.TP 8 -.B restricted_shell -The shell sets this option if it is started in restricted mode (see -.SM -.B "RESTRICTED SHELL" -below). -The value may not be changed. -This is not reset when the startup files are executed, allowing -the startup files to discover whether or not a shell is restricted. -.TP 8 -.B shift_verbose -If set, the -.B shift -builtin prints an error message when the shift count exceeds the -number of positional parameters. -.TP 8 -.B sourcepath -If set, the -\fBsource\fP (\fB.\fP) builtin uses the value of -.SM -.B PATH -to find the directory containing the file supplied as an argument. -This option is enabled by default. -.TP 8 -.B xpg_echo -If set, the \fBecho\fP builtin expands backslash-escape sequences -by default. -.RE -.PD -.TP -\fBsuspend\fP [\fB\-f\fP] -Suspend the execution of this shell until it receives a -.SM -.B SIGCONT -signal. A login shell cannot be suspended; the -.B \-f -option can be used to override this and force the suspension. -The return status is 0 unless the shell is a login shell and -.B \-f -is not supplied, or if job control is not enabled. -.TP -\fBtest\fP \fIexpr\fP -.PD 0 -.TP -\fB[\fP \fIexpr\fP \fB]\fP -Return a status of 0 (true) or 1 (false) depending on -the evaluation of the conditional expression -.IR expr . -Each operator and operand must be a separate argument. -Expressions are composed of the primaries described above under -.SM -.BR "CONDITIONAL EXPRESSIONS" . -\fBtest\fP does not accept any options, nor does it accept and ignore -an argument of \fB\-\-\fP as signifying the end of options. -.if t .sp 0.5 -.if n .sp 1 -Expressions may be combined using the following operators, listed -in decreasing order of precedence. -The evaluation depends on the number of arguments; see below. -Operator precedence is used when there are five or more arguments. -.RS -.PD 0 -.TP -.B ! \fIexpr\fP -True if -.I expr -is false. -.TP -.B ( \fIexpr\fP ) -Returns the value of \fIexpr\fP. -This may be used to override the normal precedence of operators. -.TP -\fIexpr1\fP \-\fBa\fP \fIexpr2\fP -True if both -.I expr1 -and -.I expr2 -are true. -.TP -\fIexpr1\fP \-\fBo\fP \fIexpr2\fP -True if either -.I expr1 -or -.I expr2 -is true. -.PD -.PP -\fBtest\fP and \fB[\fP evaluate conditional -expressions using a set of rules based on the number of arguments. -.if t .sp 0.5 -.if n .sp 1 -.PD 0 -.TP -0 arguments -The expression is false. -.TP -1 argument -The expression is true if and only if the argument is not null. -.TP -2 arguments -If the first argument is \fB!\fP, the expression is true if and -only if the second argument is null. -If the first argument is one of the unary conditional operators listed above -under -.SM -.BR "CONDITIONAL EXPRESSIONS" , -the expression is true if the unary test is true. -If the first argument is not a valid unary conditional operator, the expression -is false. -.TP -3 arguments -The following conditions are applied in the order listed. -If the second argument is one of the binary conditional operators listed above -under -.SM -.BR "CONDITIONAL EXPRESSIONS" , -the result of the expression is the result of the binary test using -the first and third arguments as operands. -The \fB\-a\fP and \fB\-o\fP operators are considered binary operators -when there are three arguments. -If the first argument is \fB!\fP, the value is the negation of -the two-argument test using the second and third arguments. -If the first argument is exactly \fB(\fP and the third argument is -exactly \fB)\fP, the result is the one-argument test of the second -argument. -Otherwise, the expression is false. -.TP -4 arguments -If the first argument is \fB!\fP, the result is the negation of -the three-argument expression composed of the remaining arguments. -Otherwise, the expression is parsed and evaluated according to -precedence using the rules listed above. -.TP -5 or more arguments -The expression is parsed and evaluated according to precedence -using the rules listed above. -.if t .sp 0.5 -.if n .sp 1 -.LP -When used with \fBtest\fP or \fB[\fP, the \fB<\fP and \fB>\fP operators -sort lexicographically using ASCII ordering. -.RE -.PD -.TP -.B times -Print the accumulated user and system times for the shell and -for processes run from the shell. The return status is 0. -.TP -\fBtrap\fP [\fB\-lp\fP] [[\fIarg\fP] \fIsigspec\fP ...] -The command -.I arg -is to be read and executed when the shell receives -signal(s) -.IR sigspec . -If -.I arg -is absent (and there is a single \fIsigspec\fP) or -.BR \- , -each specified signal is -reset to its original disposition (the value it had -upon entrance to the shell). -If -.I arg -is the null string the signal specified by each -.I sigspec -is ignored by the shell and by the commands it invokes. -If -.I arg -is not present and -.B \-p -has been supplied, then the trap commands associated with each -.I sigspec -are displayed. -If no arguments are supplied or if only -.B \-p -is given, -.B trap -prints the list of commands associated with each signal. -The -.B \-l -option causes the shell to print a list of signal names and -their corresponding numbers. -Each -.I sigspec -is either -a signal name defined in <\fIsignal.h\fP>, or a signal number. -Signal names are case insensitive and the -.SM -.B SIG -prefix is optional. -.if t .sp 0.5 -.if n .sp 1 -If a -.I sigspec -is -.SM -.B EXIT -(0) the command -.I arg -is executed on exit from the shell. -If a -.I sigspec -is -.SM -.BR DEBUG , -the command -.I arg -is executed before every \fIsimple command\fP, \fIfor\fP command, -\fIcase\fP command, \fIselect\fP command, every arithmetic \fIfor\fP -command, and before the first command executes in a shell function (see -.SM -.B SHELL GRAMMAR -above). -Refer to the description of the \fBextdebug\fP option to the -\fBshopt\fP builtin for details of its effect on the \fBDEBUG\fP trap. -If a -.I sigspec -is -.SM -.BR RETURN , -the command -.I arg -is executed each time a shell function or a script executed with -the \fB.\fP or \fBsource\fP builtins finishes executing. -.if t .sp 0.5 -.if n .sp 1 -If a -.I sigspec -is -.SM -.BR ERR , -the command -.I arg -is executed whenever a -a pipeline (which may consist of a single simple -command), a list, or a compound command returns a -non\-zero exit status, -subject to the following conditions. -The -.SM -.B ERR -trap is not executed if the failed -command is part of the command list immediately following a -.B while -or -.B until -keyword, -part of the test in an -.I if -statement, part of a command executed in a -.B && -or -.B || -list except the command following the final \fB&&\fP or \fB||\fP, -any command in a pipeline but the last, -or if the command's return value is -being inverted using -.BR ! . -These are the same conditions obeyed by the \fBerrexit\fP (\fB\-e\fP) option. -.if t .sp 0.5 -.if n .sp 1 -Signals ignored upon entry to the shell cannot be trapped or reset. -Trapped signals that are not being ignored are reset to their original -values in a subshell or subshell environment when one is created. -The return status is false if any -.I sigspec -is invalid; otherwise -.B trap -returns true. -.TP -\fBtype\fP [\fB\-aftpP\fP] \fIname\fP [\fIname\fP ...] -With no options, -indicate how each -.I name -would be interpreted if used as a command name. -If the -.B \-t -option is used, -.B type -prints a string which is one of -.IR alias , -.IR keyword , -.IR function , -.IR builtin , -or -.I file -if -.I name -is an alias, shell reserved word, function, builtin, or disk file, -respectively. -If the -.I name -is not found, then nothing is printed, and an exit status of false -is returned. -If the -.B \-p -option is used, -.B type -either returns the name of the disk file -that would be executed if -.I name -were specified as a command name, -or nothing if -.if t \f(CWtype -t name\fP -.if n ``type -t name'' -would not return -.IR file . -The -.B \-P -option forces a -.SM -.B PATH -search for each \fIname\fP, even if -.if t \f(CWtype -t name\fP -.if n ``type -t name'' -would not return -.IR file . -If a command is hashed, -.B \-p -and -.B \-P -print the hashed value, which is not necessarily the file that appears -first in -.SM -.BR PATH . -If the -.B \-a -option is used, -.B type -prints all of the places that contain -an executable named -.IR name . -This includes aliases and functions, -if and only if the -.B \-p -option is not also used. -The table of hashed commands is not consulted -when using -.BR \-a . -The -.B \-f -option suppresses shell function lookup, as with the \fBcommand\fP builtin. -.B type -returns true if all of the arguments are found, false if -any are not found. -.TP -\fBulimit\fP [\fB\-HSTabcdefilmnpqrstuvx\fP [\fIlimit\fP]] -Provides control over the resources available to the shell and to -processes started by it, on systems that allow such control. -The \fB\-H\fP and \fB\-S\fP options specify that the hard or soft limit is -set for the given resource. -A hard limit cannot be increased by a non-root user once it is set; -a soft limit may be increased up to the value of the hard limit. -If neither \fB\-H\fP nor \fB\-S\fP is specified, both the soft and hard -limits are set. -The value of -.I limit -can be a number in the unit specified for the resource -or one of the special values -.BR hard , -.BR soft , -or -.BR unlimited , -which stand for the current hard limit, the current soft limit, and -no limit, respectively. -If -.I limit -is omitted, the current value of the soft limit of the resource is -printed, unless the \fB\-H\fP option is given. When more than one -resource is specified, the limit name and unit are printed before the value. -Other options are interpreted as follows: -.RS -.PD 0 -.TP -.B \-a -All current limits are reported -.TP -.B \-b -The maximum socket buffer size -.TP -.B \-c -The maximum size of core files created -.TP -.B \-d -The maximum size of a process's data segment -.TP -.B \-e -The maximum scheduling priority ("nice") -.TP -.B \-f -The maximum size of files written by the shell and its children -.TP -.B \-i -The maximum number of pending signals -.TP -.B \-l -The maximum size that may be locked into memory -.TP -.B \-m -The maximum resident set size (many systems do not honor this limit) -.TP -.B \-n -The maximum number of open file descriptors (most systems do not -allow this value to be set) -.TP -.B \-p -The pipe size in 512-byte blocks (this may not be set) -.TP -.B \-q -The maximum number of bytes in POSIX message queues -.TP -.B \-r -The maximum real-time scheduling priority -.TP -.B \-s -The maximum stack size -.TP -.B \-t -The maximum amount of cpu time in seconds -.TP -.B \-u -The maximum number of processes available to a single user -.TP -.B \-v -The maximum amount of virtual memory available to the shell and, on -some systems, to its children -.TP -.B \-x -The maximum number of file locks -.TP -.B \-T -The maximum number of threads -.PD -.PP -If -.I limit -is given, and the -.B \-a -option is not used, -\fIlimit\fP is the new value of the specified resource. -If no option is given, then -.B \-f -is assumed. Values are in 1024-byte increments, except for -.BR \-t , -which is in seconds; -.BR \-p , -which is in units of 512-byte blocks; -and -.BR \-T , -.BR \-b , -.BR \-n , -and -.BR \-u , -which are unscaled values. -The return status is 0 unless an invalid option or argument is supplied, -or an error occurs while setting a new limit. -.RE -.TP -\fBumask\fP [\fB\-p\fP] [\fB\-S\fP] [\fImode\fP] -The user file-creation mask is set to -.IR mode . -If -.I mode -begins with a digit, it -is interpreted as an octal number; otherwise -it is interpreted as a symbolic mode mask similar -to that accepted by -.IR chmod (1). -If -.I mode -is omitted, the current value of the mask is printed. -The -.B \-S -option causes the mask to be printed in symbolic form; the -default output is an octal number. -If the -.B \-p -option is supplied, and -.I mode -is omitted, the output is in a form that may be reused as input. -The return status is 0 if the mode was successfully changed or if -no \fImode\fP argument was supplied, and false otherwise. -.TP -\fBunalias\fP [\-\fBa\fP] [\fIname\fP ...] -Remove each \fIname\fP from the list of defined aliases. If -.B \-a -is supplied, all alias definitions are removed. The return -value is true unless a supplied -.I name -is not a defined alias. -.TP -\fBunset\fP [\-\fBfv\fP] [\-\fBn\fP] [\fIname\fP ...] -For each -.IR name , -remove the corresponding variable or function. -If the -.B \-v -option is given, each -.I name -refers to a shell variable, and that variable is removed. -Read-only variables may not be unset. -If -.B \-f -is specified, each -.I name -refers to a shell function, and the function definition -is removed. -If the -.B \-n -option is supplied, and \fIname\fP is a variable with the \fInameref\fP -attribute, \fIname\fP will be unset rather than the variable it -references. -\fB\-n\fP has no effect if the \fB\-f\fP option is supplied. -If no options are supplied, each \fIname\fP refers to a variable; if -there is no variable by that name, any function with that name is -unset. -Each unset variable or function is removed from the environment -passed to subsequent commands. -If any of -.SM -.BR COMP_WORDBREAKS , -.SM -.BR RANDOM , -.SM -.BR SECONDS , -.SM -.BR LINENO , -.SM -.BR HISTCMD , -.SM -.BR FUNCNAME , -.SM -.BR GROUPS , -or -.SM -.B DIRSTACK -are unset, they lose their special properties, even if they are -subsequently reset. The exit status is true unless a -.I name -is readonly. -.TP -\fBwait\fP [\fB\-n\fP] [\fIn ...\fP] -Wait for each specified child process and return its termination status. -Each -.I n -may be a process -ID or a job specification; if a job spec is given, all processes -in that job's pipeline are waited for. If -.I n -is not given, all currently active child processes -are waited for, and the return status is zero. -If the \fB\-n\fP option is supplied, \fBwait\fP waits for any job to -terminate and returns its exit status. -If -.I n -specifies a non-existent process or job, the return status is -127. Otherwise, the return status is the exit status of the last -process or job waited for. -.\" bash_builtins -.if \n(zZ=1 .ig zZ -.SH "RESTRICTED SHELL" -.\" rbash.1 -.zY -.PP -If -.B bash -is started with the name -.BR rbash , -or the -.B \-r -option is supplied at invocation, -the shell becomes restricted. -A restricted shell is used to -set up an environment more controlled than the standard shell. -It behaves identically to -.B bash -with the exception that the following are disallowed or not performed: -.IP \(bu -changing directories with \fBcd\fP -.IP \(bu -setting or unsetting the values of -.SM -.BR SHELL , -.SM -.BR PATH , -.SM -.BR ENV , -or -.SM -.B BASH_ENV -.IP \(bu -specifying command names containing -.B / -.IP \(bu -specifying a filename containing a -.B / -as an argument to the -.B . -builtin command -.IP \(bu -specifying a filename containing a slash as an argument to the -.B \-p -option to the -.B hash -builtin command -.IP \(bu -importing function definitions from the shell environment at startup -.IP \(bu -parsing the value of -.SM -.B SHELLOPTS -from the shell environment at startup -.IP \(bu -redirecting output using the >, >|, <>, >&, &>, and >> redirection operators -.IP \(bu -using the -.B exec -builtin command to replace the shell with another command -.IP \(bu -adding or deleting builtin commands with the -.B \-f -and -.B \-d -options to the -.B enable -builtin command -.IP \(bu -using the \fBenable\fP builtin command to enable disabled shell builtins -.IP \(bu -specifying the -.B \-p -option to the -.B command -builtin command -.IP \(bu -turning off restricted mode with -\fBset +r\fP or \fBset +o restricted\fP. -.PP -These restrictions are enforced after any startup files are read. -.PP -.ie \n(zY=1 When a command that is found to be a shell script is executed, -.el \{ When a command that is found to be a shell script is executed -(see -.SM -.B "COMMAND EXECUTION" -above), -\} -.B rbash -turns off any restrictions in the shell spawned to execute the -script. -.\" end of rbash.1 -.if \n(zY=1 .ig zY -.SH "SEE ALSO" -.PD 0 -.TP -\fIBash Reference Manual\fP, Brian Fox and Chet Ramey -.TP -\fIThe Gnu Readline Library\fP, Brian Fox and Chet Ramey -.TP -\fIThe Gnu History Library\fP, Brian Fox and Chet Ramey -.TP -\fIPortable Operating System Interface (POSIX) Part 2: Shell and Utilities\fP, IEEE -- -http://pubs.opengroup.org/onlinepubs/9699919799/ -.TP -http://tiswww.case.edu/~chet/bash/POSIX -- a description of posix mode -.TP -\fIsh\fP(1), \fIksh\fP(1), \fIcsh\fP(1) -.TP -\fIemacs\fP(1), \fIvi\fP(1) -.TP -\fIreadline\fP(3) -.PD -.SH FILES -.PD 0 -.TP -.FN /bin/bash -The \fBbash\fP executable -.TP -.FN /etc/profile -The systemwide initialization file, executed for login shells -.TP -.FN ~/.bash_profile -The personal initialization file, executed for login shells -.TP -.FN ~/.bashrc -The individual per-interactive-shell startup file -.TP -.FN ~/.bash_logout -The individual login shell cleanup file, executed when a login shell exits -.TP -.FN ~/.inputrc -Individual \fIreadline\fP initialization file -.PD -.SH AUTHORS -Brian Fox, Free Software Foundation -.br -bfox@gnu.org -.PP -Chet Ramey, Case Western Reserve University -.br -chet.ramey@case.edu -.SH BUG REPORTS -If you find a bug in -.B bash, -you should report it. But first, you should -make sure that it really is a bug, and that it appears in the latest -version of -.BR bash . -The latest version is always available from -\fIftp://ftp.gnu.org/pub/gnu/bash/\fP. -.PP -Once you have determined that a bug actually exists, use the -.I bashbug -command to submit a bug report. -If you have a fix, you are encouraged to mail that as well! -Suggestions and `philosophical' bug reports may be mailed -to \fIbug-bash@gnu.org\fP or posted to the Usenet -newsgroup -.BR gnu.bash.bug . -.PP -ALL bug reports should include: -.PP -.PD 0 -.TP 20 -The version number of \fBbash\fR -.TP -The hardware and operating system -.TP -The compiler used to compile -.TP -A description of the bug behaviour -.TP -A short script or `recipe' which exercises the bug -.PD -.PP -.I bashbug -inserts the first three items automatically into the template -it provides for filing a bug report. -.PP -Comments and bug reports concerning -this manual page should be directed to -.IR chet.ramey@case.edu . -.SH BUGS -.PP -It's too big and too slow. -.PP -There are some subtle differences between -.B bash -and traditional versions of -.BR sh , -mostly because of the -.SM -.B POSIX -specification. -.PP -Aliases are confusing in some uses. -.PP -Shell builtin commands and functions are not stoppable/restartable. -.PP -Compound commands and command sequences of the form `a ; b ; c' -are not handled gracefully when process suspension is attempted. -When a process is stopped, the shell immediately executes the next -command in the sequence. -It suffices to place the sequence of commands between -parentheses to force it into a subshell, which may be stopped as -a unit. -.PP -Array variables may not (yet) be exported. -.PP -There may be only one active coprocess at a time. -.zZ -.zY diff --git a/doc/bashref.texi~ b/doc/bashref.texi~ deleted file mode 100644 index b5c0021a..00000000 --- a/doc/bashref.texi~ +++ /dev/null @@ -1,8756 +0,0 @@ -\input texinfo.tex @c -*- texinfo -*- -@c %**start of header -@setfilename bashref.info -@settitle Bash Reference Manual - -@include version.texi -@c %**end of header - -@copying -This text is a brief description of the features that are present in -the Bash shell (version @value{VERSION}, @value{UPDATED}). - -This is Edition @value{EDITION}, last updated @value{UPDATED}, -of @cite{The GNU Bash Reference Manual}, -for @code{Bash}, Version @value{VERSION}. - -Copyright @copyright{} 1988--2014 Free Software Foundation, Inc. - -@quotation -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.3 or -any later version published by the Free Software Foundation; with no -Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. -A copy of the license is included in the section entitled -``GNU Free Documentation License''. -@end quotation -@end copying - -@defcodeindex bt -@defcodeindex rw -@set BashFeatures - -@dircategory Basics -@direntry -* Bash: (bash). The GNU Bourne-Again SHell. -@end direntry - -@finalout - -@titlepage -@title Bash Reference Manual -@subtitle Reference Documentation for Bash -@subtitle Edition @value{EDITION}, for @code{Bash} Version @value{VERSION}. -@subtitle @value{UPDATED-MONTH} -@author Chet Ramey, Case Western Reserve University -@author Brian Fox, Free Software Foundation - -@page -@vskip 0pt plus 1filll -@insertcopying - -@end titlepage - -@contents - -@ifnottex -@node Top, Introduction, (dir), (dir) -@top Bash Features - -This text is a brief description of the features that are present in -the Bash shell (version @value{VERSION}, @value{UPDATED}). -The Bash home page is @url{http://www.gnu.org/software/bash/}. - -This is Edition @value{EDITION}, last updated @value{UPDATED}, -of @cite{The GNU Bash Reference Manual}, -for @code{Bash}, Version @value{VERSION}. - -Bash contains features that appear in other popular shells, and some -features that only appear in Bash. Some of the shells that Bash has -borrowed concepts from are the Bourne Shell (@file{sh}), the Korn Shell -(@file{ksh}), and the C-shell (@file{csh} and its successor, -@file{tcsh}). The following menu breaks the features up into -categories, noting which features were inspired by other shells and -which are specific to Bash. - -This manual is meant as a brief introduction to features found in -Bash. The Bash manual page should be used as the definitive -reference on shell behavior. - -@menu -* Introduction:: An introduction to the shell. -* Definitions:: Some definitions used in the rest of this - manual. -* Basic Shell Features:: The shell "building blocks". -* Shell Builtin Commands:: Commands that are a part of the shell. -* Shell Variables:: Variables used or set by Bash. -* Bash Features:: Features found only in Bash. -* Job Control:: What job control is and how Bash allows you - to use it. -* Command Line Editing:: Chapter describing the command line - editing features. -* Using History Interactively:: Command History Expansion -* Installing Bash:: How to build and install Bash on your system. -* Reporting Bugs:: How to report bugs in Bash. -* Major Differences From The Bourne Shell:: A terse list of the differences - between Bash and historical - versions of /bin/sh. -* GNU Free Documentation License:: Copying and sharing this documentation. -* Indexes:: Various indexes for this manual. -@end menu -@end ifnottex - -@node Introduction -@chapter Introduction -@menu -* What is Bash?:: A short description of Bash. -* What is a shell?:: A brief introduction to shells. -@end menu - -@node What is Bash? -@section What is Bash? - -Bash is the shell, or command language interpreter, -for the @sc{gnu} operating system. -The name is an acronym for the @samp{Bourne-Again SHell}, -a pun on Stephen Bourne, the author of the direct ancestor of -the current Unix shell @code{sh}, -which appeared in the Seventh Edition Bell Labs Research version -of Unix. - -Bash is largely compatible with @code{sh} and incorporates useful -features from the Korn shell @code{ksh} and the C shell @code{csh}. -It is intended to be a conformant implementation of the @sc{ieee} -@sc{posix} Shell and Tools portion of the @sc{ieee} @sc{posix} -specification (@sc{ieee} Standard 1003.1). -It offers functional improvements over @code{sh} for both interactive and -programming use. - -While the @sc{gnu} operating system provides other shells, including -a version of @code{csh}, Bash is the default shell. -Like other @sc{gnu} software, Bash is quite portable. It currently runs -on nearly every version of Unix and a few other operating systems @minus{} -independently-supported ports exist for @sc{ms-dos}, @sc{os/2}, -and Windows platforms. - -@node What is a shell? -@section What is a shell? - -At its base, a shell is simply a macro processor that executes -commands. The term macro processor means functionality where text -and symbols are expanded to create larger expressions. - -A Unix shell is both a command interpreter and a programming -language. As a command interpreter, the shell provides the user -interface to the rich set of @sc{gnu} utilities. The programming -language features allow these utilities to be combined. -Files containing commands can be created, and become -commands themselves. These new commands have the same status as -system commands in directories such as @file{/bin}, allowing users -or groups to establish custom environments to automate their common -tasks. - -Shells may be used interactively or non-interactively. In -interactive mode, they accept input typed from the keyboard. -When executing non-interactively, shells execute commands read -from a file. - -A shell allows execution of @sc{gnu} commands, both synchronously and -asynchronously. -The shell waits for synchronous commands to complete before accepting -more input; asynchronous commands continue to execute in parallel -with the shell while it reads and executes additional commands. -The @dfn{redirection} constructs permit -fine-grained control of the input and output of those commands. -Moreover, the shell allows control over the contents of commands' -environments. - -Shells also provide a small set of built-in -commands (@dfn{builtins}) implementing functionality impossible -or inconvenient to obtain via separate utilities. -For example, @code{cd}, @code{break}, @code{continue}, and -@code{exec} cannot be implemented outside of the shell because -they directly manipulate the shell itself. -The @code{history}, @code{getopts}, @code{kill}, or @code{pwd} -builtins, among others, could be implemented in separate utilities, -but they are more convenient to use as builtin commands. -All of the shell builtins are described in -subsequent sections. - -While executing commands is essential, most of the power (and -complexity) of shells is due to their embedded programming -languages. Like any high-level language, the shell provides -variables, flow control constructs, quoting, and functions. - -Shells offer features geared specifically for -interactive use rather than to augment the programming language. -These interactive features include job control, command line -editing, command history and aliases. Each of these features is -described in this manual. - -@node Definitions -@chapter Definitions -These definitions are used throughout the remainder of this manual. - -@table @code - -@item POSIX -@cindex POSIX -A family of open system standards based on Unix. Bash -is primarily concerned with the Shell and Utilities portion of the -@sc{posix} 1003.1 standard. - -@item blank -A space or tab character. - -@item builtin -@cindex builtin -A command that is implemented internally by the shell itself, rather -than by an executable program somewhere in the file system. - -@item control operator -@cindex control operator -A @code{token} that performs a control function. It is a @code{newline} -or one of the following: -@samp{||}, @samp{&&}, @samp{&}, @samp{;}, @samp{;;}, -@samp{|}, @samp{|&}, @samp{(}, or @samp{)}. - -@item exit status -@cindex exit status -The value returned by a command to its caller. The value is restricted -to eight bits, so the maximum value is 255. - -@item field -@cindex field -A unit of text that is the result of one of the shell expansions. After -expansion, when executing a command, the resulting fields are used as -the command name and arguments. - -@item filename -@cindex filename -A string of characters used to identify a file. - -@item job -@cindex job -A set of processes comprising a pipeline, and any processes descended -from it, that are all in the same process group. - -@item job control -@cindex job control -A mechanism by which users can selectively stop (suspend) and restart -(resume) execution of processes. - -@item metacharacter -@cindex metacharacter -A character that, when unquoted, separates words. A metacharacter is -a @code{blank} or one of the following characters: -@samp{|}, @samp{&}, @samp{;}, @samp{(}, @samp{)}, @samp{<}, or -@samp{>}. - -@item name -@cindex name -@cindex identifier -A @code{word} consisting solely of letters, numbers, and underscores, -and beginning with a letter or underscore. @code{Name}s are used as -shell variable and function names. -Also referred to as an @code{identifier}. - -@item operator -@cindex operator, shell -A @code{control operator} or a @code{redirection operator}. -@xref{Redirections}, for a list of redirection operators. -Operators contain at least one unquoted @code{metacharacter}. - -@item process group -@cindex process group -A collection of related processes each having the same process -group @sc{id}. - -@item process group ID -@cindex process group ID -A unique identifier that represents a @code{process group} -during its lifetime. - -@item reserved word -@cindex reserved word -A @code{word} that has a special meaning to the shell. Most reserved -words introduce shell flow control constructs, such as @code{for} and -@code{while}. - -@item return status -@cindex return status -A synonym for @code{exit status}. - -@item signal -@cindex signal -A mechanism by which a process may be notified by the kernel -of an event occurring in the system. - -@item special builtin -@cindex special builtin -A shell builtin command that has been classified as special by the -@sc{posix} standard. - -@item token -@cindex token -A sequence of characters considered a single unit by the shell. -It is either a @code{word} or an @code{operator}. - -@item word -@cindex word -A sequence of characters treated as a unit by the shell. -Words may not include unquoted @code{metacharacters}. -@end table - -@node Basic Shell Features -@chapter Basic Shell Features -@cindex Bourne shell - -Bash is an acronym for @samp{Bourne-Again SHell}. -The Bourne shell is -the traditional Unix shell originally written by Stephen Bourne. -All of the Bourne shell builtin commands are available in Bash, -The rules for evaluation and quoting are taken from the @sc{posix} -specification for the `standard' Unix shell. - -This chapter briefly summarizes the shell's `building blocks': -commands, control structures, shell functions, shell @i{parameters}, -shell expansions, -@i{redirections}, which are a way to direct input and output from -and to named files, and how the shell executes commands. - -@menu -* Shell Syntax:: What your input means to the shell. -* Shell Commands:: The types of commands you can use. -* Shell Functions:: Grouping commands by name. -* Shell Parameters:: How the shell stores values. -* Shell Expansions:: How Bash expands parameters and the various - expansions available. -* Redirections:: A way to control where input and output go. -* Executing Commands:: What happens when you run a command. -* Shell Scripts:: Executing files of shell commands. -@end menu - -@node Shell Syntax -@section Shell Syntax -@menu -* Shell Operation:: The basic operation of the shell. -* Quoting:: How to remove the special meaning from characters. -* Comments:: How to specify comments. -@end menu - -When the shell reads input, it proceeds through a -sequence of operations. If the input indicates the beginning of a -comment, the shell ignores the comment symbol (@samp{#}), and the rest -of that line. - -Otherwise, roughly speaking, the shell reads its input and -divides the input into words and operators, employing the quoting rules -to select which meanings to assign various words and characters. - -The shell then parses these tokens into commands and other constructs, -removes the special meaning of certain words or characters, expands -others, redirects input and output as needed, executes the specified -command, waits for the command's exit status, and makes that exit status -available for further inspection or processing. - -@node Shell Operation -@subsection Shell Operation - -The following is a brief description of the shell's operation when it -reads and executes a command. Basically, the shell does the -following: - -@enumerate -@item -Reads its input from a file (@pxref{Shell Scripts}), from a string -supplied as an argument to the @option{-c} invocation option -(@pxref{Invoking Bash}), or from the user's terminal. - -@item -Breaks the input into words and operators, obeying the quoting rules -described in @ref{Quoting}. These tokens are separated by -@code{metacharacters}. Alias expansion is performed by this step -(@pxref{Aliases}). - -@item -Parses the tokens into simple and compound commands -(@pxref{Shell Commands}). - -@item -Performs the various shell expansions (@pxref{Shell Expansions}), breaking -the expanded tokens into lists of filenames (@pxref{Filename Expansion}) -and commands and arguments. - -@item -Performs any necessary redirections (@pxref{Redirections}) and removes -the redirection operators and their operands from the argument list. - -@item -Executes the command (@pxref{Executing Commands}). - -@item -Optionally waits for the command to complete and collects its exit -status (@pxref{Exit Status}). - -@end enumerate - -@node Quoting -@subsection Quoting -@cindex quoting -@menu -* Escape Character:: How to remove the special meaning from a single - character. -* Single Quotes:: How to inhibit all interpretation of a sequence - of characters. -* Double Quotes:: How to suppress most of the interpretation of a - sequence of characters. -* ANSI-C Quoting:: How to expand ANSI-C sequences in quoted strings. -* Locale Translation:: How to translate strings into different languages. -@end menu - -Quoting is used to remove the special meaning of certain -characters or words to the shell. Quoting can be used to -disable special treatment for special characters, to prevent -reserved words from being recognized as such, and to prevent -parameter expansion. - -Each of the shell metacharacters (@pxref{Definitions}) -has special meaning to the shell and must be quoted if it is to -represent itself. -When the command history expansion facilities are being used -(@pxref{History Interaction}), the -@var{history expansion} character, usually @samp{!}, must be quoted -to prevent history expansion. @xref{Bash History Facilities}, for -more details concerning history expansion. - -There are three quoting mechanisms: the -@var{escape character}, single quotes, and double quotes. - -@node Escape Character -@subsubsection Escape Character -A non-quoted backslash @samp{\} is the Bash escape character. -It preserves the literal value of the next character that follows, -with the exception of @code{newline}. If a @code{\newline} pair -appears, and the backslash itself is not quoted, the @code{\newline} -is treated as a line continuation (that is, it is removed from -the input stream and effectively ignored). - -@node Single Quotes -@subsubsection Single Quotes - -Enclosing characters in single quotes (@samp{'}) preserves the literal value -of each character within the quotes. A single quote may not occur -between single quotes, even when preceded by a backslash. - -@node Double Quotes -@subsubsection Double Quotes - -Enclosing characters in double quotes (@samp{"}) preserves the literal value -of all characters within the quotes, with the exception of -@samp{$}, @samp{`}, @samp{\}, -and, when history expansion is enabled, @samp{!}. -The characters @samp{$} and @samp{`} -retain their special meaning within double quotes (@pxref{Shell Expansions}). -The backslash retains its special meaning only when followed by one of -the following characters: -@samp{$}, @samp{`}, @samp{"}, @samp{\}, or @code{newline}. -Within double quotes, backslashes that are followed by one of these -characters are removed. Backslashes preceding characters without a -special meaning are left unmodified. -A double quote may be quoted within double quotes by preceding it with -a backslash. -If enabled, history expansion will be performed unless an @samp{!} -appearing in double quotes is escaped using a backslash. -The backslash preceding the @samp{!} is not removed. - -The special parameters @samp{*} and @samp{@@} have special meaning -when in double quotes (@pxref{Shell Parameter Expansion}). - -@node ANSI-C Quoting -@subsubsection ANSI-C Quoting -@cindex quoting, ANSI - -Words of the form @code{$'@var{string}'} are treated specially. The -word expands to @var{string}, with backslash-escaped characters replaced -as specified by the ANSI C standard. Backslash escape sequences, if -present, are decoded as follows: - -@table @code -@item \a -alert (bell) -@item \b -backspace -@item \e -@itemx \E -an escape character (not ANSI C) -@item \f -form feed -@item \n -newline -@item \r -carriage return -@item \t -horizontal tab -@item \v -vertical tab -@item \\ -backslash -@item \' -single quote -@item \" -double quote -@item \@var{nnn} -the eight-bit character whose value is the octal value @var{nnn} -(one to three digits) -@item \x@var{HH} -the eight-bit character whose value is the hexadecimal value @var{HH} -(one or two hex digits) -@item \u@var{HHHH} -the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value -@var{HHHH} (one to four hex digits) -@item \U@var{HHHHHHHH} -the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value -@var{HHHHHHHH} (one to eight hex digits) -@item \c@var{x} -a control-@var{x} character -@end table - -@noindent -The expanded result is single-quoted, as if the dollar sign had not -been present. - -@node Locale Translation -@subsubsection Locale-Specific Translation -@cindex localization -@cindex internationalization -@cindex native languages -@cindex translation, native languages - -A double-quoted string preceded by a dollar sign (@samp{$}) will cause -the string to be translated according to the current locale. -If the current locale is @code{C} or @code{POSIX}, the dollar sign -is ignored. -If the string is translated and replaced, the replacement is -double-quoted. - -@vindex LC_MESSAGES -@vindex TEXTDOMAIN -@vindex TEXTDOMAINDIR -Some systems use the message catalog selected by the @env{LC_MESSAGES} -shell variable. Others create the name of the message catalog from the -value of the @env{TEXTDOMAIN} shell variable, possibly adding a -suffix of @samp{.mo}. If you use the @env{TEXTDOMAIN} variable, you -may need to set the @env{TEXTDOMAINDIR} variable to the location of -the message catalog files. Still others use both variables in this -fashion: -@env{TEXTDOMAINDIR}/@env{LC_MESSAGES}/LC_MESSAGES/@env{TEXTDOMAIN}.mo. - -@node Comments -@subsection Comments -@cindex comments, shell - -In a non-interactive shell, or an interactive shell in which the -@code{interactive_comments} option to the @code{shopt} -builtin is enabled (@pxref{The Shopt Builtin}), -a word beginning with @samp{#} -causes that word and all remaining characters on that line to -be ignored. An interactive shell without the @code{interactive_comments} -option enabled does not allow comments. The @code{interactive_comments} -option is on by default in interactive shells. -@xref{Interactive Shells}, for a description of what makes -a shell interactive. - -@node Shell Commands -@section Shell Commands -@cindex commands, shell - -A simple shell command such as @code{echo a b c} consists of the command -itself followed by arguments, separated by spaces. - -More complex shell commands are composed of simple commands arranged together -in a variety of ways: in a pipeline in which the output of one command -becomes the input of a second, in a loop or conditional construct, or in -some other grouping. - -@menu -* Simple Commands:: The most common type of command. -* Pipelines:: Connecting the input and output of several - commands. -* Lists:: How to execute commands sequentially. -* Compound Commands:: Shell commands for control flow. -* Coprocesses:: Two-way communication between commands. -* GNU Parallel:: Running commands in parallel. -@end menu - -@node Simple Commands -@subsection Simple Commands -@cindex commands, simple - -A simple command is the kind of command encountered most often. -It's just a sequence of words separated by @code{blank}s, terminated -by one of the shell's control operators (@pxref{Definitions}). The -first word generally specifies a command to be executed, with the -rest of the words being that command's arguments. - -The return status (@pxref{Exit Status}) of a simple command is -its exit status as provided -by the @sc{posix} 1003.1 @code{waitpid} function, or 128+@var{n} if -the command was terminated by signal @var{n}. - -@node Pipelines -@subsection Pipelines -@cindex pipeline -@cindex commands, pipelines - -A @code{pipeline} is a sequence of one or more commands separated by -one of the control operators @samp{|} or @samp{|&}. - -@rwindex time -@rwindex ! -@cindex command timing -The format for a pipeline is -@example -[time [-p]] [!] @var{command1} [ | or |& @var{command2} ] @dots{} -@end example - -@noindent -The output of each command in the pipeline is connected via a pipe -to the input of the next command. -That is, each command reads the previous command's output. This -connection is performed before any redirections specified by the -command. - -If @samp{|&} is used, @var{command1}'s standard error, in addition to -its standard output, is connected to -@var{command2}'s standard input through the pipe; -it is shorthand for @code{2>&1 |}. -This implicit redirection of the standard error to the standard output is -performed after any redirections specified by the command. - -The reserved word @code{time} causes timing statistics -to be printed for the pipeline once it finishes. -The statistics currently consist of elapsed (wall-clock) time and -user and system time consumed by the command's execution. -The @option{-p} option changes the output format to that specified -by @sc{posix}. -When the shell is in @sc{posix} mode (@pxref{Bash POSIX Mode}), -it does not recognize @code{time} as a reserved word if the next -token begins with a @samp{-}. -The @env{TIMEFORMAT} variable may be set to a format string that -specifies how the timing information should be displayed. -@xref{Bash Variables}, for a description of the available formats. -The use of @code{time} as a reserved word permits the timing of -shell builtins, shell functions, and pipelines. An external -@code{time} command cannot time these easily. - -When the shell is in @sc{posix} mode (@pxref{Bash POSIX Mode}), @code{time} -may be followed by a newline. In this case, the shell displays the -total user and system time consumed by the shell and its children. -The @env{TIMEFORMAT} variable may be used to specify the format of -the time information. - -If the pipeline is not executed asynchronously (@pxref{Lists}), the -shell waits for all commands in the pipeline to complete. - -Each command in a pipeline is executed in its own subshell -(@pxref{Command Execution Environment}). The exit -status of a pipeline is the exit status of the last command in the -pipeline, unless the @code{pipefail} option is enabled -(@pxref{The Set Builtin}). -If @code{pipefail} is enabled, the pipeline's return status is the -value of the last (rightmost) command to exit with a non-zero status, -or zero if all commands exit successfully. -If the reserved word @samp{!} precedes the pipeline, the -exit status is the logical negation of the exit status as described -above. -The shell waits for all commands in the pipeline to terminate before -returning a value. - -@node Lists -@subsection Lists of Commands -@cindex commands, lists - -A @code{list} is a sequence of one or more pipelines separated by one -of the operators @samp{;}, @samp{&}, @samp{&&}, or @samp{||}, -and optionally terminated by one of @samp{;}, @samp{&}, or a -@code{newline}. - -Of these list operators, @samp{&&} and @samp{||} -have equal precedence, followed by @samp{;} and @samp{&}, -which have equal precedence. - -A sequence of one or more newlines may appear in a @code{list} -to delimit commands, equivalent to a semicolon. - -If a command is terminated by the control operator @samp{&}, -the shell executes the command asynchronously in a subshell. -This is known as executing the command in the @var{background}. -The shell does not wait for the command to finish, and the return -status is 0 (true). -When job control is not active (@pxref{Job Control}), -the standard input for asynchronous commands, in the absence of any -explicit redirections, is redirected from @code{/dev/null}. - -Commands separated by a @samp{;} are executed sequentially; the shell -waits for each command to terminate in turn. The return status is the -exit status of the last command executed. - -@sc{and} and @sc{or} lists are sequences of one or more pipelines -separated by the control operators @samp{&&} and @samp{||}, -respectively. @sc{and} and @sc{or} lists are executed with left -associativity. - -An @sc{and} list has the form -@example -@var{command1} && @var{command2} -@end example - -@noindent -@var{command2} is executed if, and only if, @var{command1} -returns an exit status of zero. - -An @sc{or} list has the form -@example -@var{command1} || @var{command2} -@end example - -@noindent -@var{command2} is executed if, and only if, @var{command1} -returns a non-zero exit status. - -The return status of -@sc{and} and @sc{or} lists is the exit status of the last command -executed in the list. - -@node Compound Commands -@subsection Compound Commands -@cindex commands, compound - -@menu -* Looping Constructs:: Shell commands for iterative action. -* Conditional Constructs:: Shell commands for conditional execution. -* Command Grouping:: Ways to group commands. -@end menu - -Compound commands are the shell programming constructs. -Each construct begins with a reserved word or control operator and is -terminated by a corresponding reserved word or operator. -Any redirections (@pxref{Redirections}) associated with a compound command -apply to all commands within that compound command unless explicitly overridden. - -In most cases a list of commands in a compound command's description may be -separated from the rest of the command by one or more newlines, and may be -followed by a newline in place of a semicolon. - -Bash provides looping constructs, conditional commands, and mechanisms -to group commands and execute them as a unit. - -@node Looping Constructs -@subsubsection Looping Constructs -@cindex commands, looping - -Bash supports the following looping constructs. - -Note that wherever a @samp{;} appears in the description of a -command's syntax, it may be replaced with one or more newlines. - -@table @code -@item until -@rwindex until -@rwindex do -@rwindex done -The syntax of the @code{until} command is: - -@example -until @var{test-commands}; do @var{consequent-commands}; done -@end example - -Execute @var{consequent-commands} as long as -@var{test-commands} has an exit status which is not zero. -The return status is the exit status of the last command executed -in @var{consequent-commands}, or zero if none was executed. - -@item while -@rwindex while -The syntax of the @code{while} command is: - -@example -while @var{test-commands}; do @var{consequent-commands}; done -@end example - -Execute @var{consequent-commands} as long as -@var{test-commands} has an exit status of zero. -The return status is the exit status of the last command executed -in @var{consequent-commands}, or zero if none was executed. - -@item for -@rwindex for -The syntax of the @code{for} command is: - -@example -for @var{name} [ [in [@var{words} @dots{}] ] ; ] do @var{commands}; done -@end example - -Expand @var{words}, and execute @var{commands} once for each member -in the resultant list, with @var{name} bound to the current member. -If @samp{in @var{words}} is not present, the @code{for} command -executes the @var{commands} once for each positional parameter that is -set, as if @samp{in "$@@"} had been specified -(@pxref{Special Parameters}). -The return status is the exit status of the last command that executes. -If there are no items in the expansion of @var{words}, no commands are -executed, and the return status is zero. - -An alternate form of the @code{for} command is also supported: - -@example -for (( @var{expr1} ; @var{expr2} ; @var{expr3} )) ; do @var{commands} ; done -@end example - -First, the arithmetic expression @var{expr1} is evaluated according -to the rules described below (@pxref{Shell Arithmetic}). -The arithmetic expression @var{expr2} is then evaluated repeatedly -until it evaluates to zero. -Each time @var{expr2} evaluates to a non-zero value, @var{commands} are -executed and the arithmetic expression @var{expr3} is evaluated. -If any expression is omitted, it behaves as if it evaluates to 1. -The return value is the exit status of the last command in @var{commands} -that is executed, or false if any of the expressions is invalid. -@end table - -The @code{break} and @code{continue} builtins (@pxref{Bourne Shell Builtins}) -may be used to control loop execution. - -@node Conditional Constructs -@subsubsection Conditional Constructs -@cindex commands, conditional - -@table @code -@item if -@rwindex if -@rwindex then -@rwindex else -@rwindex elif -@rwindex fi -The syntax of the @code{if} command is: - -@example -if @var{test-commands}; then - @var{consequent-commands}; -[elif @var{more-test-commands}; then - @var{more-consequents};] -[else @var{alternate-consequents};] -fi -@end example - -The @var{test-commands} list is executed, and if its return status is zero, -the @var{consequent-commands} list is executed. -If @var{test-commands} returns a non-zero status, each @code{elif} list -is executed in turn, and if its exit status is zero, -the corresponding @var{more-consequents} is executed and the -command completes. -If @samp{else @var{alternate-consequents}} is present, and -the final command in the final @code{if} or @code{elif} clause -has a non-zero exit status, then @var{alternate-consequents} is executed. -The return status is the exit status of the last command executed, or -zero if no condition tested true. - -@item case -@rwindex case -@rwindex in -@rwindex esac -The syntax of the @code{case} command is: - -@example -case @var{word} in [ [(] @var{pattern} [| @var{pattern}]@dots{}) @var{command-list} ;;]@dots{} esac -@end example - -@code{case} will selectively execute the @var{command-list} corresponding to -the first @var{pattern} that matches @var{word}. -If the shell option @code{nocasematch} -(see the description of @code{shopt} in @ref{The Shopt Builtin}) -is enabled, the match is performed without regard to the case -of alphabetic characters. -The @samp{|} is used to separate multiple patterns, and the @samp{)} -operator terminates a pattern list. -A list of patterns and an associated command-list is known -as a @var{clause}. - -Each clause must be terminated with @samp{;;}, @samp{;&}, or @samp{;;&}. -The @var{word} undergoes tilde expansion, parameter expansion, command -substitution, arithmetic expansion, and quote removal before matching is -attempted. Each @var{pattern} undergoes tilde expansion, parameter -expansion, command substitution, and arithmetic expansion. - -There may be an arbitrary number of @code{case} clauses, each terminated -by a @samp{;;}, @samp{;&}, or @samp{;;&}. -The first pattern that matches determines the -command-list that is executed. -It's a common idiom to use @samp{*} as the final pattern to define the -default case, since that pattern will always match. - -Here is an example using @code{case} in a script that could be used to -describe one interesting feature of an animal: - -@example -echo -n "Enter the name of an animal: " -read ANIMAL -echo -n "The $ANIMAL has " -case $ANIMAL in - horse | dog | cat) echo -n "four";; - man | kangaroo ) echo -n "two";; - *) echo -n "an unknown number of";; -esac -echo " legs." -@end example - -@noindent - -If the @samp{;;} operator is used, no subsequent matches are attempted after -the first pattern match. -Using @samp{;&} in place of @samp{;;} causes execution to continue with -the @var{command-list} associated with the next clause, if any. -Using @samp{;;&} in place of @samp{;;} causes the shell to test the patterns -in the next clause, if any, and execute any associated @var{command-list} -on a successful match. - -The return status is zero if no @var{pattern} is matched. Otherwise, the -return status is the exit status of the @var{command-list} executed. - -@item select -@rwindex select - -The @code{select} construct allows the easy generation of menus. -It has almost the same syntax as the @code{for} command: - -@example -select @var{name} [in @var{words} @dots{}]; do @var{commands}; done -@end example - -The list of words following @code{in} is expanded, generating a list -of items. The set of expanded words is printed on the standard -error output stream, each preceded by a number. If the -@samp{in @var{words}} is omitted, the positional parameters are printed, -as if @samp{in "$@@"} had been specified. -The @env{PS3} prompt is then displayed and a line is read from the -standard input. -If the line consists of a number corresponding to one of the displayed -words, then the value of @var{name} is set to that word. -If the line is empty, the words and prompt are displayed again. -If @code{EOF} is read, the @code{select} command completes. -Any other value read causes @var{name} to be set to null. -The line read is saved in the variable @env{REPLY}. - -The @var{commands} are executed after each selection until a -@code{break} command is executed, at which -point the @code{select} command completes. - -Here is an example that allows the user to pick a filename from the -current directory, and displays the name and index of the file -selected. - -@example -select fname in *; -do - echo you picked $fname \($REPLY\) - break; -done -@end example - -@item ((@dots{})) -@example -(( @var{expression} )) -@end example - -The arithmetic @var{expression} is evaluated according to the rules -described below (@pxref{Shell Arithmetic}). -If the value of the expression is non-zero, the return status is 0; -otherwise the return status is 1. This is exactly equivalent to -@example -let "@var{expression}" -@end example -@noindent -@xref{Bash Builtins}, for a full description of the @code{let} builtin. - -@item [[@dots{}]] -@rwindex [[ -@rwindex ]] -@example -[[ @var{expression} ]] -@end example - -Return a status of 0 or 1 depending on the evaluation of -the conditional expression @var{expression}. -Expressions are composed of the primaries described below in -@ref{Bash Conditional Expressions}. -Word splitting and filename expansion are not performed on the words -between the @code{[[} and @code{]]}; tilde expansion, parameter and -variable expansion, arithmetic expansion, command substitution, process -substitution, and quote removal are performed. -Conditional operators such as @samp{-f} must be unquoted to be recognized -as primaries. - -When used with @code{[[}, the @samp{<} and @samp{>} operators sort -lexicographically using the current locale. - -When the @samp{==} and @samp{!=} operators are used, the string to the -right of the operator is considered a pattern and matched according -to the rules described below in @ref{Pattern Matching}, -as if the @code{extglob} shell option were enabled. -The @samp{=} operator is identical to @samp{==}. -If the shell option @code{nocasematch} -(see the description of @code{shopt} in @ref{The Shopt Builtin}) -is enabled, the match is performed without regard to the case -of alphabetic characters. -The return value is 0 if the string matches (@samp{==}) or does not -match (@samp{!=})the pattern, and 1 otherwise. -Any part of the pattern may be quoted to force the quoted portion -to be matched as a string. - -An additional binary operator, @samp{=~}, is available, with the same -precedence as @samp{==} and @samp{!=}. -When it is used, the string to the right of the operator is considered -an extended regular expression and matched accordingly (as in @i{regex}3)). -The return value is 0 if the string matches -the pattern, and 1 otherwise. -If the regular expression is syntactically incorrect, the conditional -expression's return value is 2. -If the shell option @code{nocasematch} -(see the description of @code{shopt} in @ref{The Shopt Builtin}) -is enabled, the match is performed without regard to the case -of alphabetic characters. -Any part of the pattern may be quoted to force the quoted portion -to be matched as a string. -Bracket expressions in regular expressions must be treated carefully, -since normal quoting characters lose their meanings between brackets. -If the pattern is stored in a shell variable, quoting the variable -expansion forces the entire pattern to be matched as a string. -Substrings matched by parenthesized subexpressions within the regular -expression are saved in the array variable @code{BASH_REMATCH}. -The element of @code{BASH_REMATCH} with index 0 is the portion of the string -matching the entire regular expression. -The element of @code{BASH_REMATCH} with index @var{n} is the portion of the -string matching the @var{n}th parenthesized subexpression. - -For example, the following will match a line -(stored in the shell variable @var{line}) -if there is a sequence of characters in the value consisting of -any number, including zero, of -space characters, zero or one instances of @samp{a}, then a @samp{b}: -@example -[[ $line =~ [[:space:]]*(a)?b ]] -@end example - -@noindent -That means values like @samp{aab} and @samp{ aaaaaab} will match, as -will a line containing a @samp{b} anywhere in its value. - -Storing the regular expression in a shell variable is often a useful -way to avoid problems with quoting characters that are special to the -shell. -It is sometimes difficult to specify a regular expression literally -without using quotes, or to keep track of the quoting used by regular -expressions while paying attention to the shell's quote removal. -Using a shell variable to store the pattern decreases these problems. -For example, the following is equivalent to the above: -@example -pattern='[[:space:]]*(a)?b' -[[ $line =~ $pattern ]] -@end example - -@noindent -If you want to match a character that's special to the regular expression -grammar, it has to be quoted to remove its special meaning. -This means that in the pattern @samp{xxx.txt}, the @samp{.} matches any -character in the string (its usual regular expression meaning), but in the -pattern @samp{"xxx.txt"} it can only match a literal @samp{.}. -Shell programmers should take special care with backslashes, since backslashes -are used both by the shell and regular expressions to remove the special -meaning from the following character. -The following two sets of commands are @emph{not} equivalent: -@example -pattern='\.' - -[[ . =~ $pattern ]] -[[ . =~ \. ]] - -[[ . =~ "$pattern" ]] -[[ . =~ '\.' ]] -@end example - -@noindent -The first two matches will succeed, but the second two will not, because -in the second two the backslash will be part of the pattern to be matched. -In the first two examples, the backslash removes the special meaning from -@samp{.}, so the literal @samp{.} matches. -If the string in the first examples were anything other than @samp{.}, say -@samp{a}, the pattern would not match, because the quoted @samp{.} in the -pattern loses its special meaning of matching any single character. - -Expressions may be combined using the following operators, listed -in decreasing order of precedence: - -@table @code -@item ( @var{expression} ) -Returns the value of @var{expression}. -This may be used to override the normal precedence of operators. - -@item ! @var{expression} -True if @var{expression} is false. - -@item @var{expression1} && @var{expression2} -True if both @var{expression1} and @var{expression2} are true. - -@item @var{expression1} || @var{expression2} -True if either @var{expression1} or @var{expression2} is true. -@end table - -@noindent -The @code{&&} and @code{||} operators do not evaluate @var{expression2} if the -value of @var{expression1} is sufficient to determine the return -value of the entire conditional expression. -@end table - -@node Command Grouping -@subsubsection Grouping Commands -@cindex commands, grouping - -Bash provides two ways to group a list of commands to be executed -as a unit. When commands are grouped, redirections may be applied -to the entire command list. For example, the output of all the -commands in the list may be redirected to a single stream. - -@table @code -@item () -@example -( @var{list} ) -@end example - -Placing a list of commands between parentheses causes a subshell -environment to be created (@pxref{Command Execution Environment}), and each -of the commands in @var{list} to be executed in that subshell. Since the -@var{list} is executed in a subshell, variable assignments do not remain in -effect after the subshell completes. - -@item @{@} -@rwindex @{ -@rwindex @} -@example -@{ @var{list}; @} -@end example - -Placing a list of commands between curly braces causes the list to -be executed in the current shell context. No subshell is created. -The semicolon (or newline) following @var{list} is required. -@end table - -In addition to the creation of a subshell, there is a subtle difference -between these two constructs due to historical reasons. The braces -are @code{reserved words}, so they must be separated from the @var{list} -by @code{blank}s or other shell metacharacters. -The parentheses are @code{operators}, and are -recognized as separate tokens by the shell even if they are not separated -from the @var{list} by whitespace. - -The exit status of both of these constructs is the exit status of -@var{list}. - -@node Coprocesses -@subsection Coprocesses -@cindex coprocess - -A @code{coprocess} is a shell command preceded by the @code{coproc} -reserved word. -A coprocess is executed asynchronously in a subshell, as if the command -had been terminated with the @samp{&} control operator, with a two-way pipe -established between the executing shell and the coprocess. - -The format for a coprocess is: -@example -coproc [@var{NAME}] @var{command} [@var{redirections}] -@end example - -@noindent -This creates a coprocess named @var{NAME}. -If @var{NAME} is not supplied, the default name is @var{COPROC}. -@var{NAME} must not be supplied if @var{command} is a simple -command (@pxref{Simple Commands}); otherwise, it is interpreted as -the first word of the simple command. - -When the coprocess is executed, the shell creates an array variable -(@pxref{Arrays}) -named @env{NAME} in the context of the executing shell. -The standard output of @var{command} -is connected via a pipe to a file descriptor in the executing shell, -and that file descriptor is assigned to @env{NAME}[0]. -The standard input of @var{command} -is connected via a pipe to a file descriptor in the executing shell, -and that file descriptor is assigned to @env{NAME}[1]. -This pipe is established before any redirections specified by the -command (@pxref{Redirections}). -The file descriptors can be utilized as arguments to shell commands -and redirections using standard word expansions. -The file descriptors are not available in subshells. - -The process ID of the shell spawned to execute the coprocess is -available as the value of the variable @env{NAME}_PID. -The @code{wait} -builtin command may be used to wait for the coprocess to terminate. - -Since the coprocess is created as an asynchronous command, -the @code{coproc} command always returns success. -The return status of a coprocess is the exit status of @var{command}. - -@node GNU Parallel -@subsection GNU Parallel - -There are ways to run commands in parallel that are not built into Bash. -GNU Parallel is a tool to do just that. - -GNU Parallel, as its name suggests, can be used to build and run commands -in parallel. You may run the same command with different arguments, whether -they are filenames, usernames, hostnames, or lines read from files. GNU -Parallel provides shorthand references to many of the most common operations -(input lines, various portions of the input line, different ways to specify -the input source, and so on). Parallel can replace @code{xargs} or feed -commands from its input sources to several different instances of Bash. - -For a complete description, refer to the GNU Parallel documentation. A few -examples should provide a brief introduction to its use. - -For example, it is easy to replace @code{xargs} to gzip all html files in the -current directory and its subdirectories: -@example -find . -type f -name '*.html' -print | parallel gzip -@end example -@noindent -If you need to protect special characters such as newlines in file names, -use find's @option{-print0} option and parallel's @option{-0} option. - -You can use Parallel to move files from the current directory when the -number of files is too large to process with one @code{mv} invocation: -@example -ls | parallel mv @{@} destdir -@end example - -As you can see, the @{@} is replaced with each line read from standard input. -While using @code{ls} will work in most instances, it is not sufficient to -deal with all filenames. -If you need to accommodate special characters in filenames, you can use - -@example -find . -depth 1 \! -name '.*' -print0 | parallel -0 mv @{@} destdir -@end example - -@noindent -as alluded to above. - -This will run as many @code{mv} commands as there are files in the current -directory. -You can emulate a parallel @code{xargs} by adding the @option{-X} option: -@example -find . -depth 1 \! -name '.*' -print0 | parallel -0 -X mv @{@} destdir -@end example - -GNU Parallel can replace certain common idioms that operate on lines read -from a file (in this case, filenames listed one per line): -@example - while IFS= read -r x; do - do-something1 "$x" "config-$x" - do-something2 < "$x" - done < file | process-output -@end example - -@noindent -with a more compact syntax reminiscent of lambdas: -@example -cat list | parallel "do-something1 @{@} config-@{@} ; do-something2 < @{@}" | process-output -@end example - -Parallel provides a built-in mechanism to remove filename extensions, which -lends itself to batch file transformations or renaming: -@example -ls *.gz | parallel -j+0 "zcat @{@} | bzip2 >@{.@}.bz2 && rm @{@}" -@end example -@noindent -This will recompress all files in the current directory with names ending -in .gz using bzip2, running one job per CPU (-j+0) in parallel. -(We use @code{ls} for brevity here; using @code{find} as above is more -robust in the face of filenames containing unexpected characters.) -Parallel can take arguments from the command line; the above can also be -written as - -@example -parallel "zcat @{@} | bzip2 >@{.@}.bz2 && rm @{@}" ::: *.gz -@end example - -If a command generates output, you may want to preserve the input order in -the output. For instance, the following command -@example -@{ echo foss.org.my ; echo debian.org; echo freenetproject.org; @} | parallel traceroute -@end example -@noindent -will display as output the traceroute invocation that finishes first. -Adding the @option{-k} option -@example -@{ echo foss.org.my ; echo debian.org; echo freenetproject.org; @} | parallel -k traceroute -@end example -@noindent -will ensure that the output of @code{traceroute foss.org.my} is displayed first. - -Finally, Parallel can be used to run a sequence of shell commands in parallel, -similar to @samp{cat file | bash}. -It is not uncommon to take a list of filenames, create a series of shell -commands to operate on them, and feed that list of commnds to a shell. -Parallel can speed this up. Assuming that @file{file} contains a list of -shell commands, one per line, - -@example -parallel -j 10 < file -@end example - -@noindent -will evaluate the commands using the shell (since no explicit command is -supplied as an argument), in blocks of ten shell jobs at a time. - -@node Shell Functions -@section Shell Functions -@cindex shell function -@cindex functions, shell - -Shell functions are a way to group commands for later execution -using a single name for the group. They are executed just like -a "regular" command. -When the name of a shell function is used as a simple command name, -the list of commands associated with that function name is executed. -Shell functions are executed in the current -shell context; no new process is created to interpret them. - -Functions are declared using this syntax: -@rwindex function -@example -@var{name} () @var{compound-command} [ @var{redirections} ] -@end example - -or - -@example -function @var{name} [()] @var{compound-command} [ @var{redirections} ] -@end example - -This defines a shell function named @var{name}. The reserved -word @code{function} is optional. -If the @code{function} reserved -word is supplied, the parentheses are optional. -The @var{body} of the function is the compound command -@var{compound-command} (@pxref{Compound Commands}). -That command is usually a @var{list} enclosed between @{ and @}, but -may be any compound command listed above, -with one exception: If the @code{function} reserved word is used, but the -parentheses are not supplied, the braces are required. -@var{compound-command} is executed whenever @var{name} is specified as the -name of a command. -When the shell is in @sc{posix} mode (@pxref{Bash POSIX Mode}), -@var{name} may not be the same as one of the special builtins -(@pxref{Special Builtins}). -Any redirections (@pxref{Redirections}) associated with the shell function -are performed when the function is executed. - -A function definition may be deleted using the @option{-f} option to the -@code{unset} builtin (@pxref{Bourne Shell Builtins}). - -The exit status of a function definition is zero unless a syntax error -occurs or a readonly function with the same name already exists. -When executed, the exit status of a function is the exit status of the -last command executed in the body. - -Note that for historical reasons, in the most common usage the curly braces -that surround the body of the function must be separated from the body by -@code{blank}s or newlines. -This is because the braces are reserved words and are only recognized -as such when they are separated from the command list -by whitespace or another shell metacharacter. -Also, when using the braces, the @var{list} must be terminated by a semicolon, -a @samp{&}, or a newline. - -When a function is executed, the arguments to the -function become the positional parameters -during its execution (@pxref{Positional Parameters}). -The special parameter @samp{#} that expands to the number of -positional parameters is updated to reflect the change. -Special parameter @code{0} is unchanged. -The first element of the @env{FUNCNAME} variable is set to the -name of the function while the function is executing. - -All other aspects of the shell execution -environment are identical between a function and its caller -with these exceptions: -the @env{DEBUG} and @env{RETURN} traps -are not inherited unless the function has been given the -@code{trace} attribute using the @code{declare} builtin or -the @code{-o functrace} option has been enabled with -the @code{set} builtin, -(in which case all functions inherit the @env{DEBUG} and @env{RETURN} traps), -and the @env{ERR} trap is not inherited unless the @code{-o errtrace} -shell option has been enabled. -@xref{Bourne Shell Builtins}, for the description of the -@code{trap} builtin. - -The @env{FUNCNEST} variable, if set to a numeric value greater -than 0, defines a maximum function nesting level. Function -invocations that exceed the limit cause the entire command to -abort. - -If the builtin command @code{return} -is executed in a function, the function completes and -execution resumes with the next command after the function -call. -Any command associated with the @code{RETURN} trap is executed -before execution resumes. -When a function completes, the values of the -positional parameters and the special parameter @samp{#} -are restored to the values they had prior to the function's -execution. If a numeric argument is given to @code{return}, -that is the function's return status; otherwise the function's -return status is the exit status of the last command executed -before the @code{return}. - -Variables local to the function may be declared with the -@code{local} builtin. These variables are visible only to -the function and the commands it invokes. - -Function names and definitions may be listed with the -@option{-f} option to the @code{declare} (@code{typeset}) -builtin command (@pxref{Bash Builtins}). -The @option{-F} option to @code{declare} or @code{typeset} -will list the function names only -(and optionally the source file and line number, if the @code{extdebug} -shell option is enabled). -Functions may be exported so that subshells -automatically have them defined with the -@option{-f} option to the @code{export} builtin -(@pxref{Bourne Shell Builtins}). -Note that shell functions and variables with the same name may result -in multiple identically-named entries in the environment passed to the -shell's children. -Care should be taken in cases where this may cause a problem. - -Functions may be recursive. -The @code{FUNCNEST} variable may be used to limit the depth of the -function call stack and restrict the number of function invocations. -By default, no limit is placed on the number of recursive calls. - -@node Shell Parameters -@section Shell Parameters -@cindex parameters -@cindex variable, shell -@cindex shell variable - -@menu -* Positional Parameters:: The shell's command-line arguments. -* Special Parameters:: Parameters denoted by special characters. -@end menu - -A @var{parameter} is an entity that stores values. -It can be a @code{name}, a number, or one of the special characters -listed below. -A @var{variable} is a parameter denoted by a @code{name}. -A variable has a @var{value} and zero or more @var{attributes}. -Attributes are assigned using the @code{declare} builtin command -(see the description of the @code{declare} builtin in @ref{Bash Builtins}). - -A parameter is set if it has been assigned a value. The null string is -a valid value. Once a variable is set, it may be unset only by using -the @code{unset} builtin command. - -A variable may be assigned to by a statement of the form -@example -@var{name}=[@var{value}] -@end example -@noindent -If @var{value} -is not given, the variable is assigned the null string. All -@var{value}s undergo tilde expansion, parameter and variable expansion, -command substitution, arithmetic expansion, and quote -removal (detailed below). If the variable has its @code{integer} -attribute set, then @var{value} -is evaluated as an arithmetic expression even if the @code{$((@dots{}))} -expansion is not used (@pxref{Arithmetic Expansion}). -Word splitting is not performed, with the exception -of @code{"$@@"} as explained below. -Filename expansion is not performed. -Assignment statements may also appear as arguments to the -@code{alias}, -@code{declare}, @code{typeset}, @code{export}, @code{readonly}, -and @code{local} builtin commands (@var{declaration} commands). -When in @sc{posix} mode (@pxref{Bash POSIX Mode}), these builtins may appear -in a command after one or more instances of the @code{command} builtin -and retain these assignment statement properties. - -In the context where an assignment statement is assigning a value -to a shell variable or array index (@pxref{Arrays}), the @samp{+=} -operator can be used to -append to or add to the variable's previous value. -This includes arguments to builtin commands such as @code{declare} that -accept assignment statements (@var{declaration} commands). -When @samp{+=} is applied to a variable for which the @var{integer} attribute -has been set, @var{value} is evaluated as an arithmetic expression and -added to the variable's current value, which is also evaluated. -When @samp{+=} is applied to an array variable using compound assignment -(@pxref{Arrays}), the -variable's value is not unset (as it is when using @samp{=}), and new -values are appended to the array beginning at one greater than the array's -maximum index (for indexed arrays), or added as additional key-value pairs -in an associative array. -When applied to a string-valued variable, @var{value} is expanded and -appended to the variable's value. - -A variable can be assigned the @var{nameref} attribute using the -@option{-n} option to the \fBdeclare\fP or \fBlocal\fP builtin commands -(@pxref{Bash Builtins}) -to create a @var{nameref}, or a reference to another variable. -This allows variables to be manipulated indirectly. -Whenever the nameref variable is referenced, assigned to, unset, or has -its attributes modified (other than the nameref attribute itself), the -operation is actually performed on the variable specified by the nameref -variable's value. -A nameref is commonly used within shell functions to refer to a variable -whose name is passed as an argument to the function. -For instance, if a variable name is passed to a shell function as its first -argument, running -@example -declare -n ref=$1 -@end example -@noindent -inside the function creates a nameref variable @var{ref} whose value is -the variable name passed as the first argument. -References and assignments to @var{ref}, and changes to its attributes, -are treated as references, assignments, and attribute modifications -to the variable whose name was passed as @code{$1}. - -If the control variable in a @code{for} loop has the nameref attribute, -the list of words can be a list of shell variables, and a name reference -will be established for each word in the list, in turn, when the loop is -executed. -Array variables cannot be given the nameref attribute. -However, nameref variables can reference array variables and subscripted -array variables. -Namerefs can be unset using the @option{-n} option to the @code{unset} builtin -(@pxref{Bourne Shell Builtins}). -Otherwise, if @code{unset} is executed with the name of a nameref variable -as an argument, the variable referenced by the nameref variable will be unset. - -@node Positional Parameters -@subsection Positional Parameters -@cindex parameters, positional - -A @var{positional parameter} is a parameter denoted by one or more -digits, other than the single digit @code{0}. Positional parameters are -assigned from the shell's arguments when it is invoked, -and may be reassigned using the @code{set} builtin command. -Positional parameter @code{N} may be referenced as @code{$@{N@}}, or -as @code{$N} when @code{N} consists of a single digit. -Positional parameters may not be assigned to with assignment statements. -The @code{set} and @code{shift} builtins are used to set and -unset them (@pxref{Shell Builtin Commands}). -The positional parameters are -temporarily replaced when a shell function is executed -(@pxref{Shell Functions}). - -When a positional parameter consisting of more than a single -digit is expanded, it must be enclosed in braces. - -@node Special Parameters -@subsection Special Parameters -@cindex parameters, special - -The shell treats several parameters specially. These parameters may -only be referenced; assignment to them is not allowed. - -@vtable @code - -@item * -@vindex $* -($*) Expands to the positional parameters, starting from one. -When the expansion is not within double quotes, each positional parameter -expands to a separate word. -In contexts where it is performed, those words -are subject to further word splitting and pathname expansion. -When the expansion occurs within double quotes, it expands to a single word -with the value of each parameter separated by the first character -of the @env{IFS} -special variable. That is, @code{"$*"} is equivalent -to @code{"$1@var{c}$2@var{c}@dots{}"}, where @var{c} -is the first character of the value of the @code{IFS} -variable. -If @env{IFS} is unset, the parameters are separated by spaces. -If @env{IFS} is null, the parameters are joined without intervening -separators. - -@item @@ -@vindex $@@ -($@@) Expands to the positional parameters, starting from one. When the -expansion occurs within double quotes, each parameter expands to a -separate word. That is, @code{"$@@"} is equivalent to -@code{"$1" "$2" @dots{}}. -If the double-quoted expansion occurs within a word, the expansion of -the first parameter is joined with the beginning part of the original -word, and the expansion of the last parameter is joined with the last -part of the original word. -When there are no positional parameters, @code{"$@@"} and -@code{$@@} -expand to nothing (i.e., they are removed). - -@item # -@vindex $# -($#) Expands to the number of positional parameters in decimal. - -@item ? -@vindex $? -($?) Expands to the exit status of the most recently executed foreground -pipeline. - -@item - -@vindex $- -($-, a hyphen.) Expands to the current option flags as specified upon -invocation, by the @code{set} -builtin command, or those set by the shell itself -(such as the @option{-i} option). - -@item $ -@vindex $$ -($$) Expands to the process @sc{id} of the shell. In a @code{()} subshell, it -expands to the process @sc{id} of the invoking shell, not the subshell. - -@item ! -@vindex $! -($!) Expands to the process @sc{id} of the job most recently placed into the -background, whether executed as an asynchronous command or using -the @code{bg} builtin (@pxref{Job Control Builtins}). - -@item 0 -@vindex $0 -($0) Expands to the name of the shell or shell script. This is set at -shell initialization. If Bash is invoked with a file of commands -(@pxref{Shell Scripts}), @code{$0} is set to the name of that file. -If Bash is started with the @option{-c} option (@pxref{Invoking Bash}), -then @code{$0} is set to the first argument after the string to be -executed, if one is present. Otherwise, it is set -to the filename used to invoke Bash, as given by argument zero. - -@item _ -@vindex $_ -($_, an underscore.) -At shell startup, set to the absolute pathname used to invoke the -shell or shell script being executed as passed in the environment -or argument list. -Subsequently, expands to the last argument to the previous command, -after expansion. -Also set to the full pathname used to invoke each command executed -and placed in the environment exported to that command. -When checking mail, this parameter holds the name of the mail file. -@end vtable - -@node Shell Expansions -@section Shell Expansions -@cindex expansion - -Expansion is performed on the command line after it has been split into -@code{token}s. There are seven kinds of expansion performed: - -@itemize @bullet -@item brace expansion -@item tilde expansion -@item parameter and variable expansion -@item command substitution -@item arithmetic expansion -@item word splitting -@item filename expansion -@end itemize - -@menu -* Brace Expansion:: Expansion of expressions within braces. -* Tilde Expansion:: Expansion of the ~ character. -* Shell Parameter Expansion:: How Bash expands variables to their values. -* Command Substitution:: Using the output of a command as an argument. -* Arithmetic Expansion:: How to use arithmetic in shell expansions. -* Process Substitution:: A way to write and read to and from a - command. -* Word Splitting:: How the results of expansion are split into separate - arguments. -* Filename Expansion:: A shorthand for specifying filenames matching patterns. -* Quote Removal:: How and when quote characters are removed from - words. -@end menu - -The order of expansions is: -brace expansion; -tilde expansion, parameter and variable expansion, arithmetic expansion, -and command substitution (done in a left-to-right fashion); -word splitting; -and filename expansion. - -On systems that can support it, there is an additional expansion -available: @var{process substitution}. -This is performed at the -same time as tilde, parameter, variable, and arithmetic expansion and -command substitution. - -Only brace expansion, word splitting, and filename expansion -can change the number of words of the expansion; other expansions -expand a single word to a single word. -The only exceptions to this are the expansions of -@code{"$@@"} (@pxref{Special Parameters}) and @code{"$@{@var{name}[@@]@}"} -(@pxref{Arrays}). - -After all expansions, @code{quote removal} (@pxref{Quote Removal}) -is performed. - -@node Brace Expansion -@subsection Brace Expansion -@cindex brace expansion -@cindex expansion, brace - -Brace expansion is a mechanism by which arbitrary strings may be generated. -This mechanism is similar to -@var{filename expansion} (@pxref{Filename Expansion}), -but the filenames generated need not exist. -Patterns to be brace expanded take the form of an optional @var{preamble}, -followed by either a series of comma-separated strings or a sequence expression -between a pair of braces, -followed by an optional @var{postscript}. -The preamble is prefixed to each string contained within the braces, and -the postscript is then appended to each resulting string, expanding left -to right. - -Brace expansions may be nested. -The results of each expanded string are not sorted; left to right order -is preserved. -For example, -@example -bash$ echo a@{d,c,b@}e -ade ace abe -@end example - -A sequence expression takes the form @code{@{@var{x}..@var{y}[..@var{incr}]@}}, -where @var{x} and @var{y} are either integers or single characters, -and @var{incr}, an optional increment, is an integer. -When integers are supplied, the expression expands to each number between -@var{x} and @var{y}, inclusive. -Supplied integers may be prefixed with @samp{0} to force each term to have the -same width. -When either @var{x} or @var{y} begins with a zero, the shell -attempts to force all generated terms to contain the same number of digits, -zero-padding where necessary. -When characters are supplied, the expression expands to each character -lexicographically between @var{x} and @var{y}, inclusive, -using the default C locale. -Note that both @var{x} and @var{y} must be of the same type. -When the increment is supplied, it is used as the difference between -each term. The default increment is 1 or -1 as appropriate. - -Brace expansion is performed before any other expansions, -and any characters special to other expansions are preserved -in the result. It is strictly textual. Bash -does not apply any syntactic interpretation to the context of the -expansion or the text between the braces. -To avoid conflicts with parameter expansion, the string @samp{$@{} -is not considered eligible for brace expansion. - -A correctly-formed brace expansion must contain unquoted opening -and closing braces, and at least one unquoted comma or a valid -sequence expression. -Any incorrectly formed brace expansion is left unchanged. - -A @{ or @samp{,} may be quoted with a backslash to prevent its -being considered part of a brace expression. -To avoid conflicts with parameter expansion, the string @samp{$@{} -is not considered eligible for brace expansion. - -This construct is typically used as shorthand when the common -prefix of the strings to be generated is longer than in the -above example: -@example -mkdir /usr/local/src/bash/@{old,new,dist,bugs@} -@end example -or -@example -chown root /usr/@{ucb/@{ex,edit@},lib/@{ex?.?*,how_ex@}@} -@end example - -@node Tilde Expansion -@subsection Tilde Expansion -@cindex tilde expansion -@cindex expansion, tilde - -If a word begins with an unquoted tilde character (@samp{~}), all of the -characters up to the first unquoted slash (or all characters, -if there is no unquoted slash) are considered a @var{tilde-prefix}. -If none of the characters in the tilde-prefix are quoted, the -characters in the tilde-prefix following the tilde are treated as a -possible @var{login name}. -If this login name is the null string, the tilde is replaced with the -value of the @env{HOME} shell variable. -If @env{HOME} is unset, the home directory of the user executing the -shell is substituted instead. -Otherwise, the tilde-prefix is replaced with the home directory -associated with the specified login name. - -If the tilde-prefix is @samp{~+}, the value of -the shell variable @env{PWD} replaces the tilde-prefix. -If the tilde-prefix is @samp{~-}, the value of the shell variable -@env{OLDPWD}, if it is set, is substituted. - -If the characters following the tilde in the tilde-prefix consist of a -number @var{N}, optionally prefixed by a @samp{+} or a @samp{-}, -the tilde-prefix is replaced with the -corresponding element from the directory stack, as it would be displayed -by the @code{dirs} builtin invoked with the characters following tilde -in the tilde-prefix as an argument (@pxref{The Directory Stack}). -If the tilde-prefix, sans the tilde, consists of a number without a -leading @samp{+} or @samp{-}, @samp{+} is assumed. - -If the login name is invalid, or the tilde expansion fails, the word is -left unchanged. - -Each variable assignment is checked for unquoted tilde-prefixes immediately -following a @samp{:} or the first @samp{=}. -In these cases, tilde expansion is also performed. -Consequently, one may use filenames with tildes in assignments to -@env{PATH}, @env{MAILPATH}, and @env{CDPATH}, -and the shell assigns the expanded value. - -The following table shows how Bash treats unquoted tilde-prefixes: - -@table @code -@item ~ -The value of @code{$HOME} -@item ~/foo -@file{$HOME/foo} - -@item ~fred/foo -The subdirectory @code{foo} of the home directory of the user -@code{fred} - -@item ~+/foo -@file{$PWD/foo} - -@item ~-/foo -@file{$@{OLDPWD-'~-'@}/foo} - -@item ~@var{N} -The string that would be displayed by @samp{dirs +@var{N}} - -@item ~+@var{N} -The string that would be displayed by @samp{dirs +@var{N}} - -@item ~-@var{N} -The string that would be displayed by @samp{dirs -@var{N}} -@end table - -@node Shell Parameter Expansion -@subsection Shell Parameter Expansion -@cindex parameter expansion -@cindex expansion, parameter - -The @samp{$} character introduces parameter expansion, -command substitution, or arithmetic expansion. The parameter name -or symbol to be expanded may be enclosed in braces, which -are optional but serve to protect the variable to be expanded from -characters immediately following it which could be -interpreted as part of the name. - -When braces are used, the matching ending brace is the first @samp{@}} -not escaped by a backslash or within a quoted string, and not within an -embedded arithmetic expansion, command substitution, or parameter -expansion. - -The basic form of parameter expansion is $@{@var{parameter}@}. -The value of @var{parameter} is substituted. -The @var{parameter} is a shell parameter as described above -(@pxref{Shell Parameters}) or an array reference (@pxref{Arrays}). -The braces are required when @var{parameter} -is a positional parameter with more than one digit, -or when @var{parameter} is followed by a character that is not to be -interpreted as part of its name. - -If the first character of @var{parameter} is an exclamation point (!), -it introduces a level of variable indirection. -Bash uses the value of the variable formed from the rest of -@var{parameter} as the name of the variable; this variable is then -expanded and that value is used in the rest of the substitution, rather -than the value of @var{parameter} itself. -This is known as @code{indirect expansion}. -The exceptions to this are the expansions of $@{!@var{prefix}*@} -and $@{!@var{name}[@@]@} -described below. -The exclamation point must immediately follow the left brace in order to -introduce indirection. - -In each of the cases below, @var{word} is subject to tilde expansion, -parameter expansion, command substitution, and arithmetic expansion. - -When not performing substring expansion, using the form described -below (e.g., @samp{:-}), Bash tests for a parameter that is unset or null. -Omitting the colon results in a test only for a parameter that is unset. -Put another way, if the colon is included, -the operator tests for both @var{parameter}'s existence and that its value -is not null; if the colon is omitted, the operator tests only for existence. - -@table @code - -@item $@{@var{parameter}:@minus{}@var{word}@} -If @var{parameter} is unset or null, the expansion of -@var{word} is substituted. Otherwise, the value of -@var{parameter} is substituted. - -@item $@{@var{parameter}:=@var{word}@} -If @var{parameter} -is unset or null, the expansion of @var{word} -is assigned to @var{parameter}. -The value of @var{parameter} is then substituted. -Positional parameters and special parameters may not be assigned to -in this way. - -@item $@{@var{parameter}:?@var{word}@} -If @var{parameter} -is null or unset, the expansion of @var{word} (or a message -to that effect if @var{word} -is not present) is written to the standard error and the shell, if it -is not interactive, exits. Otherwise, the value of @var{parameter} is -substituted. - -@item $@{@var{parameter}:+@var{word}@} -If @var{parameter} -is null or unset, nothing is substituted, otherwise the expansion of -@var{word} is substituted. - -@item $@{@var{parameter}:@var{offset}@} -@itemx $@{@var{parameter}:@var{offset}:@var{length}@} -This is referred to as Substring Expansion. -It expands to up to @var{length} characters of the value of @var{parameter} -starting at the character specified by @var{offset}. -If @var{parameter} is @samp{@@}, an indexed array subscripted by -@samp{@@} or @samp{*}, or an associative array name, the results differ as -described below. -If @var{length} is omitted, it expands to the substring of the value of -@var{parameter} starting at the character specified by @var{offset} -and extending to the end of the value. -@var{length} and @var{offset} are arithmetic expressions -(@pxref{Shell Arithmetic}). - -If @var{offset} evaluates to a number less than zero, the value -is used as an offset in characters -from the end of the value of @var{parameter}. -If @var{length} evaluates to a number less than zero, -it is interpreted as an offset in characters -from the end of the value of @var{parameter} rather than -a number of characters, and the expansion is the characters between -@var{offset} and that result. -Note that a negative offset must be separated from the colon by at least -one space to avoid being confused with the @samp{:-} expansion. - -Here are some examples illustrating substring expansion on parameters and -subscripted arrays: - -@verbatim -$ string=01234567890abcdefgh -$ echo ${string:7} -7890abcdefgh -$ echo ${string:7:0} - -$ echo ${string:7:2} -78 -$ echo ${string:7:-2} -7890abcdef -$ echo ${string: -7} -bcdefgh -$ echo ${string: -7:0} - -$ echo ${string: -7:2} -bc -$ echo ${string: -7:-2} -bcdef -$ set -- 01234567890abcdefgh -$ echo ${1:7} -7890abcdefgh -$ echo ${1:7:0} - -$ echo ${1:7:2} -78 -$ echo ${1:7:-2} -7890abcdef -$ echo ${1: -7} -bcdefgh -$ echo ${1: -7:0} - -$ echo ${1: -7:2} -bc -$ echo ${1: -7:-2} -bcdef -$ array[0]=01234567890abcdefgh -$ echo ${array[0]:7} -7890abcdefgh -$ echo ${array[0]:7:0} - -$ echo ${array[0]:7:2} -78 -$ echo ${array[0]:7:-2} -7890abcdef -$ echo ${array[0]: -7} -bcdefgh -$ echo ${array[0]: -7:0} - -$ echo ${array[0]: -7:2} -bc -$ echo ${array[0]: -7:-2} -bcdef -@end verbatim - -If @var{parameter} is @samp{@@}, the result is @var{length} positional -parameters beginning at @var{offset}. -A negative @var{offset} is taken relative to one greater than the greatest -positional parameter, so an offset of -1 evaluates to the last positional -parameter. -It is an expansion error if @var{length} evaluates to a number less than zero. - -The following examples illustrate substring expansion using positional -parameters: - -@verbatim -$ set -- 1 2 3 4 5 6 7 8 9 0 a b c d e f g h -$ echo ${@:7} -7 8 9 0 a b c d e f g h -$ echo ${@:7:0} - -$ echo ${@:7:2} -7 8 -$ echo ${@:7:-2} -bash: -2: substring expression < 0 -$ echo ${@: -7:2} -b c -$ echo ${@:0} -./bash 1 2 3 4 5 6 7 8 9 0 a b c d e f g h -$ echo ${@:0:2} -./bash 1 -$ echo ${@: -7:0} - -@end verbatim - -If @var{parameter} is an indexed array name subscripted -by @samp{@@} or @samp{*}, the result is the @var{length} -members of the array beginning with @code{$@{@var{parameter}[@var{offset}]@}}. -A negative @var{offset} is taken relative to one greater than the maximum -index of the specified array. -It is an expansion error if @var{length} evaluates to a number less than zero. - -These examples show how you can use substring expansion with indexed -arrays: - -@verbatim -$ array=(0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h) -$ echo ${array[@]:7} -7 8 9 0 a b c d e f g h -$ echo ${array[@]:7:2} -7 8 -$ echo ${array[@]: -7:2} -b c -$ echo ${array[@]: -7:-2} -bash: -2: substring expression < 0 -$ echo ${array[@]:0} -0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h -$ echo ${array[@]:0:2} -0 1 -$ echo ${array[@]: -7:0} - -@end verbatim - -Substring expansion applied to an associative array produces undefined -results. - -Substring indexing is zero-based unless the positional parameters -are used, in which case the indexing starts at 1 by default. -If @var{offset} is 0, and the positional parameters are used, @code{$@@} is -prefixed to the list. - -@item $@{!@var{prefix}*@} -@itemx $@{!@var{prefix}@@@} -Expands to the names of variables whose names begin with @var{prefix}, -separated by the first character of the @env{IFS} special variable. -When @samp{@@} is used and the expansion appears within double quotes, each -variable name expands to a separate word. - -@item $@{!@var{name}[@@]@} -@itemx $@{!@var{name}[*]@} -If @var{name} is an array variable, expands to the list of array indices -(keys) assigned in @var{name}. -If @var{name} is not an array, expands to 0 if @var{name} is set and null -otherwise. -When @samp{@@} is used and the expansion appears within double quotes, each -key expands to a separate word. - -@item $@{#@var{parameter}@} -The length in characters of the expanded value of @var{parameter} is -substituted. -If @var{parameter} is @samp{*} or @samp{@@}, the value substituted -is the number of positional parameters. -If @var{parameter} is an array name subscripted by @samp{*} or @samp{@@}, -the value substituted is the number of elements in the array. -If @var{parameter} -is an indexed array name subscripted by a negative number, that number is -interpreted as relative to one greater than the maximum index of -@var{parameter}, so negative indices count back from the end of the -array, and an index of -1 references the last element. - -@item $@{@var{parameter}#@var{word}@} -@itemx $@{@var{parameter}##@var{word}@} -The @var{word} -is expanded to produce a pattern just as in filename -expansion (@pxref{Filename Expansion}). If the pattern matches -the beginning of the expanded value of @var{parameter}, -then the result of the expansion is the expanded value of @var{parameter} -with the shortest matching pattern (the @samp{#} case) or the -longest matching pattern (the @samp{##} case) deleted. -If @var{parameter} is @samp{@@} or @samp{*}, -the pattern removal operation is applied to each positional -parameter in turn, and the expansion is the resultant list. -If @var{parameter} is an array variable subscripted with -@samp{@@} or @samp{*}, -the pattern removal operation is applied to each member of the -array in turn, and the expansion is the resultant list. - -@item $@{@var{parameter}%@var{word}@} -@itemx $@{@var{parameter}%%@var{word}@} -The @var{word} is expanded to produce a pattern just as in -filename expansion. -If the pattern matches a trailing portion of the expanded value of -@var{parameter}, then the result of the expansion is the value of -@var{parameter} with the shortest matching pattern (the @samp{%} case) -or the longest matching pattern (the @samp{%%} case) deleted. -If @var{parameter} is @samp{@@} or @samp{*}, -the pattern removal operation is applied to each positional -parameter in turn, and the expansion is the resultant list. -If @var{parameter} -is an array variable subscripted with @samp{@@} or @samp{*}, -the pattern removal operation is applied to each member of the -array in turn, and the expansion is the resultant list. - -@item $@{@var{parameter}/@var{pattern}/@var{string}@} - -The @var{pattern} is expanded to produce a pattern just as in -filename expansion. -@var{Parameter} is expanded and the longest match of @var{pattern} -against its value is replaced with @var{string}. -If @var{pattern} begins with @samp{/}, all matches of @var{pattern} are -replaced with @var{string}. Normally only the first match is replaced. -If @var{pattern} begins with @samp{#}, it must match at the beginning -of the expanded value of @var{parameter}. -If @var{pattern} begins with @samp{%}, it must match at the end -of the expanded value of @var{parameter}. -If @var{string} is null, matches of @var{pattern} are deleted -and the @code{/} following @var{pattern} may be omitted. -If @var{parameter} is @samp{@@} or @samp{*}, -the substitution operation is applied to each positional -parameter in turn, and the expansion is the resultant list. -If @var{parameter} -is an array variable subscripted with @samp{@@} or @samp{*}, -the substitution operation is applied to each member of the -array in turn, and the expansion is the resultant list. - -@item $@{@var{parameter}^@var{pattern}@} -@itemx $@{@var{parameter}^^@var{pattern}@} -@itemx $@{@var{parameter},@var{pattern}@} -@itemx $@{@var{parameter},,@var{pattern}@} -This expansion modifies the case of alphabetic characters in @var{parameter}. -The @var{pattern} is expanded to produce a pattern just as in -filename expansion. -Each character in the expanded value of @var{parameter} is tested against -@var{pattern}, and, if it matches the pattern, its case is converted. -The pattern should not attempt to match more than one character. -The @samp{^} operator converts lowercase letters matching @var{pattern} -to uppercase; the @samp{,} operator converts matching uppercase letters -to lowercase. -The @samp{^^} and @samp{,,} expansions convert each matched character in the -expanded value; the @samp{^} and @samp{,} expansions match and convert only -the first character in the expanded value. -If @var{pattern} is omitted, it is treated like a @samp{?}, which matches -every character. -If @var{parameter} is @samp{@@} or @samp{*}, -the case modification operation is applied to each positional -parameter in turn, and the expansion is the resultant list. -If @var{parameter} -is an array variable subscripted with @samp{@@} or @samp{*}, -the case modification operation is applied to each member of the -array in turn, and the expansion is the resultant list. -@end table - -@node Command Substitution -@subsection Command Substitution -@cindex command substitution - -Command substitution allows the output of a command to replace -the command itself. -Command substitution occurs when a command is enclosed as follows: -@example -$(@var{command}) -@end example -@noindent -or -@example -`@var{command}` -@end example - -@noindent -Bash performs the expansion by executing @var{command} and -replacing the command substitution with the standard output of the -command, with any trailing newlines deleted. -Embedded newlines are not deleted, but they may be removed during -word splitting. -The command substitution @code{$(cat @var{file})} can be -replaced by the equivalent but faster @code{$(< @var{file})}. - -When the old-style backquote form of substitution is used, -backslash retains its literal meaning except when followed by -@samp{$}, @samp{`}, or @samp{\}. -The first backquote not preceded by a backslash terminates the -command substitution. -When using the @code{$(@var{command})} form, all characters between -the parentheses make up the command; none are treated specially. - -Command substitutions may be nested. To nest when using the backquoted -form, escape the inner backquotes with backslashes. - -If the substitution appears within double quotes, word splitting and -filename expansion are not performed on the results. - -@node Arithmetic Expansion -@subsection Arithmetic Expansion -@cindex expansion, arithmetic -@cindex arithmetic expansion - -Arithmetic expansion allows the evaluation of an arithmetic expression -and the substitution of the result. The format for arithmetic expansion is: - -@example -$(( @var{expression} )) -@end example - -The expression is treated as if it were within double quotes, but -a double quote inside the parentheses is not treated specially. -All tokens in the expression undergo parameter and variable expansion, -command substitution, and quote removal. -The result is treated as the arithmetic expression to be evaluated. -Arithmetic expansions may be nested. - -The evaluation is performed according to the rules listed below -(@pxref{Shell Arithmetic}). -If the expression is invalid, Bash prints a message indicating -failure to the standard error and no substitution occurs. - -@node Process Substitution -@subsection Process Substitution -@cindex process substitution - -Process substitution is supported on systems that support named -pipes (@sc{fifo}s) or the @file{/dev/fd} method of naming open files. -It takes the form of -@example -<(@var{list}) -@end example -@noindent -or -@example ->(@var{list}) -@end example -@noindent -The process @var{list} is run with its input or output connected to a -@sc{fifo} or some file in @file{/dev/fd}. The name of this file is -passed as an argument to the current command as the result of the -expansion. If the @code{>(@var{list})} form is used, writing to -the file will provide input for @var{list}. If the -@code{<(@var{list})} form is used, the file passed as an -argument should be read to obtain the output of @var{list}. -Note that no space may appear between the @code{<} or @code{>} -and the left parenthesis, otherwise the construct would be interpreted -as a redirection. - -When available, process substitution is performed simultaneously with -parameter and variable expansion, command substitution, and arithmetic -expansion. - -@node Word Splitting -@subsection Word Splitting -@cindex word splitting - -The shell scans the results of parameter expansion, command substitution, -and arithmetic expansion that did not occur within double quotes for -word splitting. - -The shell treats each character of @env{$IFS} as a delimiter, and splits -the results of the other expansions into words using these characters -as field terminators. -If @env{IFS} is unset, or its value is exactly @code{<space><tab><newline>}, -the default, then sequences of -@code{ <space>}, @code{<tab>}, and @code{<newline>} -at the beginning and end of the results of the previous -expansions are ignored, and any sequence of @env{IFS} -characters not at the beginning or end serves to delimit words. -If @env{IFS} has a value other than the default, then sequences of -the whitespace characters @code{space} and @code{tab} -are ignored at the beginning and end of the -word, as long as the whitespace character is in the -value of @env{IFS} (an @env{IFS} whitespace character). -Any character in @env{IFS} that is not @env{IFS} -whitespace, along with any adjacent @env{IFS} -whitespace characters, delimits a field. A sequence of @env{IFS} -whitespace characters is also treated as a delimiter. -If the value of @env{IFS} is null, no word splitting occurs. - -Explicit null arguments (@code{""} or @code{''}) are retained. -Unquoted implicit null arguments, resulting from the expansion of -parameters that have no values, are removed. -If a parameter with no value is expanded within double quotes, a -null argument results and is retained. - -Note that if no expansion occurs, no splitting -is performed. - -@node Filename Expansion -@subsection Filename Expansion -@menu -* Pattern Matching:: How the shell matches patterns. -@end menu -@cindex expansion, filename -@cindex expansion, pathname -@cindex filename expansion -@cindex pathname expansion - -After word splitting, unless the @option{-f} option has been set -(@pxref{The Set Builtin}), Bash scans each word for the characters -@samp{*}, @samp{?}, and @samp{[}. -If one of these characters appears, then the word is -regarded as a @var{pattern}, -and replaced with an alphabetically sorted list of -filenames matching the pattern (@pxref{Pattern Matching}). -If no matching filenames are found, -and the shell option @code{nullglob} is disabled, the word is left -unchanged. -If the @code{nullglob} option is set, and no matches are found, the word -is removed. -If the @code{failglob} shell option is set, and no matches are found, -an error message is printed and the command is not executed. -If the shell option @code{nocaseglob} is enabled, the match is performed -without regard to the case of alphabetic characters. - -When a pattern is used for filename expansion, the character @samp{.} -at the start of a filename or immediately following a slash -must be matched explicitly, unless the shell option @code{dotglob} is set. -When matching a filename, the slash character must always be -matched explicitly. -In other cases, the @samp{.} character is not treated specially. - -See the description of @code{shopt} in @ref{The Shopt Builtin}, -for a description of the @code{nocaseglob}, @code{nullglob}, -@code{failglob}, and @code{dotglob} options. - -The @env{GLOBIGNORE} -shell variable may be used to restrict the set of filenames matching a -pattern. If @env{GLOBIGNORE} -is set, each matching filename that also matches one of the patterns in -@env{GLOBIGNORE} is removed from the list of matches. The filenames -@file{.} and @file{..} -are always ignored when @env{GLOBIGNORE} -is set and not null. -However, setting @env{GLOBIGNORE} to a non-null value has the effect of -enabling the @code{dotglob} -shell option, so all other filenames beginning with a -@samp{.} will match. -To get the old behavior of ignoring filenames beginning with a -@samp{.}, make @samp{.*} one of the patterns in @env{GLOBIGNORE}. -The @code{dotglob} option is disabled when @env{GLOBIGNORE} -is unset. - -@node Pattern Matching -@subsubsection Pattern Matching -@cindex pattern matching -@cindex matching, pattern - -Any character that appears in a pattern, other than the special pattern -characters described below, matches itself. -The @sc{nul} character may not occur in a pattern. -A backslash escapes the following character; the -escaping backslash is discarded when matching. -The special pattern characters must be quoted if they are to be matched -literally. - -The special pattern characters have the following meanings: -@table @code -@item * -Matches any string, including the null string. -When the @code{globstar} shell option is enabled, and @samp{*} is used in -a filename expansion context, two adjacent @samp{*}s used as a single -pattern will match all files and zero or more directories and -subdirectories. -If followed by a @samp{/}, two adjacent @samp{*}s will match only -directories and subdirectories. -@item ? -Matches any single character. -@item [@dots{}] -Matches any one of the enclosed characters. A pair of characters -separated by a hyphen denotes a @var{range expression}; -any character that falls between those two characters, inclusive, -using the current locale's collating sequence and character set, -is matched. If the first character following the -@samp{[} is a @samp{!} or a @samp{^} -then any character not enclosed is matched. A @samp{@minus{}} -may be matched by including it as the first or last character -in the set. A @samp{]} may be matched by including it as the first -character in the set. -The sorting order of characters in range expressions is determined by -the current locale and the values of the -@env{LC_COLLATE} and @env{LC_ALL} shell variables, if set. - -For example, in the default C locale, @samp{[a-dx-z]} is equivalent to -@samp{[abcdxyz]}. Many locales sort characters in dictionary order, and in -these locales @samp{[a-dx-z]} is typically not equivalent to @samp{[abcdxyz]}; -it might be equivalent to @samp{[aBbCcDdxXyYz]}, for example. To obtain -the traditional interpretation of ranges in bracket expressions, you can -force the use of the C locale by setting the @env{LC_COLLATE} or -@env{LC_ALL} environment variable to the value @samp{C}, or enable the -@code{globasciiranges} shell option. - -Within @samp{[} and @samp{]}, @var{character classes} can be specified -using the syntax -@code{[:}@var{class}@code{:]}, where @var{class} is one of the -following classes defined in the @sc{posix} standard: -@example -alnum alpha ascii blank cntrl digit graph lower -print punct space upper word xdigit -@end example -@noindent -A character class matches any character belonging to that class. -The @code{word} character class matches letters, digits, and the character -@samp{_}. - -Within @samp{[} and @samp{]}, an @var{equivalence class} can be -specified using the syntax @code{[=}@var{c}@code{=]}, which -matches all characters with the same collation weight (as defined -by the current locale) as the character @var{c}. - -Within @samp{[} and @samp{]}, the syntax @code{[.}@var{symbol}@code{.]} -matches the collating symbol @var{symbol}. -@end table - -If the @code{extglob} shell option is enabled using the @code{shopt} -builtin, several extended pattern matching operators are recognized. -In the following description, a @var{pattern-list} is a list of one -or more patterns separated by a @samp{|}. -Composite patterns may be formed using one or more of the following -sub-patterns: - -@table @code -@item ?(@var{pattern-list}) -Matches zero or one occurrence of the given patterns. - -@item *(@var{pattern-list}) -Matches zero or more occurrences of the given patterns. - -@item +(@var{pattern-list}) -Matches one or more occurrences of the given patterns. - -@item @@(@var{pattern-list}) -Matches one of the given patterns. - -@item !(@var{pattern-list}) -Matches anything except one of the given patterns. -@end table - -@node Quote Removal -@subsection Quote Removal - -After the preceding expansions, all unquoted occurrences of the -characters @samp{\}, @samp{'}, and @samp{"} that did not -result from one of the above expansions are removed. - -@node Redirections -@section Redirections -@cindex redirection - -Before a command is executed, its input and output -may be @var{redirected} -using a special notation interpreted by the shell. -Redirection allows commands' file handles to be -duplicated, opened, closed, -made to refer to different files, -and can change the files the command reads from and writes to. -Redirection may also be used to modify file handles in the -current shell execution environment. The following redirection -operators may precede or appear anywhere within a -simple command or may follow a command. -Redirections are processed in the order they appear, from -left to right. - -Each redirection that may be preceded by a file descriptor number -may instead be preceded by a word of the form @{@var{varname}@}. -In this case, for each redirection operator except ->&- and <&-, the shell will allocate a file descriptor greater -than 10 and assign it to @{@var{varname}@}. If >&- or <&- is preceded -by @{@var{varname}@}, the value of @var{varname} defines the file -descriptor to close. - -In the following descriptions, if the file descriptor number is -omitted, and the first character of the redirection operator is -@samp{<}, the redirection refers to the standard input (file -descriptor 0). If the first character of the redirection operator -is @samp{>}, the redirection refers to the standard output (file -descriptor 1). - -The word following the redirection operator in the following -descriptions, unless otherwise noted, is subjected to brace expansion, -tilde expansion, parameter expansion, command substitution, arithmetic -expansion, quote removal, filename expansion, and word splitting. -If it expands to more than one word, Bash reports an error. - -Note that the order of redirections is significant. For example, -the command -@example -ls > @var{dirlist} 2>&1 -@end example -@noindent -directs both standard output (file descriptor 1) and standard error -(file descriptor 2) to the file @var{dirlist}, while the command -@example -ls 2>&1 > @var{dirlist} -@end example -@noindent -directs only the standard output to file @var{dirlist}, -because the standard error was made a copy of the standard output -before the standard output was redirected to @var{dirlist}. - -Bash handles several filenames specially when they are used in -redirections, as described in the following table: - -@table @code -@item /dev/fd/@var{fd} -If @var{fd} is a valid integer, file descriptor @var{fd} is duplicated. - -@item /dev/stdin -File descriptor 0 is duplicated. - -@item /dev/stdout -File descriptor 1 is duplicated. - -@item /dev/stderr -File descriptor 2 is duplicated. - -@item /dev/tcp/@var{host}/@var{port} -If @var{host} is a valid hostname or Internet address, and @var{port} -is an integer port number or service name, Bash attempts to open -the corresponding TCP socket. - -@item /dev/udp/@var{host}/@var{port} -If @var{host} is a valid hostname or Internet address, and @var{port} -is an integer port number or service name, Bash attempts to open -the corresponding UDP socket. -@end table - -A failure to open or create a file causes the redirection to fail. - -Redirections using file descriptors greater than 9 should be used with -care, as they may conflict with file descriptors the shell uses -internally. - -@subsection Redirecting Input -Redirection of input causes the file whose name results from -the expansion of @var{word} -to be opened for reading on file descriptor @code{n}, -or the standard input (file descriptor 0) if @code{n} -is not specified. - -The general format for redirecting input is: -@example -[@var{n}]<@var{word} -@end example - -@subsection Redirecting Output -Redirection of output causes the file whose name results from -the expansion of @var{word} -to be opened for writing on file descriptor @var{n}, -or the standard output (file descriptor 1) if @var{n} -is not specified. If the file does not exist it is created; -if it does exist it is truncated to zero size. - -The general format for redirecting output is: -@example -[@var{n}]>[|]@var{word} -@end example - -If the redirection operator is @samp{>}, and the @code{noclobber} -option to the @code{set} builtin has been enabled, the redirection -will fail if the file whose name results from the expansion of -@var{word} exists and is a regular file. -If the redirection operator is @samp{>|}, or the redirection operator is -@samp{>} and the @code{noclobber} option is not enabled, the redirection -is attempted even if the file named by @var{word} exists. - -@subsection Appending Redirected Output -Redirection of output in this fashion -causes the file whose name results from -the expansion of @var{word} -to be opened for appending on file descriptor @var{n}, -or the standard output (file descriptor 1) if @var{n} -is not specified. If the file does not exist it is created. - -The general format for appending output is: -@example -[@var{n}]>>@var{word} -@end example - -@subsection Redirecting Standard Output and Standard Error -This construct allows both the -standard output (file descriptor 1) and -the standard error output (file descriptor 2) -to be redirected to the file whose name is the -expansion of @var{word}. - -There are two formats for redirecting standard output and -standard error: -@example -&>@var{word} -@end example -@noindent -and -@example ->&@var{word} -@end example -@noindent -Of the two forms, the first is preferred. -This is semantically equivalent to -@example ->@var{word} 2>&1 -@end example -When using the second form, @var{word} may not expand to a number or -@samp{-}. If it does, other redirection operators apply -(see Duplicating File Descriptors below) for compatibility reasons. - -@subsection Appending Standard Output and Standard Error -This construct allows both the -standard output (file descriptor 1) and -the standard error output (file descriptor 2) -to be appended to the file whose name is the -expansion of @var{word}. - -The format for appending standard output and standard error is: -@example -&>>@var{word} -@end example -@noindent -This is semantically equivalent to -@example ->>@var{word} 2>&1 -@end example -(see Duplicating File Descriptors below). - -@subsection Here Documents -This type of redirection instructs the shell to read input from the -current source until a line containing only @var{word} -(with no trailing blanks) is seen. All of -the lines read up to that point are then used as the standard -input for a command. - -The format of here-documents is: -@example -<<[@minus{}]@var{word} - @var{here-document} -@var{delimiter} -@end example - -No parameter and variable expansion, command substitution, -arithmetic expansion, or filename expansion is performed on -@var{word}. If any characters in @var{word} are quoted, the -@var{delimiter} is the result of quote removal on @var{word}, -and the lines in the here-document are not expanded. -If @var{word} is unquoted, -all lines of the here-document are subjected to -parameter expansion, command substitution, and arithmetic expansion, -the character sequence @code{\newline} is ignored, and @samp{\} -must be used to quote the characters -@samp{\}, @samp{$}, and @samp{`}. - -If the redirection operator is @samp{<<-}, -then all leading tab characters are stripped from input lines and the -line containing @var{delimiter}. -This allows here-documents within shell scripts to be indented in a -natural fashion. - -@subsection Here Strings -A variant of here documents, the format is: -@example -<<< @var{word} -@end example - -The @var{word} undergoes -brace expansion, tilde expansion, parameter and variable expansion, -command substitution, arithmetic expansion, and quote removal. -Pathname expansion and word splitting are not performed. -The result is supplied as a single string to the command on its -standard input. - -@subsection Duplicating File Descriptors -The redirection operator -@example -[@var{n}]<&@var{word} -@end example -@noindent -is used to duplicate input file descriptors. -If @var{word} -expands to one or more digits, the file descriptor denoted by @var{n} -is made to be a copy of that file descriptor. -If the digits in @var{word} do not specify a file descriptor open for -input, a redirection error occurs. -If @var{word} -evaluates to @samp{-}, file descriptor @var{n} is closed. -If @var{n} is not specified, the standard input (file descriptor 0) is used. - -The operator -@example -[@var{n}]>&@var{word} -@end example -@noindent -is used similarly to duplicate output file descriptors. If -@var{n} is not specified, the standard output (file descriptor 1) is used. -If the digits in @var{word} do not specify a file descriptor open for -output, a redirection error occurs. -If @var{word} -evaluates to @samp{-}, file descriptor @var{n} is closed. -As a special case, if @var{n} is omitted, and @var{word} does not -expand to one or more digits or @samp{-}, the standard output and standard -error are redirected as described previously. - -@subsection Moving File Descriptors -The redirection operator -@example -[@var{n}]<&@var{digit}- -@end example -@noindent -moves the file descriptor @var{digit} to file descriptor @var{n}, -or the standard input (file descriptor 0) if @var{n} is not specified. -@var{digit} is closed after being duplicated to @var{n}. - -Similarly, the redirection operator -@example -[@var{n}]>&@var{digit}- -@end example -@noindent -moves the file descriptor @var{digit} to file descriptor @var{n}, -or the standard output (file descriptor 1) if @var{n} is not specified. - -@subsection Opening File Descriptors for Reading and Writing -The redirection operator -@example -[@var{n}]<>@var{word} -@end example -@noindent -causes the file whose name is the expansion of @var{word} -to be opened for both reading and writing on file descriptor -@var{n}, or on file descriptor 0 if @var{n} -is not specified. If the file does not exist, it is created. - -@node Executing Commands -@section Executing Commands - -@menu -* Simple Command Expansion:: How Bash expands simple commands before - executing them. -* Command Search and Execution:: How Bash finds commands and runs them. -* Command Execution Environment:: The environment in which Bash - executes commands that are not - shell builtins. -* Environment:: The environment given to a command. -* Exit Status:: The status returned by commands and how Bash - interprets it. -* Signals:: What happens when Bash or a command it runs - receives a signal. -@end menu - -@node Simple Command Expansion -@subsection Simple Command Expansion -@cindex command expansion - -When a simple command is executed, the shell performs the following -expansions, assignments, and redirections, from left to right. - -@enumerate -@item -The words that the parser has marked as variable assignments (those -preceding the command name) and redirections are saved for later -processing. - -@item -The words that are not variable assignments or redirections are -expanded (@pxref{Shell Expansions}). -If any words remain after expansion, the first word -is taken to be the name of the command and the remaining words are -the arguments. - -@item -Redirections are performed as described above (@pxref{Redirections}). - -@item -The text after the @samp{=} in each variable assignment undergoes tilde -expansion, parameter expansion, command substitution, arithmetic expansion, -and quote removal before being assigned to the variable. -@end enumerate - -If no command name results, the variable assignments affect the current -shell environment. Otherwise, the variables are added to the environment -of the executed command and do not affect the current shell environment. -If any of the assignments attempts to assign a value to a readonly variable, -an error occurs, and the command exits with a non-zero status. - -If no command name results, redirections are performed, but do not -affect the current shell environment. A redirection error causes the -command to exit with a non-zero status. - -If there is a command name left after expansion, execution proceeds as -described below. Otherwise, the command exits. If one of the expansions -contained a command substitution, the exit status of the command is -the exit status of the last command substitution performed. If there -were no command substitutions, the command exits with a status of zero. - -@node Command Search and Execution -@subsection Command Search and Execution -@cindex command execution -@cindex command search - -After a command has been split into words, if it results in a -simple command and an optional list of arguments, the following -actions are taken. - -@enumerate -@item -If the command name contains no slashes, the shell attempts to -locate it. If there exists a shell function by that name, that -function is invoked as described in @ref{Shell Functions}. - -@item -If the name does not match a function, the shell searches for -it in the list of shell builtins. If a match is found, that -builtin is invoked. - -@item -If the name is neither a shell function nor a builtin, -and contains no slashes, Bash searches each element of -@env{$PATH} for a directory containing an executable file -by that name. Bash uses a hash table to remember the full -pathnames of executable files to avoid multiple @env{PATH} searches -(see the description of @code{hash} in @ref{Bourne Shell Builtins}). -A full search of the directories in @env{$PATH} -is performed only if the command is not found in the hash table. -If the search is unsuccessful, the shell searches for a defined shell -function named @code{command_not_found_handle}. -If that function exists, it is invoked with the original command and -the original command's arguments as its arguments, and the function's -exit status becomes the exit status of the shell. -If that function is not defined, the shell prints an error -message and returns an exit status of 127. - -@item -If the search is successful, or if the command name contains -one or more slashes, the shell executes the named program in -a separate execution environment. -Argument 0 is set to the name given, and the remaining arguments -to the command are set to the arguments supplied, if any. - -@item -If this execution fails because the file is not in executable -format, and the file is not a directory, it is assumed to be a -@var{shell script} and the shell executes it as described in -@ref{Shell Scripts}. - -@item -If the command was not begun asynchronously, the shell waits for -the command to complete and collects its exit status. - -@end enumerate - -@node Command Execution Environment -@subsection Command Execution Environment -@cindex execution environment - -The shell has an @var{execution environment}, which consists of the -following: - -@itemize @bullet -@item -open files inherited by the shell at invocation, as modified by -redirections supplied to the @code{exec} builtin - -@item -the current working directory as set by @code{cd}, @code{pushd}, or -@code{popd}, or inherited by the shell at invocation - -@item -the file creation mode mask as set by @code{umask} or inherited from -the shell's parent - -@item -current traps set by @code{trap} - -@item -shell parameters that are set by variable assignment or with @code{set} -or inherited from the shell's parent in the environment - -@item -shell functions defined during execution or inherited from the shell's -parent in the environment - -@item -options enabled at invocation (either by default or with command-line -arguments) or by @code{set} - -@item -options enabled by @code{shopt} (@pxref{The Shopt Builtin}) - -@item -shell aliases defined with @code{alias} (@pxref{Aliases}) - -@item -various process @sc{id}s, including those of background jobs -(@pxref{Lists}), the value of @code{$$}, and the value of -@env{$PPID} - -@end itemize - -When a simple command other than a builtin or shell function -is to be executed, it -is invoked in a separate execution environment that consists of -the following. Unless otherwise noted, the values are inherited -from the shell. - -@itemize @bullet -@item -the shell's open files, plus any modifications and additions specified -by redirections to the command - -@item -the current working directory - -@item -the file creation mode mask - -@item -shell variables and functions marked for export, along with variables -exported for the command, passed in the environment (@pxref{Environment}) - -@item -traps caught by the shell are reset to the values inherited from the -shell's parent, and traps ignored by the shell are ignored - -@end itemize - -A command invoked in this separate environment cannot affect the -shell's execution environment. - -Command substitution, commands grouped with parentheses, -and asynchronous commands are invoked in a -subshell environment that is a duplicate of the shell environment, -except that traps caught by the shell are reset to the values -that the shell inherited from its parent at invocation. Builtin -commands that are invoked as part of a pipeline are also executed -in a subshell environment. Changes made to the subshell environment -cannot affect the shell's execution environment. - -Subshells spawned to execute command substitutions inherit the value of -the @option{-e} option from the parent shell. When not in @sc{posix} mode, -Bash clears the @option{-e} option in such subshells. - -If a command is followed by a @samp{&} and job control is not active, the -default standard input for the command is the empty file @file{/dev/null}. -Otherwise, the invoked command inherits the file descriptors of the calling -shell as modified by redirections. - -@node Environment -@subsection Environment -@cindex environment - -When a program is invoked it is given an array of strings -called the @var{environment}. -This is a list of name-value pairs, of the form @code{name=value}. - -Bash provides several ways to manipulate the environment. -On invocation, the shell scans its own environment and -creates a parameter for each name found, automatically marking -it for @var{export} -to child processes. Executed commands inherit the environment. -The @code{export} and @samp{declare -x} -commands allow parameters and functions to be added to and -deleted from the environment. If the value of a parameter -in the environment is modified, the new value becomes part -of the environment, replacing the old. The environment -inherited by any executed command consists of the shell's -initial environment, whose values may be modified in the shell, -less any pairs removed by the @code{unset} and @samp{export -n} -commands, plus any additions via the @code{export} and -@samp{declare -x} commands. - -The environment for any simple command -or function may be augmented temporarily by prefixing it with -parameter assignments, as described in @ref{Shell Parameters}. -These assignment statements affect only the environment seen -by that command. - -If the @option{-k} option is set (@pxref{The Set Builtin}), then all -parameter assignments are placed in the environment for a command, -not just those that precede the command name. - -When Bash invokes an external command, the variable @samp{$_} -is set to the full pathname of the command and passed to that -command in its environment. - -@node Exit Status -@subsection Exit Status -@cindex exit status - -The exit status of an executed command is the value returned by the -@var{waitpid} system call or equivalent function. Exit statuses -fall between 0 and 255, though, as explained below, the shell may -use values above 125 specially. Exit statuses from shell builtins and -compound commands are also limited to this range. Under certain -circumstances, the shell will use special values to indicate specific -failure modes. - -For the shell's purposes, a command which exits with a -zero exit status has succeeded. -A non-zero exit status indicates failure. -This seemingly counter-intuitive scheme is used so there -is one well-defined way to indicate success and a variety of -ways to indicate various failure modes. -When a command terminates on a fatal signal whose number is @var{N}, -Bash uses the value 128+@var{N} as the exit status. - -If a command is not found, the child process created to -execute it returns a status of 127. If a command is found -but is not executable, the return status is 126. - -If a command fails because of an error during expansion or redirection, -the exit status is greater than zero. - -The exit status is used by the Bash conditional commands -(@pxref{Conditional Constructs}) and some of the list -constructs (@pxref{Lists}). - -All of the Bash builtins return an exit status of zero if they succeed -and a non-zero status on failure, so they may be used by the -conditional and list constructs. -All builtins return an exit status of 2 to indicate incorrect usage, -generally invalid options or missing arguments. - -@node Signals -@subsection Signals -@cindex signal handling - -When Bash is interactive, in the absence of any traps, it ignores -@code{SIGTERM} (so that @samp{kill 0} does not kill an interactive shell), -and @code{SIGINT} -is caught and handled (so that the @code{wait} builtin is interruptible). -When Bash receives a @code{SIGINT}, it breaks out of any executing loops. -In all cases, Bash ignores @code{SIGQUIT}. -If job control is in effect (@pxref{Job Control}), Bash -ignores @code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}. - -Non-builtin commands started by Bash have signal handlers set to the -values inherited by the shell from its parent. -When job control is not in effect, asynchronous commands -ignore @code{SIGINT} and @code{SIGQUIT} in addition to these inherited -handlers. -Commands run as a result of -command substitution ignore the keyboard-generated job control signals -@code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}. - -The shell exits by default upon receipt of a @code{SIGHUP}. -Before exiting, an interactive shell resends the @code{SIGHUP} to -all jobs, running or stopped. -Stopped jobs are sent @code{SIGCONT} to ensure that they receive -the @code{SIGHUP}. -To prevent the shell from sending the @code{SIGHUP} signal to a -particular job, it should be removed -from the jobs table with the @code{disown} -builtin (@pxref{Job Control Builtins}) or marked -to not receive @code{SIGHUP} using @code{disown -h}. - -If the @code{huponexit} shell option has been set with @code{shopt} -(@pxref{The Shopt Builtin}), Bash sends a @code{SIGHUP} to all jobs when -an interactive login shell exits. - -If Bash is waiting for a command to complete and receives a signal -for which a trap has been set, the trap will not be executed until -the command completes. -When Bash is waiting for an asynchronous -command via the @code{wait} builtin, the reception of a signal for -which a trap has been set will cause the @code{wait} builtin to return -immediately with an exit status greater than 128, immediately after -which the trap is executed. - -@node Shell Scripts -@section Shell Scripts -@cindex shell script - -A shell script is a text file containing shell commands. When such -a file is used as the first non-option argument when invoking Bash, -and neither the @option{-c} nor @option{-s} option is supplied -(@pxref{Invoking Bash}), -Bash reads and executes commands from the file, then exits. This -mode of operation creates a non-interactive shell. The shell first -searches for the file in the current directory, and looks in the -directories in @env{$PATH} if not found there. - -When Bash runs -a shell script, it sets the special parameter @code{0} to the name -of the file, rather than the name of the shell, and the positional -parameters are set to the remaining arguments, if any are given. -If no additional arguments are supplied, the positional parameters -are unset. - -A shell script may be made executable by using the @code{chmod} command -to turn on the execute bit. When Bash finds such a file while -searching the @env{$PATH} for a command, it spawns a subshell to -execute it. In other words, executing -@example -filename @var{arguments} -@end example -@noindent -is equivalent to executing -@example -bash filename @var{arguments} -@end example - -@noindent -if @code{filename} is an executable shell script. -This subshell reinitializes itself, so that the effect is as if a -new shell had been invoked to interpret the script, with the -exception that the locations of commands remembered by the parent -(see the description of @code{hash} in @ref{Bourne Shell Builtins}) -are retained by the child. - -Most versions of Unix make this a part of the operating system's command -execution mechanism. If the first line of a script begins with -the two characters @samp{#!}, the remainder of the line specifies -an interpreter for the program. -Thus, you can specify Bash, @code{awk}, Perl, or some other -interpreter and write the rest of the script file in that language. - -The arguments to the interpreter -consist of a single optional argument following the interpreter -name on the first line of the script file, followed by the name of -the script file, followed by the rest of the arguments. Bash -will perform this action on operating systems that do not handle it -themselves. Note that some older versions of Unix limit the interpreter -name and argument to a maximum of 32 characters. - -Bash scripts often begin with @code{#! /bin/bash} (assuming that -Bash has been installed in @file{/bin}), since this ensures that -Bash will be used to interpret the script, even if it is executed -under another shell. - -@node Shell Builtin Commands -@chapter Shell Builtin Commands - -@menu -* Bourne Shell Builtins:: Builtin commands inherited from the Bourne - Shell. -* Bash Builtins:: Table of builtins specific to Bash. -* Modifying Shell Behavior:: Builtins to modify shell attributes and - optional behavior. -* Special Builtins:: Builtin commands classified specially by - POSIX. -@end menu - -Builtin commands are contained within the shell itself. -When the name of a builtin command is used as the first word of -a simple command (@pxref{Simple Commands}), the shell executes -the command directly, without invoking another program. -Builtin commands are necessary to implement functionality impossible -or inconvenient to obtain with separate utilities. - -This section briefly describes the builtins which Bash inherits from -the Bourne Shell, as well as the builtin commands which are unique -to or have been extended in Bash. - -Several builtin commands are described in other chapters: builtin -commands which provide the Bash interface to the job control -facilities (@pxref{Job Control Builtins}), the directory stack -(@pxref{Directory Stack Builtins}), the command history -(@pxref{Bash History Builtins}), and the programmable completion -facilities (@pxref{Programmable Completion Builtins}). - -Many of the builtins have been extended by @sc{posix} or Bash. - -Unless otherwise noted, each builtin command documented as accepting -options preceded by @samp{-} accepts @samp{--} -to signify the end of the options. -The @code{:}, @code{true}, @code{false}, and @code{test} -builtins do not accept options and do not treat @samp{--} specially. -The @code{exit}, @code{logout}, @code{break}, @code{continue}, @code{let}, -and @code{shift} builtins accept and process arguments beginning -with @samp{-} without requiring @samp{--}. -Other builtins that accept arguments but are not specified as accepting -options interpret arguments beginning with @samp{-} as invalid options and -require @samp{--} to prevent this interpretation. - -@node Bourne Shell Builtins -@section Bourne Shell Builtins - -The following shell builtin commands are inherited from the Bourne Shell. -These commands are implemented as specified by the @sc{posix} standard. - -@table @code -@item : @r{(a colon)} -@btindex : -@example -: [@var{arguments}] -@end example - -Do nothing beyond expanding @var{arguments} and performing redirections. -The return status is zero. - -@item . @r{(a period)} -@btindex . -@example -. @var{filename} [@var{arguments}] -@end example - -Read and execute commands from the @var{filename} argument in the -current shell context. If @var{filename} does not contain a slash, -the @env{PATH} variable is used to find @var{filename}. -When Bash is not in @sc{posix} mode, the current directory is searched -if @var{filename} is not found in @env{$PATH}. -If any @var{arguments} are supplied, they become the positional -parameters when @var{filename} is executed. Otherwise the positional -parameters are unchanged. -The return status is the exit status of the last command executed, or -zero if no commands are executed. If @var{filename} is not found, or -cannot be read, the return status is non-zero. -This builtin is equivalent to @code{source}. - -@item break -@btindex break -@example -break [@var{n}] -@end example - -Exit from a @code{for}, @code{while}, @code{until}, or @code{select} loop. -If @var{n} is supplied, the @var{n}th enclosing loop is exited. -@var{n} must be greater than or equal to 1. -The return status is zero unless @var{n} is not greater than or equal to 1. - -@item cd -@btindex cd -@example -cd [-L|[-P [-e]] [-@@] [@var{directory}] -@end example - -Change the current working directory to @var{directory}. -If @var{directory} is not supplied, the value of the @env{HOME} -shell variable is used. -Any additional arguments following @var{directory} are ignored. -If the shell variable -@env{CDPATH} exists, it is used as a search path: -each directory name in @env{CDPATH} is searched for -@var{directory}, with alternative directory names in @env{CDPATH} -separated by a colon (@samp{:}). -If @var{directory} begins with a slash, @env{CDPATH} is not used. - -The @option{-P} option means to not follow symbolic links: symbolic links -are resolved while @code{cd} is traversing @var{directory} and before -processing an instance of @samp{..} in @var{directory}. - -By default, or when the @option{-L} option is supplied, symbolic links -in @var{directory} are resolved after @code{cd} processes an instance -of @samp{..} in @var{directory}. - -If @samp{..} appears in @var{directory}, it is processed by removing the -immediately preceding pathname component, back to a slash or the beginning -of @var{directory}. - -If the @option{-e} option is supplied with @option{-P} -and the current working directory cannot be successfully determined -after a successful directory change, @code{cd} will return an unsuccessful -status. - -On systems that support it, the @option{-@@} option presents the extended -attributes associated with a file as a directory. - -If @var{directory} is @samp{-}, it is converted to @env{$OLDPWD} -before the directory change is attempted. - -If a non-empty directory name from @env{CDPATH} is used, or if -@samp{-} is the first argument, and the directory change is -successful, the absolute pathname of the new working directory is -written to the standard output. - -The return status is zero if the directory is successfully changed, -non-zero otherwise. - -@item continue -@btindex continue -@example -continue [@var{n}] -@end example - -Resume the next iteration of an enclosing @code{for}, @code{while}, -@code{until}, or @code{select} loop. -If @var{n} is supplied, the execution of the @var{n}th enclosing loop -is resumed. -@var{n} must be greater than or equal to 1. -The return status is zero unless @var{n} is not greater than or equal to 1. - -@item eval -@btindex eval -@example -eval [@var{arguments}] -@end example - -The arguments are concatenated together into a single command, which is -then read and executed, and its exit status returned as the exit status -of @code{eval}. -If there are no arguments or only empty arguments, the return status is -zero. - -@item exec -@btindex exec -@example -exec [-cl] [-a @var{name}] [@var{command} [@var{arguments}]] -@end example - -If @var{command} -is supplied, it replaces the shell without creating a new process. -If the @option{-l} option is supplied, the shell places a dash at the -beginning of the zeroth argument passed to @var{command}. -This is what the @code{login} program does. -The @option{-c} option causes @var{command} to be executed with an empty -environment. -If @option{-a} is supplied, the shell passes @var{name} as the zeroth -argument to @var{command}. -If @var{command} -cannot be executed for some reason, a non-interactive shell exits, -unless the @code{execfail} shell option -is enabled. In that case, it returns failure. -An interactive shell returns failure if the file cannot be executed. -If no @var{command} is specified, redirections may be used to affect -the current shell environment. If there are no redirection errors, the -return status is zero; otherwise the return status is non-zero. - -@item exit -@btindex exit -@example -exit [@var{n}] -@end example - -Exit the shell, returning a status of @var{n} to the shell's parent. -If @var{n} is omitted, the exit status is that of the last command executed. -Any trap on @code{EXIT} is executed before the shell terminates. - -@item export -@btindex export -@example -export [-fn] [-p] [@var{name}[=@var{value}]] -@end example - -Mark each @var{name} to be passed to child processes -in the environment. If the @option{-f} option is supplied, the @var{name}s -refer to shell functions; otherwise the names refer to shell variables. -The @option{-n} option means to no longer mark each @var{name} for export. -If no @var{names} are supplied, or if the @option{-p} option is given, a -list of names of all exported variables is displayed. -The @option{-p} option displays output in a form that may be reused as input. -If a variable name is followed by =@var{value}, the value of -the variable is set to @var{value}. - -The return status is zero unless an invalid option is supplied, one of -the names is not a valid shell variable name, or @option{-f} is supplied -with a name that is not a shell function. - -@item getopts -@btindex getopts -@example -getopts @var{optstring} @var{name} [@var{args}] -@end example - -@code{getopts} is used by shell scripts to parse positional parameters. -@var{optstring} contains the option characters to be recognized; if a -character is followed by a colon, the option is expected to have an -argument, which should be separated from it by whitespace. -The colon (@samp{:}) and question mark (@samp{?}) may not be -used as option characters. -Each time it is invoked, @code{getopts} -places the next option in the shell variable @var{name}, initializing -@var{name} if it does not exist, -and the index of the next argument to be processed into the -variable @env{OPTIND}. -@env{OPTIND} is initialized to 1 each time the shell or a shell script -is invoked. -When an option requires an argument, -@code{getopts} places that argument into the variable @env{OPTARG}. -The shell does not reset @env{OPTIND} automatically; it must be manually -reset between multiple calls to @code{getopts} within the same shell -invocation if a new set of parameters is to be used. - -When the end of options is encountered, @code{getopts} exits with a -return value greater than zero. -@env{OPTIND} is set to the index of the first non-option argument, -and @var{name} is set to @samp{?}. - -@code{getopts} -normally parses the positional parameters, but if more arguments are -given in @var{args}, @code{getopts} parses those instead. - -@code{getopts} can report errors in two ways. If the first character of -@var{optstring} is a colon, @var{silent} -error reporting is used. In normal operation, diagnostic messages -are printed when invalid options or missing option arguments are -encountered. -If the variable @env{OPTERR} -is set to 0, no error messages will be displayed, even if the first -character of @code{optstring} is not a colon. - -If an invalid option is seen, -@code{getopts} places @samp{?} into @var{name} and, if not silent, -prints an error message and unsets @env{OPTARG}. -If @code{getopts} is silent, the option character found is placed in -@env{OPTARG} and no diagnostic message is printed. - -If a required argument is not found, and @code{getopts} -is not silent, a question mark (@samp{?}) is placed in @var{name}, -@code{OPTARG} is unset, and a diagnostic message is printed. -If @code{getopts} is silent, then a colon (@samp{:}) is placed in -@var{name} and @env{OPTARG} is set to the option character found. - -@item hash -@btindex hash -@example -hash [-r] [-p @var{filename}] [-dt] [@var{name}] -@end example - -Each time @code{hash} is invoked, it remembers the full pathnames of the -commands specified as @var{name} arguments, -so they need not be searched for on subsequent invocations. -The commands are found by searching through the directories listed in -@env{$PATH}. -Any previously-remembered pathname is discarded. -The @option{-p} option inhibits the path search, and @var{filename} is -used as the location of @var{name}. -The @option{-r} option causes the shell to forget all remembered locations. -The @option{-d} option causes the shell to forget the remembered location -of each @var{name}. -If the @option{-t} option is supplied, the full pathname to which each -@var{name} corresponds is printed. If multiple @var{name} arguments are -supplied with @option{-t} the @var{name} is printed before the hashed -full pathname. -The @option{-l} option causes output to be displayed in a format -that may be reused as input. -If no arguments are given, or if only @option{-l} is supplied, -information about remembered commands is printed. -The return status is zero unless a @var{name} is not found or an invalid -option is supplied. - -@item pwd -@btindex pwd -@example -pwd [-LP] -@end example - -Print the absolute pathname of the current working directory. -If the @option{-P} option is supplied, the pathname printed will not -contain symbolic links. -If the @option{-L} option is supplied, the pathname printed may contain -symbolic links. -The return status is zero unless an error is encountered while -determining the name of the current directory or an invalid option -is supplied. - -@item readonly -@btindex readonly -@example -readonly [-aAf] [-p] [@var{name}[=@var{value}]] @dots{} -@end example - -Mark each @var{name} as readonly. -The values of these names may not be changed by subsequent assignment. -If the @option{-f} option is supplied, each @var{name} refers to a shell -function. -The @option{-a} option means each @var{name} refers to an indexed -array variable; the @option{-A} option means each @var{name} refers -to an associative array variable. -If both options are supplied, @option{-A} takes precedence. -If no @var{name} arguments are given, or if the @option{-p} -option is supplied, a list of all readonly names is printed. -The other options may be used to restrict the output to a subset of -the set of readonly names. -The @option{-p} option causes output to be displayed in a format that -may be reused as input. -If a variable name is followed by =@var{value}, the value of -the variable is set to @var{value}. -The return status is zero unless an invalid option is supplied, one of -the @var{name} arguments is not a valid shell variable or function name, -or the @option{-f} option is supplied with a name that is not a shell function. - -@item return -@btindex return -@example -return [@var{n}] -@end example - -Cause a shell function to stop executing and return the value @var{n} -to its caller. -If @var{n} is not supplied, the return value is the exit status of the -last command executed in the function. -If @code{return} is executed by a trap handler, the last command used to -determine the status is the last command executed before the trap handler. -if @code{return} is executed during a @code{DEBUG} trap, the last command -used to determine the status is the last command executed by the trap -handler before @code{return} was invoked. -@code{return} may also be used to terminate execution of a script -being executed with the @code{.} (@code{source}) builtin, -returning either @var{n} or -the exit status of the last command executed within the script as the exit -status of the script. -If @var{n} is supplied, the return value is its least significant -8 bits. -Any command associated with the @code{RETURN} trap is executed -before execution resumes after the function or script. -The return status is non-zero if @code{return} is supplied a non-numeric -argument or is used outside a function -and not during the execution of a script by @code{.} or @code{source}. - -@item shift -@btindex shift -@example -shift [@var{n}] -@end example - -Shift the positional parameters to the left by @var{n}. -The positional parameters from @var{n}+1 @dots{} @code{$#} are -renamed to @code{$1} @dots{} @code{$#}-@var{n}. -Parameters represented by the numbers @code{$#} to @code{$#}-@var{n}+1 -are unset. -@var{n} must be a non-negative number less than or equal to @code{$#}. -If @var{n} is zero or greater than @code{$#}, the positional parameters -are not changed. -If @var{n} is not supplied, it is assumed to be 1. -The return status is zero unless @var{n} is greater than @code{$#} or -less than zero, non-zero otherwise. - -@item test -@itemx [ -@btindex test -@btindex [ -@example -test @var{expr} -@end example - -Evaluate a conditional express -ion @var{expr} and return a status of 0 -(true) or 1 (false). -Each operator and operand must be a separate argument. -Expressions are composed of the primaries described below in -@ref{Bash Conditional Expressions}. -@code{test} does not accept any options, nor does it accept and ignore -an argument of @option{--} as signifying the end of options. - -When the @code{[} form is used, the last argument to the command must -be a @code{]}. - -Expressions may be combined using the following operators, listed in -decreasing order of precedence. -The evaluation depends on the number of arguments; see below. -Operator precedence is used when there are five or more arguments. - -@table @code -@item ! @var{expr} -True if @var{expr} is false. - -@item ( @var{expr} ) -Returns the value of @var{expr}. -This may be used to override the normal precedence of operators. - -@item @var{expr1} -a @var{expr2} -True if both @var{expr1} and @var{expr2} are true. - -@item @var{expr1} -o @var{expr2} -True if either @var{expr1} or @var{expr2} is true. -@end table - -The @code{test} and @code{[} builtins evaluate conditional -expressions using a set of rules based on the number of arguments. - -@table @asis -@item 0 arguments -The expression is false. - -@item 1 argument -The expression is true if and only if the argument is not null. - -@item 2 arguments -If the first argument is @samp{!}, the expression is true if and -only if the second argument is null. -If the first argument is one of the unary conditional operators -(@pxref{Bash Conditional Expressions}), the expression -is true if the unary test is true. -If the first argument is not a valid unary operator, the expression is -false. - -@item 3 arguments -The following conditions are applied in the order listed. -If the second argument is one of the binary conditional -operators (@pxref{Bash Conditional Expressions}), the -result of the expression is the result of the binary test using the -first and third arguments as operands. -The @samp{-a} and @samp{-o} operators are considered binary operators -when there are three arguments. -If the first argument is @samp{!}, the value is the negation of -the two-argument test using the second and third arguments. -If the first argument is exactly @samp{(} and the third argument is -exactly @samp{)}, the result is the one-argument test of the second -argument. -Otherwise, the expression is false. - -@item 4 arguments -If the first argument is @samp{!}, the result is the negation of -the three-argument expression composed of the remaining arguments. -Otherwise, the expression is parsed and evaluated according to -precedence using the rules listed above. - -@item 5 or more arguments -The expression is parsed and evaluated according to precedence -using the rules listed above. -@end table - -When used with @code{test} or @samp{[}, the @samp{<} and @samp{>} -operators sort lexicographically using ASCII ordering. - -@item times -@btindex times -@example -times -@end example - -Print out the user and system times used by the shell and its children. -The return status is zero. - -@item trap -@btindex trap -@example -trap [-lp] [@var{arg}] [@var{sigspec} @dots{}] -@end example - -The commands in @var{arg} are to be read and executed when the -shell receives signal @var{sigspec}. If @var{arg} is absent (and -there is a single @var{sigspec}) or -equal to @samp{-}, each specified signal's disposition is reset -to the value it had when the shell was started. -If @var{arg} is the null string, then the signal specified by -each @var{sigspec} is ignored by the shell and commands it invokes. -If @var{arg} is not present and @option{-p} has been supplied, -the shell displays the trap commands associated with each @var{sigspec}. -If no arguments are supplied, or -only @option{-p} is given, @code{trap} prints the list of commands -associated with each signal number in a form that may be reused as -shell input. -The @option{-l} option causes the shell to print a list of signal names -and their corresponding numbers. -Each @var{sigspec} is either a signal name or a signal number. -Signal names are case insensitive and the @code{SIG} prefix is optional. - -If a @var{sigspec} -is @code{0} or @code{EXIT}, @var{arg} is executed when the shell exits. -If a @var{sigspec} is @code{DEBUG}, the command @var{arg} is executed -before every simple command, @code{for} command, @code{case} command, -@code{select} command, every arithmetic @code{for} command, and before -the first command executes in a shell function. -Refer to the description of the @code{extdebug} option to the -@code{shopt} builtin (@pxref{The Shopt Builtin}) for details of its -effect on the @code{DEBUG} trap. -If a @var{sigspec} is @code{RETURN}, the command @var{arg} is executed -each time a shell function or a script executed with the @code{.} or -@code{source} builtins finishes executing. - -If a @var{sigspec} is @code{ERR}, the command @var{arg} -is executed whenever -a pipeline (which may consist of a single simple -command), a list, or a compound command returns a -non-zero exit status, -subject to the following conditions. -The @code{ERR} trap is not executed if the failed command is part of the -command list immediately following an @code{until} or @code{while} keyword, -part of the test following the @code{if} or @code{elif} reserved words, -part of a command executed in a @code{&&} or @code{||} list -except the command following the final @code{&&} or @code{||}, -any command in a pipeline but the last, -or if the command's return -status is being inverted using @code{!}. -These are the same conditions obeyed by the @code{errexit} (@option{-e}) -option. - -Signals ignored upon entry to the shell cannot be trapped or reset. -Trapped signals that are not being ignored are reset to their original -values in a subshell or subshell environment when one is created. - -The return status is zero unless a @var{sigspec} does not specify a -valid signal. - -@item umask -@btindex umask -@example -umask [-p] [-S] [@var{mode}] -@end example - -Set the shell process's file creation mask to @var{mode}. If -@var{mode} begins with a digit, it is interpreted as an octal number; -if not, it is interpreted as a symbolic mode mask similar -to that accepted by the @code{chmod} command. If @var{mode} is -omitted, the current value of the mask is printed. If the @option{-S} -option is supplied without a @var{mode} argument, the mask is printed -in a symbolic format. -If the @option{-p} option is supplied, and @var{mode} -is omitted, the output is in a form that may be reused as input. -The return status is zero if the mode is successfully changed or if -no @var{mode} argument is supplied, and non-zero otherwise. - -Note that when the mode is interpreted as an octal number, each number -of the umask is subtracted from @code{7}. Thus, a umask of @code{022} -results in permissions of @code{755}. - -@item unset -@btindex unset -@example -unset [-fnv] [@var{name}] -@end example - -Remove each variable or function @var{name}. -If the @option{-v} option is given, each -@var{name} refers to a shell variable and that variable is remvoved. -If the @option{-f} option is given, the @var{name}s refer to shell -functions, and the function definition is removed. -If the @option{-n} option is supplied, and @var{name} is a variable with -the @var{nameref} attribute, @var{name} will be unset rather than the -variable it references. -@option{-n} has no effect if the @option{-f} option is supplied. -If no options are supplied, each @var{name} refers to a variable; if -there is no variable by that name, any function with that name is -unset. -Readonly variables and functions may not be unset. -The return status is zero unless a @var{name} is readonly. -@end table - -@node Bash Builtins -@section Bash Builtin Commands - -This section describes builtin commands which are unique to -or have been extended in Bash. -Some of these commands are specified in the @sc{posix} standard. - -@table @code - -@item alias -@btindex alias -@example -alias [-p] [@var{name}[=@var{value}] @dots{}] -@end example - -Without arguments or with the @option{-p} option, @code{alias} prints -the list of aliases on the standard output in a form that allows -them to be reused as input. -If arguments are supplied, an alias is defined for each @var{name} -whose @var{value} is given. If no @var{value} is given, the name -and value of the alias is printed. -Aliases are described in @ref{Aliases}. - -@item bind -@btindex bind -@example -bind [-m @var{keymap}] [-lpsvPSVX] -bind [-m @var{keymap}] [-q @var{function}] [-u @var{function}] [-r @var{keyseq}] -bind [-m @var{keymap}] -f @var{filename} -bind [-m @var{keymap}] -x @var{keyseq:shell-command} -bind [-m @var{keymap}] @var{keyseq:function-name} -bind [-m @var{keymap}] @var{keyseq:readline-command} -@end example - -Display current Readline (@pxref{Command Line Editing}) -key and function bindings, -bind a key sequence to a Readline function or macro, -or set a Readline variable. -Each non-option argument is a command as it would appear in a -Readline initialization file (@pxref{Readline Init File}), -but each binding or command must be passed as a separate argument; e.g., -@samp{"\C-x\C-r":re-read-init-file}. - -Options, if supplied, have the following meanings: - -@table @code -@item -m @var{keymap} -Use @var{keymap} as the keymap to be affected by -the subsequent bindings. Acceptable @var{keymap} -names are -@code{emacs}, -@code{emacs-standard}, -@code{emacs-meta}, -@code{emacs-ctlx}, -@code{vi}, -@code{vi-move}, -@code{vi-command}, and -@code{vi-insert}. -@code{vi} is equivalent to @code{vi-command}; -@code{emacs} is equivalent to @code{emacs-standard}. - -@item -l -List the names of all Readline functions. - -@item -p -Display Readline function names and bindings in such a way that they -can be used as input or in a Readline initialization file. - -@item -P -List current Readline function names and bindings. - -@item -v -Display Readline variable names and values in such a way that they -can be used as input or in a Readline initialization file. - -@item -V -List current Readline variable names and values. - -@item -s -Display Readline key sequences bound to macros and the strings they output -in such a way that they can be used as input or in a Readline -initialization file. - -@item -S -Display Readline key sequences bound to macros and the strings they output. - -@item -f @var{filename} -Read key bindings from @var{filename}. - -@item -q @var{function} -Query about which keys invoke the named @var{function}. - -@item -u @var{function} -Unbind all keys bound to the named @var{function}. - -@item -r @var{keyseq} -Remove any current binding for @var{keyseq}. - -@item -x @var{keyseq:shell-command} -Cause @var{shell-command} to be executed whenever @var{keyseq} is -entered. -When @var{shell-command} is executed, the shell sets the -@code{READLINE_LINE} variable to the contents of the Readline line -buffer and the @code{READLINE_POINT} variable to the current location -of the insertion point. -If the executed command changes the value of @code{READLINE_LINE} or -@code{READLINE_POINT}, those new values will be reflected in the -editing state. - -@item -X -List all key sequences bound to shell commands and the associated commands -in a format that can be reused as input. -@end table - -@noindent -The return status is zero unless an invalid option is supplied or an -error occurs. - -@item builtin -@btindex builtin -@example -builtin [@var{shell-builtin} [@var{args}]] -@end example - -Run a shell builtin, passing it @var{args}, and return its exit status. -This is useful when defining a shell function with the same -name as a shell builtin, retaining the functionality of the builtin within -the function. -The return status is non-zero if @var{shell-builtin} is not a shell -builtin command. - -@item caller -@btindex caller -@example -caller [@var{expr}] -@end example - -Returns the context of any active subroutine call (a shell function or -a script executed with the @code{.} or @code{source} builtins). - -Without @var{expr}, @code{caller} displays the line number and source -filename of the current subroutine call. -If a non-negative integer is supplied as @var{expr}, @code{caller} -displays the line number, subroutine name, and source file corresponding -to that position in the current execution call stack. This extra -information may be used, for example, to print a stack trace. The -current frame is frame 0. - -The return value is 0 unless the shell is not executing a subroutine -call or @var{expr} does not correspond to a valid position in the -call stack. - -@item command -@btindex command -@example -command [-pVv] @var{command} [@var{arguments} @dots{}] -@end example - -Runs @var{command} with @var{arguments} ignoring any shell function -named @var{command}. -Only shell builtin commands or commands found by searching the -@env{PATH} are executed. -If there is a shell function named @code{ls}, running @samp{command ls} -within the function will execute the external command @code{ls} -instead of calling the function recursively. -The @option{-p} option means to use a default value for @env{PATH} -that is guaranteed to find all of the standard utilities. -The return status in this case is 127 if @var{command} cannot be -found or an error occurred, and the exit status of @var{command} -otherwise. - -If either the @option{-V} or @option{-v} option is supplied, a -description of @var{command} is printed. The @option{-v} option -causes a single word indicating the command or file name used to -invoke @var{command} to be displayed; the @option{-V} option produces -a more verbose description. In this case, the return status is -zero if @var{command} is found, and non-zero if not. - -@item declare -@btindex declare -@example -declare [-aAfFgilnrtux] [-p] [@var{name}[=@var{value}] @dots{}] -@end example - -Declare variables and give them attributes. If no @var{name}s -are given, then display the values of variables instead. - -The @option{-p} option will display the attributes and values of each -@var{name}. -When @option{-p} is used with @var{name} arguments, additional options, -other than @option{-f} and @option{-F}, are ignored. - -When @option{-p} is supplied without @var{name} arguments, @code{declare} -will display the attributes and values of all variables having the -attributes specified by the additional options. -If no other options are supplied with @option{-p}, @code{declare} will -display the attributes and values of all shell variables. The @option{-f} -option will restrict the display to shell functions. - -The @option{-F} option inhibits the display of function definitions; -only the function name and attributes are printed. -If the @code{extdebug} shell option is enabled using @code{shopt} -(@pxref{The Shopt Builtin}), the source file name and line number where -the function is defined are displayed as well. -@option{-F} implies @option{-f}. - -The @option{-g} option forces variables to be created or modified at -the global scope, even when @code{declare} is executed in a shell function. -It is ignored in all other cases. - -The following options can be used to restrict output to variables with -the specified attributes or to give variables attributes: - -@table @code -@item -a -Each @var{name} is an indexed array variable (@pxref{Arrays}). - -@item -A -Each @var{name} is an associative array variable (@pxref{Arrays}). - -@item -f -Use function names only. - -@item -i -The variable is to be treated as -an integer; arithmetic evaluation (@pxref{Shell Arithmetic}) is -performed when the variable is assigned a value. - -@item -l -When the variable is assigned a value, all upper-case characters are -converted to lower-case. -The upper-case attribute is disabled. - -@item -n -Give each @var{name} the @var{nameref} attribute, making -it a name reference to another variable. -That other variable is defined by the value of @var{name}. -All references, assignments, and attribute modifications -to @var{name}, except for changing the -@option{-n} attribute itself, are performed on the variable referenced by -@var{name}'s value. -The nameref attribute cannot be applied to array variables. - -@item -r -Make @var{name}s readonly. These names cannot then be assigned values -by subsequent assignment statements or unset. - -@item -t -Give each @var{name} the @code{trace} attribute. -Traced functions inherit the @code{DEBUG} and @code{RETURN} traps from -the calling shell. -The trace attribute has no special meaning for variables. - -@item -u -When the variable is assigned a value, all lower-case characters are -converted to upper-case. -The lower-case attribute is disabled. - -@item -x -Mark each @var{name} for export to subsequent commands via -the environment. -@end table - -Using @samp{+} instead of @samp{-} turns off the attribute instead, -with the exceptions that @samp{+a} -may not be used to destroy an array variable and @samp{+r} will not -remove the readonly attribute. -When used in a function, @code{declare} makes each @var{name} local, -as with the @code{local} command, unless the @option{-g} option is used. -If a variable name is followed by =@var{value}, the value of the variable -is set to @var{value}. - -When using @option{-a} or @option{-A} and the compound assignment syntax to -create array variables, additional attributes do not take effect until -subsequent assignments. - -The return status is zero unless an invalid option is encountered, -an attempt is made to define a function using @samp{-f foo=bar}, -an attempt is made to assign a value to a readonly variable, -an attempt is made to assign a value to an array variable without -using the compound assignment syntax (@pxref{Arrays}), -one of the @var{names} is not a valid shell variable name, -an attempt is made to turn off readonly status for a readonly variable, -an attempt is made to turn off array status for an array variable, -or an attempt is made to display a non-existent function with @option{-f}. - -@item echo -@btindex echo -@example -echo [-neE] [@var{arg} @dots{}] -@end example - -Output the @var{arg}s, separated by spaces, terminated with a -newline. -The return status is 0 unless a write error occurs. -If @option{-n} is specified, the trailing newline is suppressed. -If the @option{-e} option is given, interpretation of the following -backslash-escaped characters is enabled. -The @option{-E} option disables the interpretation of these escape characters, -even on systems where they are interpreted by default. -The @code{xpg_echo} shell option may be used to -dynamically determine whether or not @code{echo} expands these -escape characters by default. -@code{echo} does not interpret @option{--} to mean the end of options. - -@code{echo} interprets the following escape sequences: -@table @code -@item \a -alert (bell) -@item \b -backspace -@item \c -suppress further output -@item \e -@itemx \E -escape -@item \f -form feed -@item \n -new line -@item \r -carriage return -@item \t -horizontal tab -@item \v -vertical tab -@item \\ -backslash -@item \0@var{nnn} -the eight-bit character whose value is the octal value @var{nnn} -(zero to three octal digits) -@item \x@var{HH} -the eight-bit character whose value is the hexadecimal value @var{HH} -(one or two hex digits) -@item \u@var{HHHH} -the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value -@var{HHHH} (one to four hex digits) -@item \U@var{HHHHHHHH} -the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value -@var{HHHHHHHH} (one to eight hex digits) -@end table - -@item enable -@btindex enable -@example -enable [-a] [-dnps] [-f @var{filename}] [@var{name} @dots{}] -@end example - -Enable and disable builtin shell commands. -Disabling a builtin allows a disk command which has the same name -as a shell builtin to be executed without specifying a full pathname, -even though the shell normally searches for builtins before disk commands. -If @option{-n} is used, the @var{name}s become disabled. Otherwise -@var{name}s are enabled. For example, to use the @code{test} binary -found via @env{$PATH} instead of the shell builtin version, type -@samp{enable -n test}. - -If the @option{-p} option is supplied, or no @var{name} arguments appear, -a list of shell builtins is printed. With no other arguments, the list -consists of all enabled shell builtins. -The @option{-a} option means to list -each builtin with an indication of whether or not it is enabled. - -The @option{-f} option means to load the new builtin command @var{name} -from shared object @var{filename}, on systems that support dynamic loading. -The @option{-d} option will delete a builtin loaded with @option{-f}. - -If there are no options, a list of the shell builtins is displayed. -The @option{-s} option restricts @code{enable} to the @sc{posix} special -builtins. If @option{-s} is used with @option{-f}, the new builtin becomes -a special builtin (@pxref{Special Builtins}). - -The return status is zero unless a @var{name} is not a shell builtin -or there is an error loading a new builtin from a shared object. - -@item help -@btindex help -@example -help [-dms] [@var{pattern}] -@end example - -Display helpful information about builtin commands. -If @var{pattern} is specified, @code{help} gives detailed help -on all commands matching @var{pattern}, otherwise a list of -the builtins is printed. - -Options, if supplied, have the following meanings: - -@table @code -@item -d -Display a short description of each @var{pattern} -@item -m -Display the description of each @var{pattern} in a manpage-like format -@item -s -Display only a short usage synopsis for each @var{pattern} -@end table - -The return status is zero unless no command matches @var{pattern}. - -@item let -@btindex let -@example -let @var{expression} [@var{expression} @dots{}] -@end example - -The @code{let} builtin allows arithmetic to be performed on shell -variables. Each @var{expression} is evaluated according to the -rules given below in @ref{Shell Arithmetic}. If the -last @var{expression} evaluates to 0, @code{let} returns 1; -otherwise 0 is returned. - -@item local -@btindex local -@example -local [@var{option}] @var{name}[=@var{value}] @dots{} -@end example - -For each argument, a local variable named @var{name} is created, -and assigned @var{value}. -The @var{option} can be any of the options accepted by @code{declare}. -@code{local} can only be used within a function; it makes the variable -@var{name} have a visible scope restricted to that function and its -children. The return status is zero unless @code{local} is used outside -a function, an invalid @var{name} is supplied, or @var{name} is a -readonly variable. - -@item logout -@btindex logout -@example -logout [@var{n}] -@end example - -Exit a login shell, returning a status of @var{n} to the shell's -parent. - -@item mapfile -@btindex mapfile -@example -mapfile [-n @var{count}] [-O @var{origin}] [-s @var{count}] [-t] [-u @var{fd}] - [-C @var{callback}] [-c @var{quantum}] [@var{array}] -@end example - -Read lines from the standard input into the indexed array variable @var{array}, -or from file descriptor @var{fd} -if the @option{-u} option is supplied. -The variable @code{MAPFILE} is the default @var{array}. -Options, if supplied, have the following meanings: - -@table @code - -@item -n -Copy at most @var{count} lines. If @var{count} is 0, all lines are copied. -@item -O -Begin assigning to @var{array} at index @var{origin}. -The default index is 0. -@item -s -Discard the first @var{count} lines read. -@item -t -Remove a trailing newline from each line read. -@item -u -Read lines from file descriptor @var{fd} instead of the standard input. -@item -C -Evaluate @var{callback} each time @var{quantum}P lines are read. -The @option{-c} option specifies @var{quantum}. -@item -c -Specify the number of lines read between each call to @var{callback}. -@end table - -If @option{-C} is specified without @option{-c}, -the default quantum is 5000. -When @var{callback} is evaluated, it is supplied the index of the next -array element to be assigned and the line to be assigned to that element -as additional arguments. -@var{callback} is evaluated after the line is read but before the -array element is assigned. - -If not supplied with an explicit origin, @code{mapfile} will clear @var{array} -before assigning to it. - -@code{mapfile} returns successfully unless an invalid option or option -argument is supplied, @var{array} is invalid or unassignable, or @var{array} -is not an indexed array. - -@item printf -@btindex printf -@example -printf [-v @var{var}] @var{format} [@var{arguments}] -@end example - -Write the formatted @var{arguments} to the standard output under the -control of the @var{format}. -The @option{-v} option causes the output to be assigned to the variable -@var{var} rather than being printed to the standard output. - -The @var{format} is a character string which contains three types of objects: -plain characters, which are simply copied to standard output, character -escape sequences, which are converted and copied to the standard output, and -format specifications, each of which causes printing of the next successive -@var{argument}. -In addition to the standard @code{printf(1)} formats, @code{printf} -interprets the following extensions: - -@table @code -@item %b -Causes @code{printf} to expand backslash escape sequences in the -corresponding @var{argument}, -except that @samp{\c} terminates output, backslashes in -@samp{\'}, @samp{\"}, and @samp{\?} are not removed, and octal escapes -beginning with @samp{\0} may contain up to four digits. -@item %q -Causes @code{printf} to output the -corresponding @var{argument} in a format that can be reused as shell input. -@item %(@var{datefmt})T -Causes @code{printf} to output the date-time string resulting from using -@var{datefmt} as a format string for @code{strftime}(3). -The corresponding @var{argument} is an integer representing the number of -seconds since the epoch. -Two special argument values may be used: -1 represents the current -time, and -2 represents the time the shell was invoked. -If no argument is specified, conversion behaves as if -1 had been given. -This is an exception to the usual @code{printf} behavior. -@end table - -@noindent -Arguments to non-string format specifiers are treated as C language constants, -except that a leading plus or minus sign is allowed, and if the leading -character is a single or double quote, the value is the ASCII value of -the following character. - -The @var{format} is reused as necessary to consume all of the @var{arguments}. -If the @var{format} requires more @var{arguments} than are supplied, the -extra format specifications behave as if a zero value or null string, as -appropriate, had been supplied. The return value is zero on success, -non-zero on failure. - -@item read -@btindex read -@example -read [-ers] [-a @var{aname}] [-d @var{delim}] [-i @var{text}] [-n @var{nchars}] - [-N @var{nchars}] [-p @var{prompt}] [-t @var{timeout}] [-u @var{fd}] [@var{name} @dots{}] -@end example - -One line is read from the standard input, or from the file descriptor -@var{fd} supplied as an argument to the @option{-u} option, and the first word -is assigned to the first @var{name}, the second word to the second @var{name}, -and so on, with leftover words and their intervening separators assigned -to the last @var{name}. -If there are fewer words read from the input stream than names, -the remaining names are assigned empty values. -The characters in the value of the @env{IFS} variable -are used to split the line into words using the same rules the shell -uses for expansion (described above in @ref{Word Splitting}). -The backslash character @samp{\} may be used to remove any special -meaning for the next character read and for line continuation. -If no names are supplied, the line read is assigned to the -variable @env{REPLY}. -The return code is zero, unless end-of-file is encountered, @code{read} -times out (in which case the return code is greater than 128), -a variable assignment error (such as assigning to a readonly variable) occurs, -or an invalid file descriptor is supplied as the argument to @option{-u}. - -Options, if supplied, have the following meanings: - -@table @code -@item -a @var{aname} -The words are assigned to sequential indices of the array variable -@var{aname}, starting at 0. -All elements are removed from @var{aname} before the assignment. -Other @var{name} arguments are ignored. - -@item -d @var{delim} -The first character of @var{delim} is used to terminate the input line, -rather than newline. - -@item -e -Readline (@pxref{Command Line Editing}) is used to obtain the line. -Readline uses the current (or default, if line editing was not previously -active) editing settings. - -@item -i @var{text} -If Readline is being used to read the line, @var{text} is placed into -the editing buffer before editing begins. - -@item -n @var{nchars} -@code{read} returns after reading @var{nchars} characters rather than -waiting for a complete line of input, but honor a delimiter if fewer -than @var{nchars} characters are read before the delimiter. - -@item -N @var{nchars} -@code{read} returns after reading exactly @var{nchars} characters rather -than waiting for a complete line of input, unless EOF is encountered or -@code{read} times out. -Delimiter characters encountered in the input are -not treated specially and do not cause @code{read} to return until -@var{nchars} characters are read. - -@item -p @var{prompt} -Display @var{prompt}, without a trailing newline, before attempting -to read any input. -The prompt is displayed only if input is coming from a terminal. - -@item -r -If this option is given, backslash does not act as an escape character. -The backslash is considered to be part of the line. -In particular, a backslash-newline pair may not be used as a line -continuation. - -@item -s -Silent mode. If input is coming from a terminal, characters are -not echoed. - -@item -t @var{timeout} -Cause @code{read} to time out and return failure if a complete line of -input (or a specified number of characters) -is not read within @var{timeout} seconds. -@var{timeout} may be a decimal number with a fractional portion following -the decimal point. -This option is only effective if @code{read} is reading input from a -terminal, pipe, or other special file; it has no effect when reading -from regular files. -If @code{read} times out, @code{read} saves any partial input read into -the specified variable @var{name}. -If @var{timeout} is 0, @code{read} returns immediately, without trying to -read and data. The exit status is 0 if input is available on -the specified file descriptor, non-zero otherwise. -The exit status is greater than 128 if the timeout is exceeded. - -@item -u @var{fd} -Read input from file descriptor @var{fd}. -@end table - -@item readarray -@btindex readarray -@example -readarray [-n @var{count}] [-O @var{origin}] [-s @var{count}] [-t] [-u @var{fd}] - [-C @var{callback}] [-c @var{quantum}] [@var{array}] -@end example - -Read lines from the standard input into the indexed array variable @var{array}, -or from file descriptor @var{fd} -if the @option{-u} option is supplied. - -A synonym for @code{mapfile}. - -@item source -@btindex source -@example -source @var{filename} -@end example - -A synonym for @code{.} (@pxref{Bourne Shell Builtins}). - -@item type -@btindex type -@example -type [-afptP] [@var{name} @dots{}] -@end example - -For each @var{name}, indicate how it would be interpreted if used as a -command name. - -If the @option{-t} option is used, @code{type} prints a single word -which is one of @samp{alias}, @samp{function}, @samp{builtin}, -@samp{file} or @samp{keyword}, -if @var{name} is an alias, shell function, shell builtin, -disk file, or shell reserved word, respectively. -If the @var{name} is not found, then nothing is printed, and -@code{type} returns a failure status. - -If the @option{-p} option is used, @code{type} either returns the name -of the disk file that would be executed, or nothing if @option{-t} -would not return @samp{file}. - -The @option{-P} option forces a path search for each @var{name}, even if -@option{-t} would not return @samp{file}. - -If a command is hashed, @option{-p} and @option{-P} print the hashed value, -which is not necessarily the file that appears first in @code{$PATH}. - -If the @option{-a} option is used, @code{type} returns all of the places -that contain an executable named @var{file}. -This includes aliases and functions, if and only if the @option{-p} option -is not also used. - -If the @option{-f} option is used, @code{type} does not attempt to find -shell functions, as with the @code{command} builtin. - -The return status is zero if all of the @var{names} are found, non-zero -if any are not found. - -@item typeset -@btindex typeset -@example -typeset [-afFgrxilnrtux] [-p] [@var{name}[=@var{value}] @dots{}] -@end example - -The @code{typeset} command is supplied for compatibility with the Korn -shell. -It is a synonym for the @code{declare} builtin command. - -@item ulimit -@btindex ulimit -@example -ulimit [-abcdefilmnpqrstuvxHST] [@var{limit}] -@end example - -@code{ulimit} provides control over the resources available to processes -started by the shell, on systems that allow such control. If an -option is given, it is interpreted as follows: - -@table @code -@item -S -Change and report the soft limit associated with a resource. - -@item -H -Change and report the hard limit associated with a resource. - -@item -a -All current limits are reported. - -@item -b -The maximum socket buffer size. - -@item -c -The maximum size of core files created. - -@item -d -The maximum size of a process's data segment. - -@item -e -The maximum scheduling priority ("nice"). - -@item -f -The maximum size of files written by the shell and its children. - -@item -i -The maximum number of pending signals. - -@item -l -The maximum size that may be locked into memory. - -@item -m -The maximum resident set size (many systems do not honor this limit). - -@item -n -The maximum number of open file descriptors (most systems do not -allow this value to be set). - -@item -p -The pipe buffer size. - -@item -q -The maximum number of bytes in POSIX message queues. - -@item -r -The maximum real-time scheduling priority. - -@item -s -The maximum stack size. - -@item -t -The maximum amount of cpu time in seconds. - -@item -u -The maximum number of processes available to a single user. - -@item -v -The maximum amount of virtual memory available to the shell, and, on -some systems, to its children. - -@item -x -The maximum number of file locks. - -@item -T -The maximum number of threads. -@end table - -If @var{limit} is given, and the @option{-a} option is not used, -@var{limit} is the new value of the specified resource. -The special @var{limit} values @code{hard}, @code{soft}, and -@code{unlimited} stand for the current hard limit, the current soft limit, -and no limit, respectively. -A hard limit cannot be increased by a non-root user once it is set; -a soft limit may be increased up to the value of the hard limit. -Otherwise, the current value of the soft limit for the specified resource -is printed, unless the @option{-H} option is supplied. -When setting new limits, if neither @option{-H} nor @option{-S} is supplied, -both the hard and soft limits are set. -If no option is given, then @option{-f} is assumed. Values are in 1024-byte -increments, except for @option{-t}, which is in seconds; @option{-p}, -which is in units of 512-byte blocks; and @option{-T}, @option{-b}, -@option{-n} and @option{-u}, which are unscaled values. - -The return status is zero unless an invalid option or argument is supplied, -or an error occurs while setting a new limit. - -@item unalias -@btindex unalias -@example -unalias [-a] [@var{name} @dots{} ] -@end example - -Remove each @var{name} from the list of aliases. If @option{-a} is -supplied, all aliases are removed. -Aliases are described in @ref{Aliases}. -@end table - -@node Modifying Shell Behavior -@section Modifying Shell Behavior - -@menu -* The Set Builtin:: Change the values of shell attributes and - positional parameters. -* The Shopt Builtin:: Modify shell optional behavior. -@end menu - -@node The Set Builtin -@subsection The Set Builtin - -This builtin is so complicated that it deserves its own section. @code{set} -allows you to change the values of shell options and set the positional -parameters, or to display the names and values of shell variables. - -@table @code -@item set -@btindex set -@example -set [--abefhkmnptuvxBCEHPT] [-o @var{option-name}] [@var{argument} @dots{}] -set [+abefhkmnptuvxBCEHPT] [+o @var{option-name}] [@var{argument} @dots{}] -@end example - -If no options or arguments are supplied, @code{set} displays the names -and values of all shell variables and functions, sorted according to the -current locale, in a format that may be reused as input -for setting or resetting the currently-set variables. -Read-only variables cannot be reset. -In @sc{posix} mode, only shell variables are listed. - -When options are supplied, they set or unset shell attributes. -Options, if specified, have the following meanings: - -@table @code -@item -a -Mark variables and function which are modified or created for export -to the environment of subsequent commands. - -@item -b -Cause the status of terminated background jobs to be reported -immediately, rather than before printing the next primary prompt. - -@item -e -Exit immediately if -a pipeline (@pxref{Pipelines}), which may consist of a single simple command -(@pxref{Simple Commands}), -a list (@pxref{Lists}), -or a compound command (@pxref{Compound Commands}) -returns a non-zero status. -The shell does not exit if the command that fails is part of the -command list immediately following a @code{while} or @code{until} keyword, -part of the test in an @code{if} statement, -part of any command executed in a @code{&&} or @code{||} list except -the command following the final @code{&&} or @code{||}, -any command in a pipeline but the last, -or if the command's return status is being inverted with @code{!}. -If a compound command other than a subshell -returns a non-zero status because a command failed -while @option{-e} was being ignored, the shell does not exit. -A trap on @code{ERR}, if set, is executed before the shell exits. - -This option applies to the shell environment and each subshell environment -separately (@pxref{Command Execution Environment}), and may cause -subshells to exit before executing all the commands in the subshell. - -If a compound command or shell function executes in a context where -@option{-e} is being ignored, -none of the commands executed within the compound command or function body -will be affected by the @option{-e} setting, even if @option{-e} is set -and a command returns a failure status. -If a compound command or shell function sets @option{-e} while executing in -a context where @option{-e} is ignored, that setting will not have any -effect until the compound command or the command containing the function -call completes. - -@item -f -Disable filename expansion (globbing). - -@item -h -Locate and remember (hash) commands as they are looked up for execution. -This option is enabled by default. - -@item -k -All arguments in the form of assignment statements are placed -in the environment for a command, not just those that precede -the command name. - -@item -m -Job control is enabled (@pxref{Job Control}). -All processes run in a separate process group. -When a background job completes, the shell prints a line -containing its exit status. - -@item -n -Read commands but do not execute them; this may be used to check a -script for syntax errors. -This option is ignored by interactive shells. - -@item -o @var{option-name} - -Set the option corresponding to @var{option-name}: - -@table @code -@item allexport -Same as @code{-a}. - -@item braceexpand -Same as @code{-B}. - -@item emacs -Use an @code{emacs}-style line editing interface (@pxref{Command Line Editing}). -This also affects the editing interface used for @code{read -e}. - -@item errexit -Same as @code{-e}. - -@item errtrace -Same as @code{-E}. - -@item functrace -Same as @code{-T}. - -@item hashall -Same as @code{-h}. - -@item histexpand -Same as @code{-H}. - -@item history -Enable command history, as described in @ref{Bash History Facilities}. -This option is on by default in interactive shells. - -@item ignoreeof -An interactive shell will not exit upon reading EOF. - -@item keyword -Same as @code{-k}. - -@item monitor -Same as @code{-m}. - -@item noclobber -Same as @code{-C}. - -@item noexec -Same as @code{-n}. - -@item noglob -Same as @code{-f}. - -@item nolog -Currently ignored. - -@item notify -Same as @code{-b}. - -@item nounset -Same as @code{-u}. - -@item onecmd -Same as @code{-t}. - -@item physical -Same as @code{-P}. - -@item pipefail -If set, the return value of a pipeline is the value of the last -(rightmost) command to exit with a non-zero status, or zero if all -commands in the pipeline exit successfully. -This option is disabled by default. - -@item posix -Change the behavior of Bash where the default operation differs -from the @sc{posix} standard to match the standard -(@pxref{Bash POSIX Mode}). -This is intended to make Bash behave as a strict superset of that -standard. - -@item privileged -Same as @code{-p}. - -@item verbose -Same as @code{-v}. - -@item vi -Use a @code{vi}-style line editing interface. -This also affects the editing interface used for @code{read -e}. - -@item xtrace -Same as @code{-x}. -@end table - -@item -p -Turn on privileged mode. -In this mode, the @env{$BASH_ENV} and @env{$ENV} files are not -processed, shell functions are not inherited from the environment, -and the @env{SHELLOPTS}, @env{BASHOPTS}, @env{CDPATH} and @env{GLOBIGNORE} -variables, if they appear in the environment, are ignored. -If the shell is started with the effective user (group) id not equal to the -real user (group) id, and the @option{-p} option is not supplied, these actions -are taken and the effective user id is set to the real user id. -If the @option{-p} option is supplied at startup, the effective user id is -not reset. -Turning this option off causes the effective user -and group ids to be set to the real user and group ids. - -@item -t -Exit after reading and executing one command. - -@item -u -Treat unset variables and parameters other than the special parameters -@samp{@@} or @samp{*} as an error when performing parameter expansion. -An error message will be written to the standard error, and a non-interactive -shell will exit. - -@item -v -Print shell input lines as they are read. - -@item -x -Print a trace of simple commands, @code{for} commands, @code{case} -commands, @code{select} commands, and arithmetic @code{for} commands -and their arguments or associated word lists after they are -expanded and before they are executed. The value of the @env{PS4} -variable is expanded and the resultant value is printed before -the command and its expanded arguments. - -@item -B -The shell will perform brace expansion (@pxref{Brace Expansion}). -This option is on by default. - -@item -C -Prevent output redirection using @samp{>}, @samp{>&}, and @samp{<>} -from overwriting existing files. - -@item -E -If set, any trap on @code{ERR} is inherited by shell functions, command -substitutions, and commands executed in a subshell environment. -The @code{ERR} trap is normally not inherited in such cases. - -@item -H -Enable @samp{!} style history substitution (@pxref{History Interaction}). -This option is on by default for interactive shells. - -@item -P -If set, do not resolve symbolic links when performing commands such as -@code{cd} which change the current directory. The physical directory -is used instead. By default, Bash follows -the logical chain of directories when performing commands -which change the current directory. - -For example, if @file{/usr/sys} is a symbolic link to @file{/usr/local/sys} -then: -@example -$ cd /usr/sys; echo $PWD -/usr/sys -$ cd ..; pwd -/usr -@end example - -@noindent -If @code{set -P} is on, then: -@example -$ cd /usr/sys; echo $PWD -/usr/local/sys -$ cd ..; pwd -/usr/local -@end example - -@item -T -If set, any trap on @code{DEBUG} and @code{RETURN} are inherited by -shell functions, command substitutions, and commands executed -in a subshell environment. -The @code{DEBUG} and @code{RETURN} traps are normally not inherited -in such cases. - -@item -- -If no arguments follow this option, then the positional parameters are -unset. Otherwise, the positional parameters are set to the -@var{arguments}, even if some of them begin with a @samp{-}. - -@item - -Signal the end of options, cause all remaining @var{arguments} -to be assigned to the positional parameters. The @option{-x} -and @option{-v} options are turned off. -If there are no arguments, the positional parameters remain unchanged. -@end table - -Using @samp{+} rather than @samp{-} causes these options to be -turned off. The options can also be used upon invocation of the -shell. The current set of options may be found in @code{$-}. - -The remaining N @var{arguments} are positional parameters and are -assigned, in order, to @code{$1}, @code{$2}, @dots{} @code{$N}. -The special parameter @code{#} is set to N. - -The return status is always zero unless an invalid option is supplied. -@end table - -@node The Shopt Builtin -@subsection The Shopt Builtin - -This builtin allows you to change additional shell optional behavior. - -@table @code - -@item shopt -@btindex shopt -@example -shopt [-pqsu] [-o] [@var{optname} @dots{}] -@end example - -Toggle the values of settings controlling optional shell behavior. -The settings can be either those listed below, or, if the -@option{-o} option is used, those available with the @option{-o} -option to the @code{set} builtin command (@pxref{The Set Builtin}). -With no options, or with the @option{-p} option, a list of all settable -options is displayed, with an indication of whether or not each is set. -The @option{-p} option causes output to be displayed in a form that -may be reused as input. -Other options have the following meanings: - -@table @code -@item -s -Enable (set) each @var{optname}. - -@item -u -Disable (unset) each @var{optname}. - -@item -q -Suppresses normal output; the return status -indicates whether the @var{optname} is set or unset. -If multiple @var{optname} arguments are given with @option{-q}, -the return status is zero if all @var{optnames} are enabled; -non-zero otherwise. - -@item -o -Restricts the values of -@var{optname} to be those defined for the @option{-o} option to the -@code{set} builtin (@pxref{The Set Builtin}). -@end table - -If either @option{-s} or @option{-u} -is used with no @var{optname} arguments, @code{shopt} shows only -those options which are set or unset, respectively. - -Unless otherwise noted, the @code{shopt} options are disabled (off) -by default. - -The return status when listing options is zero if all @var{optnames} -are enabled, non-zero otherwise. When setting or unsetting options, -the return status is zero unless an @var{optname} is not a valid shell -option. - -The list of @code{shopt} options is: -@table @code - -@item autocd -If set, a command name that is the name of a directory is executed as if -it were the argument to the @code{cd} command. -This option is only used by interactive shells. - -@item cdable_vars -If this is set, an argument to the @code{cd} builtin command that -is not a directory is assumed to be the name of a variable whose -value is the directory to change to. - -@item cdspell -If set, minor errors in the spelling of a directory component in a -@code{cd} command will be corrected. -The errors checked for are transposed characters, -a missing character, and a character too many. -If a correction is found, the corrected path is printed, -and the command proceeds. -This option is only used by interactive shells. - -@item checkhash -If this is set, Bash checks that a command found in the hash -table exists before trying to execute it. If a hashed command no -longer exists, a normal path search is performed. - -@item checkjobs -If set, Bash lists the status of any stopped and running jobs before -exiting an interactive shell. If any jobs are running, this causes -the exit to be deferred until a second exit is attempted without an -intervening command (@pxref{Job Control}). -The shell always postpones exiting if any jobs are stopped. - -@item checkwinsize -If set, Bash checks the window size after each command - and, if necessary, updates the values of -@env{LINES} and @env{COLUMNS}. - -@item cmdhist -If set, Bash -attempts to save all lines of a multiple-line -command in the same history entry. This allows -easy re-editing of multi-line commands. - -@item compat31 -If set, Bash -changes its behavior to that of version 3.1 with respect to quoted -arguments to the conditional command's @samp{=~} operator -and with respect to locale-specific -string comparison when using the @code{[[} -conditional command's @samp{<} and @samp{>} operators. -Bash versions prior to bash-4.1 use ASCII collation and strcmp(3); -bash-4.1 and later use the current locale's collation sequence and strcoll(3). - -@item compat32 -If set, Bash -changes its behavior to that of version 3.2 with respect to locale-specific -string comparison when using the @code{[[} -conditional command's @samp{<} and @samp{>} operators (see previous item). - -@item compat40 -If set, Bash -changes its behavior to that of version 4.0 with respect to locale-specific -string comparison when using the @code{[[} -conditional command's @samp{<} and @samp{>} operators (see description -of @code{compat31}) -and the effect of interrupting a command list. -Bash versions 4.0 and later interrupt the list as if the shell received the -interrupt; previous versions continue with the next command in the list. - -@item compat41 -If set, Bash, when in @sc{posix} mode, treats a single quote in a double-quoted -parameter expansion as a special character. The single quotes must match -(an even number) and the characters between the single quotes are considered -quoted. This is the behavior of @sc{posix} mode through version 4.1. -The default Bash behavior remains as in previous versions. - -@item compat42 -If set, Bash -does not process the replacement string in the pattern substitution word -expansion using quote removal. - -@item complete_fullquote -If set, Bash -quotes all shell metacharacters in filenames and directory names when -performing completion. -If not set, Bash -removes metacharacters such as the dollar sign from the set of -characters that will be quoted in completed filenames -when these metacharacters appear in shell variable references in words to be -completed. -This means that dollar signs in variable names that expand to directories -will not be quoted; -however, any dollar signs appearing in filenames will not be quoted, either. -This is active only when bash is using backslashes to quote completed -filenames. -This variable is set by default, which is the default Bash behavior in -versions through 4.2. - -@item direxpand -If set, Bash -replaces directory names with the results of word expansion when performing -filename completion. This changes the contents of the readline editing -buffer. -If not set, Bash attempts to preserve what the user typed. - -@item dirspell -If set, Bash -attempts spelling correction on directory names during word completion -if the directory name initially supplied does not exist. - -@item dotglob -If set, Bash includes filenames beginning with a `.' in -the results of filename expansion. - -@item execfail -If this is set, a non-interactive shell will not exit if -it cannot execute the file specified as an argument to the @code{exec} -builtin command. An interactive shell does not exit if @code{exec} -fails. - -@item expand_aliases -If set, aliases are expanded as described below under Aliases, -@ref{Aliases}. -This option is enabled by default for interactive shells. - -@item extdebug -If set, behavior intended for use by debuggers is enabled: - -@enumerate -@item -The @option{-F} option to the @code{declare} builtin (@pxref{Bash Builtins}) -displays the source file name and line number corresponding to each function -name supplied as an argument. - -@item -If the command run by the @code{DEBUG} trap returns a non-zero value, the -next command is skipped and not executed. - -@item -If the command run by the @code{DEBUG} trap returns a value of 2, and the -shell is executing in a subroutine (a shell function or a shell script -executed by the @code{.} or @code{source} builtins), the shell simulates -a call to @code{return}. - -@item -@code{BASH_ARGC} and @code{BASH_ARGV} are updated as described in their -descriptions (@pxref{Bash Variables}). - -@item -Function tracing is enabled: command substitution, shell functions, and -subshells invoked with @code{( @var{command} )} inherit the -@code{DEBUG} and @code{RETURN} traps. - -@item -Error tracing is enabled: command substitution, shell functions, and -subshells invoked with @code{( @var{command} )} inherit the -@code{ERR} trap. -@end enumerate - -@item extglob -If set, the extended pattern matching features described above -(@pxref{Pattern Matching}) are enabled. - -@item extquote -If set, @code{$'@var{string}'} and @code{$"@var{string}"} quoting is -performed within @code{$@{@var{parameter}@}} expansions -enclosed in double quotes. This option is enabled by default. - -@item failglob -If set, patterns which fail to match filenames during filename expansion -result in an expansion error. - -@item force_fignore -If set, the suffixes specified by the @env{FIGNORE} shell variable -cause words to be ignored when performing word completion even if -the ignored words are the only possible completions. -@xref{Bash Variables}, for a description of @env{FIGNORE}. -This option is enabled by default. - -@item globasciiranges -If set, range expressions used in pattern matching bracket expressions -(@pxref{Pattern Matching}) -behave as if in the traditional C locale when performing -comparisons. That is, the current locale's collating sequence -is not taken into account, so -@samp{b} will not collate between @samp{A} and @samp{B}, -and upper-case and lower-case ASCII characters will collate together. - -@item globstar -If set, the pattern @samp{**} used in a filename expansion context will -match all files and zero or more directories and subdirectories. -If the pattern is followed by a @samp{/}, only directories and -subdirectories match. - -@item gnu_errfmt -If set, shell error messages are written in the standard @sc{gnu} error -message format. - -@item histappend -If set, the history list is appended to the file named by the value -of the @env{HISTFILE} -variable when the shell exits, rather than overwriting the file. - -@item histreedit -If set, and Readline -is being used, a user is given the opportunity to re-edit a -failed history substitution. - -@item histverify -If set, and Readline -is being used, the results of history substitution are not immediately -passed to the shell parser. Instead, the resulting line is loaded into -the Readline editing buffer, allowing further modification. - -@item hostcomplete -If set, and Readline is being used, Bash will attempt to perform -hostname completion when a word containing a @samp{@@} is being -completed (@pxref{Commands For Completion}). This option is enabled -by default. - -@item huponexit -If set, Bash will send @code{SIGHUP} to all jobs when an interactive -login shell exits (@pxref{Signals}). - -@item interactive_comments -Allow a word beginning with @samp{#} -to cause that word and all remaining characters on that -line to be ignored in an interactive shell. -This option is enabled by default. - -@item lastpipe -If set, and job control is not active, the shell runs the last command of -a pipeline not executed in the background in the current shell environment. - -@item lithist -If enabled, and the @code{cmdhist} -option is enabled, multi-line commands are saved to the history with -embedded newlines rather than using semicolon separators where possible. - -@item login_shell -The shell sets this option if it is started as a login shell -(@pxref{Invoking Bash}). -The value may not be changed. - -@item mailwarn -If set, and a file that Bash is checking for mail has been -accessed since the last time it was checked, the message -@code{"The mail in @var{mailfile} has been read"} is displayed. - -@item no_empty_cmd_completion -If set, and Readline is being used, Bash will not attempt to search -the @env{PATH} for possible completions when completion is attempted -on an empty line. - -@item nocaseglob -If set, Bash matches filenames in a case-insensitive fashion when -performing filename expansion. - -@item nocasematch -If set, Bash matches patterns in a case-insensitive fashion when -performing matching while executing @code{case} or @code{[[} -conditional commands. - -@item nullglob -If set, Bash allows filename patterns which match no -files to expand to a null string, rather than themselves. - -@item progcomp -If set, the programmable completion facilities -(@pxref{Programmable Completion}) are enabled. -This option is enabled by default. - -@item promptvars -If set, prompt strings undergo -parameter expansion, command substitution, arithmetic -expansion, and quote removal after being expanded -as described below (@pxref{Controlling the Prompt}). -This option is enabled by default. - -@item restricted_shell -The shell sets this option if it is started in restricted mode -(@pxref{The Restricted Shell}). -The value may not be changed. -This is not reset when the startup files are executed, allowing -the startup files to discover whether or not a shell is restricted. - -@item shift_verbose -If this is set, the @code{shift} -builtin prints an error message when the shift count exceeds the -number of positional parameters. - -@item sourcepath -If set, the @code{source} builtin uses the value of @env{PATH} -to find the directory containing the file supplied as an argument. -This option is enabled by default. - -@item xpg_echo -If set, the @code{echo} builtin expands backslash-escape sequences -by default. - -@end table - -@noindent -The return status when listing options is zero if all @var{optnames} -are enabled, non-zero otherwise. -When setting or unsetting options, the return status is zero unless an -@var{optname} is not a valid shell option. -@end table - -@node Special Builtins -@section Special Builtins -@cindex special builtin - -For historical reasons, the @sc{posix} standard has classified -several builtin commands as @emph{special}. -When Bash is executing in @sc{posix} mode, the special builtins -differ from other builtin commands in three respects: - -@enumerate -@item -Special builtins are found before shell functions during command lookup. - -@item -If a special builtin returns an error status, a non-interactive shell exits. - -@item -Assignment statements preceding the command stay in effect in the shell -environment after the command completes. -@end enumerate - -When Bash is not executing in @sc{posix} mode, these builtins behave no -differently than the rest of the Bash builtin commands. -The Bash @sc{posix} mode is described in @ref{Bash POSIX Mode}. - -These are the @sc{posix} special builtins: -@example -@w{break : . continue eval exec exit export readonly return set} -@w{shift trap unset} -@end example - -@node Shell Variables -@chapter Shell Variables - -@menu -* Bourne Shell Variables:: Variables which Bash uses in the same way - as the Bourne Shell. -* Bash Variables:: List of variables that exist in Bash. -@end menu - -This chapter describes the shell variables that Bash uses. -Bash automatically assigns default values to a number of variables. - -@node Bourne Shell Variables -@section Bourne Shell Variables - -Bash uses certain shell variables in the same way as the Bourne shell. -In some cases, Bash assigns a default value to the variable. - -@vtable @code - -@item CDPATH -A colon-separated list of directories used as a search path for -the @code{cd} builtin command. - -@item HOME -The current user's home directory; the default for the @code{cd} builtin -command. -The value of this variable is also used by tilde expansion -(@pxref{Tilde Expansion}). - -@item IFS -A list of characters that separate fields; used when the shell splits -words as part of expansion. - -@item MAIL -If this parameter is set to a filename or directory name -and the @env{MAILPATH} variable -is not set, Bash informs the user of the arrival of mail in -the specified file or Maildir-format directory. - -@item MAILPATH -A colon-separated list of filenames which the shell periodically checks -for new mail. -Each list entry can specify the message that is printed when new mail -arrives in the mail file by separating the filename from the message with -a @samp{?}. -When used in the text of the message, @code{$_} expands to the name of -the current mail file. - -@item OPTARG -The value of the last option argument processed by the @code{getopts} builtin. - -@item OPTIND -The index of the last option argument processed by the @code{getopts} builtin. - -@item PATH -A colon-separated list of directories in which the shell looks for -commands. -A zero-length (null) directory name in the value of @code{PATH} indicates the -current directory. -A null directory name may appear as two adjacent colons, or as an initial -or trailing colon. - - -@item PS1 -The primary prompt string. The default value is @samp{\s-\v\$ }. -@xref{Controlling the Prompt}, for the complete list of escape -sequences that are expanded before @env{PS1} is displayed. - -@item PS2 -The secondary prompt string. The default value is @samp{> }. - -@end vtable - -@node Bash Variables -@section Bash Variables - -These variables are set or used by Bash, but other shells -do not normally treat them specially. - -A few variables used by Bash are described in different chapters: -variables for controlling the job control facilities -(@pxref{Job Control Variables}). - -@vtable @code - -@item BASH -The full pathname used to execute the current instance of Bash. - -@item BASHOPTS -A colon-separated list of enabled shell options. Each word in -the list is a valid argument for the @option{-s} option to the -@code{shopt} builtin command (@pxref{The Shopt Builtin}). -The options appearing in @env{BASHOPTS} are those reported -as @samp{on} by @samp{shopt}. -If this variable is in the environment when Bash -starts up, each shell option in the list will be enabled before -reading any startup files. This variable is readonly. - -@item BASHPID -Expands to the process ID of the current Bash process. -This differs from @code{$$} under certain circumstances, such as subshells -that do not require Bash to be re-initialized. - -@item BASH_ALIASES -An associative array variable whose members correspond to the internal -list of aliases as maintained by the @code{alias} builtin. -(@pxref{Bourne Shell Builtins}). -Elements added to this array appear in the alias list; unsetting array -elements cause aliases to be removed from the alias list. - -@item BASH_ARGC -An array variable whose values are the number of parameters in each -frame of the current bash execution call stack. The number of -parameters to the current subroutine (shell function or script executed -with @code{.} or @code{source}) is at the top of the stack. When a -subroutine is executed, the number of parameters passed is pushed onto -@code{BASH_ARGC}. -The shell sets @code{BASH_ARGC} only when in extended debugging mode -(see @ref{The Shopt Builtin} -for a description of the @code{extdebug} option to the @code{shopt} -builtin). - -@item BASH_ARGV -An array variable containing all of the parameters in the current bash -execution call stack. The final parameter of the last subroutine call -is at the top of the stack; the first parameter of the initial call is -at the bottom. When a subroutine is executed, the parameters supplied -are pushed onto @code{BASH_ARGV}. -The shell sets @code{BASH_ARGV} only when in extended debugging mode -(see @ref{The Shopt Builtin} -for a description of the @code{extdebug} option to the @code{shopt} -builtin). - -@item BASH_CMDS -An associative array variable whose members correspond to the internal -hash table of commands as maintained by the @code{hash} builtin -(@pxref{Bourne Shell Builtins}). -Elements added to this array appear in the hash table; unsetting array -elements cause commands to be removed from the hash table. - -@item BASH_COMMAND -The command currently being executed or about to be executed, unless the -shell is executing a command as the result of a trap, -in which case it is the command executing at the time of the trap. - -@item BASH_COMPAT -The value is used to set the shell's compatibility level. -@xref{The Shopt Builtin}, for a description of the various compatibility -levels and their effects. -The value may be a decimal number (e.g., 4.2) or an integer (e.g., 42) -corresponding to the desired compatibility level. -If @code{BASH_COMPAT} is unset or set to the empty string, the compatibility -level is set to the default for the current version. -If @code{BASH_COMPAT} is set to a value that is not one of the valid -compatibility levels, the shell prints an error message and sets the -compatibility level to the default for the current version. -The valid compatibility levels correspond to the compatibility options -accepted by the @code{shopt} builtin described above (for example, -@var{compat42} means that 4.2 and 42 are valid values). -The current version is also a valid value. - -@item BASH_ENV -If this variable is set when Bash is invoked to execute a shell -script, its value is expanded and used as the name of a startup file -to read before executing the script. @xref{Bash Startup Files}. - -@item BASH_EXECUTION_STRING -The command argument to the @option{-c} invocation option. - -@item BASH_LINENO -An array variable whose members are the line numbers in source files -where each corresponding member of @var{FUNCNAME} was invoked. -@code{$@{BASH_LINENO[$i]@}} is the line number in the source file -(@code{$@{BASH_SOURCE[$i+1]@}}) where -@code{$@{FUNCNAME[$i]@}} was called (or @code{$@{BASH_LINENO[$i-1]@}} if -referenced within another shell function). -Use @code{LINENO} to obtain the current line number. - -@item BASH_REMATCH -An array variable whose members are assigned by the @samp{=~} binary -operator to the @code{[[} conditional command -(@pxref{Conditional Constructs}). -The element with index 0 is the portion of the string -matching the entire regular expression. -The element with index @var{n} is the portion of the -string matching the @var{n}th parenthesized subexpression. -This variable is read-only. - -@item BASH_SOURCE -An array variable whose members are the source filenames where the -corresponding shell function names in the @code{FUNCNAME} array -variable are defined. -The shell function @code{$@{FUNCNAME[$i]@}} is defined in the file -@code{$@{BASH_SOURCE[$i]@}} and called from @code{$@{BASH_SOURCE[$i+1]@}} - -@item BASH_SUBSHELL -Incremented by one within each subshell or subshell environment when -the shell begins executing in that environment. -The initial value is 0. - -@item BASH_VERSINFO -A readonly array variable (@pxref{Arrays}) -whose members hold version information for this instance of Bash. -The values assigned to the array members are as follows: - -@table @code - -@item BASH_VERSINFO[0] -The major version number (the @var{release}). - -@item BASH_VERSINFO[1] -The minor version number (the @var{version}). - -@item BASH_VERSINFO[2] -The patch level. - -@item BASH_VERSINFO[3] -The build version. - -@item BASH_VERSINFO[4] -The release status (e.g., @var{beta1}). - -@item BASH_VERSINFO[5] -The value of @env{MACHTYPE}. -@end table - -@item BASH_VERSION -The version number of the current instance of Bash. - -@item BASH_XTRACEFD -If set to an integer corresponding to a valid file descriptor, Bash -will write the trace output generated when @samp{set -x} -is enabled to that file descriptor. -This allows tracing output to be separated from diagnostic and error -messages. -The file descriptor is closed when @code{BASH_XTRACEFD} is unset or assigned -a new value. -Unsetting @code{BASH_XTRACEFD} or assigning it the empty string causes the -trace output to be sent to the standard error. -Note that setting @code{BASH_XTRACEFD} to 2 (the standard error file -descriptor) and then unsetting it will result in the standard error -being closed. - -@item CHILD_MAX -Set the number of exited child status values for the shell to remember. -Bash will not allow this value to be decreased below a @sc{posix}-mandated -minimum, and there is a maximum value (currently 8192) that this may -not exceed. -The minimum value is system-dependent. - -@item COLUMNS -Used by the @code{select} command to determine the terminal width -when printing selection lists. -Automatically set if the @code{checkwinsize} option is enabled -(@pxref{The Shopt Builtin}), or in an interactive shell upon receipt of a -@code{SIGWINCH}. - -@item COMP_CWORD -An index into @env{$@{COMP_WORDS@}} of the word containing the current -cursor position. -This variable is available only in shell functions invoked by the -programmable completion facilities (@pxref{Programmable Completion}). - -@item COMP_LINE -The current command line. -This variable is available only in shell functions and external -commands invoked by the -programmable completion facilities (@pxref{Programmable Completion}). - -@item COMP_POINT -The index of the current cursor position relative to the beginning of -the current command. -If the current cursor position is at the end of the current command, -the value of this variable is equal to @code{$@{#COMP_LINE@}}. -This variable is available only in shell functions and external -commands invoked by the -programmable completion facilities (@pxref{Programmable Completion}). - -@item COMP_TYPE -Set to an integer value corresponding to the type of completion attempted -that caused a completion function to be called: -@var{TAB}, for normal completion, -@samp{?}, for listing completions after successive tabs, -@samp{!}, for listing alternatives on partial word completion, -@samp{@@}, to list completions if the word is not unmodified, -or -@samp{%}, for menu completion. -This variable is available only in shell functions and external -commands invoked by the -programmable completion facilities (@pxref{Programmable Completion}). - -@item COMP_KEY -The key (or final key of a key sequence) used to invoke the current -completion function. - -@item COMP_WORDBREAKS -The set of characters that the Readline library treats as word -separators when performing word completion. -If @code{COMP_WORDBREAKS} is unset, it loses its special properties, -even if it is subsequently reset. - -@item COMP_WORDS -An array variable consisting of the individual -words in the current command line. -The line is split into words as Readline would split it, using -@code{COMP_WORDBREAKS} as described above. -This variable is available only in shell functions invoked by the -programmable completion facilities (@pxref{Programmable Completion}). - -@item COMPREPLY -An array variable from which Bash reads the possible completions -generated by a shell function invoked by the programmable completion -facility (@pxref{Programmable Completion}). -Each array element contains one possible completion. - -@item COPROC -An array variable created to hold the file descriptors -for output from and input to an unnamed coprocess (@pxref{Coprocesses}). - -@item DIRSTACK -An array variable containing the current contents of the directory stack. -Directories appear in the stack in the order they are displayed by the -@code{dirs} builtin. -Assigning to members of this array variable may be used to modify -directories already in the stack, but the @code{pushd} and @code{popd} -builtins must be used to add and remove directories. -Assignment to this variable will not change the current directory. -If @env{DIRSTACK} is unset, it loses its special properties, even if -it is subsequently reset. - -@item EMACS -If Bash finds this variable in the environment when the shell -starts with value @samp{t}, it assumes that the shell is running in an -Emacs shell buffer and disables line editing. - -@item ENV -Similar to @code{BASH_ENV}; used when the shell is invoked in -@sc{posix} Mode (@pxref{Bash POSIX Mode}). - -@item EUID -The numeric effective user id of the current user. This variable -is readonly. - -@item FCEDIT -The editor used as a default by the @option{-e} option to the @code{fc} -builtin command. - -@item FIGNORE -A colon-separated list of suffixes to ignore when performing -filename completion. -A filename whose suffix matches one of the entries in -@env{FIGNORE} -is excluded from the list of matched filenames. A sample -value is @samp{.o:~} - -@item FUNCNAME -An array variable containing the names of all shell functions -currently in the execution call stack. -The element with index 0 is the name of any currently-executing -shell function. -The bottom-most element (the one with the highest index) -is @code{"main"}. -This variable exists only when a shell function is executing. -Assignments to @env{FUNCNAME} have no effect and return an error status. -If @env{FUNCNAME} is unset, it loses its special properties, even if -it is subsequently reset. - -This variable can be used with @code{BASH_LINENO} and @code{BASH_SOURCE}. -Each element of @code{FUNCNAME} has corresponding elements in -@code{BASH_LINENO} and @code{BASH_SOURCE} to describe the call stack. -For instance, @code{$@{FUNCNAME[$i]@}} was called from the file -@code{$@{BASH_SOURCE[$i+1]@}} at line number @code{$@{BASH_LINENO[$i]@}}. -The @code{caller} builtin displays the current call stack using this -information. - -@item FUNCNEST -If set to a numeric value greater than 0, defines a maximum function -nesting level. Function invocations that exceed this nesting level -will cause the current command to abort. - -@item GLOBIGNORE -A colon-separated list of patterns defining the set of filenames to -be ignored by filename expansion. -If a filename matched by a filename expansion pattern also matches one -of the patterns in @env{GLOBIGNORE}, it is removed from the list -of matches. - -@item GROUPS -An array variable containing the list of groups of which the current -user is a member. -Assignments to @env{GROUPS} have no effect and return an error status. -If @env{GROUPS} is unset, it loses its special properties, even if it is -subsequently reset. - -@item histchars -Up to three characters which control history expansion, quick -substitution, and tokenization (@pxref{History Interaction}). -The first character is the -@var{history expansion} character, that is, the character which signifies the -start of a history expansion, normally @samp{!}. The second character is the -character which signifies `quick substitution' when seen as the first -character on a line, normally @samp{^}. The optional third character is the -character which indicates that the remainder of the line is a comment when -found as the first character of a word, usually @samp{#}. The history -comment character causes history substitution to be skipped for the -remaining words on the line. It does not necessarily cause the shell -parser to treat the rest of the line as a comment. - -@item HISTCMD -The history number, or index in the history list, of the current -command. If @env{HISTCMD} is unset, it loses its special properties, -even if it is subsequently reset. - -@item HISTCONTROL -A colon-separated list of values controlling how commands are saved on -the history list. -If the list of values includes @samp{ignorespace}, lines which begin -with a space character are not saved in the history list. -A value of @samp{ignoredups} causes lines which match the previous -history entry to not be saved. -A value of @samp{ignoreboth} is shorthand for -@samp{ignorespace} and @samp{ignoredups}. -A value of @samp{erasedups} causes all previous lines matching the -current line to be removed from the history list before that line -is saved. -Any value not in the above list is ignored. -If @env{HISTCONTROL} is unset, or does not include a valid value, -all lines read by the shell parser are saved on the history list, -subject to the value of @env{HISTIGNORE}. -The second and subsequent lines of a multi-line compound command are -not tested, and are added to the history regardless of the value of -@env{HISTCONTROL}. - -@item HISTFILE -The name of the file to which the command history is saved. The -default value is @file{~/.bash_history}. - -@item HISTFILESIZE -The maximum number of lines contained in the history file. -When this variable is assigned a value, the history file is truncated, -if necessary, to contain no more than that number of lines -by removing the oldest entries. -The history file is also truncated to this size after -writing it when a shell exits. -If the value is 0, the history file is truncated to zero size. -Non-numeric values and numeric values less than zero inhibit truncation. -The shell sets the default value to the value of @env{HISTSIZE} -after reading any startup files. - -@item HISTIGNORE -A colon-separated list of patterns used to decide which command -lines should be saved on the history list. Each pattern is -anchored at the beginning of the line and must match the complete -line (no implicit @samp{*} is appended). Each pattern is tested -against the line after the checks specified by @env{HISTCONTROL} -are applied. In addition to the normal shell pattern matching -characters, @samp{&} matches the previous history line. @samp{&} -may be escaped using a backslash; the backslash is removed -before attempting a match. -The second and subsequent lines of a multi-line compound command are -not tested, and are added to the history regardless of the value of -@env{HISTIGNORE}. - -@env{HISTIGNORE} subsumes the function of @env{HISTCONTROL}. A -pattern of @samp{&} is identical to @code{ignoredups}, and a -pattern of @samp{[ ]*} is identical to @code{ignorespace}. -Combining these two patterns, separating them with a colon, -provides the functionality of @code{ignoreboth}. - -@item HISTSIZE -The maximum number of commands to remember on the history list. -If the value is 0, commands are not saved in the history list. -Numeric values less than zero result in every command being saved -on the history list (there is no limit). -The shell sets the default value to 500 after reading any startup files. - -@item HISTTIMEFORMAT -If this variable is set and not null, its value is used as a format string -for @var{strftime} to print the time stamp associated with each history -entry displayed by the @code{history} builtin. -If this variable is set, time stamps are written to the history file so -they may be preserved across shell sessions. -This uses the history comment character to distinguish timestamps from -other history lines. - -@item HOSTFILE -Contains the name of a file in the same format as @file{/etc/hosts} that -should be read when the shell needs to complete a hostname. -The list of possible hostname completions may be changed while the shell -is running; -the next time hostname completion is attempted after the -value is changed, Bash adds the contents of the new file to the -existing list. -If @env{HOSTFILE} is set, but has no value, or does not name a readable file, -Bash attempts to read -@file{/etc/hosts} to obtain the list of possible hostname completions. -When @env{HOSTFILE} is unset, the hostname list is cleared. - -@item HOSTNAME -The name of the current host. - -@item HOSTTYPE -A string describing the machine Bash is running on. - -@item IGNOREEOF -Controls the action of the shell on receipt of an @code{EOF} character -as the sole input. If set, the value denotes the number -of consecutive @code{EOF} characters that can be read as the -first character on an input line -before the shell will exit. If the variable exists but does not -have a numeric value (or has no value) then the default is 10. -If the variable does not exist, then @code{EOF} signifies the end of -input to the shell. This is only in effect for interactive shells. - -@item INPUTRC -The name of the Readline initialization file, overriding the default -of @file{~/.inputrc}. - -@item LANG -Used to determine the locale category for any category not specifically -selected with a variable starting with @code{LC_}. - -@item LC_ALL -This variable overrides the value of @env{LANG} and any other -@code{LC_} variable specifying a locale category. - -@item LC_COLLATE -This variable determines the collation order used when sorting the -results of filename expansion, and -determines the behavior of range expressions, equivalence classes, -and collating sequences within filename expansion and pattern matching -(@pxref{Filename Expansion}). - -@item LC_CTYPE -This variable determines the interpretation of characters and the -behavior of character classes within filename expansion and pattern -matching (@pxref{Filename Expansion}). - -@item LC_MESSAGES -This variable determines the locale used to translate double-quoted -strings preceded by a @samp{$} (@pxref{Locale Translation}). - -@item LC_NUMERIC -This variable determines the locale category used for number formatting. - -@item LINENO -The line number in the script or shell function currently executing. - -@item LINES -Used by the @code{select} command to determine the column length -for printing selection lists. -Automatically set if the @code{checkwinsize} option is enabled -(@pxref{The Shopt Builtin}), or in an interactive shell upon receipt of a -@code{SIGWINCH}. - -@item MACHTYPE -A string that fully describes the system type on which Bash -is executing, in the standard @sc{gnu} @var{cpu-company-system} format. - -@item MAILCHECK -How often (in seconds) that the shell should check for mail in the -files specified in the @env{MAILPATH} or @env{MAIL} variables. -The default is 60 seconds. When it is time to check -for mail, the shell does so before displaying the primary prompt. -If this variable is unset, or set to a value that is not a number -greater than or equal to zero, the shell disables mail checking. - -@item MAPFILE -An array variable created to hold the text read by the -@code{mapfile} builtin when no variable name is supplied. - -@item OLDPWD -The previous working directory as set by the @code{cd} builtin. - -@item OPTERR -If set to the value 1, Bash displays error messages -generated by the @code{getopts} builtin command. - -@item OSTYPE -A string describing the operating system Bash is running on. - -@item PIPESTATUS -An array variable (@pxref{Arrays}) -containing a list of exit status values from the processes -in the most-recently-executed foreground pipeline (which may -contain only a single command). - -@item POSIXLY_CORRECT -If this variable is in the environment when Bash starts, the shell -enters @sc{posix} mode (@pxref{Bash POSIX Mode}) before reading the -startup files, as if the @option{--posix} invocation option had been supplied. -If it is set while the shell is running, Bash enables @sc{posix} mode, -as if the command -@example -@code{set -o posix} -@end example -@noindent -had been executed. - -@item PPID -The process @sc{id} of the shell's parent process. This variable -is readonly. - -@item PROMPT_COMMAND -If set, the value is interpreted as a command to execute -before the printing of each primary prompt (@env{$PS1}). - -@item PROMPT_DIRTRIM -If set to a number greater than zero, the value is used as the number of -trailing directory components to retain when expanding the @code{\w} and -@code{\W} prompt string escapes (@pxref{Controlling the Prompt}). -Characters removed are replaced with an ellipsis. - -@item PS3 -The value of this variable is used as the prompt for the -@code{select} command. If this variable is not set, the -@code{select} command prompts with @samp{#? } - -@item PS4 -The value is the prompt printed before the command line is echoed -when the @option{-x} option is set (@pxref{The Set Builtin}). -The first character of @env{PS4} is replicated multiple times, as -necessary, to indicate multiple levels of indirection. -The default is @samp{+ }. - -@item PWD -The current working directory as set by the @code{cd} builtin. - -@item RANDOM -Each time this parameter is referenced, a random integer -between 0 and 32767 is generated. Assigning a value to this -variable seeds the random number generator. - -@item READLINE_LINE -The contents of the Readline line buffer, for use -with @samp{bind -x} (@pxref{Bash Builtins}). - -@item READLINE_POINT -The position of the insertion point in the Readline line buffer, for use -with @samp{bind -x} (@pxref{Bash Builtins}). - -@item REPLY -The default variable for the @code{read} builtin. - -@item SECONDS -This variable expands to the number of seconds since the -shell was started. Assignment to this variable resets -the count to the value assigned, and the expanded value -becomes the value assigned plus the number of seconds -since the assignment. - -@item SHELL -The full pathname to the shell is kept in this environment variable. -If it is not set when the shell starts, -Bash assigns to it the full pathname of the current user's login shell. - -@item SHELLOPTS -A colon-separated list of enabled shell options. Each word in -the list is a valid argument for the @option{-o} option to the -@code{set} builtin command (@pxref{The Set Builtin}). -The options appearing in @env{SHELLOPTS} are those reported -as @samp{on} by @samp{set -o}. -If this variable is in the environment when Bash -starts up, each shell option in the list will be enabled before -reading any startup files. This variable is readonly. - -@item SHLVL -Incremented by one each time a new instance of Bash is started. This is -intended to be a count of how deeply your Bash shells are nested. - -@item TIMEFORMAT -The value of this parameter is used as a format string specifying -how the timing information for pipelines prefixed with the @code{time} -reserved word should be displayed. -The @samp{%} character introduces an -escape sequence that is expanded to a time value or other -information. -The escape sequences and their meanings are as -follows; the braces denote optional portions. - -@table @code - -@item %% -A literal @samp{%}. - -@item %[@var{p}][l]R -The elapsed time in seconds. - -@item %[@var{p}][l]U -The number of CPU seconds spent in user mode. - -@item %[@var{p}][l]S -The number of CPU seconds spent in system mode. - -@item %P -The CPU percentage, computed as (%U + %S) / %R. -@end table - -The optional @var{p} is a digit specifying the precision, the number of -fractional digits after a decimal point. -A value of 0 causes no decimal point or fraction to be output. -At most three places after the decimal point may be specified; values -of @var{p} greater than 3 are changed to 3. -If @var{p} is not specified, the value 3 is used. - -The optional @code{l} specifies a longer format, including minutes, of -the form @var{MM}m@var{SS}.@var{FF}s. -The value of @var{p} determines whether or not the fraction is included. - -If this variable is not set, Bash acts as if it had the value -@example -@code{$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'} -@end example -If the value is null, no timing information is displayed. -A trailing newline is added when the format string is displayed. - -@item TMOUT -If set to a value greater than zero, @code{TMOUT} is treated as the -default timeout for the @code{read} builtin (@pxref{Bash Builtins}). -The @code{select} command (@pxref{Conditional Constructs}) terminates -if input does not arrive after @code{TMOUT} seconds when input is coming -from a terminal. - -In an interactive shell, the value is interpreted as -the number of seconds to wait for a line of input after issuing -the primary prompt. -Bash -terminates after waiting for that number of seconds if a complete -line of input does not arrive. - -@item TMPDIR -If set, Bash uses its value as the name of a directory in which -Bash creates temporary files for the shell's use. - -@item UID -The numeric real user id of the current user. This variable is readonly. - -@end vtable - -@node Bash Features -@chapter Bash Features - -This chapter describes features unique to Bash. - -@menu -* Invoking Bash:: Command line options that you can give - to Bash. -* Bash Startup Files:: When and how Bash executes scripts. -* Interactive Shells:: What an interactive shell is. -* Bash Conditional Expressions:: Primitives used in composing expressions for - the @code{test} builtin. -* Shell Arithmetic:: Arithmetic on shell variables. -* Aliases:: Substituting one command for another. -* Arrays:: Array Variables. -* The Directory Stack:: History of visited directories. -* Controlling the Prompt:: Customizing the various prompt strings. -* The Restricted Shell:: A more controlled mode of shell execution. -* Bash POSIX Mode:: Making Bash behave more closely to what - the POSIX standard specifies. -@end menu - -@node Invoking Bash -@section Invoking Bash - -@example -bash [long-opt] [-ir] [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_option}] [@var{argument} @dots{}] -bash [long-opt] [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_option}] -c @var{string} [@var{argument} @dots{}] -bash [long-opt] -s [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_option}] [@var{argument} @dots{}] -@end example - -All of the single-character options used with the @code{set} builtin -(@pxref{The Set Builtin}) can be used as options when the shell is invoked. -In addition, there are several multi-character -options that you can use. These options must appear on the command -line before the single-character options to be recognized. - -@table @code -@item --debugger -Arrange for the debugger profile to be executed before the shell -starts. Turns on extended debugging mode (see @ref{The Shopt Builtin} -for a description of the @code{extdebug} option to the @code{shopt} -builtin). - -@item --dump-po-strings -A list of all double-quoted strings preceded by @samp{$} -is printed on the standard output -in the @sc{gnu} @code{gettext} PO (portable object) file format. -Equivalent to @option{-D} except for the output format. - -@item --dump-strings -Equivalent to @option{-D}. - -@item --help -Display a usage message on standard output and exit successfully. - -@item --init-file @var{filename} -@itemx --rcfile @var{filename} -Execute commands from @var{filename} (instead of @file{~/.bashrc}) -in an interactive shell. - -@item --login -Equivalent to @option{-l}. - -@item --noediting -Do not use the @sc{gnu} Readline library (@pxref{Command Line Editing}) -to read command lines when the shell is interactive. - -@item --noprofile -Don't load the system-wide startup file @file{/etc/profile} -or any of the personal initialization files -@file{~/.bash_profile}, @file{~/.bash_login}, or @file{~/.profile} -when Bash is invoked as a login shell. - -@item --norc -Don't read the @file{~/.bashrc} initialization file in an -interactive shell. This is on by default if the shell is -invoked as @code{sh}. - -@item --posix -Change the behavior of Bash where the default operation differs -from the @sc{posix} standard to match the standard. This -is intended to make Bash behave as a strict superset of that -standard. @xref{Bash POSIX Mode}, for a description of the Bash -@sc{posix} mode. - -@item --restricted -Make the shell a restricted shell (@pxref{The Restricted Shell}). - -@item --verbose -Equivalent to @option{-v}. Print shell input lines as they're read. - -@item --version -Show version information for this instance of -Bash on the standard output and exit successfully. -@end table - -There are several single-character options that may be supplied at -invocation which are not available with the @code{set} builtin. - -@table @code -@item -c -Read and execute commands from the first non-option @var{argument} -after processing the options, then exit. -Any remaining arguments are assigned to the -positional parameters, starting with @code{$0}. - -@item -i -Force the shell to run interactively. Interactive shells are -described in @ref{Interactive Shells}. - -@item -l -Make this shell act as if it had been directly invoked by login. -When the shell is interactive, this is equivalent to starting a -login shell with @samp{exec -l bash}. -When the shell is not interactive, the login shell startup files will -be executed. -@samp{exec bash -l} or @samp{exec bash --login} -will replace the current shell with a Bash login shell. -@xref{Bash Startup Files}, for a description of the special behavior -of a login shell. - -@item -r -Make the shell a restricted shell (@pxref{The Restricted Shell}). - -@item -s -If this option is present, or if no arguments remain after option -processing, then commands are read from the standard input. -This option allows the positional parameters to be set -when invoking an interactive shell. - -@item -D -A list of all double-quoted strings preceded by @samp{$} -is printed on the standard output. -These are the strings that -are subject to language translation when the current locale -is not @code{C} or @code{POSIX} (@pxref{Locale Translation}). -This implies the @option{-n} option; no commands will be executed. - -@item [-+]O [@var{shopt_option}] -@var{shopt_option} is one of the shell options accepted by the -@code{shopt} builtin (@pxref{The Shopt Builtin}). -If @var{shopt_option} is present, @option{-O} sets the value of that option; -@option{+O} unsets it. -If @var{shopt_option} is not supplied, the names and values of the shell -options accepted by @code{shopt} are printed on the standard output. -If the invocation option is @option{+O}, the output is displayed in a format -that may be reused as input. - -@item -- -A @code{--} signals the end of options and disables further option -processing. -Any arguments after the @code{--} are treated as filenames and arguments. -@end table - -@cindex login shell -A @emph{login} shell is one whose first character of argument zero is -@samp{-}, or one invoked with the @option{--login} option. - -@cindex interactive shell -An @emph{interactive} shell is one started without non-option arguments, -unless @option{-s} is specified, -without specifying the @option{-c} option, and whose input and output are both -connected to terminals (as determined by @code{isatty(3)}), or one -started with the @option{-i} option. @xref{Interactive Shells}, for more -information. - -If arguments remain after option processing, and neither the -@option{-c} nor the @option{-s} -option has been supplied, the first argument is assumed to -be the name of a file containing shell commands (@pxref{Shell Scripts}). -When Bash is invoked in this fashion, @code{$0} -is set to the name of the file, and the positional parameters -are set to the remaining arguments. -Bash reads and executes commands from this file, then exits. -Bash's exit status is the exit status of the last command executed -in the script. If no commands are executed, the exit status is 0. - -@node Bash Startup Files -@section Bash Startup Files -@cindex startup files - -This section describes how Bash executes its startup files. -If any of the files exist but cannot be read, Bash reports an error. -Tildes are expanded in filenames as described above under -Tilde Expansion (@pxref{Tilde Expansion}). - -Interactive shells are described in @ref{Interactive Shells}. - -@subsubheading Invoked as an interactive login shell, or with @option{--login} - -When Bash is invoked as an interactive login shell, or as a -non-interactive shell with the @option{--login} option, it first reads and -executes commands from the file @file{/etc/profile}, if that file exists. -After reading that file, it looks for @file{~/.bash_profile}, -@file{~/.bash_login}, and @file{~/.profile}, in that order, and reads -and executes commands from the first one that exists and is readable. -The @option{--noprofile} option may be used when the shell is started to -inhibit this behavior. - -When a login shell exits, Bash reads and executes commands from -the file @file{~/.bash_logout}, if it exists. - -@subsubheading Invoked as an interactive non-login shell - -When an interactive shell that is not a login shell is started, Bash -reads and executes commands from @file{~/.bashrc}, if that file exists. -This may be inhibited by using the @option{--norc} option. -The @option{--rcfile @var{file}} option will force Bash to read and -execute commands from @var{file} instead of @file{~/.bashrc}. - -So, typically, your @file{~/.bash_profile} contains the line -@example -@code{if [ -f ~/.bashrc ]; then . ~/.bashrc; fi} -@end example -@noindent -after (or before) any login-specific initializations. - -@subsubheading Invoked non-interactively - -When Bash is started non-interactively, to run a shell script, -for example, it looks for the variable @env{BASH_ENV} in the environment, -expands its value if it appears there, and uses the expanded value as -the name of a file to read and execute. Bash behaves as if the -following command were executed: -@example -@code{if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi} -@end example -@noindent -but the value of the @env{PATH} variable is not used to search for the -filename. - -As noted above, if a non-interactive shell is invoked with the -@option{--login} option, Bash attempts to read and execute commands from the -login shell startup files. - -@subsubheading Invoked with name @code{sh} - -If Bash is invoked with the name @code{sh}, it tries to mimic the -startup behavior of historical versions of @code{sh} as closely as -possible, while conforming to the @sc{posix} standard as well. - -When invoked as an interactive login shell, or as a non-interactive -shell with the @option{--login} option, it first attempts to read -and execute commands from @file{/etc/profile} and @file{~/.profile}, in -that order. -The @option{--noprofile} option may be used to inhibit this behavior. -When invoked as an interactive shell with the name @code{sh}, Bash -looks for the variable @env{ENV}, expands its value if it is defined, -and uses the expanded value as the name of a file to read and execute. -Since a shell invoked as @code{sh} does not attempt to read and execute -commands from any other startup files, the @option{--rcfile} option has -no effect. -A non-interactive shell invoked with the name @code{sh} does not attempt -to read any other startup files. - -When invoked as @code{sh}, Bash enters @sc{posix} mode after -the startup files are read. - -@subsubheading Invoked in @sc{posix} mode - -When Bash is started in @sc{posix} mode, as with the -@option{--posix} command line option, it follows the @sc{posix} standard -for startup files. -In this mode, interactive shells expand the @env{ENV} variable -and commands are read and executed from the file whose name is the -expanded value. -No other startup files are read. - -@subsubheading Invoked by remote shell daemon - -Bash attempts to determine when it is being run with its standard input -connected to a network connection, as when executed by the remote shell -daemon, usually @code{rshd}, or the secure shell daemon @code{sshd}. -If Bash determines it is being run in -this fashion, it reads and executes commands from @file{~/.bashrc}, if that -file exists and is readable. -It will not do this if invoked as @code{sh}. -The @option{--norc} option may be used to inhibit this behavior, and the -@option{--rcfile} option may be used to force another file to be read, but -neither @code{rshd} nor @code{sshd} generally invoke the shell with those -options or allow them to be specified. - -@subsubheading Invoked with unequal effective and real @sc{uid/gid}s - -If Bash is started with the effective user (group) id not equal to the -real user (group) id, and the @option{-p} option is not supplied, no startup -files are read, shell functions are not inherited from the environment, -the @env{SHELLOPTS}, @env{BASHOPTS}, @env{CDPATH}, and @env{GLOBIGNORE} -variables, if they appear in the environment, are ignored, and the effective -user id is set to the real user id. -If the @option{-p} option is supplied at invocation, the startup behavior is -the same, but the effective user id is not reset. - -@node Interactive Shells -@section Interactive Shells -@cindex interactive shell -@cindex shell, interactive - -@menu -* What is an Interactive Shell?:: What determines whether a shell is Interactive. -* Is this Shell Interactive?:: How to tell if a shell is interactive. -* Interactive Shell Behavior:: What changes in a interactive shell? -@end menu - -@node What is an Interactive Shell? -@subsection What is an Interactive Shell? - -An interactive shell -is one started without non-option arguments, unless @option{-s} is -specified, without specifying the @option{-c} option, and -whose input and error output are both -connected to terminals (as determined by @code{isatty(3)}), -or one started with the @option{-i} option. - -An interactive shell generally reads from and writes to a user's -terminal. - -The @option{-s} invocation option may be used to set the positional parameters -when an interactive shell is started. - -@node Is this Shell Interactive? -@subsection Is this Shell Interactive? - -To determine within a startup script whether or not Bash is -running interactively, -test the value of the @samp{-} special parameter. -It contains @code{i} when the shell is interactive. For example: - -@example -case "$-" in -*i*) echo This shell is interactive ;; -*) echo This shell is not interactive ;; -esac -@end example - -Alternatively, startup scripts may examine the variable -@env{PS1}; it is unset in non-interactive shells, and set in -interactive shells. Thus: - -@example -if [ -z "$PS1" ]; then - echo This shell is not interactive -else - echo This shell is interactive -fi -@end example - -@node Interactive Shell Behavior -@subsection Interactive Shell Behavior - -When the shell is running interactively, it changes its behavior in -several ways. - -@enumerate -@item -Startup files are read and executed as described in @ref{Bash Startup Files}. - -@item -Job Control (@pxref{Job Control}) is enabled by default. When job -control is in effect, Bash ignores the keyboard-generated job control -signals @code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}. - -@item -Bash expands and displays @env{PS1} before reading the first line -of a command, and expands and displays @env{PS2} before reading the -second and subsequent lines of a multi-line command. - -@item -Bash executes the value of the @env{PROMPT_COMMAND} variable as a command -before printing the primary prompt, @env{$PS1} -(@pxref{Bash Variables}). - -@item -Readline (@pxref{Command Line Editing}) is used to read commands from -the user's terminal. - -@item -Bash inspects the value of the @code{ignoreeof} option to @code{set -o} -instead of exiting immediately when it receives an @code{EOF} on its -standard input when reading a command (@pxref{The Set Builtin}). - -@item -Command history (@pxref{Bash History Facilities}) -and history expansion (@pxref{History Interaction}) -are enabled by default. -Bash will save the command history to the file named by @env{$HISTFILE} -when a shell with history enabled exits. - -@item -Alias expansion (@pxref{Aliases}) is performed by default. - -@item -In the absence of any traps, Bash ignores @code{SIGTERM} -(@pxref{Signals}). - -@item -In the absence of any traps, @code{SIGINT} is caught and handled -((@pxref{Signals}). -@code{SIGINT} will interrupt some shell builtins. - -@item -An interactive login shell sends a @code{SIGHUP} to all jobs on exit -if the @code{huponexit} shell option has been enabled (@pxref{Signals}). - -@item -The @option{-n} invocation option is ignored, and @samp{set -n} has -no effect (@pxref{The Set Builtin}). - -@item -Bash will check for mail periodically, depending on the values of the -@env{MAIL}, @env{MAILPATH}, and @env{MAILCHECK} shell variables -(@pxref{Bash Variables}). - -@item -Expansion errors due to references to unbound shell variables after -@samp{set -u} has been enabled will not cause the shell to exit -(@pxref{The Set Builtin}). - -@item -The shell will not exit on expansion errors caused by @var{var} being unset -or null in @code{$@{@var{var}:?@var{word}@}} expansions -(@pxref{Shell Parameter Expansion}). - -@item -Redirection errors encountered by shell builtins will not cause the -shell to exit. - -@item -When running in @sc{posix} mode, a special builtin returning an error -status will not cause the shell to exit (@pxref{Bash POSIX Mode}). - -@item -A failed @code{exec} will not cause the shell to exit -(@pxref{Bourne Shell Builtins}). - -@item -Parser syntax errors will not cause the shell to exit. - -@item -Simple spelling correction for directory arguments to the @code{cd} -builtin is enabled by default (see the description of the @code{cdspell} -option to the @code{shopt} builtin in @ref{The Shopt Builtin}). - -@item -The shell will check the value of the @env{TMOUT} variable and exit -if a command is not read within the specified number of seconds after -printing @env{$PS1} (@pxref{Bash Variables}). - -@end enumerate - -@node Bash Conditional Expressions -@section Bash Conditional Expressions -@cindex expressions, conditional - -Conditional expressions are used by the @code{[[} compound command -and the @code{test} and @code{[} builtin commands. - -Expressions may be unary or binary. -Unary expressions are often used to examine the status of a file. -There are string operators and numeric comparison operators as well. -If the @var{file} argument to one of the primaries is of the form -@file{/dev/fd/@var{N}}, then file descriptor @var{N} is checked. -If the @var{file} argument to one of the primaries is one of -@file{/dev/stdin}, @file{/dev/stdout}, or @file{/dev/stderr}, file -descriptor 0, 1, or 2, respectively, is checked. - -When used with @code{[[}, the @samp{<} and @samp{>} operators sort -lexicographically using the current locale. -The @code{test} command uses ASCII ordering. - -Unless otherwise specified, primaries that operate on files follow symbolic -links and operate on the target of the link, rather than the link itself. - -@table @code -@item -a @var{file} -True if @var{file} exists. - -@item -b @var{file} -True if @var{file} exists and is a block special file. - -@item -c @var{file} -True if @var{file} exists and is a character special file. - -@item -d @var{file} -True if @var{file} exists and is a directory. - -@item -e @var{file} -True if @var{file} exists. - -@item -f @var{file} -True if @var{file} exists and is a regular file. - -@item -g @var{file} -True if @var{file} exists and its set-group-id bit is set. - -@item -h @var{file} -True if @var{file} exists and is a symbolic link. - -@item -k @var{file} -True if @var{file} exists and its "sticky" bit is set. - -@item -p @var{file} -True if @var{file} exists and is a named pipe (FIFO). - -@item -r @var{file} -True if @var{file} exists and is readable. - -@item -s @var{file} -True if @var{file} exists and has a size greater than zero. - -@item -t @var{fd} -True if file descriptor @var{fd} is open and refers to a terminal. - -@item -u @var{file} -True if @var{file} exists and its set-user-id bit is set. - -@item -w @var{file} -True if @var{file} exists and is writable. - -@item -x @var{file} -True if @var{file} exists and is executable. - -@item -G @var{file} -True if @var{file} exists and is owned by the effective group id. - -@item -L @var{file} -True if @var{file} exists and is a symbolic link. - -@item -N @var{file} -True if @var{file} exists and has been modified since it was last read. - -@item -O @var{file} -True if @var{file} exists and is owned by the effective user id. - -@item -S @var{file} -True if @var{file} exists and is a socket. - -@item @var{file1} -ef @var{file2} -True if @var{file1} and @var{file2} refer to the same device and -inode numbers. - -@item @var{file1} -nt @var{file2} -True if @var{file1} is newer (according to modification date) -than @var{file2}, or if @var{file1} exists and @var{file2} does not. - -@item @var{file1} -ot @var{file2} -True if @var{file1} is older than @var{file2}, -or if @var{file2} exists and @var{file1} does not. - -@item -o @var{optname} -True if the shell option @var{optname} is enabled. -The list of options appears in the description of the @option{-o} -option to the @code{set} builtin (@pxref{The Set Builtin}). - -@item -v @var{varname} -True if the shell variable @var{varname} is set (has been assigned a value). - -@item -R @var{varname} -True if the shell variable @var{varname} is set and is a name reference. - -@item -z @var{string} -True if the length of @var{string} is zero. - -@item -n @var{string} -@itemx @var{string} -True if the length of @var{string} is non-zero. - -@item @var{string1} == @var{string2} -@itemx @var{string1} = @var{string2} -True if the strings are equal. -When used with the @code{[[} command, this performs pattern matching as -described above (@pxref{Conditional Constructs}). - -@samp{=} should be used with the @code{test} command for @sc{posix} conformance. - -@item @var{string1} != @var{string2} -True if the strings are not equal. - -@item @var{string1} < @var{string2} -True if @var{string1} sorts before @var{string2} lexicographically. - -@item @var{string1} > @var{string2} -True if @var{string1} sorts after @var{string2} lexicographically. - -@item @var{arg1} OP @var{arg2} -@code{OP} is one of -@samp{-eq}, @samp{-ne}, @samp{-lt}, @samp{-le}, @samp{-gt}, or @samp{-ge}. -These arithmetic binary operators return true if @var{arg1} -is equal to, not equal to, less than, less than or equal to, -greater than, or greater than or equal to @var{arg2}, -respectively. @var{Arg1} and @var{arg2} -may be positive or negative integers. -@end table - -@node Shell Arithmetic -@section Shell Arithmetic -@cindex arithmetic, shell -@cindex shell arithmetic -@cindex expressions, arithmetic -@cindex evaluation, arithmetic -@cindex arithmetic evaluation - -The shell allows arithmetic expressions to be evaluated, as one of -the shell expansions or by the @code{let} and the @option{-i} option -to the @code{declare} builtins. - -Evaluation is done in fixed-width integers with no check for overflow, -though division by 0 is trapped and flagged as an error. -The operators and their precedence, associativity, and values -are the same as in the C language. -The following list of operators is grouped into levels of -equal-precedence operators. -The levels are listed in order of decreasing precedence. - -@table @code - -@item @var{id}++ @var{id}-- -variable post-increment and post-decrement - -@item ++@var{id} --@var{id} -variable pre-increment and pre-decrement - -@item - + -unary minus and plus - -@item ! ~ -logical and bitwise negation - -@item ** -exponentiation - -@item * / % -multiplication, division, remainder - -@item + - -addition, subtraction - -@item << >> -left and right bitwise shifts - -@item <= >= < > -comparison - -@item == != -equality and inequality - -@item & -bitwise AND - -@item ^ -bitwise exclusive OR - -@item | -bitwise OR - -@item && -logical AND - -@item || -logical OR - -@item expr ? expr : expr -conditional operator - -@item = *= /= %= += -= <<= >>= &= ^= |= -assignment - -@item expr1 , expr2 -comma -@end table - -Shell variables are allowed as operands; parameter expansion is -performed before the expression is evaluated. -Within an expression, shell variables may also be referenced by name -without using the parameter expansion syntax. -A shell variable that is null or unset evaluates to 0 when referenced -by name without using the parameter expansion syntax. -The value of a variable is evaluated as an arithmetic expression -when it is referenced, or when a variable which has been given the -@var{integer} attribute using @samp{declare -i} is assigned a value. -A null value evaluates to 0. -A shell variable need not have its @var{integer} attribute turned on -to be used in an expression. - -Constants with a leading 0 are interpreted as octal numbers. -A leading @samp{0x} or @samp{0X} denotes hexadecimal. Otherwise, -numbers take the form [@var{base}@code{#}]@var{n}, where the optional @var{base} -is a decimal number between 2 and 64 representing the arithmetic -base, and @var{n} is a number in that base. -If @var{base}@code{#} is omitted, then base 10 is used. -When specifying @var{n}, -he digits greater than 9 are represented by the lowercase letters, -the uppercase letters, @samp{@@}, and @samp{_}, in that order. -If @var{base} is less than or equal to 36, lowercase and uppercase -letters may be used interchangeably to represent numbers between 10 -and 35. - -Operators are evaluated in order of precedence. Sub-expressions in -parentheses are evaluated first and may override the precedence -rules above. - -@node Aliases -@section Aliases -@cindex alias expansion - -@var{Aliases} allow a string to be substituted for a word when it is used -as the first word of a simple command. -The shell maintains a list of aliases that may be set and unset with -the @code{alias} and @code{unalias} builtin commands. - -The first word of each simple command, if unquoted, is checked to see -if it has an alias. -If so, that word is replaced by the text of the alias. -The characters @samp{/}, @samp{$}, @samp{`}, @samp{=} and any of the -shell metacharacters or quoting characters listed above may not appear -in an alias name. -The replacement text may contain any valid -shell input, including shell metacharacters. -The first word of the replacement text is tested for -aliases, but a word that is identical to an alias being expanded -is not expanded a second time. -This means that one may alias @code{ls} to @code{"ls -F"}, -for instance, and Bash does not try to recursively expand the -replacement text. -If the last character of the alias value is a -@var{blank}, then the next command word following the -alias is also checked for alias expansion. - -Aliases are created and listed with the @code{alias} -command, and removed with the @code{unalias} command. - -There is no mechanism for using arguments in the replacement text, -as in @code{csh}. -If arguments are needed, a shell function should be used -(@pxref{Shell Functions}). - -Aliases are not expanded when the shell is not interactive, -unless the @code{expand_aliases} shell option is set using -@code{shopt} (@pxref{The Shopt Builtin}). - -The rules concerning the definition and use of aliases are -somewhat confusing. Bash -always reads at least one complete line -of input before executing any -of the commands on that line. Aliases are expanded when a -command is read, not when it is executed. Therefore, an -alias definition appearing on the same line as another -command does not take effect until the next line of input is read. -The commands following the alias definition -on that line are not affected by the new alias. -This behavior is also an issue when functions are executed. -Aliases are expanded when a function definition is read, -not when the function is executed, because a function definition -is itself a command. As a consequence, aliases -defined in a function are not available until after that -function is executed. To be safe, always put -alias definitions on a separate line, and do not use @code{alias} -in compound commands. - -For almost every purpose, shell functions are preferred over aliases. - -@node Arrays -@section Arrays -@cindex arrays - -Bash provides one-dimensional indexed and associative array variables. -Any variable may be used as an indexed array; -the @code{declare} builtin will explicitly declare an array. -There is no maximum -limit on the size of an array, nor any requirement that members -be indexed or assigned contiguously. -Indexed arrays are referenced using integers (including arithmetic -expressions (@pxref{Shell Arithmetic})) and are zero-based; -associative arrays use arbitrary strings. -Unless otherwise noted, indexed array indices must be non-negative integers. - -An indexed array is created automatically if any variable is assigned to -using the syntax -@example -@var{name}[@var{subscript}]=@var{value} -@end example - -@noindent -The @var{subscript} -is treated as an arithmetic expression that must evaluate to a number. -To explicitly declare an array, use -@example -declare -a @var{name} -@end example -@noindent -The syntax -@example -declare -a @var{name}[@var{subscript}] -@end example -@noindent -is also accepted; the @var{subscript} is ignored. - -@noindent -Associative arrays are created using -@example -declare -A @var{name}. -@end example - -Attributes may be -specified for an array variable using the @code{declare} and -@code{readonly} builtins. Each attribute applies to all members of -an array. - -Arrays are assigned to using compound assignments of the form -@example -@var{name}=(@var{value1} @var{value2} @dots{} ) -@end example -@noindent -where each -@var{value} is of the form @code{[@var{subscript}]=}@var{string}. -Indexed array assignments do not require anything but @var{string}. -When assigning to indexed arrays, if -the optional subscript is supplied, that index is assigned to; -otherwise the index of the element assigned is the last index assigned -to by the statement plus one. Indexing starts at zero. - -When assigning to an associative array, the subscript is required. - -This syntax is also accepted by the @code{declare} -builtin. Individual array elements may be assigned to using the -@code{@var{name}[@var{subscript}]=@var{value}} syntax introduced above. - -When assigning to an indexed array, if @var{name} -is subscripted by a negative number, that number is -interpreted as relative to one greater than the maximum index of -@var{name}, so negative indices count back from the end of the -array, and an index of -1 references the last element. - -Any element of an array may be referenced using -@code{$@{@var{name}[@var{subscript}]@}}. -The braces are required to avoid -conflicts with the shell's filename expansion operators. If the -@var{subscript} is @samp{@@} or @samp{*}, the word expands to all members -of the array @var{name}. These subscripts differ only when the word -appears within double quotes. -If the word is double-quoted, -@code{$@{@var{name}[*]@}} expands to a single word with -the value of each array member separated by the first character of the -@env{IFS} variable, and @code{$@{@var{name}[@@]@}} expands each element of -@var{name} to a separate word. When there are no array members, -@code{$@{@var{name}[@@]@}} expands to nothing. -If the double-quoted expansion occurs within a word, the expansion of -the first parameter is joined with the beginning part of the original -word, and the expansion of the last parameter is joined with the last -part of the original word. -This is analogous to the -expansion of the special parameters @samp{@@} and @samp{*}. -@code{$@{#@var{name}[@var{subscript}]@}} expands to the length of -@code{$@{@var{name}[@var{subscript}]@}}. -If @var{subscript} is @samp{@@} or -@samp{*}, the expansion is the number of elements in the array. -Referencing an array variable without a subscript is equivalent to -referencing with a subscript of 0. -If the @var{subscript} -used to reference an element of an indexed array -evaluates to a number less than zero, it is -interpreted as relative to one greater than the maximum index of the array, -so negative indices count back from the end of the array, -and an index of -1 refers to the last element. - -An array variable is considered set if a subscript has been assigned a -value. The null string is a valid value. - -It is possible to obtain the keys (indices) of an array as well as the values. -$@{!@var{name}[@@]@} and $@{!@var{name}[*]@} expand to the indices -assigned in array variable @var{name}. -The treatment when in double quotes is similar to the expansion of the -special parameters @samp{@@} and @samp{*} within double quotes. - -The @code{unset} builtin is used to destroy arrays. -@code{unset @var{name}[@var{subscript}]} -destroys the array element at index @var{subscript}. -Negative subscripts to indexed arrays are interpreted as described above. -Care must be taken to avoid unwanted side effects caused by filename -expansion. -@code{unset @var{name}}, where @var{name} is an array, removes the -entire array. A subscript of @samp{*} or @samp{@@} also removes the -entire array. - -The @code{declare}, @code{local}, and @code{readonly} -builtins each accept a @option{-a} option to specify an indexed -array and a @option{-A} option to specify an associative array. -If both options are supplied, @option{-A} takes precedence. -The @code{read} builtin accepts a @option{-a} -option to assign a list of words read from the standard input -to an array, and can read values from the standard input into -individual array elements. The @code{set} and @code{declare} -builtins display array values in a way that allows them to be -reused as input. - -@node The Directory Stack -@section The Directory Stack -@cindex directory stack - -@menu -* Directory Stack Builtins:: Bash builtin commands to manipulate - the directory stack. -@end menu - -The directory stack is a list of recently-visited directories. The -@code{pushd} builtin adds directories to the stack as it changes -the current directory, and the @code{popd} builtin removes specified -directories from the stack and changes the current directory to -the directory removed. The @code{dirs} builtin displays the contents -of the directory stack. - -The contents of the directory stack are also visible -as the value of the @env{DIRSTACK} shell variable. - -@node Directory Stack Builtins -@subsection Directory Stack Builtins - -@table @code - -@item dirs -@btindex dirs -@example -dirs [-clpv] [+@var{N} | -@var{N}] -@end example - -Display the list of currently remembered directories. Directories -are added to the list with the @code{pushd} command; the -@code{popd} command removes directories from the list. - -@table @code -@item -c -Clears the directory stack by deleting all of the elements. -@item -l -Produces a listing using full pathnames; -the default listing format uses a tilde to denote the home directory. -@item -p -Causes @code{dirs} to print the directory stack with one entry per -line. -@item -v -Causes @code{dirs} to print the directory stack with one entry per -line, prefixing each entry with its index in the stack. -@item +@var{N} -Displays the @var{N}th directory (counting from the left of the -list printed by @code{dirs} when invoked without options), starting -with zero. -@item -@var{N} -Displays the @var{N}th directory (counting from the right of the -list printed by @code{dirs} when invoked without options), starting -with zero. -@end table - -@item popd -@btindex popd -@example -popd [-n] [+@var{N} | -@var{N}] -@end example - -Remove the top entry from the directory stack, and @code{cd} -to the new top directory. -When no arguments are given, @code{popd} -removes the top directory from the stack and -performs a @code{cd} to the new top directory. The -elements are numbered from 0 starting at the first directory listed with -@code{dirs}; that is, @code{popd} is equivalent to @code{popd +0}. - -@table @code -@item -n -Suppresses the normal change of directory when removing directories -from the stack, so that only the stack is manipulated. -@item +@var{N} -Removes the @var{N}th directory (counting from the left of the -list printed by @code{dirs}), starting with zero. -@item -@var{N} -Removes the @var{N}th directory (counting from the right of the -list printed by @code{dirs}), starting with zero. -@end table - -@btindex pushd -@item pushd -@example -pushd [-n] [@var{+N} | @var{-N} | @var{dir}] -@end example - -Save the current directory on the top of the directory stack -and then @code{cd} to @var{dir}. -With no arguments, @code{pushd} exchanges the top two directories. - -@table @code -@item -n -Suppresses the normal change of directory when adding directories -to the stack, so that only the stack is manipulated. -@item +@var{N} -Brings the @var{N}th directory (counting from the left of the -list printed by @code{dirs}, starting with zero) to the top of -the list by rotating the stack. -@item -@var{N} -Brings the @var{N}th directory (counting from the right of the -list printed by @code{dirs}, starting with zero) to the top of -the list by rotating the stack. -@item @var{dir} -Makes the current working directory be the top of the stack, making -it the new current directory as if it had been supplied as an argument -to the @code{cd} builtin. -@end table -@end table - -@node Controlling the Prompt -@section Controlling the Prompt -@cindex prompting - -The value of the variable @env{PROMPT_COMMAND} is examined just before -Bash prints each primary prompt. If @env{PROMPT_COMMAND} is set and -has a non-null value, then the -value is executed just as if it had been typed on the command line. - -In addition, the following table describes the special characters which -can appear in the prompt variables @env{PS1} to @env{PS4}: - -@table @code -@item \a -A bell character. -@item \d -The date, in "Weekday Month Date" format (e.g., "Tue May 26"). -@item \D@{@var{format}@} -The @var{format} is passed to @code{strftime}(3) and the result is inserted -into the prompt string; an empty @var{format} results in a locale-specific -time representation. The braces are required. -@item \e -An escape character. -@item \h -The hostname, up to the first `.'. -@item \H -The hostname. -@item \j -The number of jobs currently managed by the shell. -@item \l -The basename of the shell's terminal device name. -@item \n -A newline. -@item \r -A carriage return. -@item \s -The name of the shell, the basename of @code{$0} (the portion -following the final slash). -@item \t -The time, in 24-hour HH:MM:SS format. -@item \T -The time, in 12-hour HH:MM:SS format. -@item \@@ -The time, in 12-hour am/pm format. -@item \A -The time, in 24-hour HH:MM format. -@item \u -The username of the current user. -@item \v -The version of Bash (e.g., 2.00) -@item \V -The release of Bash, version + patchlevel (e.g., 2.00.0) -@item \w -The current working directory, with @env{$HOME} abbreviated with a tilde -(uses the @env{$PROMPT_DIRTRIM} variable). -@item \W -The basename of @env{$PWD}, with @env{$HOME} abbreviated with a tilde. -@item \! -The history number of this command. -@item \# -The command number of this command. -@item \$ -If the effective uid is 0, @code{#}, otherwise @code{$}. -@item \@var{nnn} -The character whose ASCII code is the octal value @var{nnn}. -@item \\ -A backslash. -@item \[ -Begin a sequence of non-printing characters. This could be used to -embed a terminal control sequence into the prompt. -@item \] -End a sequence of non-printing characters. -@end table - -The command number and the history number are usually different: -the history number of a command is its position in the history -list, which may include commands restored from the history file -(@pxref{Bash History Facilities}), while the command number is -the position in the sequence of commands executed during the current -shell session. - -After the string is decoded, it is expanded via -parameter expansion, command substitution, arithmetic -expansion, and quote removal, subject to the value of the -@code{promptvars} shell option (@pxref{Bash Builtins}). - -@node The Restricted Shell -@section The Restricted Shell -@cindex restricted shell - -If Bash is started with the name @code{rbash}, or the -@option{--restricted} -or -@option{-r} -option is supplied at invocation, the shell becomes restricted. -A restricted shell is used to -set up an environment more controlled than the standard shell. -A restricted shell behaves identically to @code{bash} -with the exception that the following are disallowed or not performed: - -@itemize @bullet -@item -Changing directories with the @code{cd} builtin. -@item -Setting or unsetting the values of the @env{SHELL}, @env{PATH}, -@env{ENV}, or @env{BASH_ENV} variables. -@item -Specifying command names containing slashes. -@item -Specifying a filename containing a slash as an argument to the @code{.} -builtin command. -@item -Specifying a filename containing a slash as an argument to the @option{-p} -option to the @code{hash} builtin command. -@item -Importing function definitions from the shell environment at startup. -@item -Parsing the value of @env{SHELLOPTS} from the shell environment at startup. -@item -Redirecting output using the @samp{>}, @samp{>|}, @samp{<>}, @samp{>&}, -@samp{&>}, and @samp{>>} redirection operators. -@item -Using the @code{exec} builtin to replace the shell with another command. -@item -Adding or deleting builtin commands with the -@option{-f} and @option{-d} options to the @code{enable} builtin. -@item -Using the @code{enable} builtin command to enable disabled shell builtins. -@item -Specifying the @option{-p} option to the @code{command} builtin. -@item -Turning off restricted mode with @samp{set +r} or @samp{set +o restricted}. -@end itemize - -These restrictions are enforced after any startup files are read. - -When a command that is found to be a shell script is executed -(@pxref{Shell Scripts}), @code{rbash} turns off any restrictions in -the shell spawned to execute the script. - -@node Bash POSIX Mode -@section Bash POSIX Mode -@cindex POSIX Mode - -Starting Bash with the @option{--posix} command-line option or executing -@samp{set -o posix} while Bash is running will cause Bash to conform more -closely to the @sc{posix} standard by changing the behavior to -match that specified by @sc{posix} in areas where the Bash default differs. - -When invoked as @code{sh}, Bash enters @sc{posix} mode after reading the -startup files. - -The following list is what's changed when `@sc{posix} mode' is in effect: - -@enumerate -@item -When a command in the hash table no longer exists, Bash will re-search -@env{$PATH} to find the new location. This is also available with -@samp{shopt -s checkhash}. - -@item -The message printed by the job control code and builtins when a job -exits with a non-zero status is `Done(status)'. - -@item -The message printed by the job control code and builtins when a job -is stopped is `Stopped(@var{signame})', where @var{signame} is, for -example, @code{SIGTSTP}. - -@item -The @code{bg} builtin uses the required format to describe each job placed -in the background, which does not include an indication of whether the job -is the current or previous job. - -@item -Reserved words appearing in a context where reserved words are recognized -do not undergo alias expansion. - -@item -The @sc{posix} @env{PS1} and @env{PS2} expansions of @samp{!} to -the history number and @samp{!!} to @samp{!} are enabled, -and parameter expansion is performed on the values of @env{PS1} and -@env{PS2} regardless of the setting of the @code{promptvars} option. - -@item -The @sc{posix} startup files are executed (@env{$ENV}) rather than -the normal Bash files. - -@item -Tilde expansion is only performed on assignments preceding a command -name, rather than on all assignment statements on the line. - -@item -The @code{command} builtin does not prevent builtins that take assignment -statements as arguments from expanding them as assignment statements; -when not in @sc{posix} mode, assignment builtins lose their assignment -statement expansion properties when preceded by @code{command}. - -@item -The default history file is @file{~/.sh_history} (this is the -default value of @env{$HISTFILE}). - -@item -The output of @samp{kill -l} prints all the signal names on a single line, -separated by spaces, without the @samp{SIG} prefix. - -@item -The @code{kill} builtin does not accept signal names with a @samp{SIG} -prefix. - -@item -Non-interactive shells exit if @var{filename} in @code{.} @var{filename} -is not found. - -@item -Non-interactive shells exit if a syntax error in an arithmetic expansion -results in an invalid expression. - -@item -Non-interactive shells exit if there is a syntax error in a script read -with the @code{.} or @code{source} builtins, or in a string processed by -the @code{eval} builtin. - -@item -Redirection operators do not perform filename expansion on the word -in the redirection unless the shell is interactive. - -@item -Redirection operators do not perform word splitting on the word in the -redirection. - -@item -Function names must be valid shell @code{name}s. 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 invalid name -causes a fatal syntax error in non-interactive shells. - -@item -Function names may not be the same as one of the @sc{posix} special -builtins. - -@item -@sc{posix} special builtins are found before shell functions -during command lookup. - -@item -The @code{time} reserved word may be used by itself as a command. When -used in this way, it displays timing statistics for the shell and its -completed children. The @env{TIMEFORMAT} variable controls the format -of the timing information. - -@item -When parsing and expanding a $@{@dots{}@} expansion that appears within -double quotes, single quotes are no longer special and cannot be used to -quote a closing brace or other special character, unless the operator is -one of those defined to perform pattern removal. In this case, they do -not have to appear as matched pairs. - -@item -The parser does not recognize @code{time} as a reserved word if the next -token begins with a @samp{-}. - -@item -If a @sc{posix} special builtin returns an error status, a -non-interactive shell exits. The fatal errors are those listed in -the @sc{posix} standard, and include things like passing incorrect options, -redirection errors, variable assignment errors for assignments preceding -the command name, and so on. - -@item -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 readonly variable. - -@item -A non-interactive shell exits with an error status if a variable -assignment error occurs in an assignment statement preceding a special -builtin, but not with any other simple command. - -@item -A non-interactive shell exits with an error status if the iteration -variable in a @code{for} statement or the selection variable in a -@code{select} statement is a readonly variable. - -@item -Process substitution is not available. - -@item -While variable indirection is available, it may not be applied to the -@samp{#} and @samp{?} special parameters. - -@item -Assignment statements preceding @sc{posix} special builtins -persist in the shell environment after the builtin completes. - -@item -Assignment statements preceding shell function calls persist in the -shell environment after the function returns, as if a @sc{posix} -special builtin command had been executed. - -@item -The @code{export} and @code{readonly} builtin commands display their -output in the format required by @sc{posix}. - -@item -The @code{trap} builtin displays signal names without the leading -@code{SIG}. - -@item -The @code{trap} builtin doesn't check the first argument for a possible -signal specification and revert the signal handling to the original -disposition if it is, unless that argument consists solely of digits and -is a valid signal number. If users want to reset the handler for a given -signal to the original disposition, they should use @samp{-} as the -first argument. - -@item -The @code{.} and @code{source} builtins do not search the current directory -for the filename argument if it is not found by searching @env{PATH}. - -@item -Subshells spawned to execute command substitutions inherit the value of -the @option{-e} option from the parent shell. When not in @sc{posix} mode, -Bash clears the @option{-e} option in such subshells. - -@item -Alias expansion is always enabled, even in non-interactive shells. - -@item -When the @code{alias} builtin displays alias definitions, it does not -display them with a leading @samp{alias } unless the @option{-p} option -is supplied. - -@item -When the @code{set} builtin is invoked without options, it does not display -shell function names and definitions. - -@item -When the @code{set} builtin is invoked without options, it displays -variable values without quotes, unless they contain shell metacharacters, -even if the result contains nonprinting characters. - -@item -When the @code{cd} builtin is invoked in @var{logical} mode, and the pathname -constructed from @code{$PWD} and the directory name supplied as an argument -does not refer to an existing directory, @code{cd} will fail instead of -falling back to @var{physical} mode. - -@item -The @code{pwd} builtin verifies that the value it prints is the same as the -current directory, even if it is not asked to check the file system with the -@option{-P} option. - -@item -When listing the history, the @code{fc} builtin does not include an -indication of whether or not a history entry has been modified. - -@item -The default editor used by @code{fc} is @code{ed}. - -@item -The @code{type} and @code{command} builtins will not report a non-executable -file as having been found, though the shell will attempt to execute such a -file if it is the only so-named file found in @code{$PATH}. - -@item -The @code{vi} editing mode will invoke the @code{vi} editor directly when -the @samp{v} command is run, instead of checking @code{$VISUAL} and -@code{$EDITOR}. - -@item -When the @code{xpg_echo} option is enabled, Bash does not attempt to interpret -any arguments to @code{echo} as options. Each argument is displayed, after -escape characters are converted. - -@item -The @code{ulimit} builtin uses a block size of 512 bytes for the @option{-c} -and @option{-f} options. - -@item -The arrival of @code{SIGCHLD} when a trap is set on @code{SIGCHLD} does -not interrupt the @code{wait} builtin and cause it to return immediately. -The trap command is run once for each child that exits. - -@item -The @code{read} builtin may be interrupted by a signal for which a trap -has been set. -If Bash receives a trapped signal while executing @code{read}, the trap -handler executes and @code{read} returns an exit status greater than 128. - -@end enumerate - -There is other @sc{posix} behavior that Bash does not implement by -default even when in @sc{posix} mode. -Specifically: - -@enumerate - -@item -The @code{fc} builtin checks @code{$EDITOR} as a program to edit history -entries if @code{FCEDIT} is unset, rather than defaulting directly to -@code{ed}. @code{fc} uses @code{ed} if @code{EDITOR} is unset. - -@item -As noted above, Bash requires the @code{xpg_echo} option to be enabled for -the @code{echo} builtin to be fully conformant. - -@end enumerate - -Bash can be configured to be @sc{posix}-conformant by default, by specifying -the @option{--enable-strict-posix-default} to @code{configure} when building -(@pxref{Optional Features}). - -@node Job Control -@chapter Job Control - -This chapter discusses what job control is, how it works, and how -Bash allows you to access its facilities. - -@menu -* Job Control Basics:: How job control works. -* Job Control Builtins:: Bash builtin commands used to interact - with job control. -* Job Control Variables:: Variables Bash uses to customize job - control. -@end menu - -@node Job Control Basics -@section Job Control Basics -@cindex job control -@cindex foreground -@cindex background -@cindex suspending jobs - -Job control -refers to the ability to selectively stop (suspend) -the execution of processes and continue (resume) -their execution at a later point. A user typically employs -this facility via an interactive interface supplied jointly -by the operating system kernel's terminal driver and Bash. - -The shell associates a @var{job} with each pipeline. It keeps a -table of currently executing jobs, which may be listed with the -@code{jobs} command. When Bash starts a job -asynchronously, it prints a line that looks -like: -@example -[1] 25647 -@end example -@noindent -indicating that this job is job number 1 and that the process @sc{id} -of the last process in the pipeline associated with this job is -25647. All of the processes in a single pipeline are members of -the same job. Bash uses the @var{job} abstraction as the -basis for job control. - -To facilitate the implementation of the user interface to job -control, the operating system maintains the notion of a current terminal -process group @sc{id}. Members of this process group (processes whose -process group @sc{id} is equal to the current terminal process group -@sc{id}) receive keyboard-generated signals such as @code{SIGINT}. -These processes are said to be in the foreground. Background -processes are those whose process group @sc{id} differs from the -terminal's; such processes are immune to keyboard-generated -signals. Only foreground processes are allowed to read from or, if -the user so specifies with @code{stty tostop}, write to the terminal. -Background processes which attempt to -read from (write to when @code{stty tostop} is in effect) the -terminal are sent a @code{SIGTTIN} (@code{SIGTTOU}) -signal by the kernel's terminal driver, -which, unless caught, suspends the process. - -If the operating system on which Bash is running supports -job control, Bash contains facilities to use it. Typing the -@var{suspend} character (typically @samp{^Z}, Control-Z) while a -process is running causes that process to be stopped and returns -control to Bash. Typing the @var{delayed suspend} character -(typically @samp{^Y}, Control-Y) causes the process to be stopped -when it attempts to read input from the terminal, and control to -be returned to Bash. The user then manipulates the state of -this job, using the @code{bg} command to continue it in the -background, the @code{fg} command to continue it in the -foreground, or the @code{kill} command to kill it. A @samp{^Z} -takes effect immediately, and has the additional side effect of -causing pending output and typeahead to be discarded. - -There are a number of ways to refer to a job in the shell. The -character @samp{%} introduces a job specification (@var{jobspec}). - -Job number @code{n} may be referred to as @samp{%n}. -The symbols @samp{%%} and @samp{%+} refer to the shell's notion of the -current job, which is the last job stopped while it was in the foreground -or started in the background. -A single @samp{%} (with no accompanying job specification) also refers -to the current job. -The previous job may be referenced using @samp{%-}. -If there is only a single job, @samp{%+} and @samp{%-} can both be used -to refer to that job. -In output pertaining to jobs (e.g., the output of the @code{jobs} -command), the current job is always flagged with a @samp{+}, and the -previous job with a @samp{-}. - -A job may also be referred to -using a prefix of the name used to start it, or using a substring -that appears in its command line. For example, @samp{%ce} refers -to a stopped @code{ce} job. Using @samp{%?ce}, on the -other hand, refers to any job containing the string @samp{ce} in -its command line. If the prefix or substring matches more than one job, -Bash reports an error. - -Simply naming a job can be used to bring it into the foreground: -@samp{%1} is a synonym for @samp{fg %1}, bringing job 1 from the -background into the foreground. Similarly, @samp{%1 &} resumes -job 1 in the background, equivalent to @samp{bg %1} - -The shell learns immediately whenever a job changes state. -Normally, Bash waits until it is about to print a prompt -before reporting changes in a job's status so as to not interrupt -any other output. -If the @option{-b} option to the @code{set} builtin is enabled, -Bash reports such changes immediately (@pxref{The Set Builtin}). -Any trap on @code{SIGCHLD} is executed for each child process -that exits. - -If an attempt to exit Bash is made while jobs are stopped, (or running, if -the @code{checkjobs} option is enabled -- see @ref{The Shopt Builtin}), the -shell prints a warning message, and if the @code{checkjobs} option is -enabled, lists the jobs and their statuses. -The @code{jobs} command may then be used to inspect their status. -If a second attempt to exit is made without an intervening command, -Bash does not print another warning, and any stopped jobs are terminated. - -@node Job Control Builtins -@section Job Control Builtins - -@table @code - -@item bg -@btindex bg -@example -bg [@var{jobspec} @dots{}] -@end example - -Resume each suspended job @var{jobspec} in the background, as if it -had been started with @samp{&}. -If @var{jobspec} is not supplied, the current job is used. -The return status is zero unless it is run when job control is not -enabled, or, when run with job control enabled, any -@var{jobspec} was not found or specifies a job -that was started without job control. - -@item fg -@btindex fg -@example -fg [@var{jobspec}] -@end example - -Resume the job @var{jobspec} in the foreground and make it the current job. -If @var{jobspec} is not supplied, the current job is used. -The return status is that of the command placed into the foreground, -or non-zero if run when job control is disabled or, when run with -job control enabled, @var{jobspec} does not specify a valid job or -@var{jobspec} specifies a job that was started without job control. - -@item jobs -@btindex jobs -@example -jobs [-lnprs] [@var{jobspec}] -jobs -x @var{command} [@var{arguments}] -@end example - -The first form lists the active jobs. The options have the -following meanings: - -@table @code -@item -l -List process @sc{id}s in addition to the normal information. - -@item -n -Display information only about jobs that have changed status since -the user was last notified of their status. - -@item -p -List only the process @sc{id} of the job's process group leader. - -@item -r -Display only running jobs. - -@item -s -Display only stopped jobs. -@end table - -If @var{jobspec} is given, -output is restricted to information about that job. -If @var{jobspec} is not supplied, the status of all jobs is -listed. - -If the @option{-x} option is supplied, @code{jobs} replaces any -@var{jobspec} found in @var{command} or @var{arguments} with the -corresponding process group @sc{id}, and executes @var{command}, -passing it @var{argument}s, returning its exit status. - -@item kill -@btindex kill -@example -kill [-s @var{sigspec}] [-n @var{signum}] [-@var{sigspec}] @var{jobspec} or @var{pid} -kill -l [@var{exit_status}] -@end example - -Send a signal specified by @var{sigspec} or @var{signum} to the process -named by job specification @var{jobspec} or process @sc{id} @var{pid}. -@var{sigspec} is either a case-insensitive signal name such as -@code{SIGINT} (with or without the @code{SIG} prefix) -or a signal number; @var{signum} is a signal number. -If @var{sigspec} and @var{signum} are not present, @code{SIGTERM} is used. -The @option{-l} option lists the signal names. -If any arguments are supplied when @option{-l} is given, the names of the -signals corresponding to the arguments are listed, and the return status -is zero. -@var{exit_status} is a number specifying a signal number or the exit -status of a process terminated by a signal. -The return status is zero if at least one signal was successfully sent, -or non-zero if an error occurs or an invalid option is encountered. - -@item wait -@btindex wait -@example -wait [-n] [@var{jobspec} or @var{pid} @dots{}] -@end example - -Wait until the child process specified by each process @sc{id} @var{pid} -or job specification @var{jobspec} exits and return the exit status of the -last command waited for. -If a job spec is given, all processes in the job are waited for. -If no arguments are given, all currently active child processes are -waited for, and the return status is zero. -If the @option{-n} option is supplied, @code{wait} waits for any job to -terminate and returns its exit status. -If neither @var{jobspec} nor @var{pid} specifies an active child process -of the shell, the return status is 127. - -@item disown -@btindex disown -@example -disown [-ar] [-h] [@var{jobspec} @dots{}] -@end example - -Without options, remove each @var{jobspec} from the table of -active jobs. -If the @option{-h} option is given, the job is not removed from the table, -but is marked so that @code{SIGHUP} is not sent to the job if the shell -receives a @code{SIGHUP}. -If @var{jobspec} is not present, and neither the @option{-a} nor the -@option{-r} option is supplied, the current job is used. -If no @var{jobspec} is supplied, the @option{-a} option means to remove or -mark all jobs; the @option{-r} option without a @var{jobspec} -argument restricts operation to running jobs. - -@item suspend -@btindex suspend -@example -suspend [-f] -@end example - -Suspend the execution of this shell until it receives a -@code{SIGCONT} signal. -A login shell cannot be suspended; the @option{-f} -option can be used to override this and force the suspension. -@end table - -When job control is not active, the @code{kill} and @code{wait} -builtins do not accept @var{jobspec} arguments. They must be -supplied process @sc{id}s. - -@node Job Control Variables -@section Job Control Variables - -@vtable @code - -@item auto_resume -This variable controls how the shell interacts with the user and -job control. If this variable exists then single word simple -commands without redirections are treated as candidates for resumption -of an existing job. There is no ambiguity allowed; if there is -more than one job beginning with the string typed, then -the most recently accessed job will be selected. -The name of a stopped job, in this context, is the command line -used to start it. If this variable is set to the value @samp{exact}, -the string supplied must match the name of a stopped job exactly; -if set to @samp{substring}, -the string supplied needs to match a substring of the name of a -stopped job. The @samp{substring} value provides functionality -analogous to the @samp{%?} job @sc{id} (@pxref{Job Control Basics}). -If set to any other value, the supplied string must -be a prefix of a stopped job's name; this provides functionality -analogous to the @samp{%} job @sc{id}. - -@end vtable - -@set readline-appendix -@set history-appendix -@cindex Readline, how to use -@include rluser.texi -@cindex History, how to use -@include hsuser.texi -@clear readline-appendix -@clear history-appendix - -@node Installing Bash -@chapter Installing Bash - -This chapter provides basic instructions for installing Bash on -the various supported platforms. The distribution supports the -@sc{gnu} operating systems, nearly every version of Unix, and several -non-Unix systems such as BeOS and Interix. -Other independent ports exist for -@sc{ms-dos}, @sc{os/2}, and Windows platforms. - -@menu -* Basic Installation:: Installation instructions. -* Compilers and Options:: How to set special options for various - systems. -* Compiling For Multiple Architectures:: How to compile Bash for more - than one kind of system from - the same source tree. -* Installation Names:: How to set the various paths used by the installation. -* Specifying the System Type:: How to configure Bash for a particular system. -* Sharing Defaults:: How to share default configuration values among GNU - programs. -* Operation Controls:: Options recognized by the configuration program. -* Optional Features:: How to enable and disable optional features when - building Bash. -@end menu - -@node Basic Installation -@section Basic Installation -@cindex installation -@cindex configuration -@cindex Bash installation -@cindex Bash configuration - -These are installation instructions for Bash. - -The simplest way to compile Bash is: - -@enumerate -@item -@code{cd} to the directory containing the source code and type -@samp{./configure} to configure Bash for your system. If you're -using @code{csh} on an old version of System V, you might need to -type @samp{sh ./configure} instead to prevent @code{csh} from trying -to execute @code{configure} itself. - -Running @code{configure} takes some time. -While running, it prints messages telling which features it is -checking for. - -@item -Type @samp{make} to compile Bash and build the @code{bashbug} bug -reporting script. - -@item -Optionally, type @samp{make tests} to run the Bash test suite. - -@item -Type @samp{make install} to install @code{bash} and @code{bashbug}. -This will also install the manual pages and Info file. - -@end enumerate - -The @code{configure} shell script attempts to guess correct -values for various system-dependent variables used during -compilation. It uses those values to create a @file{Makefile} in -each directory of the package (the top directory, the -@file{builtins}, @file{doc}, and @file{support} directories, -each directory under @file{lib}, and several others). It also creates a -@file{config.h} file containing system-dependent definitions. -Finally, it creates a shell script named @code{config.status} that you -can run in the future to recreate the current configuration, a -file @file{config.cache} that saves the results of its tests to -speed up reconfiguring, and a file @file{config.log} containing -compiler output (useful mainly for debugging @code{configure}). -If at some point -@file{config.cache} contains results you don't want to keep, you -may remove or edit it. - -To find out more about the options and arguments that the -@code{configure} script understands, type - -@example -bash-2.04$ ./configure --help -@end example - -@noindent -at the Bash prompt in your Bash source directory. - -If you need to do unusual things to compile Bash, please -try to figure out how @code{configure} could check whether or not -to do them, and mail diffs or instructions to -@email{bash-maintainers@@gnu.org} so they can be -considered for the next release. - -The file @file{configure.ac} is used to create @code{configure} -by a program called Autoconf. You only need -@file{configure.ac} if you want to change it or regenerate -@code{configure} using a newer version of Autoconf. If -you do this, make sure you are using Autoconf version 2.50 or -newer. - -You can remove the program binaries and object files from the -source code directory by typing @samp{make clean}. To also remove the -files that @code{configure} created (so you can compile Bash for -a different kind of computer), type @samp{make distclean}. - -@node Compilers and Options -@section Compilers and Options - -Some systems require unusual options for compilation or linking -that the @code{configure} script does not know about. You can -give @code{configure} initial values for variables by setting -them in the environment. Using a Bourne-compatible shell, you -can do that on the command line like this: - -@example -CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure -@end example - -On systems that have the @code{env} program, you can do it like this: - -@example -env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure -@end example - -The configuration process uses GCC to build Bash if it -is available. - -@node Compiling For Multiple Architectures -@section Compiling For Multiple Architectures - -You can compile Bash for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of @code{make} that -supports the @code{VPATH} variable, such as GNU @code{make}. -@code{cd} to the -directory where you want the object files and executables to go and run -the @code{configure} script from the source directory. You may need to -supply the @option{--srcdir=PATH} argument to tell @code{configure} where the -source files are. @code{configure} automatically checks for the -source code in the directory that @code{configure} is in and in `..'. - -If you have to use a @code{make} that does not supports the @code{VPATH} -variable, you can compile Bash for one architecture at a -time in the source code directory. After you have installed -Bash for one architecture, use @samp{make distclean} before -reconfiguring for another architecture. - -Alternatively, if your system supports symbolic links, you can use the -@file{support/mkclone} script to create a build tree which has -symbolic links back to each file in the source directory. Here's an -example that creates a build directory in the current directory from a -source directory @file{/usr/gnu/src/bash-2.0}: - -@example -bash /usr/gnu/src/bash-2.0/support/mkclone -s /usr/gnu/src/bash-2.0 . -@end example - -@noindent -The @code{mkclone} script requires Bash, so you must have already built -Bash for at least one architecture before you can create build -directories for other architectures. - -@node Installation Names -@section Installation Names - -By default, @samp{make install} will install into -@file{/usr/local/bin}, @file{/usr/local/man}, etc. You can -specify an installation prefix other than @file{/usr/local} by -giving @code{configure} the option @option{--prefix=@var{PATH}}, -or by specifying a value for the @code{DESTDIR} @samp{make} -variable when running @samp{make install}. - -You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. -If you give @code{configure} the option -@option{--exec-prefix=@var{PATH}}, @samp{make install} will use -@var{PATH} as the prefix for installing programs and libraries. -Documentation and other data files will still use the regular prefix. - -@node Specifying the System Type -@section Specifying the System Type - -There may be some features @code{configure} can not figure out -automatically, but need to determine by the type of host Bash -will run on. Usually @code{configure} can figure that -out, but if it prints a message saying it can not guess the host -type, give it the @option{--host=TYPE} option. @samp{TYPE} can -either be a short name for the system type, such as @samp{sun4}, -or a canonical name with three fields: @samp{CPU-COMPANY-SYSTEM} -(e.g., @samp{i386-unknown-freebsd4.2}). - -See the file @file{support/config.sub} for the possible -values of each field. - -@node Sharing Defaults -@section Sharing Defaults - -If you want to set default values for @code{configure} scripts to -share, you can create a site shell script called -@code{config.site} that gives default values for variables like -@code{CC}, @code{cache_file}, and @code{prefix}. @code{configure} -looks for @file{PREFIX/share/config.site} if it exists, then -@file{PREFIX/etc/config.site} if it exists. Or, you can set the -@code{CONFIG_SITE} environment variable to the location of the site -script. A warning: the Bash @code{configure} looks for a site script, -but not all @code{configure} scripts do. - -@node Operation Controls -@section Operation Controls - -@code{configure} recognizes the following options to control how it -operates. - -@table @code - -@item --cache-file=@var{file} -Use and save the results of the tests in -@var{file} instead of @file{./config.cache}. Set @var{file} to -@file{/dev/null} to disable caching, for debugging -@code{configure}. - -@item --help -Print a summary of the options to @code{configure}, and exit. - -@item --quiet -@itemx --silent -@itemx -q -Do not print messages saying which checks are being made. - -@item --srcdir=@var{dir} -Look for the Bash source code in directory @var{dir}. Usually -@code{configure} can determine that directory automatically. - -@item --version -Print the version of Autoconf used to generate the @code{configure} -script, and exit. -@end table - -@code{configure} also accepts some other, not widely used, boilerplate -options. @samp{configure --help} prints the complete list. - -@node Optional Features -@section Optional Features - -The Bash @code{configure} has a number of @option{--enable-@var{feature}} -options, where @var{feature} indicates an optional part of Bash. -There are also several @option{--with-@var{package}} options, -where @var{package} is something like @samp{bash-malloc} or @samp{purify}. -To turn off the default use of a package, use -@option{--without-@var{package}}. To configure Bash without a feature -that is enabled by default, use @option{--disable-@var{feature}}. - -Here is a complete list of the @option{--enable-} and -@option{--with-} options that the Bash @code{configure} recognizes. - -@table @code -@item --with-afs -Define if you are using the Andrew File System from Transarc. - -@item --with-bash-malloc -Use the Bash version of -@code{malloc} in the directory @file{lib/malloc}. This is not the same -@code{malloc} that appears in @sc{gnu} libc, but an older version -originally derived from the 4.2 @sc{bsd} @code{malloc}. This @code{malloc} -is very fast, but wastes some space on each allocation. -This option is enabled by default. -The @file{NOTES} file contains a list of systems for -which this should be turned off, and @code{configure} disables this -option automatically for a number of systems. - -@item --with-curses -Use the curses library instead of the termcap library. This should -be supplied if your system has an inadequate or incomplete termcap -database. - -@item --with-gnu-malloc -A synonym for @code{--with-bash-malloc}. - -@item --with-installed-readline[=@var{PREFIX}] -Define this to make Bash link with a locally-installed version of Readline -rather than the version in @file{lib/readline}. This works only with -Readline 5.0 and later versions. If @var{PREFIX} is @code{yes} or not -supplied, @code{configure} uses the values of the make variables -@code{includedir} and @code{libdir}, which are subdirectories of @code{prefix} -by default, to find the installed version of Readline if it is not in -the standard system include and library directories. -If @var{PREFIX} is @code{no}, Bash links with the version in -@file{lib/readline}. -If @var{PREFIX} is set to any other value, @code{configure} treats it as -a directory pathname and looks for -the installed version of Readline in subdirectories of that directory -(include files in @var{PREFIX}/@code{include} and the library in -@var{PREFIX}/@code{lib}). - -@item --with-purify -Define this to use the Purify memory allocation checker from Rational -Software. - -@item --enable-minimal-config -This produces a shell with minimal features, close to the historical -Bourne shell. -@end table - -There are several @option{--enable-} options that alter how Bash is -compiled and linked, rather than changing run-time features. - -@table @code -@item --enable-largefile -Enable support for @uref{http://www.sas.com/standards/large_file/x_open.20Mar96.html, -large files} if the operating system requires special compiler options -to build programs which can access large files. This is enabled by -default, if the operating system provides large file support. - -@item --enable-profiling -This builds a Bash binary that produces profiling information to be -processed by @code{gprof} each time it is executed. - -@item --enable-static-link -This causes Bash to be linked statically, if @code{gcc} is being used. -This could be used to build a version to use as root's shell. -@end table - -The @samp{minimal-config} option can be used to disable all of -the following options, but it is processed first, so individual -options may be enabled using @samp{enable-@var{feature}}. - -All of the following options except for @samp{disabled-builtins}, -@samp{direxpand-default}, and -@samp{xpg-echo-default} are -enabled by default, unless the operating system does not provide the -necessary support. - -@table @code -@item --enable-alias -Allow alias expansion and include the @code{alias} and @code{unalias} -builtins (@pxref{Aliases}). - -@item --enable-arith-for-command -Include support for the alternate form of the @code{for} command -that behaves like the C language @code{for} statement -(@pxref{Looping Constructs}). - -@item --enable-array-variables -Include support for one-dimensional array shell variables -(@pxref{Arrays}). - -@item --enable-bang-history -Include support for @code{csh}-like history substitution -(@pxref{History Interaction}). - -@item --enable-brace-expansion -Include @code{csh}-like brace expansion -( @code{b@{a,b@}c} @expansion{} @code{bac bbc} ). -See @ref{Brace Expansion}, for a complete description. - -@item --enable-casemod-attributes -Include support for case-modifying attributes in the @code{declare} builtin -and assignment statements. Variables with the @var{uppercase} attribute, -for example, will have their values converted to uppercase upon assignment. - -@item --enable-casemod-expansion -Include support for case-modifying word expansions. - -@item --enable-command-timing -Include support for recognizing @code{time} as a reserved word and for -displaying timing statistics for the pipeline following @code{time} -(@pxref{Pipelines}). -This allows pipelines as well as shell builtins and functions to be timed. - -@item --enable-cond-command -Include support for the @code{[[} conditional command. -(@pxref{Conditional Constructs}). - -@item --enable-cond-regexp -Include support for matching @sc{posix} regular expressions using the -@samp{=~} binary operator in the @code{[[} conditional command. -(@pxref{Conditional Constructs}). - -@item --enable-coprocesses -Include support for coprocesses and the @code{coproc} reserved word -(@pxref{Pipelines}). - -@item --enable-debugger -Include support for the bash debugger (distributed separately). - -@item --enable-direxpand-default -Cause the @code{direxpand} shell option (@pxref{The Shopt Builtin}) -to be enabled by default when the shell starts. -It is normally disabled by default. - -@item --enable-directory-stack -Include support for a @code{csh}-like directory stack and the -@code{pushd}, @code{popd}, and @code{dirs} builtins -(@pxref{The Directory Stack}). - -@item --enable-disabled-builtins -Allow builtin commands to be invoked via @samp{builtin xxx} -even after @code{xxx} has been disabled using @samp{enable -n xxx}. -See @ref{Bash Builtins}, for details of the @code{builtin} and -@code{enable} builtin commands. - -@item --enable-dparen-arithmetic -Include support for the @code{((@dots{}))} command -(@pxref{Conditional Constructs}). - -@item --enable-extended-glob -Include support for the extended pattern matching features described -above under @ref{Pattern Matching}. - -@item --enable-extended-glob-default -Set the default value of the @var{extglob} shell option described -above under @ref{The Shopt Builtin} to be enabled. - -@item --enable-glob-asciirange-default -Set the default value of the @var{globasciiranges} shell option described -above under @ref{The Shopt Builtin} to be enabled. -This controls the behavior of character ranges when used in pattern matching -bracket expressions. - -@item --enable-help-builtin -Include the @code{help} builtin, which displays help on shell builtins and -variables (@pxref{Bash Builtins}). - -@item --enable-history -Include command history and the @code{fc} and @code{history} -builtin commands (@pxref{Bash History Facilities}). - -@item --enable-job-control -This enables the job control features (@pxref{Job Control}), -if the operating system supports them. - -@item --enable-multibyte -This enables support for multibyte characters if the operating -system provides the necessary support. - -@item --enable-net-redirections -This enables the special handling of filenames of the form -@code{/dev/tcp/@var{host}/@var{port}} and -@code{/dev/udp/@var{host}/@var{port}} -when used in redirections (@pxref{Redirections}). - -@item --enable-process-substitution -This enables process substitution (@pxref{Process Substitution}) if -the operating system provides the necessary support. - -@item --enable-progcomp -Enable the programmable completion facilities -(@pxref{Programmable Completion}). -If Readline is not enabled, this option has no effect. - -@item --enable-prompt-string-decoding -Turn on the interpretation of a number of backslash-escaped characters -in the @env{$PS1}, @env{$PS2}, @env{$PS3}, and @env{$PS4} prompt -strings. See @ref{Controlling the Prompt}, for a complete list of prompt -string escape sequences. - -@item --enable-readline -Include support for command-line editing and history with the Bash -version of the Readline library (@pxref{Command Line Editing}). - -@item --enable-restricted -Include support for a @dfn{restricted shell}. If this is enabled, Bash, -when called as @code{rbash}, enters a restricted mode. See -@ref{The Restricted Shell}, for a description of restricted mode. - -@item --enable-select -Include the @code{select} compound command, which allows the generation of -simple menus (@pxref{Conditional Constructs}). - -@item --enable-separate-helpfiles -Use external files for the documentation displayed by the @code{help} builtin -instead of storing the text internally. - -@item --enable-single-help-strings -Store the text displayed by the @code{help} builtin as a single string for -each help topic. This aids in translating the text to different languages. -You may need to disable this if your compiler cannot handle very long string -literals. - -@item --enable-strict-posix-default -Make Bash @sc{posix}-conformant by default (@pxref{Bash POSIX Mode}). - -@item --enable-usg-echo-default -A synonym for @code{--enable-xpg-echo-default}. - -@item --enable-xpg-echo-default -Make the @code{echo} builtin expand backslash-escaped characters by default, -without requiring the @option{-e} option. -This sets the default value of the @code{xpg_echo} shell option to @code{on}, -which makes the Bash @code{echo} behave more like the version specified in -the Single Unix Specification, version 3. -@xref{Bash Builtins}, for a description of the escape sequences that -@code{echo} recognizes. -@end table - -The file @file{config-top.h} contains C Preprocessor -@samp{#define} statements for options which are not settable from -@code{configure}. -Some of these are not meant to be changed; beware of the consequences if -you do. -Read the comments associated with each definition for more -information about its effect. - -@node Reporting Bugs -@appendix Reporting Bugs - -Please report all bugs you find in Bash. -But first, you should -make sure that it really is a bug, and that it appears in the latest -version of Bash. -The latest version of Bash is always available for FTP from -@uref{ftp://ftp.gnu.org/pub/gnu/bash/}. - -Once you have determined that a bug actually exists, use the -@code{bashbug} command to submit a bug report. -If you have a fix, you are encouraged to mail that as well! -Suggestions and `philosophical' bug reports may be mailed -to @email{bug-bash@@gnu.org} or posted to the Usenet -newsgroup @code{gnu.bash.bug}. - -All bug reports should include: -@itemize @bullet -@item -The version number of Bash. -@item -The hardware and operating system. -@item -The compiler used to compile Bash. -@item -A description of the bug behaviour. -@item -A short script or `recipe' which exercises the bug and may be used -to reproduce it. -@end itemize - -@noindent -@code{bashbug} inserts the first three items automatically into -the template it provides for filing a bug report. - -Please send all reports concerning this manual to -@email{bug-bash@@gnu.org}. - -@node Major Differences From The Bourne Shell -@appendix Major Differences From The Bourne Shell - -Bash implements essentially the same grammar, parameter and -variable expansion, redirection, and quoting as the Bourne Shell. -Bash uses the @sc{posix} standard as the specification of -how these features are to be implemented. There are some -differences between the traditional Bourne shell and Bash; this -section quickly details the differences of significance. A -number of these differences are explained in greater depth in -previous sections. -This section uses the version of @code{sh} included in SVR4.2 (the -last version of the historical Bourne shell) as the baseline reference. - -@itemize @bullet - -@item -Bash is @sc{posix}-conformant, even where the @sc{posix} specification -differs from traditional @code{sh} behavior (@pxref{Bash POSIX Mode}). - -@item -Bash has multi-character invocation options (@pxref{Invoking Bash}). - -@item -Bash has command-line editing (@pxref{Command Line Editing}) and -the @code{bind} builtin. - -@item -Bash provides a programmable word completion mechanism -(@pxref{Programmable Completion}), and builtin commands -@code{complete}, @code{compgen}, and @code{compopt}, to -manipulate it. - -@item -Bash has command history (@pxref{Bash History Facilities}) and the -@code{history} and @code{fc} builtins to manipulate it. -The Bash history list maintains timestamp information and uses the -value of the @code{HISTTIMEFORMAT} variable to display it. - -@item -Bash implements @code{csh}-like history expansion -(@pxref{History Interaction}). - -@item -Bash has one-dimensional array variables (@pxref{Arrays}), and the -appropriate variable expansions and assignment syntax to use them. -Several of the Bash builtins take options to act on arrays. -Bash provides a number of built-in array variables. - -@item -The @code{$'@dots{}'} quoting syntax, which expands ANSI-C -backslash-escaped characters in the text between the single quotes, -is supported (@pxref{ANSI-C Quoting}). - -@item -Bash supports the @code{$"@dots{}"} quoting syntax to do -locale-specific translation of the characters between the double -quotes. The @option{-D}, @option{--dump-strings}, and @option{--dump-po-strings} -invocation options list the translatable strings found in a script -(@pxref{Locale Translation}). - -@item -Bash implements the @code{!} keyword to negate the return value of -a pipeline (@pxref{Pipelines}). -Very useful when an @code{if} statement needs to act only if a test fails. -The Bash @samp{-o pipefail} option to @code{set} will cause a pipeline to -return a failure status if any command fails. - -@item -Bash has the @code{time} reserved word and command timing (@pxref{Pipelines}). -The display of the timing statistics may be controlled with the -@env{TIMEFORMAT} variable. - -@item -Bash implements the @code{for (( @var{expr1} ; @var{expr2} ; @var{expr3} ))} -arithmetic for command, similar to the C language (@pxref{Looping Constructs}). - -@item -Bash includes the @code{select} compound command, which allows the -generation of simple menus (@pxref{Conditional Constructs}). - -@item -Bash includes the @code{[[} compound command, which makes conditional -testing part of the shell grammar (@pxref{Conditional Constructs}), including -optional regular expression matching. - -@item -Bash provides optional case-insensitive matching for the @code{case} and -@code{[[} constructs. - -@item -Bash includes brace expansion (@pxref{Brace Expansion}) and tilde -expansion (@pxref{Tilde Expansion}). - -@item -Bash implements command aliases and the @code{alias} and @code{unalias} -builtins (@pxref{Aliases}). - -@item -Bash provides shell arithmetic, the @code{((} compound command -(@pxref{Conditional Constructs}), -and arithmetic expansion (@pxref{Shell Arithmetic}). - -@item -Variables present in the shell's initial environment are automatically -exported to child processes. The Bourne shell does not normally do -this unless the variables are explicitly marked using the @code{export} -command. - -@item -Bash supports the @samp{+=} assignment operator, which appends to the value -of the variable named on the left hand side. - -@item -Bash includes the @sc{posix} pattern removal @samp{%}, @samp{#}, @samp{%%} -and @samp{##} expansions to remove leading or trailing substrings from -variable values (@pxref{Shell Parameter Expansion}). - -@item -The expansion @code{$@{#xx@}}, which returns the length of @code{$@{xx@}}, -is supported (@pxref{Shell Parameter Expansion}). - -@item -The expansion @code{$@{var:}@var{offset}@code{[:}@var{length}@code{]@}}, -which expands to the substring of @code{var}'s value of length -@var{length}, beginning at @var{offset}, is present -(@pxref{Shell Parameter Expansion}). - -@item -The expansion -@code{$@{var/[/]}@var{pattern}@code{[/}@var{replacement}@code{]@}}, -which matches @var{pattern} and replaces it with @var{replacement} in -the value of @code{var}, is available (@pxref{Shell Parameter Expansion}). - -@item -The expansion @code{$@{!@var{prefix}*@}} expansion, which expands to -the names of all shell variables whose names begin with @var{prefix}, -is available (@pxref{Shell Parameter Expansion}). - -@item -Bash has @var{indirect} variable expansion using @code{$@{!word@}} -(@pxref{Shell Parameter Expansion}). - -@item -Bash can expand positional parameters beyond @code{$9} using -@code{$@{@var{num}@}}. - -@item -The @sc{posix} @code{$()} form of command substitution -is implemented (@pxref{Command Substitution}), -and preferred to the Bourne shell's @code{``} (which -is also implemented for backwards compatibility). - -@item -Bash has process substitution (@pxref{Process Substitution}). - -@item -Bash automatically assigns variables that provide information about the -current user (@env{UID}, @env{EUID}, and @env{GROUPS}), the current host -(@env{HOSTTYPE}, @env{OSTYPE}, @env{MACHTYPE}, and @env{HOSTNAME}), -and the instance of Bash that is running (@env{BASH}, -@env{BASH_VERSION}, and @env{BASH_VERSINFO}). @xref{Bash Variables}, -for details. - -@item -The @env{IFS} variable is used to split only the results of expansion, -not all words (@pxref{Word Splitting}). -This closes a longstanding shell security hole. - -@item -The filename expansion bracket expression code uses @samp{!} and @samp{^} -to negate the set of characters between the brackets. -The Bourne shell uses only @samp{!}. - -@item -Bash implements the full set of @sc{posix} filename expansion operators, -including @var{character classes}, @var{equivalence classes}, and -@var{collating symbols} (@pxref{Filename Expansion}). - -@item -Bash implements extended pattern matching features when the @code{extglob} -shell option is enabled (@pxref{Pattern Matching}). - -@item -It is possible to have a variable and a function with the same name; -@code{sh} does not separate the two name spaces. - -@item -Bash functions are permitted to have local variables using the -@code{local} builtin, and thus useful recursive functions may be written -(@pxref{Bash Builtins}). - -@item -Variable assignments preceding commands affect only that command, even -builtins and functions (@pxref{Environment}). -In @code{sh}, all variable assignments -preceding commands are global unless the command is executed from the -file system. - -@item -Bash performs filename expansion on filenames specified as operands -to input and output redirection operators (@pxref{Redirections}). - -@item -Bash contains the @samp{<>} redirection operator, allowing a file to be -opened for both reading and writing, and the @samp{&>} redirection -operator, for directing standard output and standard error to the same -file (@pxref{Redirections}). - -@item -Bash includes the @samp{<<<} redirection operator, allowing a string to -be used as the standard input to a command. - -@item -Bash implements the @samp{[n]<&@var{word}} and @samp{[n]>&@var{word}} -redirection operators, which move one file descriptor to another. - -@item -Bash treats a number of filenames specially when they are -used in redirection operators (@pxref{Redirections}). - -@item -Bash can open network connections to arbitrary machines and services -with the redirection operators (@pxref{Redirections}). - -@item -The @code{noclobber} option is available to avoid overwriting existing -files with output redirection (@pxref{The Set Builtin}). -The @samp{>|} redirection operator may be used to override @code{noclobber}. - -@item -The Bash @code{cd} and @code{pwd} builtins (@pxref{Bourne Shell Builtins}) -each take @option{-L} and @option{-P} options to switch between logical and -physical modes. - -@item -Bash allows a function to override a builtin with the same name, and provides -access to that builtin's functionality within the function via the -@code{builtin} and @code{command} builtins (@pxref{Bash Builtins}). - -@item -The @code{command} builtin allows selective disabling of functions -when command lookup is performed (@pxref{Bash Builtins}). - -@item -Individual builtins may be enabled or disabled using the @code{enable} -builtin (@pxref{Bash Builtins}). - -@item -The Bash @code{exec} builtin takes additional options that allow users -to control the contents of the environment passed to the executed -command, and what the zeroth argument to the command is to be -(@pxref{Bourne Shell Builtins}). - -@item -Shell functions may be exported to children via the environment -using @code{export -f} (@pxref{Shell Functions}). - -@item -The Bash @code{export}, @code{readonly}, and @code{declare} builtins can -take a @option{-f} option to act on shell functions, a @option{-p} option to -display variables with various attributes set in a format that can be -used as shell input, a @option{-n} option to remove various variable -attributes, and @samp{name=value} arguments to set variable attributes -and values simultaneously. - -@item -The Bash @code{hash} builtin allows a name to be associated with -an arbitrary filename, even when that filename cannot be found by -searching the @env{$PATH}, using @samp{hash -p} -(@pxref{Bourne Shell Builtins}). - -@item -Bash includes a @code{help} builtin for quick reference to shell -facilities (@pxref{Bash Builtins}). - -@item -The @code{printf} builtin is available to display formatted output -(@pxref{Bash Builtins}). - -@item -The Bash @code{read} builtin (@pxref{Bash Builtins}) -will read a line ending in @samp{\} with -the @option{-r} option, and will use the @env{REPLY} variable as a -default if no non-option arguments are supplied. -The Bash @code{read} builtin -also accepts a prompt string with the @option{-p} option and will use -Readline to obtain the line when given the @option{-e} option. -The @code{read} builtin also has additional options to control input: -the @option{-s} option will turn off echoing of input characters as -they are read, the @option{-t} option will allow @code{read} to time out -if input does not arrive within a specified number of seconds, the -@option{-n} option will allow reading only a specified number of -characters rather than a full line, and the @option{-d} option will read -until a particular character rather than newline. - -@item -The @code{return} builtin may be used to abort execution of scripts -executed with the @code{.} or @code{source} builtins -(@pxref{Bourne Shell Builtins}). - -@item -Bash includes the @code{shopt} builtin, for finer control of shell -optional capabilities (@pxref{The Shopt Builtin}), and allows these options -to be set and unset at shell invocation (@pxref{Invoking Bash}). - -@item -Bash has much more optional behavior controllable with the @code{set} -builtin (@pxref{The Set Builtin}). - -@item -The @samp{-x} (@option{xtrace}) option displays commands other than -simple commands when performing an execution trace -(@pxref{The Set Builtin}). - -@item -The @code{test} builtin (@pxref{Bourne Shell Builtins}) -is slightly different, as it implements the @sc{posix} algorithm, -which specifies the behavior based on the number of arguments. - -@item -Bash includes the @code{caller} builtin, which displays the context of -any active subroutine call (a shell function or a script executed with -the @code{.} or @code{source} builtins). This supports the bash -debugger. - -@item -The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows a -@code{DEBUG} pseudo-signal specification, similar to @code{EXIT}. -Commands specified with a @code{DEBUG} trap are executed before every -simple command, @code{for} command, @code{case} command, -@code{select} command, every arithmetic @code{for} command, and before -the first command executes in a shell function. -The @code{DEBUG} trap is not inherited by shell functions unless the -function has been given the @code{trace} attribute or the -@code{functrace} option has been enabled using the @code{shopt} builtin. -The @code{extdebug} shell option has additional effects on the -@code{DEBUG} trap. - -The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows an -@code{ERR} pseudo-signal specification, similar to @code{EXIT} and @code{DEBUG}. -Commands specified with an @code{ERR} trap are executed after a simple -command fails, with a few exceptions. -The @code{ERR} trap is not inherited by shell functions unless the -@code{-o errtrace} option to the @code{set} builtin is enabled. - -The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows a -@code{RETURN} pseudo-signal specification, similar to -@code{EXIT} and @code{DEBUG}. -Commands specified with an @code{RETURN} trap are executed before -execution resumes after a shell function or a shell script executed with -@code{.} or @code{source} returns. -The @code{RETURN} trap is not inherited by shell functions unless the -function has been given the @code{trace} attribute or the -@code{functrace} option has been enabled using the @code{shopt} builtin. - -@item -The Bash @code{type} builtin is more extensive and gives more information -about the names it finds (@pxref{Bash Builtins}). - -@item -The Bash @code{umask} builtin permits a @option{-p} option to cause -the output to be displayed in the form of a @code{umask} command -that may be reused as input (@pxref{Bourne Shell Builtins}). - -@item -Bash implements a @code{csh}-like directory stack, and provides the -@code{pushd}, @code{popd}, and @code{dirs} builtins to manipulate it -(@pxref{The Directory Stack}). -Bash also makes the directory stack visible as the value of the -@env{DIRSTACK} shell variable. - -@item -Bash interprets special backslash-escaped characters in the prompt -strings when interactive (@pxref{Controlling the Prompt}). - -@item -The Bash restricted mode is more useful (@pxref{The Restricted Shell}); -the SVR4.2 shell restricted mode is too limited. - -@item -The @code{disown} builtin can remove a job from the internal shell -job table (@pxref{Job Control Builtins}) or suppress the sending -of @code{SIGHUP} to a job when the shell exits as the result of a -@code{SIGHUP}. - -@item -Bash includes a number of features to support a separate debugger for -shell scripts. - -@item -The SVR4.2 shell has two privilege-related builtins -(@code{mldmode} and @code{priv}) not present in Bash. - -@item -Bash does not have the @code{stop} or @code{newgrp} builtins. - -@item -Bash does not use the @env{SHACCT} variable or perform shell accounting. - -@item -The SVR4.2 @code{sh} uses a @env{TIMEOUT} variable like Bash uses -@env{TMOUT}. - -@end itemize - -@noindent -More features unique to Bash may be found in @ref{Bash Features}. - - -@appendixsec Implementation Differences From The SVR4.2 Shell - -Since Bash is a completely new implementation, it does not suffer from -many of the limitations of the SVR4.2 shell. For instance: - -@itemize @bullet - -@item -Bash does not fork a subshell when redirecting into or out of -a shell control structure such as an @code{if} or @code{while} -statement. - -@item -Bash does not allow unbalanced quotes. The SVR4.2 shell will silently -insert a needed closing quote at @code{EOF} under certain circumstances. -This can be the cause of some hard-to-find errors. - -@item -The SVR4.2 shell uses a baroque memory management scheme based on -trapping @code{SIGSEGV}. If the shell is started from a process with -@code{SIGSEGV} blocked (e.g., by using the @code{system()} C library -function call), it misbehaves badly. - -@item -In a questionable attempt at security, the SVR4.2 shell, -when invoked without the @option{-p} option, will alter its real -and effective @sc{uid} and @sc{gid} if they are less than some -magic threshold value, commonly 100. -This can lead to unexpected results. - -@item -The SVR4.2 shell does not allow users to trap @code{SIGSEGV}, -@code{SIGALRM}, or @code{SIGCHLD}. - -@item -The SVR4.2 shell does not allow the @env{IFS}, @env{MAILCHECK}, -@env{PATH}, @env{PS1}, or @env{PS2} variables to be unset. - -@item -The SVR4.2 shell treats @samp{^} as the undocumented equivalent of -@samp{|}. - -@item -Bash allows multiple option arguments when it is invoked (@code{-x -v}); -the SVR4.2 shell allows only one option argument (@code{-xv}). In -fact, some versions of the shell dump core if the second argument begins -with a @samp{-}. - -@item -The SVR4.2 shell exits a script if any builtin fails; Bash exits -a script only if one of the @sc{posix} special builtins fails, and -only for certain failures, as enumerated in the @sc{posix} standard. - -@item -The SVR4.2 shell behaves differently when invoked as @code{jsh} -(it turns on job control). -@end itemize - -@node GNU Free Documentation License -@appendix GNU Free Documentation License - -@include fdl.texi - -@node Indexes -@appendix Indexes - -@menu -* Builtin Index:: Index of Bash builtin commands. -* Reserved Word Index:: Index of Bash reserved words. -* Variable Index:: Quick reference helps you find the - variable you want. -* Function Index:: Index of bindable Readline functions. -* Concept Index:: General index for concepts described in - this manual. -@end menu - -@node Builtin Index -@appendixsec Index of Shell Builtin Commands -@printindex bt - -@node Reserved Word Index -@appendixsec Index of Shell Reserved Words -@printindex rw - -@node Variable Index -@appendixsec Parameter and Variable Index -@printindex vr - -@node Function Index -@appendixsec Function Index -@printindex fn - -@node Concept Index -@appendixsec Concept Index -@printindex cp - -@bye diff --git a/doc/version.texi~ b/doc/version.texi~ deleted file mode 100644 index 155ee0ef..00000000 --- a/doc/version.texi~ +++ /dev/null @@ -1,10 +0,0 @@ -@ignore -Copyright (C) 1988-2014 Free Software Foundation, Inc. -@end ignore - -@set LASTCHANGE Mon May 12 10:32:34 EDT 2014 - -@set EDITION 4.3 -@set VERSION 4.3 -@set UPDATED 12 May 2014 -@set UPDATED-MONTH May 2014 diff --git a/examples/loadables/Makefile.in.save b/examples/loadables/Makefile.in.save deleted file mode 100644 index f6208f5c..00000000 --- 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 83f5f4d3..00000000 --- a/execute_cmd.c~ +++ /dev/null @@ -1,5502 +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 <http://www.gnu.org/licenses/>. -*/ - -#include "config.h" - -#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX) - #pragma alloca -#endif /* _AIX && RISC6000 && !__GNUC__ */ - -#include <stdio.h> -#include "chartypes.h" -#include "bashtypes.h" -#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H) -# include <sys/file.h> -#endif -#include "filecntl.h" -#include "posixstat.h" -#include <signal.h> -#if defined (HAVE_SYS_PARAM_H) -# include <sys/param.h> -#endif - -#if defined (HAVE_UNISTD_H) -# include <unistd.h> -#endif - -#include "posixtime.h" - -#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE) -# include <sys/resource.h> -#endif - -#if defined (HAVE_SYS_TIMES_H) && defined (HAVE_TIMES) -# include <sys/times.h> -#endif - -#include <errno.h> - -#if !defined (errno) -extern int errno; -#endif - -#define NEED_FPURGE_DECL - -#include "bashansi.h" -#include "bashintl.h" - -#include "memalloc.h" -#include "shell.h" -#include <y.tab.h> /* 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 <glob/strmatch.h> -#include <tilde/tilde.h> - -#if defined (BUFFERED_INPUT) -# include "input.h" -#endif - -#if defined (ALIAS) -# include "alias.h" -#endif - -#if defined (HISTORY) -# include "bashhist.h" -#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 = 4096; - -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); - } - 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); - 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; - 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) - append_process (savestring (the_printed_command), dollar_dollar_pid, exec_result, lastpipe_jid); -#endif - lstdin = wait_for (lastpid); -#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 (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))) - { - if (ignore_return && command->value.Connection->second) - command->value.Connection->second->flags |= CMD_IGNORE_RETURN; - - exec_result = execute_command (command->value.Connection->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 (integer) - w->word->flags |= W_ASSIGNINT; - } -#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] == '-' && (strchr (w->word->word+1, 'A') || strchr (w->word->word+1, 'a') || strchr (w->word->word+1, 'g'))) -#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; - if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'i')) - integer = 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; - 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 doesn't make a difference */ - evalnest++; /* 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 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, *nfv, *bash_source_v, *bash_lineno_v; - ARRAY *funcname_a; - volatile ARRAY *bash_source_a; - volatile ARRAY *bash_lineno_a; -#endif - FUNCTION_DEF *shell_fn; - char *sfile, *t; - - 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; - - if (subshell == 0) - { - begin_unwind_frame ("function_calling"); - push_context (var->name, subshell, temporary_env); - 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 (loop_level); - unwind_protect_int (funcnest); - } - 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 - - /* 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 - - 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 (subshell == 0) - run_unwind_frame ("function_calling"); - -#if defined (ARRAY_VARS) - /* These two variables cannot be unset, and cannot be affected by the - function. */ - array_pop ((ARRAY *)bash_source_a); - array_pop ((ARRAY *)bash_lineno_a); - - /* FUNCNAME can be unset, and so can potentially be changed by the - function. */ - GET_ARRAY_FROM_VAR ("FUNCNAME", nfv, funcname_a); - if (nfv == funcname_v) - array_pop (funcname_a); -#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; - - 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; - - 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 */ - if (ansic_shouldquote (pathname)) - pathname = ansic_quote (pathname, 0, NULL); - 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 = 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 */ - - clear_fifo_list (); /* pipe fds are what they are now */ - - 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/externs.h~ b/externs.h~ deleted file mode 100644 index 8db43f28..00000000 --- a/externs.h~ +++ /dev/null @@ -1,517 +0,0 @@ -/* externs.h -- extern function declarations which do not appear in their - own header file. */ - -/* Copyright (C) 1993-2010 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 <http://www.gnu.org/licenses/>. -*/ - -/* Make sure that this is included *after* config.h! */ - -#if !defined (_EXTERNS_H_) -# define _EXTERNS_H_ - -#include "stdc.h" - -/* Functions from expr.c. */ -extern intmax_t evalexp __P((char *, int *)); - -/* Functions from print_cmd.c. */ -#define FUNC_MULTILINE 0x01 -#define FUNC_EXTERNAL 0x02 - -extern char *make_command_string __P((COMMAND *)); -extern char *named_function_string __P((char *, COMMAND *, int)); - -extern void print_command __P((COMMAND *)); -extern void print_simple_command __P((SIMPLE_COM *)); -extern void print_word_list __P((WORD_LIST *, char *)); - -/* debugger support */ -extern void print_for_command_head __P((FOR_COM *)); -#if defined (SELECT_COMMAND) -extern void print_select_command_head __P((SELECT_COM *)); -#endif -extern void print_case_command_head __P((CASE_COM *)); -#if defined (DPAREN_ARITHMETIC) -extern void print_arith_command __P((WORD_LIST *)); -#endif -#if defined (COND_COMMAND) -extern void print_cond_command __P((COND_COM *)); -#endif - -/* set -x support */ -extern void xtrace_init __P((void)); -#ifdef NEED_XTRACE_SET_DECL -extern void xtrace_set __P((int, FILE *)); -#endif -extern void xtrace_fdchk __P((int)); -extern void xtrace_reset __P((void)); -extern char *indirection_level_string __P((void)); -extern void xtrace_print_assignment __P((char *, char *, int, int)); -extern void xtrace_print_word_list __P((WORD_LIST *, int)); -extern void xtrace_print_for_command_head __P((FOR_COM *)); -#if defined (SELECT_COMMAND) -extern void xtrace_print_select_command_head __P((SELECT_COM *)); -#endif -extern void xtrace_print_case_command_head __P((CASE_COM *)); -#if defined (DPAREN_ARITHMETIC) -extern void xtrace_print_arith_cmd __P((WORD_LIST *)); -#endif -#if defined (COND_COMMAND) -extern void xtrace_print_cond_term __P((int, int, WORD_DESC *, char *, char *)); -#endif - -/* Functions from shell.c. */ -extern void exit_shell __P((int)) __attribute__((__noreturn__)); -extern void sh_exit __P((int)) __attribute__((__noreturn__)); -extern void subshell_exit __P((int)) __attribute__((__noreturn__)); -extern void disable_priv_mode __P((void)); -extern void unbind_args __P((void)); - -#if defined (RESTRICTED_SHELL) -extern int shell_is_restricted __P((char *)); -extern int maybe_make_restricted __P((char *)); -#endif - -extern void unset_bash_input __P((int)); -extern void get_current_user_info __P((void)); - -/* Functions from eval.c. */ -extern int reader_loop __P((void)); -extern int parse_command __P((void)); -extern int read_command __P((void)); - -/* Functions from braces.c. */ -#if defined (BRACE_EXPANSION) -extern char **brace_expand __P((char *)); -#endif - -/* Miscellaneous functions from parse.y */ -extern int yyparse __P((void)); -extern int return_EOF __P((void)); -extern char *xparse_dolparen __P((char *, char *, int *, int)); -extern void reset_parser __P((void)); -extern WORD_LIST *parse_string_to_word_list __P((char *, int, const char *)); - -extern int parser_in_command_position __P((void)); - -extern void free_pushed_string_input __P((void)); - -extern int parser_expanding_alias __P((void)); -extern void parser_save_alias __P((void)); -extern void parser_restore_alias __P((void)); - -extern char *decode_prompt_string __P((char *)); - -extern int get_current_prompt_level __P((void)); -extern void set_current_prompt_level __P((int)); - -#if defined (HISTORY) -extern char *history_delimiting_chars __P((const char *)); -#endif - -/* Declarations for functions defined in locale.c */ -extern void set_default_locale __P((void)); -extern void set_default_locale_vars __P((void)); -extern int set_locale_var __P((char *, char *)); -extern int set_lang __P((char *, char *)); -extern void set_default_lang __P((void)); -extern char *get_locale_var __P((char *)); -extern char *localetrans __P((char *, int, int *)); -extern char *mk_msgstr __P((char *, int *)); -extern char *localeexpand __P((char *, int, int, int, int *)); - -/* Declarations for functions defined in list.c. */ -extern void list_walk __P((GENERIC_LIST *, sh_glist_func_t *)); -extern void wlist_walk __P((WORD_LIST *, sh_icpfunc_t *)); -extern GENERIC_LIST *list_reverse (); -extern int list_length (); -extern GENERIC_LIST *list_append (); -extern GENERIC_LIST *list_remove (); - -/* Declarations for functions defined in stringlib.c */ -extern int find_string_in_alist __P((char *, STRING_INT_ALIST *, int)); -extern char *find_token_in_alist __P((int, STRING_INT_ALIST *, int)); -extern int find_index_in_alist __P((char *, STRING_INT_ALIST *, int)); - -extern char *substring __P((const char *, int, int)); -extern char *strsub __P((char *, char *, char *, int)); -extern char *strcreplace __P((char *, int, char *, int)); -extern void strip_leading __P((char *)); -extern void strip_trailing __P((char *, int, int)); -extern void xbcopy __P((char *, char *, int)); - -/* Functions from version.c. */ -extern char *shell_version_string __P((void)); -extern void show_shell_version __P((int)); - -/* Functions from the bash library, lib/sh/libsh.a. These should really - go into a separate include file. */ - -/* declarations for functions defined in lib/sh/casemod.c */ -extern char *sh_modcase __P((const char *, char *, int)); - -/* Defines for flags argument to sh_modcase. These need to agree with what's - in lib/sh/casemode.c */ -#define CASE_LOWER 0x0001 -#define CASE_UPPER 0x0002 -#define CASE_CAPITALIZE 0x0004 -#define CASE_UNCAP 0x0008 -#define CASE_TOGGLE 0x0010 -#define CASE_TOGGLEALL 0x0020 -#define CASE_UPFIRST 0x0040 -#define CASE_LOWFIRST 0x0080 - -#define CASE_USEWORDS 0x1000 - -/* declarations for functions defined in lib/sh/clktck.c */ -extern long get_clk_tck __P((void)); - -/* declarations for functions defined in lib/sh/clock.c */ -extern void clock_t_to_secs (); -extern void print_clock_t (); - -/* Declarations for functions defined in lib/sh/dprintf.c */ -#if !defined (HAVE_DPRINTF) -extern void dprintf __P((int, const char *, ...)) __attribute__((__format__ (printf, 2, 3))); -#endif - -/* Declarations for functions defined in lib/sh/fmtulong.c */ -#define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */ -#define FL_ADDBASE 0x02 /* add base# prefix to converted value */ -#define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */ -#define FL_UNSIGNED 0x08 /* don't add any sign */ - -extern char *fmtulong __P((unsigned long int, int, char *, size_t, int)); - -/* Declarations for functions defined in lib/sh/fmtulong.c */ -#if defined (HAVE_LONG_LONG) -extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int)); -#endif - -/* Declarations for functions defined in lib/sh/fmtumax.c */ -extern char *fmtumax __P((uintmax_t, int, char *, size_t, int)); - -/* Declarations for functions defined in lib/sh/fnxform.c */ -extern char *fnx_fromfs __P((char *, size_t)); -extern char *fnx_tofs __P((char *, size_t)); - -/* Declarations for functions defined in lib/sh/fpurge.c */ - -#if defined NEED_FPURGE_DECL -#if !HAVE_DECL_FPURGE - -#if HAVE_FPURGE -# define fpurge _bash_fpurge -#endif -extern int fpurge __P((FILE *stream)); - -#endif /* HAVE_DECL_FPURGE */ -#endif /* NEED_FPURGE_DECL */ - -/* Declarations for functions defined in lib/sh/getcwd.c */ -#if !defined (HAVE_GETCWD) -extern char *getcwd __P((char *, size_t)); -#endif - -/* Declarations for functions defined in lib/sh/input_avail.c */ -extern int input_avail __P((int)); - -/* Declarations for functions defined in lib/sh/itos.c */ -extern char *inttostr __P((intmax_t, char *, size_t)); -extern char *itos __P((intmax_t)); -extern char *mitos __P((intmax_t)); -extern char *uinttostr __P((uintmax_t, char *, size_t)); -extern char *uitos __P((uintmax_t)); - -/* declarations for functions defined in lib/sh/makepath.c */ -#define MP_DOTILDE 0x01 -#define MP_DOCWD 0x02 -#define MP_RMDOT 0x04 -#define MP_IGNDOT 0x08 - -extern char *sh_makepath __P((const char *, const char *, int)); - -/* declarations for functions defined in lib/sh/mbscasecmp.c */ -#if !defined (HAVE_MBSCASECMP) -extern char *mbscasecmp __P((const char *, const char *)); -#endif - -/* declarations for functions defined in lib/sh/mbschr.c */ -#if !defined (HAVE_MBSCHR) -extern char *mbschr __P((const char *, int)); -#endif - -/* declarations for functions defined in lib/sh/mbscmp.c */ -#if !defined (HAVE_MBSCMP) -extern char *mbscmp __P((const char *, const char *)); -#endif - -/* declarations for functions defined in lib/sh/netconn.c */ -extern int isnetconn __P((int)); - -/* declarations for functions defined in lib/sh/netopen.c */ -extern int netopen __P((char *)); - -/* Declarations for functions defined in lib/sh/oslib.c */ - -#if !defined (HAVE_DUP2) || defined (DUP2_BROKEN) -extern int dup2 __P((int, int)); -#endif - -#if !defined (HAVE_GETDTABLESIZE) -extern int getdtablesize __P((void)); -#endif /* !HAVE_GETDTABLESIZE */ - -#if !defined (HAVE_GETHOSTNAME) -extern int gethostname __P((char *, int)); -#endif /* !HAVE_GETHOSTNAME */ - -extern int getmaxgroups __P((void)); -extern long getmaxchild __P((void)); - -/* declarations for functions defined in lib/sh/pathcanon.c */ -#define PATH_CHECKDOTDOT 0x0001 -#define PATH_CHECKEXISTS 0x0002 -#define PATH_HARDPATH 0x0004 -#define PATH_NOALLOC 0x0008 - -extern char *sh_canonpath __P((char *, int)); - -/* declarations for functions defined in lib/sh/pathphys.c */ -extern char *sh_physpath __P((char *, int)); -extern char *sh_realpath __P((const char *, char *)); - -/* declarations for functions defined in lib/sh/setlinebuf.c */ -#ifdef NEED_SH_SETLINEBUF_DECL -extern int sh_setlinebuf __P((FILE *)); -#endif - -/* declarations for functions defined in lib/sh/shaccess.c */ -extern int sh_eaccess __P((char *, int)); - -/* declarations for functions defined in lib/sh/shmatch.c */ -extern int sh_regmatch __P((const char *, const char *, int)); - -/* defines for flags argument to sh_regmatch. */ -#define SHMAT_SUBEXP 0x001 /* save subexpressions in SH_REMATCH */ -#define SHMAT_PWARN 0x002 /* print a warning message on invalid regexp */ - -/* declarations for functions defined in lib/sh/shmbchar.c */ -extern size_t mbstrlen __P((const char *)); -extern char *mbsmbchar __P((const char *)); -extern int sh_mbsnlen __P((const char *, size_t, int)); - -/* declarations for functions defined in lib/sh/shquote.c */ -extern char *sh_single_quote __P((const char *)); -extern char *sh_double_quote __P((const char *)); -extern char *sh_mkdoublequoted __P((const char *, int, int)); -extern char *sh_un_double_quote __P((char *)); -extern char *sh_backslash_quote __P((char *, const char *, int)); -extern char *sh_backslash_quote_for_double_quotes __P((char *)); -extern int sh_contains_shell_metas __P((char *)); -extern int sh_contains_quotes __P((char *)); - -/* declarations for functions defined in lib/sh/spell.c */ -extern int spname __P((char *, char *)); -extern char *dirspell __P((char *)); - -/* declarations for functions defined in lib/sh/strcasecmp.c */ -#if !defined (HAVE_STRCASECMP) -extern int strncasecmp __P((const char *, const char *, int)); -extern int strcasecmp __P((const char *, const char *)); -#endif /* HAVE_STRCASECMP */ - -/* declarations for functions defined in lib/sh/strcasestr.c */ -#if ! HAVE_STRCASESTR -extern char *strcasestr __P((const char *, const char *)); -#endif - -/* declarations for functions defined in lib/sh/strchrnul.c */ -#if ! HAVE_STRCHRNUL -extern char *strchrnul __P((const char *, int)); -#endif - -/* declarations for functions defined in lib/sh/strerror.c */ -#if !defined (HAVE_STRERROR) && !defined (strerror) -extern char *strerror __P((int)); -#endif - -/* declarations for functions defined in lib/sh/strftime.c */ -#if !defined (HAVE_STRFTIME) && defined (NEED_STRFTIME_DECL) -extern size_t strftime __P((char *, size_t, const char *, const struct tm *)); -#endif - -/* declarations for functions and structures defined in lib/sh/stringlist.c */ - -/* This is a general-purpose argv-style array struct. */ -typedef struct _list_of_strings { - char **list; - int list_size; - int list_len; -} STRINGLIST; - -typedef int sh_strlist_map_func_t __P((char *)); - -extern STRINGLIST *strlist_create __P((int)); -extern STRINGLIST *strlist_resize __P((STRINGLIST *, int)); -extern void strlist_flush __P((STRINGLIST *)); -extern void strlist_dispose __P((STRINGLIST *)); -extern int strlist_remove __P((STRINGLIST *, char *)); -extern STRINGLIST *strlist_copy __P((STRINGLIST *)); -extern STRINGLIST *strlist_merge __P((STRINGLIST *, STRINGLIST *)); -extern STRINGLIST *strlist_append __P((STRINGLIST *, STRINGLIST *)); -extern STRINGLIST *strlist_prefix_suffix __P((STRINGLIST *, char *, char *)); -extern void strlist_print __P((STRINGLIST *, char *)); -extern void strlist_walk __P((STRINGLIST *, sh_strlist_map_func_t *)); -extern void strlist_sort __P((STRINGLIST *)); - -/* declarations for functions defined in lib/sh/stringvec.c */ - -extern char **strvec_create __P((int)); -extern char **strvec_resize __P((char **, int)); -extern char **strvec_mcreate __P((int)); -extern char **strvec_mresize __P((char **, int)); -extern void strvec_flush __P((char **)); -extern void strvec_dispose __P((char **)); -extern int strvec_remove __P((char **, char *)); -extern int strvec_len __P((char **)); -extern int strvec_search __P((char **, char *)); -extern char **strvec_copy __P((char **)); -extern int strvec_strcmp __P((char **, char **)); -extern void strvec_sort __P((char **)); - -extern char **strvec_from_word_list __P((WORD_LIST *, int, int, int *)); -extern WORD_LIST *strvec_to_word_list __P((char **, int, int)); - -/* declarations for functions defined in lib/sh/strnlen.c */ -#if !defined (HAVE_STRNLEN) -extern size_t strnlen __P((const char *, size_t)); -#endif - -/* declarations for functions defined in lib/sh/strpbrk.c */ -#if !defined (HAVE_STRPBRK) -extern char *strpbrk __P((const char *, const char *)); -#endif - -/* declarations for functions defined in lib/sh/strtod.c */ -#if !defined (HAVE_STRTOD) -extern double strtod __P((const char *, char **)); -#endif - -/* declarations for functions defined in lib/sh/strtol.c */ -#if !HAVE_DECL_STRTOL -extern long strtol __P((const char *, char **, int)); -#endif - -/* declarations for functions defined in lib/sh/strtoll.c */ -#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOLL -extern long long strtoll __P((const char *, char **, int)); -#endif - -/* declarations for functions defined in lib/sh/strtoul.c */ -#if !HAVE_DECL_STRTOUL -extern unsigned long strtoul __P((const char *, char **, int)); -#endif - -/* declarations for functions defined in lib/sh/strtoull.c */ -#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOULL -extern unsigned long long strtoull __P((const char *, char **, int)); -#endif - -/* declarations for functions defined in lib/sh/strimax.c */ -#if !HAVE_DECL_STRTOIMAX -extern intmax_t strtoimax __P((const char *, char **, int)); -#endif - -/* declarations for functions defined in lib/sh/strumax.c */ -#if !HAVE_DECL_STRTOUMAX -extern uintmax_t strtoumax __P((const char *, char **, int)); -#endif - -/* declarations for functions defined in lib/sh/strtrans.c */ -extern char *ansicstr __P((char *, int, int, int *, int *)); -extern char *ansic_quote __P((char *, int, int *)); -extern int ansic_shouldquote __P((const char *)); -extern char *ansiexpand __P((char *, int, int, int *)); - -/* declarations for functions defined in lib/sh/timeval.c. No prototypes - so we don't have to count on having a definition of struct timeval in - scope when this file is included. */ -extern void timeval_to_secs (); -extern void print_timeval (); - -/* declarations for functions defined in lib/sh/tmpfile.c */ -#define MT_USETMPDIR 0x0001 -#define MT_READWRITE 0x0002 -#define MT_USERANDOM 0x0004 - -extern char *sh_mktmpname __P((char *, int)); -extern int sh_mktmpfd __P((char *, int, char **)); -/* extern FILE *sh_mktmpfp __P((char *, int, char **)); */ - -/* declarations for functions defined in lib/sh/uconvert.c */ -extern int uconvert __P((char *, long *, long *)); - -/* declarations for functions defined in lib/sh/ufuncs.c */ -extern unsigned int falarm __P((unsigned int, unsigned int)); -extern unsigned int fsleep __P((unsigned int, unsigned int)); - -/* declarations for functions defined in lib/sh/unicode.c */ -extern int u32cconv __P((unsigned long, char *)); -extern void u32reset __P((void)); - -/* declarations for functions defined in lib/sh/wcsnwidth.c */ -#if defined (HANDLE_MULTIBYTE) -extern int wcsnwidth __P((const wchar_t *, size_t, int)); -#endif - -/* declarations for functions defined in lib/sh/winsize.c */ -extern void get_new_window_size __P((int, int *, int *)); - -/* declarations for functions defined in lib/sh/zcatfd.c */ -extern int zcatfd __P((int, int, char *)); - -/* declarations for functions defined in lib/sh/zgetline.c */ -extern ssize_t zgetline __P((int, char **, size_t *, int)); - -/* declarations for functions defined in lib/sh/zmapfd.c */ -extern int zmapfd __P((int, char **, char *)); - -/* declarations for functions defined in lib/sh/zread.c */ -extern ssize_t zread __P((int, char *, size_t)); -extern ssize_t zreadretry __P((int, char *, size_t)); -extern ssize_t zreadintr __P((int, char *, size_t)); -extern ssize_t zreadc __P((int, char *)); -extern ssize_t zreadcintr __P((int, char *)); -extern ssize_t zreadn __P((int, char *, size_t)); -extern void zreset __P((void)); -extern void zsyncfd __P((int)); - -/* declarations for functions defined in lib/sh/zwrite.c */ -extern int zwrite __P((int, char *, size_t)); - -/* declarations for functions defined in lib/glob/gmisc.c */ -extern int match_pattern_char __P((char *, char *)); -extern int umatchlen __P((char *, size_t)); - -#if defined (HANDLE_MULTIBYTE) -extern int match_pattern_wchar __P((wchar_t *, wchar_t *)); -extern int wmatchlen __P((wchar_t *, size_t)); -#endif - -#endif /* _EXTERNS_H_ */ diff --git a/findcmd.c~ b/findcmd.c~ deleted file mode 100644 index 9f3d954f..00000000 --- a/findcmd.c~ +++ /dev/null @@ -1,623 +0,0 @@ -/* findcmd.c -- Functions to search for commands by name. */ - -/* Copyright (C) 1997-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 <http://www.gnu.org/licenses/>. -*/ - -#include "config.h" - -#include <stdio.h> -#include "chartypes.h" -#include "bashtypes.h" -#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H) -# include <sys/file.h> -#endif -#include "filecntl.h" -#include "posixstat.h" - -#if defined (HAVE_UNISTD_H) -# include <unistd.h> -#endif -#include <errno.h> - -#include "bashansi.h" - -#include "memalloc.h" -#include "shell.h" -#include "flags.h" -#include "hashlib.h" -#include "pathexp.h" -#include "hashcmd.h" -#include "findcmd.h" /* matching prototypes and declarations */ - -#if !defined (errno) -extern int errno; -#endif - -extern int posixly_correct; -extern int last_command_exit_value; - -/* Static functions defined and used in this file. */ -static char *_find_user_command_internal __P((const char *, int)); -static char *find_user_command_internal __P((const char *, int)); -static char *find_user_command_in_path __P((const char *, char *, int)); -static char *find_in_path_element __P((const char *, char *, int, int, struct stat *)); -static char *find_absolute_program __P((const char *, int)); - -static char *get_next_path_element __P((char *, int *)); - -/* The file name which we would try to execute, except that it isn't - possible to execute it. This is the first file that matches the - name that we are looking for while we are searching $PATH for a - suitable one to execute. If we cannot find a suitable executable - file, then we use this one. */ -static char *file_to_lose_on; - -/* Non-zero if we should stat every command found in the hash table to - make sure it still exists. */ -int check_hashed_filenames; - -/* DOT_FOUND_IN_SEARCH becomes non-zero when find_user_command () - encounters a `.' as the directory pathname while scanning the - list of possible pathnames; i.e., if `.' comes before the directory - containing the file of interest. */ -int dot_found_in_search = 0; - -/* Return some flags based on information about this file. - The EXISTS bit is non-zero if the file is found. - The EXECABLE bit is non-zero the file is executble. - Zero is returned if the file is not found. */ -int -file_status (name) - const char *name; -{ - struct stat finfo; - int r; - - /* Determine whether this file exists or not. */ - if (stat (name, &finfo) < 0) - return (0); - - /* If the file is a directory, then it is not "executable" in the - sense of the shell. */ - if (S_ISDIR (finfo.st_mode)) - return (FS_EXISTS|FS_DIRECTORY); - - r = FS_EXISTS; - -#if defined (HAVE_EACCESS) - /* Use eaccess(2) if we have it to take things like ACLs and other - file access mechanisms into account. eaccess uses the effective - user and group IDs, not the real ones. We could use sh_eaccess, - but we don't want any special treatment for /dev/fd. */ - if (eaccess (name, X_OK) == 0) - r |= FS_EXECABLE; - if (eaccess (name, R_OK) == 0) - r |= FS_READABLE; - - return r; -#elif defined (AFS) - /* We have to use access(2) to determine access because AFS does not - support Unix file system semantics. This may produce wrong - answers for non-AFS files when ruid != euid. I hate AFS. */ - if (access (name, X_OK) == 0) - r |= FS_EXECABLE; - if (access (name, R_OK) == 0) - r |= FS_READABLE; - - return r; -#else /* !HAVE_EACCESS && !AFS */ - - /* Find out if the file is actually executable. By definition, the - only other criteria is that the file has an execute bit set that - we can use. The same with whether or not a file is readable. */ - - /* Root only requires execute permission for any of owner, group or - others to be able to exec a file, and can read any file. */ - if (current_user.euid == (uid_t)0) - { - r |= FS_READABLE; - if (finfo.st_mode & S_IXUGO) - r |= FS_EXECABLE; - return r; - } - - /* If we are the owner of the file, the owner bits apply. */ - if (current_user.euid == finfo.st_uid) - { - if (finfo.st_mode & S_IXUSR) - r |= FS_EXECABLE; - if (finfo.st_mode & S_IRUSR) - r |= FS_READABLE; - } - - /* If we are in the owning group, the group permissions apply. */ - else if (group_member (finfo.st_gid)) - { - if (finfo.st_mode & S_IXGRP) - r |= FS_EXECABLE; - if (finfo.st_mode & S_IRGRP) - r |= FS_READABLE; - } - - /* Else we check whether `others' have permission to execute the file */ - else - { - if (finfo.st_mode & S_IXOTH) - r |= FS_EXECABLE; - if (finfo.st_mode & S_IROTH) - r |= FS_READABLE; - } - - return r; -#endif /* !AFS */ -} - -/* Return non-zero if FILE exists and is executable. - Note that this function is the definition of what an - executable file is; do not change this unless YOU know - what an executable file is. */ -int -executable_file (file) - const char *file; -{ - int s; - - s = file_status (file); -#if defined EISDIR - if (s & FS_DIRECTORY) - errno = EISDIR; /* let's see if we can improve error messages */ -#endif - return ((s & FS_EXECABLE) && ((s & FS_DIRECTORY) == 0)); -} - -int -is_directory (file) - const char *file; -{ - return (file_status (file) & FS_DIRECTORY); -} - -int -executable_or_directory (file) - const char *file; -{ - int s; - - s = file_status (file); - return ((s & FS_EXECABLE) || (s & FS_DIRECTORY)); -} - -/* Locate the executable file referenced by NAME, searching along - the contents of the shell PATH variable. Return a new string - which is the full pathname to the file, or NULL if the file - couldn't be found. If a file is found that isn't executable, - and that is the only match, then return that. */ -char * -find_user_command (name) - const char *name; -{ - return (find_user_command_internal (name, FS_EXEC_PREFERRED|FS_NODIRS)); -} - -/* Locate the file referenced by NAME, searching along the contents - of the shell PATH variable. Return a new string which is the full - pathname to the file, or NULL if the file couldn't be found. This - returns the first readable file found; designed to be used to look - for shell scripts or files to source. */ -char * -find_path_file (name) - const char *name; -{ - return (find_user_command_internal (name, FS_READABLE)); -} - -static char * -_find_user_command_internal (name, flags) - const char *name; - int flags; -{ - char *path_list, *cmd; - SHELL_VAR *var; - - /* Search for the value of PATH in both the temporary environments and - in the regular list of variables. */ - if (var = find_variable_tempenv ("PATH")) /* XXX could be array? */ - path_list = value_cell (var); - else - path_list = (char *)NULL; - - if (path_list == 0 || *path_list == '\0') - return (savestring (name)); - - cmd = find_user_command_in_path (name, path_list, flags); - - return (cmd); -} - -static char * -find_user_command_internal (name, flags) - const char *name; - int flags; -{ -#ifdef __WIN32__ - char *res, *dotexe; - - dotexe = (char *)xmalloc (strlen (name) + 5); - strcpy (dotexe, name); - strcat (dotexe, ".exe"); - res = _find_user_command_internal (dotexe, flags); - free (dotexe); - if (res == 0) - res = _find_user_command_internal (name, flags); - return res; -#else - return (_find_user_command_internal (name, flags)); -#endif -} - -/* Return the next element from PATH_LIST, a colon separated list of - paths. PATH_INDEX_POINTER is the address of an index into PATH_LIST; - the index is modified by this function. - Return the next element of PATH_LIST or NULL if there are no more. */ -static char * -get_next_path_element (path_list, path_index_pointer) - char *path_list; - int *path_index_pointer; -{ - char *path; - - path = extract_colon_unit (path_list, path_index_pointer); - - if (path == 0) - return (path); - - if (*path == '\0') - { - free (path); - path = savestring ("."); - } - - return (path); -} - -/* Look for PATHNAME in $PATH. Returns either the hashed command - corresponding to PATHNAME or the first instance of PATHNAME found - in $PATH. If (FLAGS&1) is non-zero, insert the instance of PATHNAME - found in $PATH into the command hash table. Returns a newly-allocated - string. */ -char * -search_for_command (pathname, flags) - const char *pathname; - int flags; -{ - char *hashed_file, *command; - int temp_path, st; - SHELL_VAR *path; - - hashed_file = command = (char *)NULL; - - /* If PATH is in the temporary environment for this command, don't use the - hash table to search for the full pathname. */ - path = find_variable_tempenv ("PATH"); - temp_path = path && tempvar_p (path); - if (temp_path == 0 && path) - path = (SHELL_VAR *)NULL; - - /* Don't waste time trying to find hashed data for a pathname - that is already completely specified or if we're using a command- - specific value for PATH. */ - if (path == 0 && absolute_program (pathname) == 0) - hashed_file = phash_search (pathname); - - /* If a command found in the hash table no longer exists, we need to - look for it in $PATH. Thank you Posix.2. This forces us to stat - every command found in the hash table. */ - - if (hashed_file && (posixly_correct || check_hashed_filenames)) - { - st = file_status (hashed_file); - if ((st & (FS_EXISTS|FS_EXECABLE)) != (FS_EXISTS|FS_EXECABLE)) - { - phash_remove (pathname); - free (hashed_file); - hashed_file = (char *)NULL; - } - } - - if (hashed_file) - command = hashed_file; - else if (absolute_program (pathname)) - /* A command containing a slash is not looked up in PATH or saved in - the hash table. */ - command = savestring (pathname); - else - { - /* If $PATH is in the temporary environment, we've already retrieved - it, so don't bother trying again. */ - if (temp_path) - { - command = find_user_command_in_path (pathname, value_cell (path), - FS_EXEC_PREFERRED|FS_NODIRS); - } - else - command = find_user_command (pathname); - if (command && hashing_enabled && temp_path == 0 && (flags & 1)) - phash_insert ((char *)pathname, command, dot_found_in_search, 1); /* XXX fix const later */ - } - return (command); -} - -char * -user_command_matches (name, flags, state) - const char *name; - int flags, state; -{ - register int i; - int path_index, name_len; - char *path_list, *path_element, *match; - struct stat dotinfo; - static char **match_list = NULL; - static int match_list_size = 0; - static int match_index = 0; - - if (state == 0) - { - /* Create the list of matches. */ - if (match_list == 0) - { - match_list_size = 5; - match_list = strvec_create (match_list_size); - } - - /* Clear out the old match list. */ - for (i = 0; i < match_list_size; i++) - match_list[i] = 0; - - /* We haven't found any files yet. */ - match_index = 0; - - if (absolute_program (name)) - { - match_list[0] = find_absolute_program (name, flags); - match_list[1] = (char *)NULL; - path_list = (char *)NULL; - } - else - { - name_len = strlen (name); - file_to_lose_on = (char *)NULL; - dot_found_in_search = 0; - if (stat (".", &dotinfo) < 0) - dotinfo.st_dev = dotinfo.st_ino = 0; /* so same_file won't match */ - path_list = get_string_value ("PATH"); - path_index = 0; - } - - while (path_list && path_list[path_index]) - { - path_element = get_next_path_element (path_list, &path_index); - - if (path_element == 0) - break; - - match = find_in_path_element (name, path_element, flags, name_len, &dotinfo); - - free (path_element); - - if (match == 0) - continue; - - if (match_index + 1 == match_list_size) - { - match_list_size += 10; - match_list = strvec_resize (match_list, (match_list_size + 1)); - } - - match_list[match_index++] = match; - match_list[match_index] = (char *)NULL; - FREE (file_to_lose_on); - file_to_lose_on = (char *)NULL; - } - - /* We haven't returned any strings yet. */ - match_index = 0; - } - - match = match_list[match_index]; - - if (match) - match_index++; - - return (match); -} - -static char * -find_absolute_program (name, flags) - const char *name; - int flags; -{ - int st; - - st = file_status (name); - - /* If the file doesn't exist, quit now. */ - if ((st & FS_EXISTS) == 0) - return ((char *)NULL); - - /* If we only care about whether the file exists or not, return - this filename. Otherwise, maybe we care about whether this - file is executable. If it is, and that is what we want, return it. */ - if ((flags & FS_EXISTS) || ((flags & FS_EXEC_ONLY) && (st & FS_EXECABLE))) - return (savestring (name)); - - return (NULL); -} - -static char * -find_in_path_element (name, path, flags, name_len, dotinfop) - const char *name; - char *path; - int flags, name_len; - struct stat *dotinfop; -{ - int status; - char *full_path, *xpath; - - xpath = (*path == '~') ? bash_tilde_expand (path, 0) : path; - - /* Remember the location of "." in the path, in all its forms - (as long as they begin with a `.', e.g. `./.') */ - if (dot_found_in_search == 0 && *xpath == '.') - dot_found_in_search = same_file (".", xpath, dotinfop, (struct stat *)NULL); - - full_path = sh_makepath (xpath, name, 0); - - status = file_status (full_path); - - if (xpath != path) - free (xpath); - - if ((status & FS_EXISTS) == 0) - { - free (full_path); - return ((char *)NULL); - } - - /* The file exists. If the caller simply wants the first file, here it is. */ - if (flags & FS_EXISTS) - return (full_path); - - /* If we have a readable file, and the caller wants a readable file, this - is it. */ - if ((flags & FS_READABLE) && (status & FS_READABLE)) - return (full_path); - - /* If the file is executable, then it satisfies the cases of - EXEC_ONLY and EXEC_PREFERRED. Return this file unconditionally. */ - if ((status & FS_EXECABLE) && (flags & (FS_EXEC_ONLY|FS_EXEC_PREFERRED)) && - (((flags & FS_NODIRS) == 0) || ((status & FS_DIRECTORY) == 0))) - { - FREE (file_to_lose_on); - file_to_lose_on = (char *)NULL; - return (full_path); - } - - /* The file is not executable, but it does exist. If we prefer - an executable, then remember this one if it is the first one - we have found. */ - if ((flags & FS_EXEC_PREFERRED) && file_to_lose_on == 0) - file_to_lose_on = savestring (full_path); - - /* If we want only executable files, or we don't want directories and - this file is a directory, or we want a readable file and this file - isn't readable, fail. */ - if ((flags & (FS_EXEC_ONLY|FS_EXEC_PREFERRED)) || - ((flags & FS_NODIRS) && (status & FS_DIRECTORY)) || - ((flags & FS_READABLE) && (status & FS_READABLE) == 0)) - { - free (full_path); - return ((char *)NULL); - } - else - return (full_path); -} - -/* This does the dirty work for find_user_command_internal () and - user_command_matches (). - NAME is the name of the file to search for. - PATH_LIST is a colon separated list of directories to search. - FLAGS contains bit fields which control the files which are eligible. - Some values are: - FS_EXEC_ONLY: The file must be an executable to be found. - FS_EXEC_PREFERRED: If we can't find an executable, then the - the first file matching NAME will do. - FS_EXISTS: The first file found will do. - FS_NODIRS: Don't find any directories. -*/ -static char * -find_user_command_in_path (name, path_list, flags) - const char *name; - char *path_list; - int flags; -{ - char *full_path, *path; - int path_index, name_len; - struct stat dotinfo; - - /* We haven't started looking, so we certainly haven't seen - a `.' as the directory path yet. */ - dot_found_in_search = 0; - - if (absolute_program (name)) - { - full_path = find_absolute_program (name, flags); - return (full_path); - } - - if (path_list == 0 || *path_list == '\0') - return (savestring (name)); /* XXX */ - - file_to_lose_on = (char *)NULL; - name_len = strlen (name); - if (stat (".", &dotinfo) < 0) - dotinfo.st_dev = dotinfo.st_ino = 0; - path_index = 0; - - while (path_list[path_index]) - { - /* Allow the user to interrupt out of a lengthy path search. */ - QUIT; - - path = get_next_path_element (path_list, &path_index); - if (path == 0) - break; - - /* Side effects: sets dot_found_in_search, possibly sets - file_to_lose_on. */ - full_path = find_in_path_element (name, path, flags, name_len, &dotinfo); - free (path); - - /* This should really be in find_in_path_element, but there isn't the - right combination of flags. */ - if (full_path && is_directory (full_path)) - { - free (full_path); - continue; - } - - if (full_path) - { - FREE (file_to_lose_on); - return (full_path); - } - } - - /* We didn't find exactly what the user was looking for. Return - the contents of FILE_TO_LOSE_ON which is NULL when the search - required an executable, or non-NULL if a file was found and the - search would accept a non-executable as a last resort. If the - caller specified FS_NODIRS, and file_to_lose_on is a directory, - return NULL. */ - if (file_to_lose_on && (flags & FS_NODIRS) && is_directory (file_to_lose_on)) - { - free (file_to_lose_on); - file_to_lose_on = (char *)NULL; - } - - return (file_to_lose_on); -} diff --git a/lib/glob/sm_loop.c~ b/lib/glob/sm_loop.c~ deleted file mode 100644 index 5529139a..00000000 --- a/lib/glob/sm_loop.c~ +++ /dev/null @@ -1,835 +0,0 @@ -/* Copyright (C) 1991-2011 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 <http://www.gnu.org/licenses/>. -*/ - -int FCT __P((CHAR *, CHAR *, int)); - -static int GMATCH __P((CHAR *, CHAR *, CHAR *, CHAR *, int)); -static CHAR *PARSE_COLLSYM __P((CHAR *, INT *)); -static CHAR *BRACKMATCH __P((CHAR *, U_CHAR, int)); -static int EXTMATCH __P((INT, CHAR *, CHAR *, CHAR *, CHAR *, int)); - -/*static*/ CHAR *PATSCAN __P((CHAR *, CHAR *, INT)); - -int -FCT (pattern, string, flags) - CHAR *pattern; - CHAR *string; - int flags; -{ - CHAR *se, *pe; - - if (string == 0 || pattern == 0) - return FNM_NOMATCH; - - se = string + STRLEN ((XCHAR *)string); - pe = pattern + STRLEN ((XCHAR *)pattern); - - return (GMATCH (string, se, pattern, pe, flags)); -} - -/* Match STRING against the filename pattern PATTERN, returning zero if - it matches, FNM_NOMATCH if not. */ -static int -GMATCH (string, se, pattern, pe, flags) - CHAR *string, *se; - CHAR *pattern, *pe; - int flags; -{ - CHAR *p, *n; /* pattern, string */ - INT c; /* current pattern character - XXX U_CHAR? */ - INT sc; /* current string character - XXX U_CHAR? */ - - p = pattern; - n = string; - - if (string == 0 || pattern == 0) - return FNM_NOMATCH; - -#if DEBUG_MATCHING -fprintf(stderr, "gmatch: string = %s; se = %s\n", string, se); -fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe); -#endif - - while (p < pe) - { - c = *p++; - c = FOLD (c); - - sc = n < se ? *n : '\0'; - -#ifdef EXTENDED_GLOB - /* EXTMATCH () will handle recursively calling GMATCH, so we can - just return what EXTMATCH() returns. */ - if ((flags & FNM_EXTMATCH) && *p == L('(') && - (c == L('+') || c == L('*') || c == L('?') || c == L('@') || c == L('!'))) /* ) */ - { - int lflags; - /* If we're not matching the start of the string, we're not - concerned about the special cases for matching `.' */ - lflags = (n == string) ? flags : (flags & ~FNM_PERIOD); - return (EXTMATCH (c, n, se, p, pe, lflags)); - } -#endif /* EXTENDED_GLOB */ - - switch (c) - { - case L('?'): /* Match single character */ - if (sc == '\0') - return FNM_NOMATCH; - else if ((flags & FNM_PATHNAME) && sc == L('/')) - /* If we are matching a pathname, `?' can never match a `/'. */ - return FNM_NOMATCH; - else if ((flags & FNM_PERIOD) && sc == L('.') && - (n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/')))) - /* `?' cannot match a `.' if it is the first character of the - string or if it is the first character following a slash and - we are matching a pathname. */ - return FNM_NOMATCH; - break; - - case L('\\'): /* backslash escape removes special meaning */ - if (p == pe) - return FNM_NOMATCH; - - if ((flags & FNM_NOESCAPE) == 0) - { - c = *p++; - /* A trailing `\' cannot match. */ - if (p > pe) - return FNM_NOMATCH; - c = FOLD (c); - } - if (FOLD (sc) != (U_CHAR)c) - return FNM_NOMATCH; - break; - - case '*': /* Match zero or more characters */ - if (p == pe) - return 0; - - if ((flags & FNM_PERIOD) && sc == L('.') && - (n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/')))) - /* `*' cannot match a `.' if it is the first character of the - string or if it is the first character following a slash and - we are matching a pathname. */ - return FNM_NOMATCH; - - /* Collapse multiple consecutive `*' and `?', but make sure that - one character of the string is consumed for each `?'. */ - for (c = *p++; (c == L('?') || c == L('*')); c = *p++) - { - if ((flags & FNM_PATHNAME) && sc == L('/')) - /* A slash does not match a wildcard under FNM_PATHNAME. */ - return FNM_NOMATCH; -#ifdef EXTENDED_GLOB - else if ((flags & FNM_EXTMATCH) && c == L('?') && *p == L('(')) /* ) */ - { - CHAR *newn; - for (newn = n; newn < se; ++newn) - { - if (EXTMATCH (c, newn, se, p, pe, flags) == 0) - return (0); - } - /* We didn't match. If we have a `?(...)', we can match 0 - or 1 times. */ - return 0; - } -#endif - else if (c == L('?')) - { - if (sc == L('\0')) - return FNM_NOMATCH; - /* One character of the string is consumed in matching - this ? wildcard, so *??? won't match if there are - fewer than three characters. */ - n++; - sc = n < se ? *n : '\0'; - } - -#ifdef EXTENDED_GLOB - /* Handle ******(patlist) */ - if ((flags & FNM_EXTMATCH) && c == L('*') && *p == L('(')) /*)*/ - { - CHAR *newn; - /* We need to check whether or not the extended glob - pattern matches the remainder of the string. - If it does, we match the entire pattern. */ - for (newn = n; newn < se; ++newn) - { - if (EXTMATCH (c, newn, se, p, pe, flags) == 0) - return (0); - } - /* We didn't match the extended glob pattern, but - that's OK, since we can match 0 or more occurrences. - We need to skip the glob pattern and see if we - match the rest of the string. */ - newn = PATSCAN (p + 1, pe, 0); - /* If NEWN is 0, we have an ill-formed pattern. */ - p = newn ? newn : pe; - } -#endif - if (p == pe) - break; - } - - /* The wildcards are the last element of the pattern. The name - cannot match completely if we are looking for a pathname and - it contains another slash, unless FNM_LEADING_DIR is set. */ - if (c == L('\0')) - { - int r = (flags & FNM_PATHNAME) == 0 ? 0 : FNM_NOMATCH; - if (flags & FNM_PATHNAME) - { - if (flags & FNM_LEADING_DIR) - r = 0; - else if (MEMCHR (n, L('/'), se - n) == NULL) - r = 0; - } - return r; - } - - /* If we've hit the end of the pattern and the last character of - the pattern was handled by the loop above, we've succeeded. - Otherwise, we need to match that last character. */ - if (p == pe && (c == L('?') || c == L('*'))) - return (0); - - /* If we've hit the end of the string and the rest of the pattern - is something that matches the empty string, we can succeed. */ -#if defined (EXTENDED_GLOB) - if (n == se && ((flags & FNM_EXTMATCH) && (c == L('!') || c == L('?')) && *p == L('('))) - { - --p; - if (EXTMATCH (c, n, se, p, pe, flags) == 0) - return (c == L('!') ? FNM_NOMATCH : 0); - return (c == L('!') ? 0 : FNM_NOMATCH); - } -#endif - - /* If we stop at a slash in the pattern and we are looking for a - pathname ([star]/foo), then consume enough of the string to stop - at any slash and then try to match the rest of the pattern */ - if (c == L('/') && (flags & FNM_PATHNAME)) - { - while (n < se && *n != L('/')) - ++n; - if (n < se && *n == L('/') && (GMATCH (n+1, se, p, pe, flags) == 0)) - return 0; - return FNM_NOMATCH; /* XXX */ - } - else - /* General case, use recursion. */ - { - U_CHAR c1; - const CHAR *endp; - - endp = MEMCHR (n, (flags & FNM_PATHNAME) ? L('/') : L('\0'), se - n); - if (endp == 0) - endp = se; - c1 = ((flags & FNM_NOESCAPE) == 0 && c == L('\\')) ? *p : c; - c1 = FOLD (c1); - for (--p; n < endp; ++n) - { - /* Only call strmatch if the first character indicates a - possible match. We can check the first character if - we're not doing an extended glob match. */ - if ((flags & FNM_EXTMATCH) == 0 && c != L('[') && FOLD (*n) != c1) /*]*/ - continue; - - /* If we're doing an extended glob match and the pattern is not - one of the extended glob patterns, we can check the first - character. */ - if ((flags & FNM_EXTMATCH) && p[1] != L('(') && /*)*/ - STRCHR (L("?*+@!"), *p) == 0 && c != L('[') && FOLD (*n) != c1) /*]*/ - continue; - - /* Otherwise, we just recurse. */ - if (GMATCH (n, se, p, pe, flags & ~FNM_PERIOD) == 0) - return (0); - } - return FNM_NOMATCH; - } - - case L('['): - { - if (sc == L('\0') || n == se) - return FNM_NOMATCH; - - /* A character class cannot match a `.' if it is the first - character of the string or if it is the first character - following a slash and we are matching a pathname. */ - if ((flags & FNM_PERIOD) && sc == L('.') && - (n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/')))) - return (FNM_NOMATCH); - - p = BRACKMATCH (p, sc, flags); - if (p == 0) - return FNM_NOMATCH; - } - break; - - default: - if ((U_CHAR)c != FOLD (sc)) - return (FNM_NOMATCH); - } - - ++n; - } - - if (n == se) - return (0); - - if ((flags & FNM_LEADING_DIR) && *n == L('/')) - /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ - return 0; - - return (FNM_NOMATCH); -} - -/* Parse a bracket expression collating symbol ([.sym.]) starting at P, find - the value of the symbol, and move P past the collating symbol expression. - The value is returned in *VP, if VP is not null. */ -static CHAR * -PARSE_COLLSYM (p, vp) - CHAR *p; - INT *vp; -{ - register int pc; - INT val; - - p++; /* move past the `.' */ - - for (pc = 0; p[pc]; pc++) - if (p[pc] == L('.') && p[pc+1] == L(']')) - break; - val = COLLSYM (p, pc); - if (vp) - *vp = val; - return (p + pc + 2); -} - -/* Use prototype definition here because of type promotion. */ -static CHAR * -#if defined (PROTOTYPES) -BRACKMATCH (CHAR *p, U_CHAR test, int flags) -#else -BRACKMATCH (p, test, flags) - CHAR *p; - U_CHAR test; - int flags; -#endif -{ - register CHAR cstart, cend, c; - register int not; /* Nonzero if the sense of the character class is inverted. */ - int brcnt, forcecoll; - INT pc; - CHAR *savep; - - test = FOLD (test); - - savep = p; - - /* POSIX.2 3.13.1 says that an exclamation mark (`!') shall replace the - circumflex (`^') in its role in a `nonmatching list'. A bracket - expression starting with an unquoted circumflex character produces - unspecified results. This implementation treats the two identically. */ - if (not = (*p == L('!') || *p == L('^'))) - ++p; - - c = *p++; - for (;;) - { - /* Initialize cstart and cend in case `-' is the last - character of the pattern. */ - cstart = cend = c; - forcecoll = 0; - - /* POSIX.2 equivalence class: [=c=]. See POSIX.2 2.8.3.2. Find - the end of the equivalence class, move the pattern pointer past - it, and check for equivalence. XXX - this handles only - single-character equivalence classes, which is wrong, or at - least incomplete. */ - if (c == L('[') && *p == L('=') && p[2] == L('=') && p[3] == L(']')) - { - pc = FOLD (p[1]); - p += 4; - if (COLLEQUIV (test, pc)) - { -/*[*/ /* Move past the closing `]', since the first thing we do at - the `matched:' label is back p up one. */ - p++; - goto matched; - } - else - { - c = *p++; - if (c == L('\0')) - return ((test == L('[')) ? savep : (CHAR *)0); /*]*/ - c = FOLD (c); - continue; - } - } - - /* POSIX.2 character class expression. See POSIX.2 2.8.3.2. */ - if (c == L('[') && *p == L(':')) - { - CHAR *close, *ccname; - - pc = 0; /* make sure invalid char classes don't match. */ - /* Find end of character class name */ - for (close = p + 1; *close != '\0'; close++) - if (*close == L(':') && *(close+1) == L(']')) - break; - - if (*close != L('\0')) - { - ccname = (CHAR *)malloc ((close - p) * sizeof (CHAR)); - if (ccname == 0) - pc = 0; - else - { - bcopy (p + 1, ccname, (close - p - 1) * sizeof (CHAR)); - *(ccname + (close - p - 1)) = L('\0'); - pc = IS_CCLASS (test, (XCHAR *)ccname); - } - if (pc == -1) - pc = 0; - else - p = close + 2; - - free (ccname); - } - - if (pc) - { -/*[*/ /* Move past the closing `]', since the first thing we do at - the `matched:' label is back p up one. */ - p++; - goto matched; - } - else - { - /* continue the loop here, since this expression can't be - the first part of a range expression. */ - c = *p++; - if (c == L('\0')) - return ((test == L('[')) ? savep : (CHAR *)0); - else if (c == L(']')) - break; - c = FOLD (c); - continue; - } - } - - /* POSIX.2 collating symbols. See POSIX.2 2.8.3.2. Find the end of - the symbol name, make sure it is terminated by `.]', translate - the name to a character using the external table, and do the - comparison. */ - if (c == L('[') && *p == L('.')) - { - p = PARSE_COLLSYM (p, &pc); - /* An invalid collating symbol cannot be the first point of a - range. If it is, we set cstart to one greater than `test', - so any comparisons later will fail. */ - cstart = (pc == INVALID) ? test + 1 : pc; - forcecoll = 1; - } - - if (!(flags & FNM_NOESCAPE) && c == L('\\')) - { - if (*p == '\0') - return (CHAR *)0; - cstart = cend = *p++; - } - - cstart = cend = FOLD (cstart); - - /* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that - is not preceded by a backslash and is not part of a bracket - expression produces undefined results.' This implementation - treats the `[' as just a character to be matched if there is - not a closing `]'. */ - if (c == L('\0')) - return ((test == L('[')) ? savep : (CHAR *)0); - - c = *p++; - c = FOLD (c); - - if ((flags & FNM_PATHNAME) && c == L('/')) - /* [/] can never match when matching a pathname. */ - return (CHAR *)0; - - /* This introduces a range, unless the `-' is the last - character of the class. Find the end of the range - and move past it. */ - if (c == L('-') && *p != L(']')) - { - cend = *p++; - if (!(flags & FNM_NOESCAPE) && cend == L('\\')) - cend = *p++; - if (cend == L('\0')) - return (CHAR *)0; - if (cend == L('[') && *p == L('.')) - { - p = PARSE_COLLSYM (p, &pc); - /* An invalid collating symbol cannot be the second part of a - range expression. If we get one, we set cend to one fewer - than the test character to make sure the range test fails. */ - cend = (pc == INVALID) ? test - 1 : pc; - forcecoll = 1; - } - cend = FOLD (cend); - - c = *p++; - - /* POSIX.2 2.8.3.2: ``The ending range point shall collate - equal to or higher than the starting range point; otherwise - the expression shall be treated as invalid.'' Note that this - applies to only the range expression; the rest of the bracket - expression is still checked for matches. */ - if (RANGECMP (cstart, cend, forcecoll) > 0) - { - if (c == L(']')) - break; - c = FOLD (c); - continue; - } - } - - if (RANGECMP (test, cstart, forcecoll) >= 0 && RANGECMP (test, cend, forcecoll) <= 0) - goto matched; - - if (c == L(']')) - break; - } - /* No match. */ - return (!not ? (CHAR *)0 : p); - -matched: - /* Skip the rest of the [...] that already matched. */ - c = *--p; - brcnt = 1; - while (brcnt > 0) - { - /* A `[' without a matching `]' is just another character to match. */ - if (c == L('\0')) - return ((test == L('[')) ? savep : (CHAR *)0); - - c = *p++; - if (c == L('[') && (*p == L('=') || *p == L(':') || *p == L('.'))) - brcnt++; - else if (c == L(']')) - brcnt--; - else if (!(flags & FNM_NOESCAPE) && c == L('\\')) - { - if (*p == '\0') - return (CHAR *)0; - /* XXX 1003.2d11 is unclear if this is right. */ - ++p; - } - } - return (not ? (CHAR *)0 : p); -} - -#if defined (EXTENDED_GLOB) -/* ksh-like extended pattern matching: - - [?*+@!](pat-list) - - where pat-list is a list of one or patterns separated by `|'. Operation - is as follows: - - ?(patlist) match zero or one of the given patterns - *(patlist) match zero or more of the given patterns - +(patlist) match one or more of the given patterns - @(patlist) match exactly one of the given patterns - !(patlist) match anything except one of the given patterns -*/ - -/* Scan a pattern starting at STRING and ending at END, keeping track of - embedded () and []. If DELIM is 0, we scan until a matching `)' - because we're scanning a `patlist'. Otherwise, we scan until we see - DELIM. In all cases, we never scan past END. The return value is the - first character after the matching DELIM or NULL if the pattern is - empty or invalid. */ -/*static*/ CHAR * -PATSCAN (string, end, delim) - CHAR *string, *end; - INT delim; -{ - int pnest, bnest, skip; - INT cchar; - CHAR *s, c, *bfirst; - - pnest = bnest = skip = 0; - cchar = 0; - bfirst = NULL; - - if (string == end) - return (NULL); - - for (s = string; c = *s; s++) - { - if (s >= end) - return (s); - if (skip) - { - skip = 0; - continue; - } - switch (c) - { - case L('\\'): - skip = 1; - break; - - case L('\0'): - return ((CHAR *)NULL); - - /* `[' is not special inside a bracket expression, but it may - introduce one of the special POSIX bracket expressions - ([.SYM.], [=c=], [: ... :]) that needs special handling. */ - case L('['): - if (bnest == 0) - { - bfirst = s + 1; - if (*bfirst == L('!') || *bfirst == L('^')) - bfirst++; - bnest++; - } - else if (s[1] == L(':') || s[1] == L('.') || s[1] == L('=')) - cchar = s[1]; - break; - - /* `]' is not special if it's the first char (after a leading `!' - or `^') in a bracket expression or if it's part of one of the - special POSIX bracket expressions ([.SYM.], [=c=], [: ... :]) */ - case L(']'): - if (bnest) - { - if (cchar && s[-1] == cchar) - cchar = 0; - else if (s != bfirst) - { - bnest--; - bfirst = 0; - } - } - break; - - case L('('): - if (bnest == 0) - pnest++; - break; - - case L(')'): - if (bnest == 0 && pnest-- <= 0) - return ++s; - break; - - case L('|'): - if (bnest == 0 && pnest == 0 && delim == L('|')) - return ++s; - break; - } - } - - return (NULL); -} - -/* Return 0 if dequoted pattern matches S in the current locale. */ -static int -STRCOMPARE (p, pe, s, se) - CHAR *p, *pe, *s, *se; -{ - int ret; - CHAR c1, c2; - int l1, l2; - - l1 = pe - p; - l2 = se - s; - - if (l1 != l2) - return (FNM_NOMATCH); /* unequal lengths, can't be identical */ - - c1 = *pe; - c2 = *se; - - if (c1 != 0) - *pe = '\0'; - if (c2 != 0) - *se = '\0'; - -#if HAVE_MULTIBYTE || defined (HAVE_STRCOLL) - ret = STRCOLL ((XCHAR *)p, (XCHAR *)s); -#else - ret = STRCMP ((XCHAR *)p, (XCHAR *)s); -#endif - - if (c1 != 0) - *pe = c1; - if (c2 != 0) - *se = c2; - - return (ret == 0 ? ret : FNM_NOMATCH); -} - -/* Match a ksh extended pattern specifier. Return FNM_NOMATCH on failure or - 0 on success. This is handed the entire rest of the pattern and string - the first time an extended pattern specifier is encountered, so it calls - gmatch recursively. */ -static int -EXTMATCH (xc, s, se, p, pe, flags) - INT xc; /* select which operation */ - CHAR *s, *se; - CHAR *p, *pe; - int flags; -{ - CHAR *prest; /* pointer to rest of pattern */ - CHAR *psub; /* pointer to sub-pattern */ - CHAR *pnext; /* pointer to next sub-pattern */ - CHAR *srest; /* pointer to rest of string */ - int m1, m2, xflags; /* xflags = flags passed to recursive matches */ - -#if DEBUG_MATCHING -fprintf(stderr, "extmatch: xc = %c\n", xc); -fprintf(stderr, "extmatch: s = %s; se = %s\n", s, se); -fprintf(stderr, "extmatch: p = %s; pe = %s\n", p, pe); -fprintf(stderr, "extmatch: flags = %d\n", flags); -#endif - - prest = PATSCAN (p + (*p == L('(')), pe, 0); /* ) */ - if (prest == 0) - /* If PREST is 0, we failed to scan a valid pattern. In this - case, we just want to compare the two as strings. */ - return (STRCOMPARE (p - 1, pe, s, se)); - - switch (xc) - { - case L('+'): /* match one or more occurrences */ - case L('*'): /* match zero or more occurrences */ - /* If we can get away with no matches, don't even bother. Just - call GMATCH on the rest of the pattern and return success if - it succeeds. */ - if (xc == L('*') && (GMATCH (s, se, prest, pe, flags) == 0)) - return 0; - - /* OK, we have to do this the hard way. First, we make sure one of - the subpatterns matches, then we try to match the rest of the - string. */ - for (psub = p + 1; ; psub = pnext) - { - pnext = PATSCAN (psub, pe, L('|')); - for (srest = s; srest <= se; srest++) - { - /* Match this substring (S -> SREST) against this - subpattern (psub -> pnext - 1) */ - m1 = GMATCH (s, srest, psub, pnext - 1, flags) == 0; - /* OK, we matched a subpattern, so make sure the rest of the - string matches the rest of the pattern. Also handle - multiple matches of the pattern. */ - if (m1) - { - /* if srest > s, we are not at start of string */ - xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags; - m2 = (GMATCH (srest, se, prest, pe, xflags) == 0) || - (s != srest && GMATCH (srest, se, p - 1, pe, xflags) == 0); - } - if (m1 && m2) - return (0); - } - if (pnext == prest) - break; - } - return (FNM_NOMATCH); - - case L('?'): /* match zero or one of the patterns */ - case L('@'): /* match one (or more) of the patterns */ - /* If we can get away with no matches, don't even bother. Just - call gmatch on the rest of the pattern and return success if - it succeeds. */ - if (xc == L('?') && (GMATCH (s, se, prest, pe, flags) == 0)) - return 0; - - /* OK, we have to do this the hard way. First, we see if one of - the subpatterns matches, then, if it does, we try to match the - rest of the string. */ - for (psub = p + 1; ; psub = pnext) - { - pnext = PATSCAN (psub, pe, L('|')); - srest = (prest == pe) ? se : s; - for ( ; srest <= se; srest++) - { - /* if srest > s, we are not at start of string */ - xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags; - if (GMATCH (s, srest, psub, pnext - 1, flags) == 0 && - GMATCH (srest, se, prest, pe, xflags) == 0) - return (0); - } - if (pnext == prest) - break; - } - return (FNM_NOMATCH); - - case '!': /* match anything *except* one of the patterns */ - for (srest = s; srest <= se; srest++) - { - m1 = 0; - for (psub = p + 1; ; psub = pnext) - { - pnext = PATSCAN (psub, pe, L('|')); - /* If one of the patterns matches, just bail immediately. */ - if (m1 = (GMATCH (s, srest, psub, pnext - 1, flags) == 0)) - break; - if (pnext == prest) - break; - } - /* if srest > s, we are not at start of string */ - xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags; - if (m1 == 0 && GMATCH (srest, se, prest, pe, xflags) == 0) - return (0); - } - return (FNM_NOMATCH); - } - - return (FNM_NOMATCH); -} -#endif /* EXTENDED_GLOB */ - -#undef IS_CCLASS -#undef FOLD -#undef CHAR -#undef U_CHAR -#undef XCHAR -#undef INT -#undef INVALID -#undef FCT -#undef GMATCH -#undef COLLSYM -#undef PARSE_COLLSYM -#undef PATSCAN -#undef STRCOMPARE -#undef EXTMATCH -#undef BRACKMATCH -#undef STRCHR -#undef STRCOLL -#undef STRLEN -#undef STRCMP -#undef COLLEQUIV -#undef RANGECMP -#undef L diff --git a/lib/glob/smatch.c~ b/lib/glob/smatch.c~ deleted file mode 100644 index 848610ab..00000000 --- a/lib/glob/smatch.c~ +++ /dev/null @@ -1,415 +0,0 @@ -/* strmatch.c -- ksh-like extended pattern matching for the shell and filename - globbing. */ - -/* Copyright (C) 1991-2011 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 <http://www.gnu.org/licenses/>. -*/ - -#include <config.h> - -#include <stdio.h> /* for debugging */ - -#include "strmatch.h" -#include <chartypes.h> - -#include "bashansi.h" -#include "shmbutil.h" -#include "xmalloc.h" - -/* First, compile `sm_loop.c' for single-byte characters. */ -#define CHAR unsigned char -#define U_CHAR unsigned char -#define XCHAR char -#define INT int -#define L(CS) CS -#define INVALID -1 - -#undef STREQ -#undef STREQN -#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0) -#define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0) - -#ifndef GLOBASCII_DEFAULT -# define GLOBASCII_DEFAULT 0 -#endif - -int glob_asciirange = GLOBASCII_DEFAULT; - -/* We use strcoll(3) for range comparisons in bracket expressions, - even though it can have unwanted side effects in locales - other than POSIX or US. For instance, in the de locale, [A-Z] matches - all characters. If GLOB_ASCIIRANGE is non-zero, and we're not forcing - the use of strcoll (e.g., for explicit collating symbols), we use - straight ordering as if in the C locale. */ - -#if defined (HAVE_STRCOLL) -/* Helper function for collating symbol equivalence. */ -static int -rangecmp (c1, c2, forcecoll) - int c1, c2; - int forcecoll; -{ - static char s1[2] = { ' ', '\0' }; - static char s2[2] = { ' ', '\0' }; - int ret; - - /* Eight bits only. Period. */ - c1 &= 0xFF; - c2 &= 0xFF; - - if (c1 == c2) - return (0); - - if (forcecoll == 0 && glob_asciirange) - return (c1 - c2); - - s1[0] = c1; - s2[0] = c2; - - if ((ret = strcoll (s1, s2)) != 0) - return ret; - return (c1 - c2); -} -#else /* !HAVE_STRCOLL */ -# define rangecmp(c1, c2, f) ((int)(c1) - (int)(c2)) -#endif /* !HAVE_STRCOLL */ - -#if defined (HAVE_STRCOLL) -static int -collequiv (c1, c2) - int c1, c2; -{ - return (rangecmp (c1, c2, 1) == 0); -} -#else -# define collequiv(c1, c2) ((c1) == (c2)) -#endif - -#define _COLLSYM _collsym -#define __COLLSYM __collsym -#define POSIXCOLL posix_collsyms -#include "collsyms.h" - -static int -collsym (s, len) - CHAR *s; - int len; -{ - register struct _collsym *csp; - char *x; - - x = (char *)s; - for (csp = posix_collsyms; csp->name; csp++) - { - if (STREQN(csp->name, x, len) && csp->name[len] == '\0') - return (csp->code); - } - if (len == 1) - return s[0]; - return INVALID; -} - -/* unibyte character classification */ -#if !defined (isascii) && !defined (HAVE_ISASCII) -# define isascii(c) ((unsigned int)(c) <= 0177) -#endif - -enum char_class - { - CC_NO_CLASS = 0, - CC_ASCII, CC_ALNUM, CC_ALPHA, CC_BLANK, CC_CNTRL, CC_DIGIT, CC_GRAPH, - CC_LOWER, CC_PRINT, CC_PUNCT, CC_SPACE, CC_UPPER, CC_WORD, CC_XDIGIT - }; - -static char const *const cclass_name[] = - { - "", - "ascii", "alnum", "alpha", "blank", "cntrl", "digit", "graph", - "lower", "print", "punct", "space", "upper", "word", "xdigit" - }; - -#define N_CHAR_CLASS (sizeof(cclass_name) / sizeof (cclass_name[0])) - -static int -is_cclass (c, name) - int c; - const char *name; -{ - enum char_class char_class = CC_NO_CLASS; - int i, result; - - for (i = 1; i < N_CHAR_CLASS; i++) - { - if (STREQ (name, cclass_name[i])) - { - char_class = (enum char_class)i; - break; - } - } - - if (char_class == 0) - return -1; - - switch (char_class) - { - case CC_ASCII: - result = isascii (c); - break; - case CC_ALNUM: - result = ISALNUM (c); - break; - case CC_ALPHA: - result = ISALPHA (c); - break; - case CC_BLANK: - result = ISBLANK (c); - break; - case CC_CNTRL: - result = ISCNTRL (c); - break; - case CC_DIGIT: - result = ISDIGIT (c); - break; - case CC_GRAPH: - result = ISGRAPH (c); - break; - case CC_LOWER: - result = ISLOWER (c); - break; - case CC_PRINT: - result = ISPRINT (c); - break; - case CC_PUNCT: - result = ISPUNCT (c); - break; - case CC_SPACE: - result = ISSPACE (c); - break; - case CC_UPPER: - result = ISUPPER (c); - break; - case CC_WORD: - result = (ISALNUM (c) || c == '_'); - break; - case CC_XDIGIT: - result = ISXDIGIT (c); - break; - default: - result = -1; - break; - } - - return result; -} - -/* Now include `sm_loop.c' for single-byte characters. */ -/* The result of FOLD is an `unsigned char' */ -# define FOLD(c) ((flags & FNM_CASEFOLD) \ - ? TOLOWER ((unsigned char)c) \ - : ((unsigned char)c)) - -#define FCT internal_strmatch -#define GMATCH gmatch -#define COLLSYM collsym -#define PARSE_COLLSYM parse_collsym -#define BRACKMATCH brackmatch -#define PATSCAN glob_patscan -#define STRCOMPARE strcompare -#define EXTMATCH extmatch -#define STRCHR(S, C) strchr((S), (C)) -#define STRCOLL(S1, S2) strcoll((S1), (S2)) -#define STRLEN(S) strlen(S) -#define STRCMP(S1, S2) strcmp((S1), (S2)) -#define RANGECMP(C1, C2, F) rangecmp((C1), (C2), (F)) -#define COLLEQUIV(C1, C2) collequiv((C1), (C2)) -#define CTYPE_T enum char_class -#define IS_CCLASS(C, S) is_cclass((C), (S)) -#include "sm_loop.c" - -#if HANDLE_MULTIBYTE - -# define CHAR wchar_t -# define U_CHAR wint_t -# define XCHAR wchar_t -# define INT wint_t -# define L(CS) L##CS -# define INVALID WEOF - -# undef STREQ -# undef STREQN -# define STREQ(s1, s2) ((wcscmp (s1, s2) == 0)) -# define STREQN(a, b, n) ((a)[0] == (b)[0] && wcsncmp(a, b, n) == 0) - -extern char *mbsmbchar __P((const char *)); - -static int -rangecmp_wc (c1, c2, forcecoll) - wint_t c1, c2; - int forcecoll; -{ - static wchar_t s1[2] = { L' ', L'\0' }; - static wchar_t s2[2] = { L' ', L'\0' }; - - if (c1 == c2) - return 0; - - if (forcecoll == 0 && glob_asciirange && c1 <= UCHAR_MAX && c2 <= UCHAR_MAX) - return ((int)(c1 - c2)); - - s1[0] = c1; - s2[0] = c2; - - return (wcscoll (s1, s2)); -} - -static int -collequiv_wc (c, equiv) - wint_t c, equiv; -{ - return (c == equiv); -} - -/* Helper function for collating symbol. */ -# define _COLLSYM _collwcsym -# define __COLLSYM __collwcsym -# define POSIXCOLL posix_collwcsyms -# include "collsyms.h" - -static wint_t -collwcsym (s, len) - wchar_t *s; - int len; -{ - register struct _collwcsym *csp; - - for (csp = posix_collwcsyms; csp->name; csp++) - { - if (STREQN(csp->name, s, len) && csp->name[len] == L'\0') - return (csp->code); - } - if (len == 1) - return s[0]; - return INVALID; -} - -static int -is_wcclass (wc, name) - wint_t wc; - wchar_t *name; -{ - char *mbs; - mbstate_t state; - size_t mbslength; - wctype_t desc; - int want_word; - - if ((wctype ("ascii") == (wctype_t)0) && (wcscmp (name, L"ascii") == 0)) - { - int c; - - if ((c = wctob (wc)) == EOF) - return 0; - else - return (c <= 0x7F); - } - - want_word = (wcscmp (name, L"word") == 0); - if (want_word) - name = L"alnum"; - - memset (&state, '\0', sizeof (mbstate_t)); - mbs = (char *) malloc (wcslen(name) * MB_CUR_MAX + 1); - mbslength = wcsrtombs (mbs, (const wchar_t **)&name, (wcslen(name) * MB_CUR_MAX + 1), &state); - - if (mbslength == (size_t)-1 || mbslength == (size_t)-2) - { - free (mbs); - return -1; - } - desc = wctype (mbs); - free (mbs); - - if (desc == (wctype_t)0) - return -1; - - if (want_word) - return (iswctype (wc, desc) || wc == L'_'); - else - return (iswctype (wc, desc)); -} - -/* Now include `sm_loop.c' for multibyte characters. */ -#define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c)) -#define FCT internal_wstrmatch -#define GMATCH gmatch_wc -#define COLLSYM collwcsym -#define PARSE_COLLSYM parse_collwcsym -#define BRACKMATCH brackmatch_wc -#define PATSCAN glob_patscan_wc -#define STRCOMPARE wscompare -#define EXTMATCH extmatch_wc -#define STRCHR(S, C) wcschr((S), (C)) -#define STRCOLL(S1, S2) wcscoll((S1), (S2)) -#define STRLEN(S) wcslen(S) -#define STRCMP(S1, S2) wcscmp((S1), (S2)) -#define RANGECMP(C1, C2, F) rangecmp_wc((C1), (C2), (F)) -#define COLLEQUIV(C1, C2) collequiv_wc((C1), (C2)) -#define CTYPE_T enum char_class -#define IS_CCLASS(C, S) is_wcclass((C), (S)) -#include "sm_loop.c" - -#endif /* HAVE_MULTIBYTE */ - -int -xstrmatch (pattern, string, flags) - char *pattern; - char *string; - int flags; -{ -#if HANDLE_MULTIBYTE - int ret; - size_t n; - wchar_t *wpattern, *wstring; - size_t plen, slen, mplen, mslen; - - if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0) - return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags)); - - if (MB_CUR_MAX == 1) - return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags)); - - n = xdupmbstowcs (&wpattern, NULL, pattern); - if (n == (size_t)-1 || n == (size_t)-2) - return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags)); - - n = xdupmbstowcs (&wstring, NULL, string); - if (n == (size_t)-1 || n == (size_t)-2) - { - free (wpattern); - return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags)); - } - - ret = internal_wstrmatch (wpattern, wstring, flags); - - free (wpattern); - free (wstring); - - return ret; -#else - return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags)); -#endif /* !HANDLE_MULTIBYTE */ -} diff --git a/lib/readline/doc/Makefile.old b/lib/readline/doc/Makefile.old deleted file mode 100644 index 58d4dd76..00000000 --- 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/doc/history.3~ b/lib/readline/doc/history.3~ deleted file mode 100644 index 82ef33a2..00000000 --- a/lib/readline/doc/history.3~ +++ /dev/null @@ -1,673 +0,0 @@ -.\" -.\" MAN PAGE COMMENTS to -.\" -.\" Chet Ramey -.\" Information Network Services -.\" Case Western Reserve University -.\" chet.ramey@case.edu -.\" -.\" Last Change: Thu Thu Jun 27 10:34:44 EDT 2013 -.\" -.TH HISTORY 3 "2013 June 27" "GNU History 6.3" -.\" -.\" File Name macro. This used to be `.PN', for Path Name, -.\" but Sun doesn't seem to like that very much. -.\" -.de FN -\fI\|\\$1\|\fP -.. -.ds lp \fR\|(\fP -.ds rp \fR\|)\fP -.\" FnN return-value fun-name N arguments -.de Fn1 -\fI\\$1\fP \fB\\$2\fP \\*(lp\fI\\$3\fP\\*(rp -.br -.. -.de Fn2 -.if t \fI\\$1\fP \fB\\$2\fP \\*(lp\fI\\$3,\|\\$4\fP\\*(rp -.if n \fI\\$1\fP \fB\\$2\fP \\*(lp\fI\\$3, \\$4\fP\\*(rp -.br -.. -.de Fn3 -.if t \fI\\$1\fP \fB\\$2\fP \\*(lp\fI\\$3,\|\\$4,\|\\$5\fP\|\\*(rp -.if n \fI\\$1\fP \fB\\$2\fP \\*(lp\fI\\$3, \\$4, \\$5\fP\\*(rp -.br -.. -.de Vb -\fI\\$1\fP \fB\\$2\fP -.br -.. -.SH NAME -history \- GNU History Library -.SH COPYRIGHT -.if t The GNU History Library is Copyright \(co 1989-2011 by the Free Software Foundation, Inc. -.if n The GNU History Library is Copyright (C) 1989-2011 by the Free Software Foundation, Inc. -.SH DESCRIPTION -Many programs read input from the user a line at a time. The GNU -History library is able to keep track of those lines, associate arbitrary -data with each line, and utilize information from previous lines in -composing new ones. -.PP -.SH "HISTORY EXPANSION" -.PP -The history library supports a history expansion feature that -is identical to the history expansion in -.BR bash. -This section describes what syntax features are available. -.PP -History expansions introduce words from the history list into -the input stream, making it easy to repeat commands, insert the -arguments to a previous command into the current input line, or -fix errors in previous commands quickly. -.PP -History expansion is usually performed immediately after a complete line -is read. -It takes place in two parts. -The first is to determine which line from the history list -to use during substitution. -The second is to select portions of that line for inclusion into -the current one. -The line selected from the history is the \fIevent\fP, -and the portions of that line that are acted upon are \fIwords\fP. -Various \fImodifiers\fP are available to manipulate the selected words. -The line is broken into words in the same fashion as \fBbash\fP -does when reading input, -so that several words that would otherwise be separated -are considered one word when surrounded by quotes (see the -description of \fBhistory_tokenize()\fP below). -History expansions are introduced by the appearance of the -history expansion character, which is \^\fB!\fP\^ by default. -Only backslash (\^\fB\e\fP\^) and single quotes can quote -the history expansion character. -.SS Event Designators -.PP -An event designator is a reference to a command line entry in the -history list. -Unless the reference is absolute, events are relative to the current -position in the history list. -.PP -.PD 0 -.TP -.B ! -Start a history substitution, except when followed by a -.BR blank , -newline, = or (. -.TP -.B !\fIn\fR -Refer to command line -.IR n . -.TP -.B !\-\fIn\fR -Refer to the current command minus -.IR n . -.TP -.B !! -Refer to the previous command. This is a synonym for `!\-1'. -.TP -.B !\fIstring\fR -Refer to the most recent command -preceding the current position in the history list -starting with -.IR string . -.TP -.B !?\fIstring\fR\fB[?]\fR -Refer to the most recent command -preceding the current position in the history list -containing -.IR string . -The trailing \fB?\fP may be omitted if -.I string -is followed immediately by a newline. -.TP -.B \d\s+2^\s-2\u\fIstring1\fP\d\s+2^\s-2\u\fIstring2\fP\d\s+2^\s-2\u -Quick substitution. Repeat the last command, replacing -.I string1 -with -.IR string2 . -Equivalent to -``!!:s/\fIstring1\fP/\fIstring2\fP/'' -(see \fBModifiers\fP below). -.TP -.B !# -The entire command line typed so far. -.PD -.SS Word Designators -.PP -Word designators are used to select desired words from the event. -A -.B : -separates the event specification from the word designator. -It may be omitted if the word designator begins with a -.BR ^ , -.BR $ , -.BR * , -.BR \- , -or -.BR % . -Words are numbered from the beginning of the line, -with the first word being denoted by 0 (zero). -Words are inserted into the current line separated by single spaces. -.PP -.PD 0 -.TP -.B 0 (zero) -The zeroth word. For the shell, this is the command -word. -.TP -.I n -The \fIn\fRth word. -.TP -.B ^ -The first argument. That is, word 1. -.TP -.B $ -The last word. This is usually the last argument, but will expand to the -zeroth word if there is only one word in the line. -.TP -.B % -The word matched by the most recent `?\fIstring\fR?' search. -.TP -.I x\fB\-\fPy -A range of words; `\-\fIy\fR' abbreviates `0\-\fIy\fR'. -.TP -.B * -All of the words but the zeroth. This is a synonym -for `\fI1\-$\fP'. It is not an error to use -.B * -if there is just one -word in the event; the empty string is returned in that case. -.TP -.B x* -Abbreviates \fIx\-$\fP. -.TP -.B x\- -Abbreviates \fIx\-$\fP like \fBx*\fP, but omits the last word. -.PD -.PP -If a word designator is supplied without an event specification, the -previous command is used as the event. -.SS Modifiers -.PP -After the optional word designator, there may appear a sequence of -one or more of the following modifiers, each preceded by a `:'. -.PP -.PD 0 -.PP -.TP -.B h -Remove a trailing file name component, leaving only the head. -.TP -.B t -Remove all leading file name components, leaving the tail. -.TP -.B r -Remove a trailing suffix of the form \fI.xxx\fP, leaving the -basename. -.TP -.B e -Remove all but the trailing suffix. -.TP -.B p -Print the new command but do not execute it. -.TP -.B q -Quote the substituted words, escaping further substitutions. -.TP -.B x -Quote the substituted words as with -.BR q , -but break into words at -.B blanks -and newlines. -.TP -.B s/\fIold\fP/\fInew\fP/ -Substitute -.I new -for the first occurrence of -.I old -in the event line. Any delimiter can be used in place of /. The -final delimiter is optional if it is the last character of the -event line. The delimiter may be quoted in -.I old -and -.I new -with a single backslash. If & appears in -.IR new , -it is replaced by -.IR old . -A single backslash will quote the &. If -.I old -is null, it is set to the last -.I old -substituted, or, if no previous history substitutions took place, -the last -.I string -in a -.B !?\fIstring\fR\fB[?]\fR -search. -.TP -.B & -Repeat the previous substitution. -.TP -.B g -Cause changes to be applied over the entire event line. This is -used in conjunction with `\fB:s\fP' (e.g., `\fB:gs/\fIold\fP/\fInew\fP/\fR') -or `\fB:&\fP'. If used with -`\fB:s\fP', any delimiter can be used -in place of /, and the final delimiter is optional -if it is the last character of the event line. -An \fBa\fP may be used as a synonym for \fBg\fP. -.TP -.B G -Apply the following `\fBs\fP' modifier once to each word in the event line. -.PD -.SH "PROGRAMMING WITH HISTORY FUNCTIONS" -This section describes how to use the History library in other programs. -.SS Introduction to History -.PP -The programmer using the History library has available functions -for remembering lines on a history list, associating arbitrary data -with a line, removing lines from the list, searching through the list -for a line containing an arbitrary text string, and referencing any line -in the list directly. In addition, a history \fIexpansion\fP function -is available which provides for a consistent user interface across -different programs. -.PP -The user using programs written with the History library has the -benefit of a consistent user interface with a set of well-known -commands for manipulating the text of previous lines and using that text -in new commands. The basic history manipulation commands are -identical to -the history substitution provided by \fBbash\fP. -.PP -If the programmer desires, he can use the Readline library, which -includes some history manipulation by default, and has the added -advantage of command line editing. -.PP -Before declaring any functions using any functionality the History -library provides in other code, an application writer should include -the file -.FN <readline/history.h> -in any file that uses the -History library's features. It supplies extern declarations for all -of the library's public functions and variables, and declares all of -the public data structures. - -.SS History Storage -.PP -The history list is an array of history entries. A history entry is -declared as follows: -.PP -.Vb "typedef void *" histdata_t; -.PP -.nf -typedef struct _hist_entry { - char *line; - char *timestamp; - histdata_t data; -} HIST_ENTRY; -.fi -.PP -The history list itself might therefore be declared as -.PP -.Vb "HIST_ENTRY **" the_history_list; -.PP -The state of the History library is encapsulated into a single structure: -.PP -.nf -/* - * A structure used to pass around the current state of the history. - */ -typedef struct _hist_state { - HIST_ENTRY **entries; /* Pointer to the entries themselves. */ - int offset; /* The location pointer within this array. */ - int length; /* Number of elements within this array. */ - int size; /* Number of slots allocated to this array. */ - int flags; -} HISTORY_STATE; -.fi -.PP -If the flags member includes \fBHS_STIFLED\fP, the history has been -stifled. -.SH "History Functions" -.PP -This section describes the calling sequence for the various functions -exported by the GNU History library. -.SS Initializing History and State Management -This section describes functions used to initialize and manage -the state of the History library when you want to use the history -functions in your program. - -.Fn1 void using_history void -Begin a session in which the history functions might be used. This -initializes the interactive variables. - -.Fn1 "HISTORY_STATE *" history_get_history_state void -Return a structure describing the current state of the input history. - -.Fn1 void history_set_history_state "HISTORY_STATE *state" -Set the state of the history list according to \fIstate\fP. - -.SS History List Management - -These functions manage individual entries on the history list, or set -parameters managing the list itself. - -.Fn1 void add_history "const char *string" -Place \fIstring\fP at the end of the history list. The associated data -field (if any) is set to \fBNULL\fP. - -.Fn1 void add_history_time "const char *string" -Change the time stamp associated with the most recent history entry to -\fIstring\fP. - -.Fn1 "HIST_ENTRY *" remove_history "int which" -Remove history entry at offset \fIwhich\fP from the history. The -removed element is returned so you can free the line, data, -and containing structure. - -.Fn1 "histdata_t" free_history_entry "HIST_ENTRY *histent" -Free the history entry \fIhistent\fP and any history library private -data associated with it. Returns the application-specific data -so the caller can dispose of it. - -.Fn3 "HIST_ENTRY *" replace_history_entry "int which" "const char *line" "histdata_t data" -Make the history entry at offset \fIwhich\fP have \fIline\fP and \fIdata\fP. -This returns the old entry so the caller can dispose of any -application-specific data. In the case -of an invalid \fIwhich\fP, a \fBNULL\fP pointer is returned. - -.Fn1 void clear_history "void" -Clear the history list by deleting all the entries. - -.Fn1 void stifle_history "int max" -Stifle the history list, remembering only the last \fImax\fP entries. - -.Fn1 int unstifle_history "void" -Stop stifling the history. This returns the previously-set -maximum number of history entries (as set by \fBstifle_history()\fP). -history was stifled. The value is positive if the history was -stifled, negative if it wasn't. - -.Fn1 int history_is_stifled "void" -Returns non-zero if the history is stifled, zero if it is not. - -.SS Information About the History List - -These functions return information about the entire history list or -individual list entries. - -.Fn1 "HIST_ENTRY **" history_list "void" -Return a \fBNULL\fP terminated array of \fIHIST_ENTRY *\fP which is the -current input history. Element 0 of this list is the beginning of time. -If there is no history, return \fBNULL\fP. - -.Fn1 int where_history "void" -Returns the offset of the current history element. - -.Fn1 "HIST_ENTRY *" current_history "void" -Return the history entry at the current position, as determined by -\fBwhere_history()\fP. If there is no entry there, return a \fBNULL\fP -pointer. - -.Fn1 "HIST_ENTRY *" history_get "int offset" -Return the history entry at position \fIoffset\fP, starting from -\fBhistory_base\fP. -If there is no entry there, or if \fIoffset\fP -is greater than the history length, return a \fBNULL\fP pointer. - -.Fn1 "time_t" history_get_time "HIST_ENTRY *" -Return the time stamp associated with the history entry passed as the argument. - -.Fn1 int history_total_bytes "void" -Return the number of bytes that the primary history entries are using. -This function returns the sum of the lengths of all the lines in the -history. - -.SS Moving Around the History List - -These functions allow the current index into the history list to be -set or changed. - -.Fn1 int history_set_pos "int pos" -Set the current history offset to \fIpos\fP, an absolute index -into the list. -Returns 1 on success, 0 if \fIpos\fP is less than zero or greater -than the number of history entries. - -.Fn1 "HIST_ENTRY *" previous_history "void" -Back up the current history offset to the previous history entry, and -return a pointer to that entry. If there is no previous entry, return -a \fBNULL\fP pointer. - -.Fn1 "HIST_ENTRY *" next_history "void" -Move the current history offset forward to the next history entry, and -return the a pointer to that entry. If there is no next entry, return -a \fBNULL\fP pointer. - -.SS Searching the History List - -These functions allow searching of the history list for entries containing -a specific string. Searching may be performed both forward and backward -from the current history position. The search may be \fIanchored\fP, -meaning that the string must match at the beginning of the history entry. - -.Fn2 int history_search "const char *string" "int direction" -Search the history for \fIstring\fP, starting at the current history offset. -If \fIdirection\fP is less than 0, then the search is through -previous entries, otherwise through subsequent entries. -If \fIstring\fP is found, then -the current history index is set to that history entry, and the value -returned is the offset in the line of the entry where -\fIstring\fP was found. Otherwise, nothing is changed, and a -1 is -returned. - -.Fn2 int history_search_prefix "const char *string" "int direction" -Search the history for \fIstring\fP, starting at the current history -offset. The search is anchored: matching lines must begin with -\fIstring\fP. If \fIdirection\fP is less than 0, then the search is -through previous entries, otherwise through subsequent entries. -If \fIstring\fP is found, then the -current history index is set to that entry, and the return value is 0. -Otherwise, nothing is changed, and a -1 is returned. - -.Fn3 int history_search_pos "const char *string" "int direction" "int pos" -Search for \fIstring\fP in the history list, starting at \fIpos\fP, an -absolute index into the list. If \fIdirection\fP is negative, the search -proceeds backward from \fIpos\fP, otherwise forward. Returns the absolute -index of the history element where \fIstring\fP was found, or -1 otherwise. - -.SS Managing the History File -The History library can read the history from and write it to a file. -This section documents the functions for managing a history file. - -.Fn1 int read_history "const char *filename" -Add the contents of \fIfilename\fP to the history list, a line at a time. -If \fIfilename\fP is \fBNULL\fP, then read from \fI~/.history\fP. -Returns 0 if successful, or \fBerrno\fP if not. - -.Fn3 int read_history_range "const char *filename" "int from" "int to" -Read a range of lines from \fIfilename\fP, adding them to the history list. -Start reading at line \fIfrom\fP and end at \fIto\fP. -If \fIfrom\fP is zero, start at the beginning. If \fIto\fP is less than -\fIfrom\fP, then read until the end of the file. If \fIfilename\fP is -\fBNULL\fP, then read from \fI~/.history\fP. Returns 0 if successful, -or \fBerrno\fP if not. - -.Fn1 int write_history "const char *filename" -Write the current history to \fIfilename\fP, overwriting \fIfilename\fP -if necessary. -If \fIfilename\fP is \fBNULL\fP, then write the history list to \fI~/.history\fP. -Returns 0 on success, or \fBerrno\fP on a read or write error. - - -.Fn2 int append_history "int nelements" "const char *filename" -Append the last \fInelements\fP of the history list to \fIfilename\fP. -If \fIfilename\fP is \fBNULL\fP, then append to \fI~/.history\fP. -Returns 0 on success, or \fBerrno\fP on a read or write error. - -.Fn2 int history_truncate_file "const char *filename" "int nlines" -Truncate the history file \fIfilename\fP, leaving only the last -\fInlines\fP lines. -If \fIfilename\fP is \fBNULL\fP, then \fI~/.history\fP is truncated. -Returns 0 on success, or \fBerrno\fP on failure. - -.SS History Expansion - -These functions implement history expansion. - -.Fn2 int history_expand "char *string" "char **output" -Expand \fIstring\fP, placing the result into \fIoutput\fP, a pointer -to a string. Returns: -.RS -.PD 0 -.TP -0 -If no expansions took place (or, if the only change in -the text was the removal of escape characters preceding the history expansion -character); -.TP -1 -if expansions did take place; -.TP --1 -if there was an error in expansion; -.TP -2 -if the returned line should be displayed, but not executed, -as with the \fB:p\fP modifier. -.PD -.RE -If an error ocurred in expansion, then \fIoutput\fP contains a descriptive -error message. - -.Fn3 "char *" get_history_event "const char *string" "int *cindex" "int qchar" -Returns the text of the history event beginning at \fIstring\fP + -\fI*cindex\fP. \fI*cindex\fP is modified to point to after the event -specifier. At function entry, \fIcindex\fP points to the index into -\fIstring\fP where the history event specification begins. \fIqchar\fP -is a character that is allowed to end the event specification in addition -to the ``normal'' terminating characters. - -.Fn1 "char **" history_tokenize "const char *string" -Return an array of tokens parsed out of \fIstring\fP, much as the -shell might. -The tokens are split on the characters in the -\fBhistory_word_delimiters\fP variable, -and shell quoting conventions are obeyed. - -.Fn3 "char *" history_arg_extract "int first" "int last" "const char *string" -Extract a string segment consisting of the \fIfirst\fP through \fIlast\fP -arguments present in \fIstring\fP. Arguments are split using -\fBhistory_tokenize()\fP. - -.SS History Variables - -This section describes the externally-visible variables exported by -the GNU History Library. - -.Vb int history_base -The logical offset of the first entry in the history list. - -.Vb int history_length -The number of entries currently stored in the history list. - -.Vb int history_max_entries -The maximum number of history entries. This must be changed using -\fBstifle_history()\fP. - -.Vb int history_wite_timestamps -If non-zero, timestamps are written to the history file, so they can be -preserved between sessions. The default value is 0, meaning that -timestamps are not saved. -The current timestamp format uses the value of \fIhistory_comment_char\fP -to delimit timestamp entries in the history file. If that variable does -not have a value (the default), timestamps will not be written. - -.Vb char history_expansion_char -The character that introduces a history event. The default is \fB!\fP. -Setting this to 0 inhibits history expansion. - -.Vb char history_subst_char -The character that invokes word substitution if found at the start of -a line. The default is \fB^\fP. - -.Vb char history_comment_char -During tokenization, if this character is seen as the first character -of a word, then it and all subsequent characters up to a newline are -ignored, suppressing history expansion for the remainder of the line. -This is disabled by default. - -.Vb "char *" history_word_delimiters -The characters that separate tokens for \fBhistory_tokenize()\fP. -The default value is \fB"\ \et\en()<>;&|"\fP. - -.Vb "char *" history_no_expand_chars -The list of characters which inhibit history expansion if found immediately -following \fBhistory_expansion_char\fP. The default is space, tab, newline, -\fB\er\fP, and \fB=\fP. - -.Vb "char *" history_search_delimiter_chars -The list of additional characters which can delimit a history search -string, in addition to space, tab, \fI:\fP and \fI?\fP in the case of -a substring search. The default is empty. - -.Vb int history_quotes_inhibit_expansion -If non-zero, double-quoted words are not scanned for the history expansion -character or the history comment character. The default value is 0. - -.Vb "rl_linebuf_func_t *" history_inhibit_expansion_function -This should be set to the address of a function that takes two arguments: -a \fBchar *\fP (\fIstring\fP) -and an \fBint\fP index into that string (\fIi\fP). -It should return a non-zero value if the history expansion starting at -\fIstring[i]\fP should not be performed; zero if the expansion should -be done. -It is intended for use by applications like \fBbash\fP that use the history -expansion character for additional purposes. -By default, this variable is set to \fBNULL\fP. -.SH FILES -.PD 0 -.TP -.FN ~/.history -Default filename for reading and writing saved history -.PD -.SH "SEE ALSO" -.PD 0 -.TP -\fIThe Gnu Readline Library\fP, Brian Fox and Chet Ramey -.TP -\fIThe Gnu History Library\fP, Brian Fox and Chet Ramey -.TP -\fIbash\fP(1) -.TP -\fIreadline\fP(3) -.PD -.SH AUTHORS -Brian Fox, Free Software Foundation -.br -bfox@gnu.org -.PP -Chet Ramey, Case Western Reserve University -.br -chet.ramey@case.edu -.SH BUG REPORTS -If you find a bug in the -.B history -library, you should report it. But first, you should -make sure that it really is a bug, and that it appears in the latest -version of the -.B history -library that you have. -.PP -Once you have determined that a bug actually exists, mail a -bug report to \fIbug\-readline\fP@\fIgnu.org\fP. -If you have a fix, you are welcome to mail that -as well! Suggestions and `philosophical' bug reports may be mailed -to \fPbug-readline\fP@\fIgnu.org\fP or posted to the Usenet -newsgroup -.BR gnu.bash.bug . -.PP -Comments and bug reports concerning -this manual page should be directed to -.IR chet.ramey@case.edu . diff --git a/lib/readline/doc/hstech.texi~ b/lib/readline/doc/hstech.texi~ deleted file mode 100644 index 6487f20b..00000000 --- a/lib/readline/doc/hstech.texi~ +++ /dev/null @@ -1,577 +0,0 @@ -@ignore -This file documents the user interface to the GNU History library. - -Copyright (C) 1988-2014 Free Software Foundation, Inc. -Authored by Brian Fox and Chet Ramey. - -Permission is granted to make and distribute verbatim copies of this manual -provided the copyright notice and this permission notice are preserved on -all copies. - -Permission is granted to process this file through Tex and print the -results, provided the printed document carries copying permission notice -identical to this one except for the removal of this paragraph (this -paragraph not being relevant to the printed manual). - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided also that the -GNU Copyright statement is available to the distributee, and provided that -the entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -Permission is granted to copy and distribute translations of this manual -into another language, under the above conditions for modified versions. -@end ignore - -@node Programming with GNU History -@chapter Programming with GNU History - -This chapter describes how to interface programs that you write -with the @sc{gnu} History Library. -It should be considered a technical guide. -For information on the interactive use of @sc{gnu} History, @pxref{Using -History Interactively}. - -@menu -* Introduction to History:: What is the GNU History library for? -* History Storage:: How information is stored. -* History Functions:: Functions that you can use. -* History Variables:: Variables that control behaviour. -* History Programming Example:: Example of using the GNU History Library. -@end menu - -@node Introduction to History -@section Introduction to History - -Many programs read input from the user a line at a time. The @sc{gnu} -History library is able to keep track of those lines, associate arbitrary -data with each line, and utilize information from previous lines in -composing new ones. - -The programmer using the History library has available functions -for remembering lines on a history list, associating arbitrary data -with a line, removing lines from the list, searching through the list -for a line containing an arbitrary text string, and referencing any line -in the list directly. In addition, a history @dfn{expansion} function -is available which provides for a consistent user interface across -different programs. - -The user using programs written with the History library has the -benefit of a consistent user interface with a set of well-known -commands for manipulating the text of previous lines and using that text -in new commands. The basic history manipulation commands are similar to -the history substitution provided by @code{csh}. - -If the programmer desires, he can use the Readline library, which -includes some history manipulation by default, and has the added -advantage of command line editing. - -Before declaring any functions using any functionality the History -library provides in other code, an application writer should include -the file @code{<readline/history.h>} in any file that uses the -History library's features. It supplies extern declarations for all -of the library's public functions and variables, and declares all of -the public data structures. - -@node History Storage -@section History Storage - -The history list is an array of history entries. A history entry is -declared as follows: - -@example -typedef void *histdata_t; - -typedef struct _hist_entry @{ - char *line; - char *timestamp; - histdata_t data; -@} HIST_ENTRY; -@end example - -The history list itself might therefore be declared as - -@example -HIST_ENTRY **the_history_list; -@end example - -The state of the History library is encapsulated into a single structure: - -@example -/* - * A structure used to pass around the current state of the history. - */ -typedef struct _hist_state @{ - HIST_ENTRY **entries; /* Pointer to the entries themselves. */ - int offset; /* The location pointer within this array. */ - int length; /* Number of elements within this array. */ - int size; /* Number of slots allocated to this array. */ - int flags; -@} HISTORY_STATE; -@end example - -If the flags member includes @code{HS_STIFLED}, the history has been -stifled. - -@node History Functions -@section History Functions - -This section describes the calling sequence for the various functions -exported by the @sc{gnu} History library. - -@menu -* Initializing History and State Management:: Functions to call when you - want to use history in a - program. -* History List Management:: Functions used to manage the list - of history entries. -* Information About the History List:: Functions returning information about - the history list. -* Moving Around the History List:: Functions used to change the position - in the history list. -* Searching the History List:: Functions to search the history list - for entries containing a string. -* Managing the History File:: Functions that read and write a file - containing the history list. -* History Expansion:: Functions to perform csh-like history - expansion. -@end menu - -@node Initializing History and State Management -@subsection Initializing History and State Management - -This section describes functions used to initialize and manage -the state of the History library when you want to use the history -functions in your program. - -@deftypefun void using_history (void) -Begin a session in which the history functions might be used. This -initializes the interactive variables. -@end deftypefun - -@deftypefun {HISTORY_STATE *} history_get_history_state (void) -Return a structure describing the current state of the input history. -@end deftypefun - -@deftypefun void history_set_history_state (HISTORY_STATE *state) -Set the state of the history list according to @var{state}. -@end deftypefun - -@node History List Management -@subsection History List Management - -These functions manage individual entries on the history list, or set -parameters managing the list itself. - -@deftypefun void add_history (const char *string) -Place @var{string} at the end of the history list. The associated data -field (if any) is set to @code{NULL}. -@end deftypefun - -@deftypefun void add_history_time (const char *string) -Change the time stamp associated with the most recent history entry to -@var{string}. -@end deftypefun - -@deftypefun {HIST_ENTRY *} remove_history (int which) -Remove history entry at offset @var{which} from the history. The -removed element is returned so you can free the line, data, -and containing structure. -@end deftypefun - -@deftypefun {histdata_t} free_history_entry (HIST_ENTRY *histent) -Free the history entry @var{histent} and any history library private -data associated with it. Returns the application-specific data -so the caller can dispose of it. -@end deftypefun - -@deftypefun {HIST_ENTRY *} replace_history_entry (int which, const char *line, histdata_t data) -Make the history entry at offset @var{which} have @var{line} and @var{data}. -This returns the old entry so the caller can dispose of any -application-specific data. In the case -of an invalid @var{which}, a @code{NULL} pointer is returned. -@end deftypefun - -@deftypefun void clear_history (void) -Clear the history list by deleting all the entries. -@end deftypefun - -@deftypefun void stifle_history (int max) -Stifle the history list, remembering only the last @var{max} entries. -@end deftypefun - -@deftypefun int unstifle_history (void) -Stop stifling the history. This returns the previously-set -maximum number of history entries (as set by @code{stifle_history()}). -The value is positive if the history was -stifled, negative if it wasn't. -@end deftypefun - -@deftypefun int history_is_stifled (void) -Returns non-zero if the history is stifled, zero if it is not. -@end deftypefun - -@node Information About the History List -@subsection Information About the History List - -These functions return information about the entire history list or -individual list entries. - -@deftypefun {HIST_ENTRY **} history_list (void) -Return a @code{NULL} terminated array of @code{HIST_ENTRY *} which is the -current input history. Element 0 of this list is the beginning of time. -If there is no history, return @code{NULL}. -@end deftypefun - -@deftypefun int where_history (void) -Returns the offset of the current history element. -@end deftypefun - -@deftypefun {HIST_ENTRY *} current_history (void) -Return the history entry at the current position, as determined by -@code{where_history()}. If there is no entry there, return a @code{NULL} -pointer. -@end deftypefun - -@deftypefun {HIST_ENTRY *} history_get (int offset) -Return the history entry at position @var{offset}, starting from -@code{history_base} (@pxref{History Variables}). -If there is no entry there, or if @var{offset} -is greater than the history length, return a @code{NULL} pointer. -@end deftypefun - -@deftypefun time_t history_get_time (HIST_ENTRY *entry) -Return the time stamp associated with the history entry @var{entry}. -@end deftypefun - -@deftypefun int history_total_bytes (void) -Return the number of bytes that the primary history entries are using. -This function returns the sum of the lengths of all the lines in the -history. -@end deftypefun - -@node Moving Around the History List -@subsection Moving Around the History List - -These functions allow the current index into the history list to be -set or changed. - -@deftypefun int history_set_pos (int pos) -Set the current history offset to @var{pos}, an absolute index -into the list. -Returns 1 on success, 0 if @var{pos} is less than zero or greater -than the number of history entries. -@end deftypefun - -@deftypefun {HIST_ENTRY *} previous_history (void) -Back up the current history offset to the previous history entry, and -return a pointer to that entry. If there is no previous entry, return -a @code{NULL} pointer. -@end deftypefun - -@deftypefun {HIST_ENTRY *} next_history (void) -Move the current history offset forward to the next history entry, and -return the a pointer to that entry. If there is no next entry, return -a @code{NULL} pointer. -@end deftypefun - -@node Searching the History List -@subsection Searching the History List -@cindex History Searching - -These functions allow searching of the history list for entries containing -a specific string. Searching may be performed both forward and backward -from the current history position. The search may be @dfn{anchored}, -meaning that the string must match at the beginning of the history entry. -@cindex anchored search - -@deftypefun int history_search (const char *string, int direction) -Search the history for @var{string}, starting at the current history offset. -If @var{direction} is less than 0, then the search is through -previous entries, otherwise through subsequent entries. -If @var{string} is found, then -the current history index is set to that history entry, and the value -returned is the offset in the line of the entry where -@var{string} was found. Otherwise, nothing is changed, and a -1 is -returned. -@end deftypefun - -@deftypefun int history_search_prefix (const char *string, int direction) -Search the history for @var{string}, starting at the current history -offset. The search is anchored: matching lines must begin with -@var{string}. If @var{direction} is less than 0, then the search is -through previous entries, otherwise through subsequent entries. -If @var{string} is found, then the -current history index is set to that entry, and the return value is 0. -Otherwise, nothing is changed, and a -1 is returned. -@end deftypefun - -@deftypefun int history_search_pos (const char *string, int direction, int pos) -Search for @var{string} in the history list, starting at @var{pos}, an -absolute index into the list. If @var{direction} is negative, the search -proceeds backward from @var{pos}, otherwise forward. Returns the absolute -index of the history element where @var{string} was found, or -1 otherwise. -@end deftypefun - -@node Managing the History File -@subsection Managing the History File - -The History library can read the history from and write it to a file. -This section documents the functions for managing a history file. - -@deftypefun int read_history (const char *filename) -Add the contents of @var{filename} to the history list, a line at a time. -If @var{filename} is @code{NULL}, then read from @file{~/.history}. -Returns 0 if successful, or @code{errno} if not. -@end deftypefun - -@deftypefun int read_history_range (const char *filename, int from, int to) -Read a range of lines from @var{filename}, adding them to the history list. -Start reading at line @var{from} and end at @var{to}. -If @var{from} is zero, start at the beginning. If @var{to} is less than -@var{from}, then read until the end of the file. If @var{filename} is -@code{NULL}, then read from @file{~/.history}. Returns 0 if successful, -or @code{errno} if not. -@end deftypefun - -@deftypefun int write_history (const char *filename) -Write the current history to @var{filename}, overwriting @var{filename} -if necessary. -If @var{filename} is @code{NULL}, then write the history list to -@file{~/.history}. -Returns 0 on success, or @code{errno} on a read or write error. -@end deftypefun - -@deftypefun int append_history (int nelements, const char *filename) -Append the last @var{nelements} of the history list to @var{filename}. -If @var{filename} is @code{NULL}, then append to @file{~/.history}. -Returns 0 on success, or @code{errno} on a read or write error. -@end deftypefun - -@deftypefun int history_truncate_file (const char *filename, int nlines) -Truncate the history file @var{filename}, leaving only the last -@var{nlines} lines. -If @var{filename} is @code{NULL}, then @file{~/.history} is truncated. -Returns 0 on success, or @code{errno} on failure. -@end deftypefun - -@node History Expansion -@subsection History Expansion - -These functions implement history expansion. - -@deftypefun int history_expand (char *string, char **output) -Expand @var{string}, placing the result into @var{output}, a pointer -to a string (@pxref{History Interaction}). Returns: -@table @code -@item 0 -If no expansions took place (or, if the only change in -the text was the removal of escape characters preceding the history expansion -character); -@item 1 -if expansions did take place; -@item -1 -if there was an error in expansion; -@item 2 -if the returned line should be displayed, but not executed, -as with the @code{:p} modifier (@pxref{Modifiers}). -@end table - -If an error occurred in expansion, then @var{output} contains a descriptive -error message. -@end deftypefun - -@deftypefun {char *} get_history_event (const char *string, int *cindex, int qchar) -Returns the text of the history event beginning at @var{string} + -@var{*cindex}. @var{*cindex} is modified to point to after the event -specifier. At function entry, @var{cindex} points to the index into -@var{string} where the history event specification begins. @var{qchar} -is a character that is allowed to end the event specification in addition -to the ``normal'' terminating characters. -@end deftypefun - -@deftypefun {char **} history_tokenize (const char *string) -Return an array of tokens parsed out of @var{string}, much as the -shell might. The tokens are split on the characters in the -@var{history_word_delimiters} variable, -and shell quoting conventions are obeyed. -@end deftypefun - -@deftypefun {char *} history_arg_extract (int first, int last, const char *string) -Extract a string segment consisting of the @var{first} through @var{last} -arguments present in @var{string}. Arguments are split using -@code{history_tokenize}. -@end deftypefun - -@node History Variables -@section History Variables - -This section describes the externally-visible variables exported by -the @sc{gnu} History Library. - -@deftypevar int history_base -The logical offset of the first entry in the history list. -@end deftypevar - -@deftypevar int history_length -The number of entries currently stored in the history list. -@end deftypevar - -@deftypevar int history_max_entries -The maximum number of history entries. This must be changed using -@code{stifle_history()}. -@end deftypevar - -@deftypevar int history_write_timestamps -If non-zero, timestamps are written to the history file, so they can be -preserved between sessions. The default value is 0, meaning that -timestamps are not saved. - -The current timestamp format uses the value of @var{history_comment_char} -to delimit timestamp entries in the history file. If that variable does -not have a value (the default), timestamps will not be written. -@end deftypevar - -@deftypevar char history_expansion_char -The character that introduces a history event. The default is @samp{!}. -Setting this to 0 inhibits history expansion. -@end deftypevar - -@deftypevar char history_subst_char -The character that invokes word substitution if found at the start of -a line. The default is @samp{^}. -@end deftypevar - -@deftypevar char history_comment_char -During tokenization, if this character is seen as the first character -of a word, then it and all subsequent characters up to a newline are -ignored, suppressing history expansion for the remainder of the line. -This is disabled by default. -@end deftypevar - -@deftypevar {char *} history_word_delimiters -The characters that separate tokens for @code{history_tokenize()}. -The default value is @code{" \t\n()<>;&|"}. -@end deftypevar - -@deftypevar {char *} history_search_delimiter_chars -The list of additional characters which can delimit a history search -string, in addition to space, TAB, @samp{:} and @samp{?} in the case of -a substring search. The default is empty. -@end deftypevar - -@deftypevar {char *} history_no_expand_chars -The list of characters which inhibit history expansion if found immediately -following @var{history_expansion_char}. The default is space, tab, newline, -carriage return, and @samp{=}. -@end deftypevar - -@deftypevar int history_quotes_inhibit_expansion -If non-zero, single-quoted words are not scanned for the history expansion -character. The default value is 0. -@end deftypevar - -@deftypevar {rl_linebuf_func_t *} history_inhibit_expansion_function -This should be set to the address of a function that takes two arguments: -a @code{char *} (@var{string}) -and an @code{int} index into that string (@var{i}). -It should return a non-zero value if the history expansion starting at -@var{string[i]} should not be performed; zero if the expansion should -be done. -It is intended for use by applications like Bash that use the history -expansion character for additional purposes. -By default, this variable is set to @code{NULL}. -@end deftypevar - -@node History Programming Example -@section History Programming Example - -The following program demonstrates simple use of the @sc{gnu} History Library. - -@smallexample -#include <stdio.h> -#include <readline/history.h> - -main (argc, argv) - int argc; - char **argv; -@{ - char line[1024], *t; - int len, done = 0; - - line[0] = 0; - - using_history (); - while (!done) - @{ - printf ("history$ "); - fflush (stdout); - t = fgets (line, sizeof (line) - 1, stdin); - if (t && *t) - @{ - len = strlen (t); - if (t[len - 1] == '\n') - t[len - 1] = '\0'; - @} - - if (!t) - strcpy (line, "quit"); - - if (line[0]) - @{ - char *expansion; - int result; - - result = history_expand (line, &expansion); - if (result) - fprintf (stderr, "%s\n", expansion); - - if (result < 0 || result == 2) - @{ - free (expansion); - continue; - @} - - add_history (expansion); - strncpy (line, expansion, sizeof (line) - 1); - free (expansion); - @} - - if (strcmp (line, "quit") == 0) - done = 1; - else if (strcmp (line, "save") == 0) - write_history ("history_file"); - else if (strcmp (line, "read") == 0) - read_history ("history_file"); - else if (strcmp (line, "list") == 0) - @{ - register HIST_ENTRY **the_list; - register int i; - - the_list = history_list (); - if (the_list) - for (i = 0; the_list[i]; i++) - printf ("%d: %s\n", i + history_base, the_list[i]->line); - @} - else if (strncmp (line, "delete", 6) == 0) - @{ - int which; - if ((sscanf (line + 6, "%d", &which)) == 1) - @{ - HIST_ENTRY *entry = remove_history (which); - if (!entry) - fprintf (stderr, "No such entry %d\n", which); - else - @{ - free (entry->line); - free (entry); - @} - @} - else - @{ - fprintf (stderr, "non-numeric arg given to `delete'\n"); - @} - @} - @} -@} -@end smallexample diff --git a/lib/readline/doc/version.texi~ b/lib/readline/doc/version.texi~ deleted file mode 100644 index 6675bb56..00000000 --- a/lib/readline/doc/version.texi~ +++ /dev/null @@ -1,10 +0,0 @@ -@ignore -Copyright (C) 1988-2014 Free Software Foundation, Inc. -@end ignore - -@set EDITION 6.3 -@set VERSION 6.3 -@set UPDATED 16 May 2014 -@set UPDATED-MONTH May 2014 - -@set LASTCHANGE Fri May 16 09:36:19 EDT 2014 diff --git a/lib/readline/histexpand.c~ b/lib/readline/histexpand.c~ deleted file mode 100644 index ad8b6aa1..00000000 --- a/lib/readline/histexpand.c~ +++ /dev/null @@ -1,1661 +0,0 @@ -/* histexpand.c -- history expansion. */ - -/* Copyright (C) 1989-2012 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 <http://www.gnu.org/licenses/>. -*/ - -#define READLINE_LIBRARY - -#if defined (HAVE_CONFIG_H) -# include <config.h> -#endif - -#include <stdio.h> - -#if defined (HAVE_STDLIB_H) -# include <stdlib.h> -#else -# include "ansi_stdlib.h" -#endif /* HAVE_STDLIB_H */ - -#if defined (HAVE_UNISTD_H) -# ifndef _MINIX -# include <sys/types.h> -# endif -# include <unistd.h> -#endif - -#include "rlmbutil.h" - -#include "history.h" -#include "histlib.h" - -#include "rlshell.h" -#include "xmalloc.h" - -#define HISTORY_WORD_DELIMITERS " \t\n;&()|<>" -#define HISTORY_QUOTE_CHARACTERS "\"'`" - -#define slashify_in_quotes "\\`\"$" - -typedef int _hist_search_func_t PARAMS((const char *, int)); - -static char error_pointer; - -static char *subst_lhs; -static char *subst_rhs; -static int subst_lhs_len; -static int subst_rhs_len; - -static char *get_history_word_specifier PARAMS((char *, char *, int *)); -static int history_tokenize_word PARAMS((const char *, int)); -static char **history_tokenize_internal PARAMS((const char *, int, int *)); -static char *history_substring PARAMS((const char *, int, int)); -static void freewords PARAMS((char **, int)); -static char *history_find_word PARAMS((char *, int)); - -static char *quote_breaks PARAMS((char *)); - -/* Variables exported by this file. */ -/* The character that represents the start of a history expansion - request. This is usually `!'. */ -char history_expansion_char = '!'; - -/* The character that invokes word substitution if found at the start of - a line. This is usually `^'. */ -char history_subst_char = '^'; - -/* During tokenization, if this character is seen as the first character - of a word, then it, and all subsequent characters upto a newline are - ignored. For a Bourne shell, this should be '#'. Bash special cases - the interactive comment character to not be a comment delimiter. */ -char history_comment_char = '\0'; - -/* The list of characters which inhibit the expansion of text if found - immediately following history_expansion_char. */ -char *history_no_expand_chars = " \t\n\r="; - -/* If set to a non-zero value, single quotes inhibit history expansion. - The default is 0. */ -int history_quotes_inhibit_expansion = 0; - -/* Used to split words by history_tokenize_internal. */ -char *history_word_delimiters = HISTORY_WORD_DELIMITERS; - -/* If set, this points to a function that is called to verify that a - particular history expansion should be performed. */ -rl_linebuf_func_t *history_inhibit_expansion_function; - -/* **************************************************************** */ -/* */ -/* History Expansion */ -/* */ -/* **************************************************************** */ - -/* Hairy history expansion on text, not tokens. This is of general - use, and thus belongs in this library. */ - -/* The last string searched for by a !?string? search. */ -static char *search_string; - -/* The last string matched by a !?string? search. */ -static char *search_match; - -/* Return the event specified at TEXT + OFFSET modifying OFFSET to - point to after the event specifier. Just a pointer to the history - line is returned; NULL is returned in the event of a bad specifier. - You pass STRING with *INDEX equal to the history_expansion_char that - begins this specification. - DELIMITING_QUOTE is a character that is allowed to end the string - specification for what to search for in addition to the normal - characters `:', ` ', `\t', `\n', and sometimes `?'. - So you might call this function like: - line = get_history_event ("!echo:p", &index, 0); */ -char * -get_history_event (string, caller_index, delimiting_quote) - const char *string; - int *caller_index; - int delimiting_quote; -{ - register int i; - register char c; - HIST_ENTRY *entry; - int which, sign, local_index, substring_okay; - _hist_search_func_t *search_func; - char *temp; - - /* The event can be specified in a number of ways. - - !! the previous command - !n command line N - !-n current command-line minus N - !str the most recent command starting with STR - !?str[?] - the most recent command containing STR - - All values N are determined via HISTORY_BASE. */ - - i = *caller_index; - - if (string[i] != history_expansion_char) - return ((char *)NULL); - - /* Move on to the specification. */ - i++; - - sign = 1; - substring_okay = 0; - -#define RETURN_ENTRY(e, w) \ - return ((e = history_get (w)) ? e->line : (char *)NULL) - - /* Handle !! case. */ - if (string[i] == history_expansion_char) - { - i++; - which = history_base + (history_length - 1); - *caller_index = i; - RETURN_ENTRY (entry, which); - } - - /* Hack case of numeric line specification. */ - if (string[i] == '-') - { - sign = -1; - i++; - } - - if (_rl_digit_p (string[i])) - { - /* Get the extent of the digits and compute the value. */ - for (which = 0; _rl_digit_p (string[i]); i++) - which = (which * 10) + _rl_digit_value (string[i]); - - *caller_index = i; - - if (sign < 0) - which = (history_length + history_base) - which; - - RETURN_ENTRY (entry, which); - } - - /* This must be something to search for. If the spec begins with - a '?', then the string may be anywhere on the line. Otherwise, - the string must be found at the start of a line. */ - if (string[i] == '?') - { - substring_okay++; - i++; - } - - /* Only a closing `?' or a newline delimit a substring search string. */ - for (local_index = i; c = string[i]; i++) - { -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - int v; - mbstate_t ps; - - memset (&ps, 0, sizeof (mbstate_t)); - /* These produce warnings because we're passing a const string to a - function that takes a non-const string. */ - _rl_adjust_point ((char *)string, i, &ps); - if ((v = _rl_get_char_len ((char *)string + i, &ps)) > 1) - { - i += v - 1; - continue; - } - } - -#endif /* HANDLE_MULTIBYTE */ - if ((!substring_okay && (whitespace (c) || c == ':' || - (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) || - string[i] == delimiting_quote)) || - string[i] == '\n' || - (substring_okay && string[i] == '?')) - break; - } - - which = i - local_index; - temp = (char *)xmalloc (1 + which); - if (which) - strncpy (temp, string + local_index, which); - temp[which] = '\0'; - - if (substring_okay && string[i] == '?') - i++; - - *caller_index = i; - -#define FAIL_SEARCH() \ - do { \ - history_offset = history_length; xfree (temp) ; return (char *)NULL; \ - } while (0) - - /* If there is no search string, try to use the previous search string, - if one exists. If not, fail immediately. */ - if (*temp == '\0' && substring_okay) - { - if (search_string) - { - xfree (temp); - temp = savestring (search_string); - } - else - FAIL_SEARCH (); - } - - search_func = substring_okay ? history_search : history_search_prefix; - while (1) - { - local_index = (*search_func) (temp, -1); - - if (local_index < 0) - FAIL_SEARCH (); - - if (local_index == 0 || substring_okay) - { - entry = current_history (); - if (entry == 0) - FAIL_SEARCH (); - history_offset = history_length; - - /* If this was a substring search, then remember the - string that we matched for word substitution. */ - if (substring_okay) - { - FREE (search_string); - search_string = temp; - - FREE (search_match); - search_match = history_find_word (entry->line, local_index); - } - else - xfree (temp); - - return (entry->line); - } - - if (history_offset) - history_offset--; - else - FAIL_SEARCH (); - } -#undef FAIL_SEARCH -#undef RETURN_ENTRY -} - -/* Function for extracting single-quoted strings. Used for inhibiting - history expansion within single quotes. */ - -/* Extract the contents of STRING as if it is enclosed in single quotes. - SINDEX, when passed in, is the offset of the character immediately - following the opening single quote; on exit, SINDEX is left pointing - to the closing single quote. FLAGS currently used to allow backslash - to escape a single quote (e.g., for bash $'...'). */ -static void -hist_string_extract_single_quoted (string, sindex, flags) - char *string; - int *sindex, flags; -{ - register int i; - - for (i = *sindex; string[i] && string[i] != '\''; i++) - { - if ((flags & 1) && string[i] == '\\' && string[i+1]) - i++; - } - - *sindex = i; -} - -static char * -quote_breaks (s) - char *s; -{ - register char *p, *r; - char *ret; - int len = 3; - - for (p = s; p && *p; p++, len++) - { - if (*p == '\'') - len += 3; - else if (whitespace (*p) || *p == '\n') - len += 2; - } - - r = ret = (char *)xmalloc (len); - *r++ = '\''; - for (p = s; p && *p; ) - { - if (*p == '\'') - { - *r++ = '\''; - *r++ = '\\'; - *r++ = '\''; - *r++ = '\''; - p++; - } - else if (whitespace (*p) || *p == '\n') - { - *r++ = '\''; - *r++ = *p++; - *r++ = '\''; - } - else - *r++ = *p++; - } - *r++ = '\''; - *r = '\0'; - return ret; -} - -static char * -hist_error(s, start, current, errtype) - char *s; - int start, current, errtype; -{ - char *temp; - const char *emsg; - int ll, elen; - - ll = current - start; - - switch (errtype) - { - case EVENT_NOT_FOUND: - emsg = "event not found"; - elen = 15; - break; - case BAD_WORD_SPEC: - emsg = "bad word specifier"; - elen = 18; - break; - case SUBST_FAILED: - emsg = "substitution failed"; - elen = 19; - break; - case BAD_MODIFIER: - emsg = "unrecognized history modifier"; - elen = 29; - break; - case NO_PREV_SUBST: - emsg = "no previous substitution"; - elen = 24; - break; - default: - emsg = "unknown expansion error"; - elen = 23; - break; - } - - temp = (char *)xmalloc (ll + elen + 3); - strncpy (temp, s + start, ll); - temp[ll] = ':'; - temp[ll + 1] = ' '; - strcpy (temp + ll + 2, emsg); - return (temp); -} - -/* Get a history substitution string from STR starting at *IPTR - and return it. The length is returned in LENPTR. - - A backslash can quote the delimiter. If the string is the - empty string, the previous pattern is used. If there is - no previous pattern for the lhs, the last history search - string is used. - - If IS_RHS is 1, we ignore empty strings and set the pattern - to "" anyway. subst_lhs is not changed if the lhs is empty; - subst_rhs is allowed to be set to the empty string. */ - -static char * -get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr) - char *str; - int *iptr, delimiter, is_rhs, *lenptr; -{ - register int si, i, j, k; - char *s; -#if defined (HANDLE_MULTIBYTE) - mbstate_t ps; -#endif - - s = (char *)NULL; - i = *iptr; - -#if defined (HANDLE_MULTIBYTE) - memset (&ps, 0, sizeof (mbstate_t)); - _rl_adjust_point (str, i, &ps); -#endif - - for (si = i; str[si] && str[si] != delimiter; si++) -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - int v; - if ((v = _rl_get_char_len (str + si, &ps)) > 1) - si += v - 1; - else if (str[si] == '\\' && str[si + 1] == delimiter) - si++; - } - else -#endif /* HANDLE_MULTIBYTE */ - if (str[si] == '\\' && str[si + 1] == delimiter) - si++; - - if (si > i || is_rhs) - { - s = (char *)xmalloc (si - i + 1); - for (j = 0, k = i; k < si; j++, k++) - { - /* Remove a backslash quoting the search string delimiter. */ - if (str[k] == '\\' && str[k + 1] == delimiter) - k++; - s[j] = str[k]; - } - s[j] = '\0'; - if (lenptr) - *lenptr = j; - } - - i = si; - if (str[i]) - i++; - *iptr = i; - - return s; -} - -static void -postproc_subst_rhs () -{ - char *new; - int i, j, new_size; - - new = (char *)xmalloc (new_size = subst_rhs_len + subst_lhs_len); - for (i = j = 0; i < subst_rhs_len; i++) - { - if (subst_rhs[i] == '&') - { - if (j + subst_lhs_len >= new_size) - new = (char *)xrealloc (new, (new_size = new_size * 2 + subst_lhs_len)); - strcpy (new + j, subst_lhs); - j += subst_lhs_len; - } - else - { - /* a single backslash protects the `&' from lhs interpolation */ - if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&') - i++; - if (j >= new_size) - new = (char *)xrealloc (new, new_size *= 2); - new[j++] = subst_rhs[i]; - } - } - new[j] = '\0'; - xfree (subst_rhs); - subst_rhs = new; - subst_rhs_len = j; -} - -/* Expand the bulk of a history specifier starting at STRING[START]. - Returns 0 if everything is OK, -1 if an error occurred, and 1 - if the `p' modifier was supplied and the caller should just print - the returned string. Returns the new index into string in - *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */ -static int -history_expand_internal (string, start, qc, end_index_ptr, ret_string, current_line) - char *string; - int start, qc, *end_index_ptr; - char **ret_string; - char *current_line; /* for !# */ -{ - int i, n, starting_index; - int substitute_globally, subst_bywords, want_quotes, print_only; - char *event, *temp, *result, *tstr, *t, c, *word_spec; - int result_len; -#if defined (HANDLE_MULTIBYTE) - mbstate_t ps; - - memset (&ps, 0, sizeof (mbstate_t)); -#endif - - result = (char *)xmalloc (result_len = 128); - - i = start; - - /* If it is followed by something that starts a word specifier, - then !! is implied as the event specifier. */ - - if (member (string[i + 1], ":$*%^")) - { - char fake_s[3]; - int fake_i = 0; - i++; - fake_s[0] = fake_s[1] = history_expansion_char; - fake_s[2] = '\0'; - event = get_history_event (fake_s, &fake_i, 0); - } - else if (string[i + 1] == '#') - { - i += 2; - event = current_line; - } - else - event = get_history_event (string, &i, qc); - - if (event == 0) - { - *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND); - xfree (result); - return (-1); - } - - /* If a word specifier is found, then do what that requires. */ - starting_index = i; - word_spec = get_history_word_specifier (string, event, &i); - - /* There is no such thing as a `malformed word specifier'. However, - it is possible for a specifier that has no match. In that case, - we complain. */ - if (word_spec == (char *)&error_pointer) - { - *ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC); - xfree (result); - return (-1); - } - - /* If no word specifier, than the thing of interest was the event. */ - temp = word_spec ? savestring (word_spec) : savestring (event); - FREE (word_spec); - - /* Perhaps there are other modifiers involved. Do what they say. */ - want_quotes = substitute_globally = subst_bywords = print_only = 0; - starting_index = i; - - while (string[i] == ':') - { - c = string[i + 1]; - - if (c == 'g' || c == 'a') - { - substitute_globally = 1; - i++; - c = string[i + 1]; - } - else if (c == 'G') - { - subst_bywords = 1; - i++; - c = string[i + 1]; - } - - switch (c) - { - default: - *ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER); - xfree (result); - xfree (temp); - return -1; - - case 'q': - want_quotes = 'q'; - break; - - case 'x': - want_quotes = 'x'; - break; - - /* :p means make this the last executed line. So we - return an error state after adding this line to the - history. */ - case 'p': - print_only++; - break; - - /* :t discards all but the last part of the pathname. */ - case 't': - tstr = strrchr (temp, '/'); - if (tstr) - { - tstr++; - t = savestring (tstr); - xfree (temp); - temp = t; - } - break; - - /* :h discards the last part of a pathname. */ - case 'h': - tstr = strrchr (temp, '/'); - if (tstr) - *tstr = '\0'; - break; - - /* :r discards the suffix. */ - case 'r': - tstr = strrchr (temp, '.'); - if (tstr) - *tstr = '\0'; - break; - - /* :e discards everything but the suffix. */ - case 'e': - tstr = strrchr (temp, '.'); - if (tstr) - { - t = savestring (tstr); - xfree (temp); - temp = t; - } - break; - - /* :s/this/that substitutes `that' for the first - occurrence of `this'. :gs/this/that substitutes `that' - for each occurrence of `this'. :& repeats the last - substitution. :g& repeats the last substitution - globally. */ - - case '&': - case 's': - { - char *new_event; - int delimiter, failed, si, l_temp, ws, we; - - if (c == 's') - { - if (i + 2 < (int)strlen (string)) - { -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - _rl_adjust_point (string, i + 2, &ps); - if (_rl_get_char_len (string + i + 2, &ps) > 1) - delimiter = 0; - else - delimiter = string[i + 2]; - } - else -#endif /* HANDLE_MULTIBYTE */ - delimiter = string[i + 2]; - } - else - break; /* no search delimiter */ - - i += 3; - - t = get_subst_pattern (string, &i, delimiter, 0, &subst_lhs_len); - /* An empty substitution lhs with no previous substitution - uses the last search string as the lhs. */ - if (t) - { - FREE (subst_lhs); - subst_lhs = t; - } - else if (!subst_lhs) - { - if (search_string && *search_string) - { - subst_lhs = savestring (search_string); - subst_lhs_len = strlen (subst_lhs); - } - else - { - subst_lhs = (char *) NULL; - subst_lhs_len = 0; - } - } - - FREE (subst_rhs); - subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len); - - /* If `&' appears in the rhs, it's supposed to be replaced - with the lhs. */ - if (member ('&', subst_rhs)) - postproc_subst_rhs (); - } - else - i += 2; - - /* If there is no lhs, the substitution can't succeed. */ - if (subst_lhs_len == 0) - { - *ret_string = hist_error (string, starting_index, i, NO_PREV_SUBST); - xfree (result); - xfree (temp); - return -1; - } - - l_temp = strlen (temp); - /* Ignore impossible cases. */ - if (subst_lhs_len > l_temp) - { - *ret_string = hist_error (string, starting_index, i, SUBST_FAILED); - xfree (result); - xfree (temp); - return (-1); - } - - /* Find the first occurrence of THIS in TEMP. */ - /* Substitute SUBST_RHS for SUBST_LHS in TEMP. There are three - cases to consider: - - 1. substitute_globally == subst_bywords == 0 - 2. substitute_globally == 1 && subst_bywords == 0 - 3. substitute_globally == 0 && subst_bywords == 1 - - In the first case, we substitute for the first occurrence only. - In the second case, we substitute for every occurrence. - In the third case, we tokenize into words and substitute the - first occurrence of each word. */ - - si = we = 0; - for (failed = 1; (si + subst_lhs_len) <= l_temp; si++) - { - /* First skip whitespace and find word boundaries if - we're past the end of the word boundary we found - the last time. */ - if (subst_bywords && si > we) - { - for (; temp[si] && whitespace (temp[si]); si++) - ; - ws = si; - we = history_tokenize_word (temp, si); - } - - if (STREQN (temp+si, subst_lhs, subst_lhs_len)) - { - int len = subst_rhs_len - subst_lhs_len + l_temp; - new_event = (char *)xmalloc (1 + len); - strncpy (new_event, temp, si); - strncpy (new_event + si, subst_rhs, subst_rhs_len); - strncpy (new_event + si + subst_rhs_len, - temp + si + subst_lhs_len, - l_temp - (si + subst_lhs_len)); - new_event[len] = '\0'; - xfree (temp); - temp = new_event; - - failed = 0; - - if (substitute_globally) - { - /* Reported to fix a bug that causes it to skip every - other match when matching a single character. Was - si += subst_rhs_len previously. */ - si += subst_rhs_len - 1; - l_temp = strlen (temp); - substitute_globally++; - continue; - } - else if (subst_bywords) - { - si = we; - l_temp = strlen (temp); - continue; - } - else - break; - } - } - - if (substitute_globally > 1) - { - substitute_globally = 0; - continue; /* don't want to increment i */ - } - - if (failed == 0) - continue; /* don't want to increment i */ - - *ret_string = hist_error (string, starting_index, i, SUBST_FAILED); - xfree (result); - xfree (temp); - return (-1); - } - } - i += 2; - } - /* Done with modifiers. */ - /* Believe it or not, we have to back the pointer up by one. */ - --i; - - if (want_quotes) - { - char *x; - - if (want_quotes == 'q') - x = sh_single_quote (temp); - else if (want_quotes == 'x') - x = quote_breaks (temp); - else - x = savestring (temp); - - xfree (temp); - temp = x; - } - - n = strlen (temp); - if (n >= result_len) - result = (char *)xrealloc (result, n + 2); - strcpy (result, temp); - xfree (temp); - - *end_index_ptr = i; - *ret_string = result; - return (print_only); -} - -/* Expand the string STRING, placing the result into OUTPUT, a pointer - to a string. Returns: - - -1) If there was an error in expansion. - 0) If no expansions took place (or, if the only change in - the text was the de-slashifying of the history expansion - character) - 1) If expansions did take place - 2) If the `p' modifier was given and the caller should print the result - - If an error ocurred in expansion, then OUTPUT contains a descriptive - error message. */ - -#define ADD_STRING(s) \ - do \ - { \ - int sl = strlen (s); \ - j += sl; \ - if (j >= result_len) \ - { \ - while (j >= result_len) \ - result_len += 128; \ - result = (char *)xrealloc (result, result_len); \ - } \ - strcpy (result + j - sl, s); \ - } \ - while (0) - -#define ADD_CHAR(c) \ - do \ - { \ - if (j >= result_len - 1) \ - result = (char *)xrealloc (result, result_len += 64); \ - result[j++] = c; \ - result[j] = '\0'; \ - } \ - while (0) - -int -history_expand (hstring, output) - char *hstring; - char **output; -{ - register int j; - int i, r, l, passc, cc, modified, eindex, only_printing, dquote, squote, flag; - char *string; - - /* The output string, and its length. */ - int result_len; - char *result; - -#if defined (HANDLE_MULTIBYTE) - char mb[MB_LEN_MAX]; - mbstate_t ps; -#endif - - /* Used when adding the string. */ - char *temp; - - if (output == 0) - return 0; - - /* Setting the history expansion character to 0 inhibits all - history expansion. */ - if (history_expansion_char == 0) - { - *output = savestring (hstring); - return (0); - } - - /* Prepare the buffer for printing error messages. */ - result = (char *)xmalloc (result_len = 256); - result[0] = '\0'; - - only_printing = modified = 0; - l = strlen (hstring); - - /* Grovel the string. Only backslash and single quotes can quote the - history escape character. We also handle arg specifiers. */ - - /* Before we grovel forever, see if the history_expansion_char appears - anywhere within the text. */ - - /* The quick substitution character is a history expansion all right. That - is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact, - that is the substitution that we do. */ - if (hstring[0] == history_subst_char) - { - string = (char *)xmalloc (l + 5); - - string[0] = string[1] = history_expansion_char; - string[2] = ':'; - string[3] = 's'; - strcpy (string + 4, hstring); - l += 4; - } - else - { -#if defined (HANDLE_MULTIBYTE) - memset (&ps, 0, sizeof (mbstate_t)); -#endif - - string = hstring; - /* If not quick substitution, still maybe have to do expansion. */ - - /* `!' followed by one of the characters in history_no_expand_chars - is NOT an expansion. */ - for (i = dquote = squote = 0; string[i]; i++) - { -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - int v; - v = _rl_get_char_len (string + i, &ps); - if (v > 1) - { - i += v - 1; - continue; - } - } -#endif /* HANDLE_MULTIBYTE */ - - cc = string[i + 1]; - /* The history_comment_char, if set, appearing at the beginning - of a word signifies that the rest of the line should not have - history expansion performed on it. - Skip the rest of the line and break out of the loop. */ - if (history_comment_char && string[i] == history_comment_char && - dquote == 0 && - (i == 0 || member (string[i - 1], history_word_delimiters))) - { -itrace("history_comment char found: dquote = %d", dquote); - while (string[i]) - i++; - break; - } - else if (string[i] == history_expansion_char) - { - if (cc == 0 || member (cc, history_no_expand_chars)) - continue; - /* DQUOTE won't be set unless history_quotes_inhibit_expansion - is set. The idea here is to treat double-quoted strings the - same as the word outside double quotes; in effect making the - double quote part of history_no_expand_chars when DQUOTE is - set. */ - else if (dquote && cc == '"') - continue; - /* If the calling application has set - history_inhibit_expansion_function to a function that checks - for special cases that should not be history expanded, - call the function and skip the expansion if it returns a - non-zero value. */ - else if (history_inhibit_expansion_function && - (*history_inhibit_expansion_function) (string, i)) - continue; - else - break; - } - /* Shell-like quoting: allow backslashes to quote double quotes - inside a double-quoted string. */ - else if (dquote && string[i] == '\\' && cc == '"') - i++; - /* More shell-like quoting: if we're paying attention to single - quotes and letting them quote the history expansion character, - then we need to pay attention to double quotes, because single - quotes are not special inside double-quoted strings. */ - else if (history_quotes_inhibit_expansion && string[i] == '"') - { - dquote = 1 - dquote; - } - else if (dquote == 0 && history_quotes_inhibit_expansion && string[i] == '\'') - { - /* If this is bash, single quotes inhibit history expansion. */ - flag = (i > 0 && string[i - 1] == '$'); - i++; - hist_string_extract_single_quoted (string, &i, flag); - } - else if (history_quotes_inhibit_expansion && string[i] == '\\') - { - /* If this is bash, allow backslashes to quote single - quotes and the history expansion character. */ - if (cc == '\'' || cc == history_expansion_char) - i++; - } - - } - - if (string[i] != history_expansion_char) - { - xfree (result); - *output = savestring (string); - return (0); - } - } - - /* Extract and perform the substitution. */ - for (passc = dquote = squote = i = j = 0; i < l; i++) - { - int qc, tchar = string[i]; - - if (passc) - { - passc = 0; - ADD_CHAR (tchar); - continue; - } - -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - int k, c; - - c = tchar; - memset (mb, 0, sizeof (mb)); - for (k = 0; k < MB_LEN_MAX; k++) - { - mb[k] = (char)c; - memset (&ps, 0, sizeof (mbstate_t)); - if (_rl_get_char_len (mb, &ps) == -2) - c = string[++i]; - else - break; - } - if (strlen (mb) > 1) - { - ADD_STRING (mb); - continue; - } - } -#endif /* HANDLE_MULTIBYTE */ - - if (tchar == history_expansion_char) - tchar = -3; - else if (tchar == history_comment_char) - tchar = -2; - - switch (tchar) - { - default: - ADD_CHAR (string[i]); - break; - - case '\\': - passc++; - ADD_CHAR (tchar); - break; - - case '"': - dquote = 1 - dquote; - ADD_CHAR (tchar); - break; - - case '\'': - { - /* If history_quotes_inhibit_expansion is set, single quotes - inhibit history expansion, otherwise they are treated like - double quotes. */ - if (squote) - { - squote = 0; - ADD_CHAR (tchar); - } - else if (dquote == 0 && history_quotes_inhibit_expansion) - { - int quote, slen; - - flag = (i > 0 && string[i - 1] == '$'); - quote = i++; - hist_string_extract_single_quoted (string, &i, flag); - - slen = i - quote + 2; - temp = (char *)xmalloc (slen); - strncpy (temp, string + quote, slen); - temp[slen - 1] = '\0'; - ADD_STRING (temp); - xfree (temp); - } - else if (dquote == 0 && squote == 0 && history_quotes_inhibit_expansion == 0) - { - squote = 1; - ADD_CHAR (string[i]); - } - else - ADD_CHAR (string[i]); - break; - } - - case -2: /* history_comment_char */ - if ((dquote == 0 || history_quotes_inhibit_expansion == 0) && - (i == 0 || member (string[i - 1], history_word_delimiters))) - { - temp = (char *)xmalloc (l - i + 1); - strcpy (temp, string + i); - ADD_STRING (temp); - xfree (temp); - i = l; - } - else - ADD_CHAR (string[i]); - break; - - case -3: /* history_expansion_char */ - cc = string[i + 1]; - - /* If the history_expansion_char is followed by one of the - characters in history_no_expand_chars, then it is not a - candidate for expansion of any kind. */ - if (cc == 0 || member (cc, history_no_expand_chars) || - (dquote && cc == '"') || - (history_inhibit_expansion_function && (*history_inhibit_expansion_function) (string, i))) - { - ADD_CHAR (string[i]); - break; - } - -#if defined (NO_BANG_HASH_MODIFIERS) - /* There is something that is listed as a `word specifier' in csh - documentation which means `the expanded text to this point'. - That is not a word specifier, it is an event specifier. If we - don't want to allow modifiers with `!#', just stick the current - output line in again. */ - if (cc == '#') - { - if (result) - { - temp = (char *)xmalloc (1 + strlen (result)); - strcpy (temp, result); - ADD_STRING (temp); - xfree (temp); - } - i++; - break; - } -#endif - qc = squote ? '\'' : (dquote ? '"' : 0); - r = history_expand_internal (string, i, qc, &eindex, &temp, result); - if (r < 0) - { - *output = temp; - xfree (result); - if (string != hstring) - xfree (string); - return -1; - } - else - { - if (temp) - { - modified++; - if (*temp) - ADD_STRING (temp); - xfree (temp); - } - only_printing = r == 1; - i = eindex; - } - break; - } - } - - *output = result; - if (string != hstring) - xfree (string); - - if (only_printing) - { -#if 0 - add_history (result); -#endif - return (2); - } - - return (modified != 0); -} - -/* Return a consed string which is the word specified in SPEC, and found - in FROM. NULL is returned if there is no spec. The address of - ERROR_POINTER is returned if the word specified cannot be found. - CALLER_INDEX is the offset in SPEC to start looking; it is updated - to point to just after the last character parsed. */ -static char * -get_history_word_specifier (spec, from, caller_index) - char *spec, *from; - int *caller_index; -{ - register int i = *caller_index; - int first, last; - int expecting_word_spec = 0; - char *result; - - /* The range of words to return doesn't exist yet. */ - first = last = 0; - result = (char *)NULL; - - /* If we found a colon, then this *must* be a word specification. If - it isn't, then it is an error. */ - if (spec[i] == ':') - { - i++; - expecting_word_spec++; - } - - /* Handle special cases first. */ - - /* `%' is the word last searched for. */ - if (spec[i] == '%') - { - *caller_index = i + 1; - return (search_match ? savestring (search_match) : savestring ("")); - } - - /* `*' matches all of the arguments, but not the command. */ - if (spec[i] == '*') - { - *caller_index = i + 1; - result = history_arg_extract (1, '$', from); - return (result ? result : savestring ("")); - } - - /* `$' is last arg. */ - if (spec[i] == '$') - { - *caller_index = i + 1; - return (history_arg_extract ('$', '$', from)); - } - - /* Try to get FIRST and LAST figured out. */ - - if (spec[i] == '-') - first = 0; - else if (spec[i] == '^') - { - first = 1; - i++; - } - else if (_rl_digit_p (spec[i]) && expecting_word_spec) - { - for (first = 0; _rl_digit_p (spec[i]); i++) - first = (first * 10) + _rl_digit_value (spec[i]); - } - else - return ((char *)NULL); /* no valid `first' for word specifier */ - - if (spec[i] == '^' || spec[i] == '*') - { - last = (spec[i] == '^') ? 1 : '$'; /* x* abbreviates x-$ */ - i++; - } - else if (spec[i] != '-') - last = first; - else - { - i++; - - if (_rl_digit_p (spec[i])) - { - for (last = 0; _rl_digit_p (spec[i]); i++) - last = (last * 10) + _rl_digit_value (spec[i]); - } - else if (spec[i] == '$') - { - i++; - last = '$'; - } -#if 0 - else if (!spec[i] || spec[i] == ':') - /* check against `:' because there could be a modifier separator */ -#else - else - /* csh seems to allow anything to terminate the word spec here, - leaving it as an abbreviation. */ -#endif - last = -1; /* x- abbreviates x-$ omitting word `$' */ - } - - *caller_index = i; - - if (last >= first || last == '$' || last < 0) - result = history_arg_extract (first, last, from); - - return (result ? result : (char *)&error_pointer); -} - -/* Extract the args specified, starting at FIRST, and ending at LAST. - The args are taken from STRING. If either FIRST or LAST is < 0, - then make that arg count from the right (subtract from the number of - tokens, so that FIRST = -1 means the next to last token on the line). - If LAST is `$' the last arg from STRING is used. */ -char * -history_arg_extract (first, last, string) - int first, last; - const char *string; -{ - register int i, len; - char *result; - int size, offset; - char **list; - - /* XXX - think about making history_tokenize return a struct array, - each struct in array being a string and a length to avoid the - calls to strlen below. */ - if ((list = history_tokenize (string)) == NULL) - return ((char *)NULL); - - for (len = 0; list[len]; len++) - ; - - if (last < 0) - last = len + last - 1; - - if (first < 0) - first = len + first - 1; - - if (last == '$') - last = len - 1; - - if (first == '$') - first = len - 1; - - last++; - - if (first >= len || last > len || first < 0 || last < 0 || first > last) - result = ((char *)NULL); - else - { - for (size = 0, i = first; i < last; i++) - size += strlen (list[i]) + 1; - result = (char *)xmalloc (size + 1); - result[0] = '\0'; - - for (i = first, offset = 0; i < last; i++) - { - strcpy (result + offset, list[i]); - offset += strlen (list[i]); - if (i + 1 < last) - { - result[offset++] = ' '; - result[offset] = 0; - } - } - } - - for (i = 0; i < len; i++) - xfree (list[i]); - xfree (list); - - return (result); -} - -static int -history_tokenize_word (string, ind) - const char *string; - int ind; -{ - register int i; - int delimiter, nestdelim, delimopen; - - i = ind; - delimiter = nestdelim = 0; - - if (member (string[i], "()\n")) - { - i++; - return i; - } - - if (member (string[i], "<>;&|$")) - { - int peek = string[i + 1]; - - if (peek == string[i] && peek != '$') - { - if (peek == '<' && string[i + 2] == '-') - i++; - else if (peek == '<' && string[i + 2] == '<') - i++; - i += 2; - return i; - } - else if ((peek == '&' && (string[i] == '>' || string[i] == '<')) || - (peek == '>' && string[i] == '&')) - { - i += 2; - return i; - } - /* XXX - separated out for later -- bash-4.2 */ - else if ((peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */ - (peek == '(' && string[i] == '$')) /*)*/ - { - i += 2; - delimopen = '('; - delimiter = ')'; - nestdelim = 1; - goto get_word; - } -#if 0 - else if (peek == '\'' && string[i] == '$') - { - i += 2; /* XXX */ - return i; - } -#endif - - if (string[i] != '$') - { - i++; - return i; - } - } - - /* same code also used for $(...)/<(...)/>(...) above */ - if (member (string[i], "!@?+*")) - { - int peek = string[i + 1]; - - if (peek == '(') /*)*/ - { - /* Shell extended globbing patterns */ - i += 2; - delimopen = '('; - delimiter = ')'; /* XXX - not perfect */ - nestdelim = 1; - } - } - -get_word: - /* Get word from string + i; */ - - if (delimiter == 0 && member (string[i], HISTORY_QUOTE_CHARACTERS)) - delimiter = string[i++]; - - for (; string[i]; i++) - { - if (string[i] == '\\' && string[i + 1] == '\n') - { - i++; - continue; - } - - if (string[i] == '\\' && delimiter != '\'' && - (delimiter != '"' || member (string[i], slashify_in_quotes))) - { - i++; - continue; - } - - /* delimiter must be set and set to something other than a quote if - nestdelim is set, so these tests are safe. */ - if (nestdelim && string[i] == delimopen) - { - nestdelim++; - continue; - } - if (nestdelim && string[i] == delimiter) - { - nestdelim--; - if (nestdelim == 0) - delimiter = 0; - continue; - } - - if (delimiter && string[i] == delimiter) - { - delimiter = 0; - continue; - } - - if (delimiter == 0 && (member (string[i], history_word_delimiters))) - break; - - if (delimiter == 0 && member (string[i], HISTORY_QUOTE_CHARACTERS)) - delimiter = string[i]; - } - - return i; -} - -static char * -history_substring (string, start, end) - const char *string; - int start, end; -{ - register int len; - register char *result; - - len = end - start; - result = (char *)xmalloc (len + 1); - strncpy (result, string + start, len); - result[len] = '\0'; - return result; -} - -/* Parse STRING into tokens and return an array of strings. If WIND is - not -1 and INDP is not null, we also want the word surrounding index - WIND. The position in the returned array of strings is returned in - *INDP. */ -static char ** -history_tokenize_internal (string, wind, indp) - const char *string; - int wind, *indp; -{ - char **result; - register int i, start, result_index, size; - - /* If we're searching for a string that's not part of a word (e.g., " "), - make sure we set *INDP to a reasonable value. */ - if (indp && wind != -1) - *indp = -1; - - /* Get a token, and stuff it into RESULT. The tokens are split - exactly where the shell would split them. */ - for (i = result_index = size = 0, result = (char **)NULL; string[i]; ) - { - /* Skip leading whitespace. */ - for (; string[i] && whitespace (string[i]); i++) - ; - if (string[i] == 0 || string[i] == history_comment_char) - return (result); - - start = i; - - i = history_tokenize_word (string, start); - - /* If we have a non-whitespace delimiter character (which would not be - skipped by the loop above), use it and any adjacent delimiters to - make a separate field. Any adjacent white space will be skipped the - next time through the loop. */ - if (i == start && history_word_delimiters) - { - i++; - while (string[i] && member (string[i], history_word_delimiters)) - i++; - } - - /* If we are looking for the word in which the character at a - particular index falls, remember it. */ - if (indp && wind != -1 && wind >= start && wind < i) - *indp = result_index; - - if (result_index + 2 >= size) - result = (char **)xrealloc (result, ((size += 10) * sizeof (char *))); - - result[result_index++] = history_substring (string, start, i); - result[result_index] = (char *)NULL; - } - - return (result); -} - -/* Return an array of tokens, much as the shell might. The tokens are - parsed out of STRING. */ -char ** -history_tokenize (string) - const char *string; -{ - return (history_tokenize_internal (string, -1, (int *)NULL)); -} - -/* Free members of WORDS from START to an empty string */ -static void -freewords (words, start) - char **words; - int start; -{ - register int i; - - for (i = start; words[i]; i++) - xfree (words[i]); -} - -/* Find and return the word which contains the character at index IND - in the history line LINE. Used to save the word matched by the - last history !?string? search. */ -static char * -history_find_word (line, ind) - char *line; - int ind; -{ - char **words, *s; - int i, wind; - - words = history_tokenize_internal (line, ind, &wind); - if (wind == -1 || words == 0) - { - if (words) - freewords (words, 0); - FREE (words); - return ((char *)NULL); - } - s = words[wind]; - for (i = 0; i < wind; i++) - xfree (words[i]); - freewords (words, wind + 1); - xfree (words); - return s; -} diff --git a/lib/readline/histfile.c~ b/lib/readline/histfile.c~ deleted file mode 100644 index 2d735b1b..00000000 --- a/lib/readline/histfile.c~ +++ /dev/null @@ -1,609 +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 <http://www.gnu.org/licenses/>. -*/ - -/* 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 <floss.h> -#endif - -#if defined (HAVE_CONFIG_H) -# include <config.h> -#endif - -#include <stdio.h> - -#include <sys/types.h> -#if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H) -# include <sys/file.h> -#endif -#include "posixstat.h" -#include <fcntl.h> - -#if defined (HAVE_STDLIB_H) -# include <stdlib.h> -#else -# include "ansi_stdlib.h" -#endif /* HAVE_STDLIB_H */ - -#if defined (HAVE_UNISTD_H) -# include <unistd.h> -#endif - -#include <ctype.h> - -#if defined (__EMX__) -# undef HAVE_MMAP -#endif - -#ifdef HISTORY_USE_MMAP -# include <sys/mman.h> - -# 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 <errno.h> -#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; - -/* 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 - - 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; - } - - 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; - struct stat finfo; - size_t file_size; - - buffer = (char *)NULL; - filename = history_filename (fname); - bakname = 0; - file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1; - rv = 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; - } - - 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; - } - - /* 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; - 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; - rename (bakname, filename); - } - -#if defined (__BEOS__) - /* BeOS ignores O_TRUNC. */ - ftruncate (file, chars_read - (bp - buffer)); -#endif - - if (close (file) < 0 && rv == 0) - { - rv = errno; - rename (bakname, filename); - } - } - else - { - rv = errno; - rename (bakname, filename); - } - - truncate_exit: - - FREE (buffer); - - xfree (filename); - FREE (bakname); - - return rv; -} - -/* Workhorse function for writing history. Writes 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; -#ifdef HISTORY_USE_MMAP - size_t cursize; - - 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; - - 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 - } - - if (close (file) < 0 && rv == 0) - rv = errno; - - if (rv != 0 && output && bakname) - rename (bakname, output); - else if (rv == 0 && bakname) - unlink (bakname); - - 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/misc.c~ b/lib/readline/misc.c~ deleted file mode 100644 index 1f8bed49..00000000 --- a/lib/readline/misc.c~ +++ /dev/null @@ -1,693 +0,0 @@ -/* misc.c -- miscellaneous bindable readline 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 <http://www.gnu.org/licenses/>. -*/ - -#define READLINE_LIBRARY - -#if defined (HAVE_CONFIG_H) -# include <config.h> -#endif - -#if defined (HAVE_UNISTD_H) -# include <unistd.h> -#endif /* HAVE_UNISTD_H */ - -#if defined (HAVE_STDLIB_H) -# include <stdlib.h> -#else -# include "ansi_stdlib.h" -#endif /* HAVE_STDLIB_H */ - -#if defined (HAVE_LOCALE_H) -# include <locale.h> -#endif - -#include <stdio.h> - -/* System-specific feature definitions and include files. */ -#include "rldefs.h" -#include "rlmbutil.h" - -/* Some standard library routines. */ -#include "readline.h" -#include "history.h" - -#include "rlprivate.h" -#include "rlshell.h" -#include "xmalloc.h" - -static int rl_digit_loop PARAMS((void)); -static void _rl_history_set_point PARAMS((void)); - -extern int history_offset; - -/* Forward declarations used in this file */ -void _rl_free_history_entry PARAMS((HIST_ENTRY *)); - -/* If non-zero, rl_get_previous_history and rl_get_next_history attempt - to preserve the value of rl_point from line to line. */ -int _rl_history_preserve_point = 0; - -_rl_arg_cxt _rl_argcxt; - -/* Saved target point for when _rl_history_preserve_point is set. Special - value of -1 means that point is at the end of the line. */ -int _rl_history_saved_point = -1; - -/* **************************************************************** */ -/* */ -/* Numeric Arguments */ -/* */ -/* **************************************************************** */ - -int -_rl_arg_overflow () -{ - if (rl_numeric_arg > 1000000) - { - _rl_argcxt = 0; - rl_explicit_arg = rl_numeric_arg = 0; - rl_ding (); - rl_restore_prompt (); - rl_clear_message (); - RL_UNSETSTATE(RL_STATE_NUMERICARG); - return 1; - } - return 0; -} - -void -_rl_arg_init () -{ - rl_save_prompt (); - _rl_argcxt = 0; - RL_SETSTATE(RL_STATE_NUMERICARG); -} - -int -_rl_arg_getchar () -{ - int c; - - rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); - RL_SETSTATE(RL_STATE_MOREINPUT); - c = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); - - return c; -} - -/* Process C as part of the current numeric argument. Return -1 if the - argument should be aborted, 0 if we should not read any more chars, and - 1 if we should continue to read chars. */ -int -_rl_arg_dispatch (cxt, c) - _rl_arg_cxt cxt; - int c; -{ - int key, r; - - key = c; - - /* If we see a key bound to `universal-argument' after seeing digits, - it ends the argument but is otherwise ignored. */ - if (_rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) - { - if ((cxt & NUM_SAWDIGITS) == 0) - { - rl_numeric_arg *= 4; - return 1; - } - else if (RL_ISSTATE (RL_STATE_CALLBACK)) - { - _rl_argcxt |= NUM_READONE; - return 0; /* XXX */ - } - else - { - RL_SETSTATE(RL_STATE_MOREINPUT); - key = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); - rl_restore_prompt (); - rl_clear_message (); - RL_UNSETSTATE(RL_STATE_NUMERICARG); - if (key < 0) - return -1; - return (_rl_dispatch (key, _rl_keymap)); - } - } - - c = UNMETA (c); - - if (_rl_digit_p (c)) - { - r = _rl_digit_value (c); - rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + r : r; - rl_explicit_arg = 1; - _rl_argcxt |= NUM_SAWDIGITS; - } - else if (c == '-' && rl_explicit_arg == 0) - { - rl_numeric_arg = 1; - _rl_argcxt |= NUM_SAWMINUS; - rl_arg_sign = -1; - } - else - { - /* Make M-- command equivalent to M--1 command. */ - if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0) - rl_explicit_arg = 1; - rl_restore_prompt (); - rl_clear_message (); - RL_UNSETSTATE(RL_STATE_NUMERICARG); - - r = _rl_dispatch (key, _rl_keymap); - if (RL_ISSTATE (RL_STATE_CALLBACK)) - { - /* At worst, this will cause an extra redisplay. Otherwise, - we have to wait until the next character comes in. */ - if (rl_done == 0) - (*rl_redisplay_function) (); - r = 0; - } - return r; - } - - return 1; -} - -/* Handle C-u style numeric args, as well as M--, and M-digits. */ -static int -rl_digit_loop () -{ - int c, r; - - while (1) - { - if (_rl_arg_overflow ()) - return 1; - - c = _rl_arg_getchar (); - - if (c < 0) - { - _rl_abort_internal (); - return -1; - } - - r = _rl_arg_dispatch (_rl_argcxt, c); - if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)) - break; - } - - return r; -} - -/* Create a default argument. */ -void -_rl_reset_argument () -{ - rl_numeric_arg = rl_arg_sign = 1; - rl_explicit_arg = 0; - _rl_argcxt = 0; -} - -/* Start a numeric argument with initial value KEY */ -int -rl_digit_argument (ignore, key) - int ignore, key; -{ - _rl_arg_init (); - if (RL_ISSTATE (RL_STATE_CALLBACK)) - { - _rl_arg_dispatch (_rl_argcxt, key); - rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); - return 0; - } - else - { - rl_execute_next (key); - return (rl_digit_loop ()); - } -} - -/* C-u, universal argument. Multiply the current argument by 4. - Read a key. If the key has nothing to do with arguments, then - dispatch on it. If the key is the abort character then abort. */ -int -rl_universal_argument (count, key) - int count, key; -{ - _rl_arg_init (); - rl_numeric_arg *= 4; - - return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ()); -} - -int -_rl_arg_callback (cxt) - _rl_arg_cxt cxt; -{ - int c, r; - - c = _rl_arg_getchar (); - - if (_rl_argcxt & NUM_READONE) - { - _rl_argcxt &= ~NUM_READONE; - rl_restore_prompt (); - rl_clear_message (); - RL_UNSETSTATE(RL_STATE_NUMERICARG); - rl_execute_next (c); - return 0; - } - - r = _rl_arg_dispatch (cxt, c); - return (r != 1); -} - -/* What to do when you abort reading an argument. */ -int -rl_discard_argument () -{ - rl_ding (); - rl_clear_message (); - _rl_reset_argument (); - - return 0; -} - -/* **************************************************************** */ -/* */ -/* History Utilities */ -/* */ -/* **************************************************************** */ - -/* We already have a history library, and that is what we use to control - the history features of readline. This is our local interface to - the history mechanism. */ - -/* While we are editing the history, this is the saved - version of the original line. */ -HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL; - -/* Set the history pointer back to the last entry in the history. */ -void -_rl_start_using_history () -{ - using_history (); - if (_rl_saved_line_for_history) - _rl_free_history_entry (_rl_saved_line_for_history); - - _rl_saved_line_for_history = (HIST_ENTRY *)NULL; -} - -/* Free the contents (and containing structure) of a HIST_ENTRY. */ -void -_rl_free_history_entry (entry) - HIST_ENTRY *entry; -{ - if (entry == 0) - return; - - FREE (entry->line); - FREE (entry->timestamp); - - xfree (entry); -} - -/* Perhaps put back the current line if it has changed. */ -int -rl_maybe_replace_line () -{ - HIST_ENTRY *temp; - - temp = current_history (); - /* If the current line has changed, save the changes. */ - if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) - { - temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list); - xfree (temp->line); - FREE (temp->timestamp); - xfree (temp); - } - return 0; -} - -/* Restore the _rl_saved_line_for_history if there is one. */ -int -rl_maybe_unsave_line () -{ - if (_rl_saved_line_for_history) - { - /* Can't call with `1' because rl_undo_list might point to an undo - list from a history entry, as in rl_replace_from_history() below. */ - rl_replace_line (_rl_saved_line_for_history->line, 0); - rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data; - _rl_free_history_entry (_rl_saved_line_for_history); - _rl_saved_line_for_history = (HIST_ENTRY *)NULL; - rl_point = rl_end; /* rl_replace_line sets rl_end */ - } - else - rl_ding (); - return 0; -} - -/* Save the current line in _rl_saved_line_for_history. */ -int -rl_maybe_save_line () -{ - if (_rl_saved_line_for_history == 0) - { - _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); - _rl_saved_line_for_history->line = savestring (rl_line_buffer); - _rl_saved_line_for_history->timestamp = (char *)NULL; - _rl_saved_line_for_history->data = (char *)rl_undo_list; - } - - return 0; -} - -int -_rl_free_saved_history_line () -{ - if (_rl_saved_line_for_history) - { - _rl_free_history_entry (_rl_saved_line_for_history); - _rl_saved_line_for_history = (HIST_ENTRY *)NULL; - } - return 0; -} - -static void -_rl_history_set_point () -{ - rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1) - ? _rl_history_saved_point - : rl_end; - if (rl_point > rl_end) - rl_point = rl_end; - -#if defined (VI_MODE) - if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap) - rl_point = 0; -#endif /* VI_MODE */ - - if (rl_editing_mode == emacs_mode) - rl_mark = (rl_point == rl_end ? 0 : rl_end); -} - -void -rl_replace_from_history (entry, flags) - HIST_ENTRY *entry; - int flags; /* currently unused */ -{ - /* Can't call with `1' because rl_undo_list might point to an undo list - from a history entry, just like we're setting up here. */ - rl_replace_line (entry->line, 0); - rl_undo_list = (UNDO_LIST *)entry->data; - rl_point = rl_end; - rl_mark = 0; - -#if defined (VI_MODE) - if (rl_editing_mode == vi_mode) - { - rl_point = 0; - rl_mark = rl_end; - } -#endif -} - -/* Process and free undo lists attached to each history entry prior to the - current entry, inclusive, reverting each line to its saved state. This - is destructive, and state about the current line is lost. This is not - intended to be called while actively editing, and the current line is - not assumed to have been added to the history list. */ -void -_rl_revert_all_lines () -{ - int hpos; - HIST_ENTRY *entry; - UNDO_LIST *ul, *saved_undo_list; - char *lbuf; - - lbuf = savestring (rl_line_buffer); - saved_undo_list = rl_undo_list; - hpos = where_history (); - - entry = (hpos == history_length) ? previous_history () : current_history (); - while (entry) - { - if (ul = (UNDO_LIST *)entry->data) - { - if (ul == saved_undo_list) - saved_undo_list = 0; - /* Set up rl_line_buffer and other variables from history entry */ - rl_replace_from_history (entry, 0); /* entry->line is now current */ -/* entry->data = 0; /* entry->data is now current undo list */ - /* Undo all changes to this history entry */ - while (rl_undo_list) - rl_do_undo (); - /* And copy the reverted line back to the history entry, preserving - the timestamp. */ - FREE (entry->line); - entry->line = savestring (rl_line_buffer); - entry->data = 0; - } - entry = previous_history (); - } - - /* Restore history state */ - rl_undo_list = saved_undo_list; /* may have been set to null */ - history_set_pos (hpos); - - /* reset the line buffer */ - rl_replace_line (lbuf, 0); - _rl_set_the_line (); - - /* and clean up */ - xfree (lbuf); -} - -/* Free the history list, including private readline data and take care - of pointer aliases to history data. Resets rl_undo_list if it points - to an UNDO_LIST * saved as some history entry's data member. This - should not be called while editing is active. */ -void -rl_clear_history () -{ - HIST_ENTRY **hlist, *hent; - register int i; - UNDO_LIST *ul, *saved_undo_list; - - saved_undo_list = rl_undo_list; - hlist = history_list (); /* direct pointer, not copy */ - - for (i = 0; i < history_length; i++) - { - hent = hlist[i]; - if (ul = (UNDO_LIST *)hent->data) - { - if (ul == saved_undo_list) - saved_undo_list = 0; - _rl_free_undo_list (ul); - hent->data = 0; - } - _rl_free_history_entry (hent); - } - - history_offset = history_length = 0; - rl_undo_list = saved_undo_list; /* should be NULL */ -} - -/* **************************************************************** */ -/* */ -/* History Commands */ -/* */ -/* **************************************************************** */ - -/* Meta-< goes to the start of the history. */ -int -rl_beginning_of_history (count, key) - int count, key; -{ - return (rl_get_previous_history (1 + where_history (), key)); -} - -/* Meta-> goes to the end of the history. (The current line). */ -int -rl_end_of_history (count, key) - int count, key; -{ - rl_maybe_replace_line (); - using_history (); - rl_maybe_unsave_line (); - return 0; -} - -/* Move down to the next history line. */ -int -rl_get_next_history (count, key) - int count, key; -{ - HIST_ENTRY *temp; - - if (count < 0) - return (rl_get_previous_history (-count, key)); - - if (count == 0) - return 0; - - rl_maybe_replace_line (); - - /* either not saved by rl_newline or at end of line, so set appropriately. */ - if (_rl_history_saved_point == -1 && (rl_point || rl_end)) - _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; - - temp = (HIST_ENTRY *)NULL; - while (count) - { - temp = next_history (); - if (!temp) - break; - --count; - } - - if (temp == 0) - rl_maybe_unsave_line (); - else - { - rl_replace_from_history (temp, 0); - _rl_history_set_point (); - } - return 0; -} - -/* Get the previous item out of our interactive history, making it the current - line. If there is no previous history, just ding. */ -int -rl_get_previous_history (count, key) - int count, key; -{ - HIST_ENTRY *old_temp, *temp; - - if (count < 0) - return (rl_get_next_history (-count, key)); - - if (count == 0) - return 0; - - /* either not saved by rl_newline or at end of line, so set appropriately. */ - if (_rl_history_saved_point == -1 && (rl_point || rl_end)) - _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; - - /* If we don't have a line saved, then save this one. */ - rl_maybe_save_line (); - - /* If the current line has changed, save the changes. */ - rl_maybe_replace_line (); - - temp = old_temp = (HIST_ENTRY *)NULL; - while (count) - { - temp = previous_history (); - if (temp == 0) - break; - - old_temp = temp; - --count; - } - - /* If there was a large argument, and we moved back to the start of the - history, that is not an error. So use the last value found. */ - if (!temp && old_temp) - temp = old_temp; - - if (temp == 0) - rl_ding (); - else - { - rl_replace_from_history (temp, 0); - _rl_history_set_point (); - } - - return 0; -} - -/* **************************************************************** */ -/* */ -/* Editing Modes */ -/* */ -/* **************************************************************** */ -/* How to toggle back and forth between editing modes. */ -int -rl_vi_editing_mode (count, key) - int count, key; -{ -#if defined (VI_MODE) - _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */ - rl_editing_mode = vi_mode; - rl_vi_insert_mode (1, key); -#endif /* VI_MODE */ - - return 0; -} - -int -rl_emacs_editing_mode (count, key) - int count, key; -{ - rl_editing_mode = emacs_mode; - _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */ - _rl_keymap = emacs_standard_keymap; - - if (_rl_show_mode_in_prompt) - _rl_reset_prompt (); - - return 0; -} - -/* Function for the rest of the library to use to set insert/overwrite mode. */ -void -_rl_set_insert_mode (im, force) - int im, force; -{ -#ifdef CURSOR_MODE - _rl_set_cursor (im, force); -#endif - - rl_insert_mode = im; -} - -/* Toggle overwrite mode. A positive explicit argument selects overwrite - mode. A negative or zero explicit argument selects insert mode. */ -int -rl_overwrite_mode (count, key) - int count, key; -{ - if (rl_explicit_arg == 0) - _rl_set_insert_mode (rl_insert_mode ^ 1, 0); - else if (count > 0) - _rl_set_insert_mode (RL_IM_OVERWRITE, 0); - else - _rl_set_insert_mode (RL_IM_INSERT, 0); - - return 0; -} diff --git a/lib/sh/zgetline.c~ b/lib/sh/zgetline.c~ deleted file mode 100644 index b0135ff9..00000000 --- a/lib/sh/zgetline.c~ +++ /dev/null @@ -1,125 +0,0 @@ -/* zgetline - read a line of input from a specified file descriptor and return - a pointer to a newly-allocated buffer containing the data. */ - -/* Copyright (C) 2008,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 <http://www.gnu.org/licenses/>. -*/ - -#include <config.h> - -#include <sys/types.h> - -#if defined (HAVE_UNISTD_H) -# include <unistd.h> -#endif - -#include <errno.h> -#include "xmalloc.h" - -#if !defined (errno) -extern int errno; -#endif - -extern ssize_t zread __P((int, char *, size_t)); -extern ssize_t zreadc __P((int, char *)); -extern ssize_t zreadintr __P((int, char *, size_t)); -extern ssize_t zreadcintr __P((int, char *)); - -typedef ssize_t breadfunc_t __P((int, char *, size_t)); -typedef ssize_t creadfunc_t __P((int, char *)); - -/* Initial memory allocation for automatic growing buffer in zreadlinec */ -#define GET_LINE_INITIAL_ALLOCATION 16 - -/* Derived from GNU libc's getline. - The behavior is almost the same as getline. See man getline. - The differences are - (1) using file descriptor instead of FILE *; - (2) the order of arguments: the file descriptor comes first; - (3) the addition of a third argument, DELIM; sets the delimiter to - be something other than newline if desired. If setting DELIM, - the next argument should be 1; and - (4) the addition of a fourth argument, UNBUFFERED_READ; this argument - controls whether get_line uses buffering or not to get a byte data - from FD. get_line uses zreadc if UNBUFFERED_READ is zero; and - uses zread if UNBUFFERED_READ is non-zero. - - Returns number of bytes read or -1 on error. */ - -ssize_t -zgetline (fd, lineptr, n, delim, unbuffered_read) - int fd; - char **lineptr; - size_t *n; - int delim; - int unbuffered_read; -{ - int nr, retval; - char *line, c; - - if (lineptr == 0 || n == 0 || (*lineptr == 0 && *n != 0)) - return -1; - - nr = 0; - line = *lineptr; - - while (1) - { - retval = unbuffered_read ? zread (fd, &c, 1) : zreadc(fd, &c); - - if (retval <= 0) - { - if (line && nr > 0) - line[nr] = '\0'; - break; - } - - if (nr + 2 >= *n) - { - size_t new_size; - - new_size = (*n == 0) ? GET_LINE_INITIAL_ALLOCATION : *n * 2; - line = (*n >= new_size) ? NULL : xrealloc (*lineptr, new_size); - - if (line) - { - *lineptr = line; - *n = new_size; - } - else - { - if (*n > 0) - { - (*lineptr)[*n - 1] = '\0'; - nr = *n - 2; - } - break; - } - } - - line[nr] = c; - nr++; - - if (c == delim) - { - line[nr] = '\0'; - break; - } - } - - return nr - 1; -} diff --git a/pathexp.c~ b/pathexp.c~ deleted file mode 100644 index d7315e38..00000000 --- a/pathexp.c~ +++ /dev/null @@ -1,609 +0,0 @@ -/* pathexp.c -- The shell interface to the globbing library. */ - -/* Copyright (C) 1995-2014 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 <http://www.gnu.org/licenses/>. -*/ - -#include "config.h" - -#include "bashtypes.h" -#include <stdio.h> - -#if defined (HAVE_UNISTD_H) -# include <unistd.h> -#endif - -#include "bashansi.h" - -#include "shell.h" -#include "pathexp.h" -#include "flags.h" - -#include "shmbutil.h" -#include "bashintl.h" - -#include <glob/strmatch.h> - -static int glob_name_is_acceptable __P((const char *)); -static void ignore_globbed_names __P((char **, sh_ignore_func_t *)); -static char *split_ignorespec __P((char *, int *)); - -#if defined (USE_POSIX_GLOB_LIBRARY) -# include <glob.h> -typedef int posix_glob_errfunc_t __P((const char *, int)); -#else -# include <glob/glob.h> -#endif - -/* Control whether * matches .files in globbing. */ -int glob_dot_filenames; - -/* Control whether the extended globbing features are enabled. */ -int extended_glob = EXTGLOB_DEFAULT; - -/* Control enabling special handling of `**' */ -int glob_star = 0; - -/* Return nonzero if STRING has any unquoted special globbing chars in it. */ -int -unquoted_glob_pattern_p (string) - register char *string; -{ - register int c; - char *send; - int open; - - DECLARE_MBSTATE; - - open = 0; - send = string + strlen (string); - - while (c = *string++) - { - switch (c) - { - case '?': - case '*': - return (1); - - case '[': - open++; - continue; - - case ']': - if (open) - return (1); - continue; - - case '+': - case '@': - case '!': - if (*string == '(') /*)*/ - return (1); - continue; - - case CTLESC: - case '\\': - if (*string++ == '\0') - return (0); - } - - /* Advance one fewer byte than an entire multibyte character to - account for the auto-increment in the loop above. */ -#ifdef HANDLE_MULTIBYTE - string--; - ADVANCE_CHAR_P (string, send - string); - string++; -#else - ADVANCE_CHAR_P (string, send - string); -#endif - } - return (0); -} - -/* Return 1 if C is a character that is `special' in a POSIX ERE and needs to - be quoted to match itself. */ -static inline int -ere_char (c) - int c; -{ - switch (c) - { - case '.': - case '[': - case '\\': - case '(': - case ')': - case '*': - case '+': - case '?': - case '{': - case '|': - case '^': - case '$': - return 1; - default: - return 0; - } - return (0); -} - -int -glob_char_p (s) - const char *s; -{ - switch (*s) - { - case '*': - case '[': - case ']': - case '?': - case '\\': - return 1; - case '+': - case '@': - case '!': - if (s[1] == '(') /*(*/ - return 1; - break; - } - return 0; -} - -/* PATHNAME can contain characters prefixed by CTLESC; this indicates - that the character is to be quoted. We quote it here in the style - that the glob library recognizes. If flags includes QGLOB_CVTNULL, - we change quoted null strings (pathname[0] == CTLNUL) into empty - strings (pathname[0] == 0). If this is called after quote removal - is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote - removal has not been done (for example, before attempting to match a - pattern while executing a case statement), flags should include - QGLOB_CVTNULL. If flags includes QGLOB_FILENAME, appropriate quoting - to match a filename should be performed. QGLOB_REGEXP means we're - quoting for a Posix ERE (for [[ string =~ pat ]]) and that requires - some special handling. */ -char * -quote_string_for_globbing (pathname, qflags) - const char *pathname; - int qflags; -{ - char *temp; - register int i, j; - int brack, cclass, collsym, equiv, c, last_was_backslash; - - temp = (char *)xmalloc (2 * strlen (pathname) + 1); - - if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname)) - { - temp[0] = '\0'; - return temp; - } - - brack = cclass = collsym = equiv = last_was_backslash = 0; - for (i = j = 0; pathname[i]; i++) - { - /* Fix for CTLESC at the end of the string? */ - if (pathname[i] == CTLESC && pathname[i+1] == '\0') - { - temp[j++] = pathname[i++]; - break; - } - /* If we are parsing regexp, turn CTLESC CTLESC into CTLESC. It's not an - ERE special character, so we should just be able to pass it through. */ - else if ((qflags & QGLOB_REGEXP) && pathname[i] == CTLESC && pathname[i+1] == CTLESC) - { - i++; - temp[j++] = pathname[i]; - continue; - } - else if (pathname[i] == CTLESC) - { - if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/') - continue; - /* What to do if preceding char is backslash? */ - if (pathname[i+1] != CTLESC && (qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0) - continue; - temp[j++] = '\\'; - i++; - if (pathname[i] == '\0') - break; - } - else if ((qflags & QGLOB_REGEXP) && (i == 0 || pathname[i-1] != CTLESC) && pathname[i] == '[') /*]*/ - { - brack = 1; - temp[j++] = pathname[i++]; /* open bracket */ - c = pathname[i++]; /* c == char after open bracket */ - do - { - if (c == 0) - goto endpat; - else if (c == CTLESC) - { - /* skip c, check for EOS, let assignment at end of loop */ - /* pathname[i] == backslash-escaped character */ - if (pathname[i] == 0) - goto endpat; - temp[j++] = pathname[i++]; - } - else if (c == '[' && pathname[i] == ':') - { - temp[j++] = c; - temp[j++] = pathname[i++]; - cclass = 1; - } - else if (cclass && c == ':' && pathname[i] == ']') - { - temp[j++] = c; - temp[j++] = pathname[i++]; - cclass = 0; - } - else if (c == '[' && pathname[i] == '=') - { - temp[j++] = c; - temp[j++] = pathname[i++]; - if (pathname[i] == ']') - temp[j++] = pathname[i++]; /* right brack can be in equiv */ - equiv = 1; - } - else if (equiv && c == '=' && pathname[i] == ']') - { - temp[j++] = c; - temp[j++] = pathname[i++]; - equiv = 0; - } - else if (c == '[' && pathname[i] == '.') - { - temp[j++] = c; - temp[j++] = pathname[i++]; - if (pathname[i] == ']') - temp[j++] = pathname[i++]; /* right brack can be in collsym */ - collsym = 1; - } - else if (collsym && c == '.' && pathname[i] == ']') - { - temp[j++] = c; - temp[j++] = pathname[i++]; - collsym = 0; - } - else - temp[j++] = c; - } - while ((c = pathname[i++]) != ']'); - temp[j++] = c; /* closing right bracket */ - i--; /* increment will happen above in loop */ - continue; /* skip double assignment below */ - } - else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP) == 0) - { - /* XXX - if not quoting regexp, use backslash as quote char. Should - we just pass it through without treating it as special? That is - what ksh93 seems to do. */ - - /* If we want to pass through backslash unaltered, comment out these - lines. */ - temp[j++] = '\\'; - - i++; - if (pathname[i] == '\0') - break; - } - else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP)) - last_was_backslash = 1; - temp[j++] = pathname[i]; - } -endpat: - temp[j] = '\0'; - - return (temp); -} - -char * -quote_globbing_chars (string) - char *string; -{ - size_t slen; - char *temp, *s, *t, *send; - DECLARE_MBSTATE; - - slen = strlen (string); - send = string + slen; - - temp = (char *)xmalloc (slen * 2 + 1); - for (t = temp, s = string; *s; ) - { - if (glob_char_p (s)) - *t++ = '\\'; - - /* Copy a single (possibly multibyte) character from s to t, - incrementing both. */ - COPY_CHAR_P (t, s, send); - } - *t = '\0'; - return temp; -} - -/* Call the glob library to do globbing on PATHNAME. */ -char ** -shell_glob_filename (pathname) - const char *pathname; -{ -#if defined (USE_POSIX_GLOB_LIBRARY) - register int i; - char *temp, **results; - glob_t filenames; - int glob_flags; - - temp = quote_string_for_globbing (pathname, QGLOB_FILENAME); - - filenames.gl_offs = 0; - -# if defined (GLOB_PERIOD) - glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0; -# else - glob_flags = 0; -# endif /* !GLOB_PERIOD */ - - glob_flags |= (GLOB_ERR | GLOB_DOOFFS); - - i = glob (temp, glob_flags, (posix_glob_errfunc_t *)NULL, &filenames); - - free (temp); - - if (i == GLOB_NOSPACE || i == GLOB_ABORTED) - return ((char **)NULL); - else if (i == GLOB_NOMATCH) - filenames.gl_pathv = (char **)NULL; - else if (i != 0) /* other error codes not in POSIX.2 */ - filenames.gl_pathv = (char **)NULL; - - results = filenames.gl_pathv; - - if (results && ((GLOB_FAILED (results)) == 0)) - { - if (should_ignore_glob_matches ()) - ignore_glob_matches (results); - if (results && results[0]) - strvec_sort (results); - else - { - FREE (results); - results = (char **)NULL; - } - } - - return (results); - -#else /* !USE_POSIX_GLOB_LIBRARY */ - - char *temp, **results; - - noglob_dot_filenames = glob_dot_filenames == 0; - - temp = quote_string_for_globbing (pathname, QGLOB_FILENAME); - results = glob_filename (temp, glob_star ? GX_GLOBSTAR : 0); - free (temp); - - if (results && ((GLOB_FAILED (results)) == 0)) - { - if (should_ignore_glob_matches ()) - ignore_glob_matches (results); - if (results && results[0]) - strvec_sort (results); - else - { - FREE (results); - results = (char **)&glob_error_return; - } - } - - return (results); -#endif /* !USE_POSIX_GLOB_LIBRARY */ -} - -/* Stuff for GLOBIGNORE. */ - -static struct ignorevar globignore = -{ - "GLOBIGNORE", - (struct ign *)0, - 0, - (char *)0, - (sh_iv_item_func_t *)0, -}; - -/* Set up to ignore some glob matches because the value of GLOBIGNORE - has changed. If GLOBIGNORE is being unset, we also need to disable - the globbing of filenames beginning with a `.'. */ -void -setup_glob_ignore (name) - char *name; -{ - char *v; - - v = get_string_value (name); - setup_ignore_patterns (&globignore); - - if (globignore.num_ignores) - glob_dot_filenames = 1; - else if (v == 0) - glob_dot_filenames = 0; -} - -int -should_ignore_glob_matches () -{ - return globignore.num_ignores; -} - -/* Return 0 if NAME matches a pattern in the globignore.ignores list. */ -static int -glob_name_is_acceptable (name) - const char *name; -{ - struct ign *p; - int flags; - - /* . and .. are never matched */ - if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) - return (0); - - flags = FNM_PATHNAME | FNMATCH_EXTFLAG; - for (p = globignore.ignores; p->val; p++) - { - if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH) - return (0); - } - return (1); -} - -/* Internal function to test whether filenames in NAMES should be - ignored. NAME_FUNC is a pointer to a function to call with each - name. It returns non-zero if the name is acceptable to the particular - ignore function which called _ignore_names; zero if the name should - be removed from NAMES. */ - -static void -ignore_globbed_names (names, name_func) - char **names; - sh_ignore_func_t *name_func; -{ - char **newnames; - int n, i; - - for (i = 0; names[i]; i++) - ; - newnames = strvec_create (i + 1); - - for (n = i = 0; names[i]; i++) - { - if ((*name_func) (names[i])) - newnames[n++] = names[i]; - else - free (names[i]); - } - - newnames[n] = (char *)NULL; - - if (n == 0) - { - names[0] = (char *)NULL; - free (newnames); - return; - } - - /* Copy the acceptable names from NEWNAMES back to NAMES and set the - new array end. */ - for (n = 0; newnames[n]; n++) - names[n] = newnames[n]; - names[n] = (char *)NULL; - free (newnames); -} - -void -ignore_glob_matches (names) - char **names; -{ - if (globignore.num_ignores == 0) - return; - - ignore_globbed_names (names, glob_name_is_acceptable); -} - -static char * -split_ignorespec (s, ip) - char *s; - int *ip; -{ - char *t; - int n, i; - - if (s == 0) - return 0; - - i = *ip; - if (s[i] == 0) - return 0; - - n = skip_to_delim (s, i, ":", SD_NOJMP|SD_EXTGLOB); - t = substring (s, i, n); - - if (s[n] == ':') - n++; - *ip = n; - return t; -} - -void -setup_ignore_patterns (ivp) - struct ignorevar *ivp; -{ - int numitems, maxitems, ptr; - char *colon_bit, *this_ignoreval; - struct ign *p; - - this_ignoreval = get_string_value (ivp->varname); - - /* If nothing has changed then just exit now. */ - if ((this_ignoreval && ivp->last_ignoreval && STREQ (this_ignoreval, ivp->last_ignoreval)) || - (!this_ignoreval && !ivp->last_ignoreval)) - return; - - /* Oops. The ignore variable has changed. Re-parse it. */ - ivp->num_ignores = 0; - - if (ivp->ignores) - { - for (p = ivp->ignores; p->val; p++) - free(p->val); - free (ivp->ignores); - ivp->ignores = (struct ign *)NULL; - } - - if (ivp->last_ignoreval) - { - free (ivp->last_ignoreval); - ivp->last_ignoreval = (char *)NULL; - } - - if (this_ignoreval == 0 || *this_ignoreval == '\0') - return; - - ivp->last_ignoreval = savestring (this_ignoreval); - - numitems = maxitems = ptr = 0; - -#if 0 - while (colon_bit = extract_colon_unit (this_ignoreval, &ptr)) -#else - while (colon_bit = split_ignorespec (this_ignoreval, &ptr)) -#endif - { - if (numitems + 1 >= maxitems) - { - maxitems += 10; - ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign)); - } - ivp->ignores[numitems].val = colon_bit; - ivp->ignores[numitems].len = strlen (colon_bit); - ivp->ignores[numitems].flags = 0; - if (ivp->item_func) - (*ivp->item_func) (&ivp->ignores[numitems]); - numitems++; - } - ivp->ignores[numitems].val = (char *)NULL; - ivp->num_ignores = numitems; -} diff --git a/subst.c~ b/subst.c~ deleted file mode 100644 index 1e61fb44..00000000 --- a/subst.c~ +++ /dev/null @@ -1,9817 +0,0 @@ -/* subst.c -- The part of the shell that does parameter, command, arithmetic, - and globbing substitutions. */ - -/* ``Have a little faith, there's magic in the night. You ain't a - beauty, but, hey, you're alright.'' */ - -/* Copyright (C) 1987-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 <http://www.gnu.org/licenses/>. -*/ - -#include "config.h" - -#include "bashtypes.h" -#include <stdio.h> -#include "chartypes.h" -#if defined (HAVE_PWD_H) -# include <pwd.h> -#endif -#include <signal.h> -#include <errno.h> - -#if defined (HAVE_UNISTD_H) -# include <unistd.h> -#endif - -#include "bashansi.h" -#include "posixstat.h" -#include "bashintl.h" - -#include "shell.h" -#include "parser.h" -#include "flags.h" -#include "jobs.h" -#include "execute_cmd.h" -#include "filecntl.h" -#include "trap.h" -#include "pathexp.h" -#include "mailcheck.h" - -#include "shmbutil.h" -#include "typemax.h" - -#include "builtins/getopt.h" -#include "builtins/common.h" - -#include "builtins/builtext.h" - -#include <tilde/tilde.h> -#include <glob/strmatch.h> - -#if !defined (errno) -extern int errno; -#endif /* !errno */ - -/* The size that strings change by. */ -#define DEFAULT_INITIAL_ARRAY_SIZE 112 -#define DEFAULT_ARRAY_SIZE 128 - -/* Variable types. */ -#define VT_VARIABLE 0 -#define VT_POSPARMS 1 -#define VT_ARRAYVAR 2 -#define VT_ARRAYMEMBER 3 -#define VT_ASSOCVAR 4 - -#define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */ - -/* Flags for quoted_strchr */ -#define ST_BACKSL 0x01 -#define ST_CTLESC 0x02 -#define ST_SQUOTE 0x04 /* unused yet */ -#define ST_DQUOTE 0x08 /* unused yet */ - -/* Flags for the `pflags' argument to param_expand() */ -#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */ -#define PF_IGNUNBOUND 0x02 /* ignore unbound vars even if -u set */ -#define PF_NOSPLIT2 0x04 /* same as W_NOSPLIT2 */ -#define PF_ASSIGNRHS 0x08 /* same as W_ASSIGNRHS */ - -/* These defs make it easier to use the editor. */ -#define LBRACE '{' -#define RBRACE '}' -#define LPAREN '(' -#define RPAREN ')' -#define LBRACK '[' -#define RBRACK ']' - -#if defined (HANDLE_MULTIBYTE) -#define WLPAREN L'(' -#define WRPAREN L')' -#endif - -/* Evaluates to 1 if C is one of the shell's special parameters whose length - can be taken, but is also one of the special expansion characters. */ -#define VALID_SPECIAL_LENGTH_PARAM(c) \ - ((c) == '-' || (c) == '?' || (c) == '#') - -/* Evaluates to 1 if C is one of the shell's special parameters for which an - indirect variable reference may be made. */ -#define VALID_INDIR_PARAM(c) \ - ((posixly_correct == 0 && (c) == '#') || (posixly_correct == 0 && (c) == '?') || (c) == '@' || (c) == '*') - -/* Evaluates to 1 if C is one of the OP characters that follows the parameter - in ${parameter[:]OPword}. */ -#define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP) - -/* Evaluates to 1 if this is one of the shell's special variables. */ -#define SPECIAL_VAR(name, wi) \ - ((DIGIT (*name) && all_digits (name)) || \ - (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \ - (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1]))) - -/* An expansion function that takes a string and a quoted flag and returns - a WORD_LIST *. Used as the type of the third argument to - expand_string_if_necessary(). */ -typedef WORD_LIST *EXPFUNC __P((char *, int)); - -/* Process ID of the last command executed within command substitution. */ -pid_t last_command_subst_pid = NO_PID; -pid_t current_command_subst_pid = NO_PID; - -/* Variables used to keep track of the characters in IFS. */ -SHELL_VAR *ifs_var; -char *ifs_value; -unsigned char ifs_cmap[UCHAR_MAX + 1]; -int ifs_is_set, ifs_is_null; - -#if defined (HANDLE_MULTIBYTE) -unsigned char ifs_firstc[MB_LEN_MAX]; -size_t ifs_firstc_len; -#else -unsigned char ifs_firstc; -#endif - -/* Sentinel to tell when we are performing variable assignments preceding a - command name and putting them into the environment. Used to make sure - we use the temporary environment when looking up variable values. */ -int assigning_in_environment; - -/* Used to hold a list of variable assignments preceding a command. Global - so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a - SIGCHLD trap and so it can be saved and restored by the trap handlers. */ -WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL; - -/* Extern functions and variables from different files. */ -extern int last_command_exit_value, last_command_exit_signal; -extern int subshell_environment, line_number; -extern int subshell_level, parse_and_execute_level, sourcelevel; -extern int eof_encountered; -extern int return_catch_flag, return_catch_value; -extern pid_t dollar_dollar_pid; -extern int posixly_correct; -extern char *this_command_name; -extern struct fd_bitmap *current_fds_to_close; -extern int wordexp_only; -extern int expanding_redir; -extern int tempenv_assign_error; -extern int builtin_ignoring_errexit; - -#if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE) -extern wchar_t *wcsdup __P((const wchar_t *)); -#endif - -/* Non-zero means to allow unmatched globbed filenames to expand to - a null file. */ -int allow_null_glob_expansion; - -/* Non-zero means to throw an error when globbing fails to match anything. */ -int fail_glob_expansion; - -#if 0 -/* Variables to keep track of which words in an expanded word list (the - output of expand_word_list_internal) are the result of globbing - expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c. - (CURRENTLY UNUSED). */ -char *glob_argv_flags; -static int glob_argv_flags_size; -#endif - -static WORD_LIST expand_word_error, expand_word_fatal; -static WORD_DESC expand_wdesc_error, expand_wdesc_fatal; -static char expand_param_error, expand_param_fatal; -static char extract_string_error, extract_string_fatal; - -/* Tell the expansion functions to not longjmp back to top_level on fatal - errors. Enabled when doing completion and prompt string expansion. */ -static int no_longjmp_on_fatal_error = 0; - -/* Set by expand_word_unsplit; used to inhibit splitting and re-joining - $* on $IFS, primarily when doing assignment statements. */ -static int expand_no_split_dollar_star = 0; - -/* A WORD_LIST of words to be expanded by expand_word_list_internal, - without any leading variable assignments. */ -static WORD_LIST *garglist = (WORD_LIST *)NULL; - -static char *quoted_substring __P((char *, int, int)); -static int quoted_strlen __P((char *)); -static char *quoted_strchr __P((char *, int, int)); - -static char *expand_string_if_necessary __P((char *, int, EXPFUNC *)); -static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *)); -static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *)); -static WORD_LIST *expand_string_internal __P((char *, int)); -static WORD_LIST *expand_string_leave_quoted __P((char *, int)); -static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *)); - -static WORD_LIST *list_quote_escapes __P((WORD_LIST *)); -static WORD_LIST *list_dequote_escapes __P((WORD_LIST *)); - -static char *make_quoted_char __P((int)); -static WORD_LIST *quote_list __P((WORD_LIST *)); - -static int unquoted_substring __P((char *, char *)); -static int unquoted_member __P((int, char *)); - -#if defined (ARRAY_VARS) -static SHELL_VAR *do_compound_assignment __P((char *, char *, int)); -#endif -static int do_assignment_internal __P((const WORD_DESC *, int)); - -static char *string_extract_verbatim __P((char *, size_t, int *, char *, int)); -static char *string_extract __P((char *, int *, char *, int)); -static char *string_extract_double_quoted __P((char *, int *, int)); -static inline char *string_extract_single_quoted __P((char *, int *)); -static inline int skip_single_quoted __P((const char *, size_t, int)); -static int skip_double_quoted __P((char *, size_t, int)); -static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int)); -static char *extract_dollar_brace_string __P((char *, int *, int, int)); -static int skip_matched_pair __P((const char *, int, int, int, int)); - -static char *pos_params __P((char *, int, int, int)); - -static unsigned char *mb_getcharlens __P((char *, int)); - -static char *remove_upattern __P((char *, char *, int)); -#if defined (HANDLE_MULTIBYTE) -static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int)); -#endif -static char *remove_pattern __P((char *, char *, int)); - -static int match_upattern __P((char *, char *, int, char **, char **)); -#if defined (HANDLE_MULTIBYTE) -static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **)); -#endif -static int match_pattern __P((char *, char *, int, char **, char **)); -static int getpatspec __P((int, char *)); -static char *getpattern __P((char *, int, int)); -static char *variable_remove_pattern __P((char *, char *, int, int)); -static char *list_remove_pattern __P((WORD_LIST *, char *, int, int, int)); -static char *parameter_list_remove_pattern __P((int, char *, int, int)); -#ifdef ARRAY_VARS -static char *array_remove_pattern __P((SHELL_VAR *, char *, int, char *, int)); -#endif -static char *parameter_brace_remove_pattern __P((char *, char *, int, char *, int, int, int)); - -static char *process_substitute __P((char *, int)); - -static char *read_comsub __P((int, int, int *)); - -#ifdef ARRAY_VARS -static arrayind_t array_length_reference __P((char *)); -#endif - -static int valid_brace_expansion_word __P((char *, int)); -static int chk_atstar __P((char *, int, int *, int *)); -static int chk_arithsub __P((const char *, int)); - -static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int, arrayind_t *)); -static char *parameter_brace_find_indir __P((char *, int, int, int)); -static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *)); -static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *)); -static void parameter_brace_expand_error __P((char *, char *)); - -static int valid_length_expression __P((char *)); -static intmax_t parameter_brace_expand_length __P((char *)); - -static char *skiparith __P((char *, int)); -static int verify_substring_values __P((SHELL_VAR *, char *, char *, int, intmax_t *, intmax_t *)); -static int get_var_and_type __P((char *, char *, arrayind_t, int, int, SHELL_VAR **, char **)); -static char *mb_substring __P((char *, int, int)); -static char *parameter_brace_substring __P((char *, char *, int, char *, int, int)); - -static int shouldexp_replacement __P((char *)); - -static char *pos_params_pat_subst __P((char *, char *, char *, int)); - -static char *parameter_brace_patsub __P((char *, char *, int, char *, int, int)); - -static char *pos_params_casemod __P((char *, char *, int, int)); -static char *parameter_brace_casemod __P((char *, char *, int, int, char *, int, int)); - -static WORD_DESC *parameter_brace_expand __P((char *, int *, int, int, int *, int *)); -static WORD_DESC *param_expand __P((char *, int *, int, int *, int *, int *, int *, int)); - -static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *)); - -static WORD_LIST *word_list_split __P((WORD_LIST *)); - -static void exp_jump_to_top_level __P((int)); - -static WORD_LIST *separate_out_assignments __P((WORD_LIST *)); -static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int)); -#ifdef BRACE_EXPANSION -static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int)); -#endif -#if defined (ARRAY_VARS) -static int make_internal_declare __P((char *, char *)); -#endif -static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int)); -static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int)); - -/* **************************************************************** */ -/* */ -/* Utility Functions */ -/* */ -/* **************************************************************** */ - -#if defined (DEBUG) -void -dump_word_flags (flags) - int flags; -{ - int f; - - f = flags; - fprintf (stderr, "%d -> ", f); - if (f & W_ASSIGNASSOC) - { - f &= ~W_ASSIGNASSOC; - fprintf (stderr, "W_ASSIGNASSOC%s", f ? "|" : ""); - } - if (f & W_ASSIGNARRAY) - { - f &= ~W_ASSIGNARRAY; - fprintf (stderr, "W_ASSIGNARRAY%s", f ? "|" : ""); - } - if (f & W_HASCTLESC) - { - f &= ~W_HASCTLESC; - fprintf (stderr, "W_HASCTLESC%s", f ? "|" : ""); - } - if (f & W_NOPROCSUB) - { - f &= ~W_NOPROCSUB; - fprintf (stderr, "W_NOPROCSUB%s", f ? "|" : ""); - } - if (f & W_DQUOTE) - { - f &= ~W_DQUOTE; - fprintf (stderr, "W_DQUOTE%s", f ? "|" : ""); - } - if (f & W_HASQUOTEDNULL) - { - f &= ~W_HASQUOTEDNULL; - fprintf (stderr, "W_HASQUOTEDNULL%s", f ? "|" : ""); - } - if (f & W_ASSIGNARG) - { - f &= ~W_ASSIGNARG; - fprintf (stderr, "W_ASSIGNARG%s", f ? "|" : ""); - } - if (f & W_ASSNBLTIN) - { - f &= ~W_ASSNBLTIN; - fprintf (stderr, "W_ASSNBLTIN%s", f ? "|" : ""); - } - if (f & W_ASSNGLOBAL) - { - f &= ~W_ASSNGLOBAL; - fprintf (stderr, "W_ASSNGLOBAL%s", f ? "|" : ""); - } - if (f & W_ASSIGNINT) - { - f &= ~W_ASSIGNINT; - fprintf (stderr, "W_ASSIGNINT%s", f ? "|" : ""); - } - if (f & W_COMPASSIGN) - { - f &= ~W_COMPASSIGN; - fprintf (stderr, "W_COMPASSIGN%s", f ? "|" : ""); - } - if (f & W_NOEXPAND) - { - f &= ~W_NOEXPAND; - fprintf (stderr, "W_NOEXPAND%s", f ? "|" : ""); - } - if (f & W_ITILDE) - { - f &= ~W_ITILDE; - fprintf (stderr, "W_ITILDE%s", f ? "|" : ""); - } - if (f & W_NOTILDE) - { - f &= ~W_NOTILDE; - fprintf (stderr, "W_NOTILDE%s", f ? "|" : ""); - } - if (f & W_ASSIGNRHS) - { - f &= ~W_ASSIGNRHS; - fprintf (stderr, "W_ASSIGNRHS%s", f ? "|" : ""); - } - if (f & W_NOCOMSUB) - { - f &= ~W_NOCOMSUB; - fprintf (stderr, "W_NOCOMSUB%s", f ? "|" : ""); - } - if (f & W_DOLLARSTAR) - { - f &= ~W_DOLLARSTAR; - fprintf (stderr, "W_DOLLARSTAR%s", f ? "|" : ""); - } - if (f & W_DOLLARAT) - { - f &= ~W_DOLLARAT; - fprintf (stderr, "W_DOLLARAT%s", f ? "|" : ""); - } - if (f & W_TILDEEXP) - { - f &= ~W_TILDEEXP; - fprintf (stderr, "W_TILDEEXP%s", f ? "|" : ""); - } - if (f & W_NOSPLIT2) - { - f &= ~W_NOSPLIT2; - fprintf (stderr, "W_NOSPLIT2%s", f ? "|" : ""); - } - if (f & W_NOSPLIT) - { - f &= ~W_NOSPLIT; - fprintf (stderr, "W_NOSPLIT%s", f ? "|" : ""); - } - if (f & W_NOBRACE) - { - f &= ~W_NOBRACE; - fprintf (stderr, "W_NOBRACE%s", f ? "|" : ""); - } - if (f & W_NOGLOB) - { - f &= ~W_NOGLOB; - fprintf (stderr, "W_NOGLOB%s", f ? "|" : ""); - } - if (f & W_SPLITSPACE) - { - f &= ~W_SPLITSPACE; - fprintf (stderr, "W_SPLITSPACE%s", f ? "|" : ""); - } - if (f & W_ASSIGNMENT) - { - f &= ~W_ASSIGNMENT; - fprintf (stderr, "W_ASSIGNMENT%s", f ? "|" : ""); - } - if (f & W_QUOTED) - { - f &= ~W_QUOTED; - fprintf (stderr, "W_QUOTED%s", f ? "|" : ""); - } - if (f & W_HASDOLLAR) - { - f &= ~W_HASDOLLAR; - fprintf (stderr, "W_HASDOLLAR%s", f ? "|" : ""); - } - fprintf (stderr, "\n"); - fflush (stderr); -} -#endif - -#ifdef INCLUDE_UNUSED -static char * -quoted_substring (string, start, end) - char *string; - int start, end; -{ - register int len, l; - register char *result, *s, *r; - - len = end - start; - - /* Move to string[start], skipping quoted characters. */ - for (s = string, l = 0; *s && l < start; ) - { - if (*s == CTLESC) - { - s++; - continue; - } - l++; - if (*s == 0) - break; - } - - r = result = (char *)xmalloc (2*len + 1); /* save room for quotes */ - - /* Copy LEN characters, including quote characters. */ - s = string + l; - for (l = 0; l < len; s++) - { - if (*s == CTLESC) - *r++ = *s++; - *r++ = *s; - l++; - if (*s == 0) - break; - } - *r = '\0'; - return result; -} -#endif - -#ifdef INCLUDE_UNUSED -/* Return the length of S, skipping over quoted characters */ -static int -quoted_strlen (s) - char *s; -{ - register char *p; - int i; - - i = 0; - for (p = s; *p; p++) - { - if (*p == CTLESC) - { - p++; - if (*p == 0) - return (i + 1); - } - i++; - } - - return i; -} -#endif - -/* Find the first occurrence of character C in string S, obeying shell - quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped - characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters - escaped with CTLESC are skipped. */ -static char * -quoted_strchr (s, c, flags) - char *s; - int c, flags; -{ - register char *p; - - for (p = s; *p; p++) - { - if (((flags & ST_BACKSL) && *p == '\\') - || ((flags & ST_CTLESC) && *p == CTLESC)) - { - p++; - if (*p == '\0') - return ((char *)NULL); - continue; - } - else if (*p == c) - return p; - } - return ((char *)NULL); -} - -/* Return 1 if CHARACTER appears in an unquoted portion of - STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */ -static int -unquoted_member (character, string) - int character; - char *string; -{ - size_t slen; - int sindex, c; - DECLARE_MBSTATE; - - slen = strlen (string); - sindex = 0; - while (c = string[sindex]) - { - if (c == character) - return (1); - - switch (c) - { - default: - ADVANCE_CHAR (string, slen, sindex); - break; - - case '\\': - sindex++; - if (string[sindex]) - ADVANCE_CHAR (string, slen, sindex); - break; - - case '\'': - sindex = skip_single_quoted (string, slen, ++sindex); - break; - - case '"': - sindex = skip_double_quoted (string, slen, ++sindex); - break; - } - } - return (0); -} - -/* Return 1 if SUBSTR appears in an unquoted portion of STRING. */ -static int -unquoted_substring (substr, string) - char *substr, *string; -{ - size_t slen; - int sindex, c, sublen; - DECLARE_MBSTATE; - - if (substr == 0 || *substr == '\0') - return (0); - - slen = strlen (string); - sublen = strlen (substr); - for (sindex = 0; c = string[sindex]; ) - { - if (STREQN (string + sindex, substr, sublen)) - return (1); - - switch (c) - { - case '\\': - sindex++; - if (string[sindex]) - ADVANCE_CHAR (string, slen, sindex); - break; - - case '\'': - sindex = skip_single_quoted (string, slen, ++sindex); - break; - - case '"': - sindex = skip_double_quoted (string, slen, ++sindex); - break; - - default: - ADVANCE_CHAR (string, slen, sindex); - break; - } - } - return (0); -} - -/* Most of the substitutions must be done in parallel. In order - to avoid using tons of unclear goto's, I have some functions - for manipulating malloc'ed strings. They all take INDX, a - pointer to an integer which is the offset into the string - where manipulation is taking place. They also take SIZE, a - pointer to an integer which is the current length of the - character array for this string. */ - -/* Append SOURCE to TARGET at INDEX. SIZE is the current amount - of space allocated to TARGET. SOURCE can be NULL, in which - case nothing happens. Gets rid of SOURCE by freeing it. - Returns TARGET in case the location has changed. */ -INLINE char * -sub_append_string (source, target, indx, size) - char *source, *target; - int *indx, *size; -{ - if (source) - { - int srclen, n; - - srclen = STRLEN (source); - if (srclen >= (int)(*size - *indx)) - { - n = srclen + *indx; - n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE); - target = (char *)xrealloc (target, (*size = n)); - } - - FASTCOPY (source, target + *indx, srclen); - *indx += srclen; - target[*indx] = '\0'; - - free (source); - } - return (target); -} - -#if 0 -/* UNUSED */ -/* Append the textual representation of NUMBER to TARGET. - INDX and SIZE are as in SUB_APPEND_STRING. */ -char * -sub_append_number (number, target, indx, size) - intmax_t number; - int *indx, *size; - char *target; -{ - char *temp; - - temp = itos (number); - return (sub_append_string (temp, target, indx, size)); -} -#endif - -/* Extract a substring from STRING, starting at SINDEX and ending with - one of the characters in CHARLIST. Don't make the ending character - part of the string. Leave SINDEX pointing at the ending character. - Understand about backslashes in the string. If (flags & SX_VARNAME) - is non-zero, and array variables have been compiled into the shell, - everything between a `[' and a corresponding `]' is skipped over. - If (flags & SX_NOALLOC) is non-zero, don't return the substring, just - update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must - contain a closing character from CHARLIST. */ -static char * -string_extract (string, sindex, charlist, flags) - char *string; - int *sindex; - char *charlist; - int flags; -{ - register int c, i; - int found; - size_t slen; - char *temp; - DECLARE_MBSTATE; - - slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0; - i = *sindex; - found = 0; - while (c = string[i]) - { - if (c == '\\') - { - if (string[i + 1]) - i++; - else - break; - } -#if defined (ARRAY_VARS) - else if ((flags & SX_VARNAME) && c == '[') - { - int ni; - /* If this is an array subscript, skip over it and continue. */ - ni = skipsubscript (string, i, 0); - if (string[ni] == ']') - i = ni; - } -#endif - else if (MEMBER (c, charlist)) - { - found = 1; - break; - } - - ADVANCE_CHAR (string, slen, i); - } - - /* If we had to have a matching delimiter and didn't find one, return an - error and let the caller deal with it. */ - if ((flags & SX_REQMATCH) && found == 0) - { - *sindex = i; - return (&extract_string_error); - } - - temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i); - *sindex = i; - - return (temp); -} - -/* Extract the contents of STRING as if it is enclosed in double quotes. - SINDEX, when passed in, is the offset of the character immediately - following the opening double quote; on exit, SINDEX is left pointing after - the closing double quote. If STRIPDQ is non-zero, unquoted double - quotes are stripped and the string is terminated by a null byte. - Backslashes between the embedded double quotes are processed. If STRIPDQ - is zero, an unquoted `"' terminates the string. */ -static char * -string_extract_double_quoted (string, sindex, stripdq) - char *string; - int *sindex, stripdq; -{ - size_t slen; - char *send; - int j, i, t; - unsigned char c; - char *temp, *ret; /* The new string we return. */ - int pass_next, backquote, si; /* State variables for the machine. */ - int dquote; - DECLARE_MBSTATE; - - slen = strlen (string + *sindex) + *sindex; - send = string + slen; - - pass_next = backquote = dquote = 0; - temp = (char *)xmalloc (1 + slen - *sindex); - - j = 0; - i = *sindex; - while (c = string[i]) - { - /* Process a character that was quoted by a backslash. */ - if (pass_next) - { - /* XXX - take another look at this in light of Interp 221 */ - /* Posix.2 sez: - - ``The backslash shall retain its special meaning as an escape - character only when followed by one of the characters: - $ ` " \ <newline>''. - - If STRIPDQ is zero, we handle the double quotes here and let - expand_word_internal handle the rest. If STRIPDQ is non-zero, - we have already been through one round of backslash stripping, - and want to strip these backslashes only if DQUOTE is non-zero, - indicating that we are inside an embedded double-quoted string. */ - - /* If we are in an embedded quoted string, then don't strip - backslashes before characters for which the backslash - retains its special meaning, but remove backslashes in - front of other characters. If we are not in an - embedded quoted string, don't strip backslashes at all. - This mess is necessary because the string was already - surrounded by double quotes (and sh has some really weird - quoting rules). - The returned string will be run through expansion as if - it were double-quoted. */ - if ((stripdq == 0 && c != '"') || - (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0))) - temp[j++] = '\\'; - pass_next = 0; - -add_one_character: - COPY_CHAR_I (temp, j, string, send, i); - continue; - } - - /* A backslash protects the next character. The code just above - handles preserving the backslash in front of any character but - a double quote. */ - if (c == '\\') - { - pass_next++; - i++; - continue; - } - - /* Inside backquotes, ``the portion of the quoted string from the - initial backquote and the characters up to the next backquote - that is not preceded by a backslash, having escape characters - removed, defines that command''. */ - if (backquote) - { - if (c == '`') - backquote = 0; - temp[j++] = c; - i++; - continue; - } - - if (c == '`') - { - temp[j++] = c; - backquote++; - i++; - continue; - } - - /* Pass everything between `$(' and the matching `)' or a quoted - ${ ... } pair through according to the Posix.2 specification. */ - if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE))) - { - int free_ret = 1; - - si = i + 2; - if (string[i + 1] == LPAREN) - ret = extract_command_subst (string, &si, 0); - else - ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, 0); - - temp[j++] = '$'; - temp[j++] = string[i + 1]; - - /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error - is set. */ - if (ret == 0 && no_longjmp_on_fatal_error) - { - free_ret = 0; - ret = string + i + 2; - } - - for (t = 0; ret[t]; t++, j++) - temp[j] = ret[t]; - temp[j] = string[si]; - - if (string[si]) - { - j++; - i = si + 1; - } - else - i = si; - - if (free_ret) - free (ret); - continue; - } - - /* Add any character but a double quote to the quoted string we're - accumulating. */ - if (c != '"') - goto add_one_character; - - /* c == '"' */ - if (stripdq) - { - dquote ^= 1; - i++; - continue; - } - - break; - } - temp[j] = '\0'; - - /* Point to after the closing quote. */ - if (c) - i++; - *sindex = i; - - return (temp); -} - -/* This should really be another option to string_extract_double_quoted. */ -static int -skip_double_quoted (string, slen, sind) - char *string; - size_t slen; - int sind; -{ - int c, i; - char *ret; - int pass_next, backquote, si; - DECLARE_MBSTATE; - - pass_next = backquote = 0; - i = sind; - while (c = string[i]) - { - if (pass_next) - { - pass_next = 0; - ADVANCE_CHAR (string, slen, i); - continue; - } - else if (c == '\\') - { - pass_next++; - i++; - continue; - } - else if (backquote) - { - if (c == '`') - backquote = 0; - ADVANCE_CHAR (string, slen, i); - continue; - } - else if (c == '`') - { - backquote++; - i++; - continue; - } - else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE))) - { - si = i + 2; - if (string[i + 1] == LPAREN) - ret = extract_command_subst (string, &si, SX_NOALLOC); - else - ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, SX_NOALLOC); - - i = si + 1; - continue; - } - else if (c != '"') - { - ADVANCE_CHAR (string, slen, i); - continue; - } - else - break; - } - - if (c) - i++; - - return (i); -} - -/* Extract the contents of STRING as if it is enclosed in single quotes. - SINDEX, when passed in, is the offset of the character immediately - following the opening single quote; on exit, SINDEX is left pointing after - the closing single quote. */ -static inline char * -string_extract_single_quoted (string, sindex) - char *string; - int *sindex; -{ - register int i; - size_t slen; - char *t; - DECLARE_MBSTATE; - - /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */ - slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0; - i = *sindex; - while (string[i] && string[i] != '\'') - ADVANCE_CHAR (string, slen, i); - - t = substring (string, *sindex, i); - - if (string[i]) - i++; - *sindex = i; - - return (t); -} - -static inline int -skip_single_quoted (string, slen, sind) - const char *string; - size_t slen; - int sind; -{ - register int c; - DECLARE_MBSTATE; - - c = sind; - while (string[c] && string[c] != '\'') - ADVANCE_CHAR (string, slen, c); - - if (string[c]) - c++; - return c; -} - -/* Just like string_extract, but doesn't hack backslashes or any of - that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */ -static char * -string_extract_verbatim (string, slen, sindex, charlist, flags) - char *string; - size_t slen; - int *sindex; - char *charlist; - int flags; -{ - register int i; -#if defined (HANDLE_MULTIBYTE) - size_t clen; - wchar_t *wcharlist; -#endif - int c; - char *temp; - DECLARE_MBSTATE; - - if (charlist[0] == '\'' && charlist[1] == '\0') - { - temp = string_extract_single_quoted (string, sindex); - --*sindex; /* leave *sindex at separator character */ - return temp; - } - - i = *sindex; -#if 0 - /* See how the MBLEN and ADVANCE_CHAR macros work to understand why we need - this only if MB_CUR_MAX > 1. */ - slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 1; -#endif -#if defined (HANDLE_MULTIBYTE) - clen = strlen (charlist); - wcharlist = 0; -#endif - while (c = string[i]) - { -#if defined (HANDLE_MULTIBYTE) - size_t mblength; -#endif - if ((flags & SX_NOCTLESC) == 0 && c == CTLESC) - { - i += 2; - continue; - } - /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL - through, to protect the CTLNULs from later calls to - remove_quoted_nulls. */ - else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL) - { - i += 2; - continue; - } - -#if defined (HANDLE_MULTIBYTE) - mblength = MBLEN (string + i, slen - i); - if (mblength > 1) - { - wchar_t wc; - mblength = mbtowc (&wc, string + i, slen - i); - if (MB_INVALIDCH (mblength)) - { - if (MEMBER (c, charlist)) - break; - } - else - { - if (wcharlist == 0) - { - size_t len; - len = mbstowcs (wcharlist, charlist, 0); - if (len == -1) - len = 0; - wcharlist = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1)); - mbstowcs (wcharlist, charlist, len + 1); - } - - if (wcschr (wcharlist, wc)) - break; - } - } - else -#endif - if (MEMBER (c, charlist)) - break; - - ADVANCE_CHAR (string, slen, i); - } - -#if defined (HANDLE_MULTIBYTE) - FREE (wcharlist); -#endif - - temp = substring (string, *sindex, i); - *sindex = i; - - return (temp); -} - -/* Extract the $( construct in STRING, and return a new string. - Start extracting at (SINDEX) as if we had just seen "$(". - Make (SINDEX) get the position of the matching ")". ) - XFLAGS is additional flags to pass to other extraction functions. */ -char * -extract_command_subst (string, sindex, xflags) - char *string; - int *sindex; - int xflags; -{ - if (string[*sindex] == LPAREN) - return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/ - else - { - xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0); - return (xparse_dolparen (string, string+*sindex, sindex, xflags)); - } -} - -/* Extract the $[ construct in STRING, and return a new string. (]) - Start extracting at (SINDEX) as if we had just seen "$[". - Make (SINDEX) get the position of the matching "]". */ -char * -extract_arithmetic_subst (string, sindex) - char *string; - int *sindex; -{ - return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/ -} - -#if defined (PROCESS_SUBSTITUTION) -/* Extract the <( or >( construct in STRING, and return a new string. - Start extracting at (SINDEX) as if we had just seen "<(". - Make (SINDEX) get the position of the matching ")". */ /*))*/ -char * -extract_process_subst (string, starter, sindex, xflags) - char *string; - char *starter; - int *sindex; - int xflags; -{ -#if 0 - return (extract_delimited_string (string, sindex, starter, "(", ")", SX_COMMAND)); -#else - xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0); - return (xparse_dolparen (string, string+*sindex, sindex, xflags)); -#endif -} -#endif /* PROCESS_SUBSTITUTION */ - -#if defined (ARRAY_VARS) -/* This can be fooled by unquoted right parens in the passed string. If - each caller verifies that the last character in STRING is a right paren, - we don't even need to call extract_delimited_string. */ -char * -extract_array_assignment_list (string, sindex) - char *string; - int *sindex; -{ - int slen; - char *ret; - - slen = strlen (string); /* ( */ - if (string[slen - 1] == ')') - { - ret = substring (string, *sindex, slen - 1); - *sindex = slen - 1; - return ret; - } - return 0; -} -#endif - -/* Extract and create a new string from the contents of STRING, a - character string delimited with OPENER and CLOSER. SINDEX is - the address of an int describing the current offset in STRING; - it should point to just after the first OPENER found. On exit, - SINDEX gets the position of the last character of the matching CLOSER. - If OPENER is more than a single character, ALT_OPENER, if non-null, - contains a character string that can also match CLOSER and thus - needs to be skipped. */ -static char * -extract_delimited_string (string, sindex, opener, alt_opener, closer, flags) - char *string; - int *sindex; - char *opener, *alt_opener, *closer; - int flags; -{ - int i, c, si; - size_t slen; - char *t, *result; - int pass_character, nesting_level, in_comment; - int len_closer, len_opener, len_alt_opener; - DECLARE_MBSTATE; - - slen = strlen (string + *sindex) + *sindex; - len_opener = STRLEN (opener); - len_alt_opener = STRLEN (alt_opener); - len_closer = STRLEN (closer); - - pass_character = in_comment = 0; - - nesting_level = 1; - i = *sindex; - - while (nesting_level) - { - c = string[i]; - - if (c == 0) - break; - - if (in_comment) - { - if (c == '\n') - in_comment = 0; - ADVANCE_CHAR (string, slen, i); - continue; - } - - if (pass_character) /* previous char was backslash */ - { - pass_character = 0; - ADVANCE_CHAR (string, slen, i); - continue; - } - - /* Not exactly right yet; should handle shell metacharacters and - multibyte characters, too. See COMMENT_BEGIN define in parse.y */ - if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1]))) - { - in_comment = 1; - ADVANCE_CHAR (string, slen, i); - continue; - } - - if (c == CTLESC || c == '\\') - { - pass_character++; - i++; - continue; - } - - /* Process a nested command substitution, but only if we're parsing an - arithmetic substitution. */ - if ((flags & SX_COMMAND) && string[i] == '$' && string[i+1] == LPAREN) - { - si = i + 2; - t = extract_command_subst (string, &si, flags|SX_NOALLOC); - i = si + 1; - continue; - } - - /* Process a nested OPENER. */ - if (STREQN (string + i, opener, len_opener)) - { - si = i + len_opener; - t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|SX_NOALLOC); - i = si + 1; - continue; - } - - /* Process a nested ALT_OPENER */ - if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener)) - { - si = i + len_alt_opener; - t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|SX_NOALLOC); - i = si + 1; - continue; - } - - /* If the current substring terminates the delimited string, decrement - the nesting level. */ - if (STREQN (string + i, closer, len_closer)) - { - i += len_closer - 1; /* move to last byte of the closer */ - nesting_level--; - if (nesting_level == 0) - break; - } - - /* Pass old-style command substitution through verbatim. */ - if (c == '`') - { - si = i + 1; - t = string_extract (string, &si, "`", flags|SX_NOALLOC); - i = si + 1; - continue; - } - - /* Pass single-quoted and double-quoted strings through verbatim. */ - if (c == '\'' || c == '"') - { - si = i + 1; - i = (c == '\'') ? skip_single_quoted (string, slen, si) - : skip_double_quoted (string, slen, si); - continue; - } - - /* move past this character, which was not special. */ - ADVANCE_CHAR (string, slen, i); - } - - if (c == 0 && nesting_level) - { - if (no_longjmp_on_fatal_error == 0) - { - last_command_exit_value = EXECUTION_FAILURE; - report_error (_("bad substitution: no closing `%s' in %s"), closer, string); - exp_jump_to_top_level (DISCARD); - } - else - { - *sindex = i; - return (char *)NULL; - } - } - - si = i - *sindex - len_closer + 1; - if (flags & SX_NOALLOC) - result = (char *)NULL; - else - { - result = (char *)xmalloc (1 + si); - strncpy (result, string + *sindex, si); - result[si] = '\0'; - } - *sindex = i; - - return (result); -} - -/* Extract a parameter expansion expression within ${ and } from STRING. - Obey the Posix.2 rules for finding the ending `}': count braces while - skipping over enclosed quoted strings and command substitutions. - SINDEX is the address of an int describing the current offset in STRING; - it should point to just after the first `{' found. On exit, SINDEX - gets the position of the matching `}'. QUOTED is non-zero if this - occurs inside double quotes. */ -/* XXX -- this is very similar to extract_delimited_string -- XXX */ -static char * -extract_dollar_brace_string (string, sindex, quoted, flags) - char *string; - int *sindex, quoted, flags; -{ - register int i, c; - size_t slen; - int pass_character, nesting_level, si, dolbrace_state; - char *result, *t; - DECLARE_MBSTATE; - - pass_character = 0; - nesting_level = 1; - slen = strlen (string + *sindex) + *sindex; - - /* The handling of dolbrace_state needs to agree with the code in parse.y: - parse_matched_pair(). The different initial value is to handle the - case where this function is called to parse the word in - ${param op word} (SX_WORD). */ - dolbrace_state = (flags & SX_WORD) ? DOLBRACE_WORD : DOLBRACE_PARAM; - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && (flags & SX_POSIXEXP)) - dolbrace_state = DOLBRACE_QUOTE; - - i = *sindex; - while (c = string[i]) - { - if (pass_character) - { - pass_character = 0; - ADVANCE_CHAR (string, slen, i); - continue; - } - - /* CTLESCs and backslashes quote the next character. */ - if (c == CTLESC || c == '\\') - { - pass_character++; - i++; - continue; - } - - if (string[i] == '$' && string[i+1] == LBRACE) - { - nesting_level++; - i += 2; - continue; - } - - if (c == RBRACE) - { - nesting_level--; - if (nesting_level == 0) - break; - i++; - continue; - } - - /* Pass the contents of old-style command substitutions through - verbatim. */ - if (c == '`') - { - si = i + 1; - t = string_extract (string, &si, "`", flags|SX_NOALLOC); - i = si + 1; - continue; - } - - /* Pass the contents of new-style command substitutions and - arithmetic substitutions through verbatim. */ - if (string[i] == '$' && string[i+1] == LPAREN) - { - si = i + 2; - t = extract_command_subst (string, &si, flags|SX_NOALLOC); - i = si + 1; - continue; - } - - /* Pass the contents of double-quoted strings through verbatim. */ - if (c == '"') - { - si = i + 1; - i = skip_double_quoted (string, slen, si); - /* skip_XXX_quoted leaves index one past close quote */ - continue; - } - - if (c == '\'') - { -/*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/ - if (posixly_correct && shell_compatibility_level > 42 && dolbrace_state != DOLBRACE_QUOTE && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) - ADVANCE_CHAR (string, slen, i); - else - { - si = i + 1; - i = skip_single_quoted (string, slen, si); - } - - continue; - } - - /* move past this character, which was not special. */ - ADVANCE_CHAR (string, slen, i); - - /* This logic must agree with parse.y:parse_matched_pair, since they - share the same defines. */ - if (dolbrace_state == DOLBRACE_PARAM && c == '%' && (i - *sindex) > 1) - dolbrace_state = DOLBRACE_QUOTE; - else if (dolbrace_state == DOLBRACE_PARAM && c == '#' && (i - *sindex) > 1) - dolbrace_state = DOLBRACE_QUOTE; - else if (dolbrace_state == DOLBRACE_PARAM && c == '/' && (i - *sindex) > 1) - dolbrace_state = DOLBRACE_QUOTE2; /* XXX */ - else if (dolbrace_state == DOLBRACE_PARAM && c == '^' && (i - *sindex) > 1) - dolbrace_state = DOLBRACE_QUOTE; - else if (dolbrace_state == DOLBRACE_PARAM && c == ',' && (i - *sindex) > 1) - dolbrace_state = DOLBRACE_QUOTE; - else if (dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", c) != 0) - dolbrace_state = DOLBRACE_OP; - else if (dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", c) == 0) - dolbrace_state = DOLBRACE_WORD; - } - - if (c == 0 && nesting_level) - { - if (no_longjmp_on_fatal_error == 0) - { /* { */ - last_command_exit_value = EXECUTION_FAILURE; - report_error (_("bad substitution: no closing `%s' in %s"), "}", string); - exp_jump_to_top_level (DISCARD); - } - else - { - *sindex = i; - return ((char *)NULL); - } - } - - result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i); - *sindex = i; - - return (result); -} - -/* Remove backslashes which are quoting backquotes from STRING. Modifies - STRING, and returns a pointer to it. */ -char * -de_backslash (string) - char *string; -{ - register size_t slen; - register int i, j, prev_i; - DECLARE_MBSTATE; - - slen = strlen (string); - i = j = 0; - - /* Loop copying string[i] to string[j], i >= j. */ - while (i < slen) - { - if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' || - string[i + 1] == '$')) - i++; - prev_i = i; - ADVANCE_CHAR (string, slen, i); - if (j < prev_i) - do string[j++] = string[prev_i++]; while (prev_i < i); - else - j = i; - } - string[j] = '\0'; - - return (string); -} - -#if 0 -/*UNUSED*/ -/* Replace instances of \! in a string with !. */ -void -unquote_bang (string) - char *string; -{ - register int i, j; - register char *temp; - - temp = (char *)xmalloc (1 + strlen (string)); - - for (i = 0, j = 0; (temp[j] = string[i]); i++, j++) - { - if (string[i] == '\\' && string[i + 1] == '!') - { - temp[j] = '!'; - i++; - } - } - strcpy (string, temp); - free (temp); -} -#endif - -#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0) - -/* This function assumes s[i] == open; returns with s[ret] == close; used to - parse array subscripts. FLAGS & 1 means to not attempt to skip over - matched pairs of quotes or backquotes, or skip word expansions; it is - intended to be used after expansion has been performed and during final - assignment parsing (see arrayfunc.c:assign_compound_array_list()). */ -static int -skip_matched_pair (string, start, open, close, flags) - const char *string; - int start, open, close, flags; -{ - int i, pass_next, backq, si, c, count; - size_t slen; - char *temp, *ss; - DECLARE_MBSTATE; - - slen = strlen (string + start) + start; - no_longjmp_on_fatal_error = 1; - - i = start + 1; /* skip over leading bracket */ - count = 1; - pass_next = backq = 0; - ss = (char *)string; - while (c = string[i]) - { - if (pass_next) - { - pass_next = 0; - if (c == 0) - CQ_RETURN(i); - ADVANCE_CHAR (string, slen, i); - continue; - } - else if (c == '\\') - { - pass_next = 1; - i++; - continue; - } - else if (backq) - { - if (c == '`') - backq = 0; - ADVANCE_CHAR (string, slen, i); - continue; - } - else if ((flags & 1) == 0 && c == '`') - { - backq = 1; - i++; - continue; - } - else if ((flags & 1) == 0 && c == open) - { - count++; - i++; - continue; - } - else if (c == close) - { - count--; - if (count == 0) - break; - i++; - continue; - } - else if ((flags & 1) == 0 && (c == '\'' || c == '"')) - { - i = (c == '\'') ? skip_single_quoted (ss, slen, ++i) - : skip_double_quoted (ss, slen, ++i); - /* no increment, the skip functions increment past the closing quote. */ - } - else if ((flags&1) == 0 && c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE)) - { - si = i + 2; - if (string[si] == '\0') - CQ_RETURN(si); - - if (string[i+1] == LPAREN) - temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */ - else - temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC); - i = si; - if (string[i] == '\0') /* don't increment i past EOS in loop */ - break; - i++; - continue; - } - else - ADVANCE_CHAR (string, slen, i); - } - - CQ_RETURN(i); -} - -#if defined (ARRAY_VARS) -int -skipsubscript (string, start, flags) - const char *string; - int start, flags; -{ - return (skip_matched_pair (string, start, '[', ']', flags)); -} -#endif - -/* Skip characters in STRING until we find a character in DELIMS, and return - the index of that character. START is the index into string at which we - begin. This is similar in spirit to strpbrk, but it returns an index into - STRING and takes a starting index. This little piece of code knows quite - a lot of shell syntax. It's very similar to skip_double_quoted and other - functions of that ilk. */ -int -skip_to_delim (string, start, delims, flags) - char *string; - int start; - char *delims; - int flags; -{ - int i, pass_next, backq, si, c, invert, skipquote, skipcmd, noprocsub; - size_t slen; - char *temp, open[3]; - DECLARE_MBSTATE; - - slen = strlen (string + start) + start; - if (flags & SD_NOJMP) - no_longjmp_on_fatal_error = 1; - invert = (flags & SD_INVERT); - skipcmd = (flags & SD_NOSKIPCMD) == 0; - noprocsub = (flags & SD_NOPROCSUB); - - i = start; - pass_next = backq = 0; - while (c = string[i]) - { - /* If this is non-zero, we should not let quote characters be delimiters - and the current character is a single or double quote. We should not - test whether or not it's a delimiter until after we skip single- or - double-quoted strings. */ - skipquote = ((flags & SD_NOQUOTEDELIM) && (c == '\'' || c =='"')); - if (pass_next) - { - pass_next = 0; - if (c == 0) - CQ_RETURN(i); - ADVANCE_CHAR (string, slen, i); - continue; - } - else if (c == '\\') - { - pass_next = 1; - i++; - continue; - } - else if (backq) - { - if (c == '`') - backq = 0; - ADVANCE_CHAR (string, slen, i); - continue; - } - else if (c == '`') - { - backq = 1; - i++; - continue; - } - else if (skipquote == 0 && invert == 0 && member (c, delims)) - break; - else if (c == '\'' || c == '"') - { - i = (c == '\'') ? skip_single_quoted (string, slen, ++i) - : skip_double_quoted (string, slen, ++i); - /* no increment, the skip functions increment past the closing quote. */ - } - else if (c == '$' && ((skipcmd && string[i+1] == LPAREN) || string[i+1] == LBRACE)) - { - si = i + 2; - if (string[si] == '\0') - CQ_RETURN(si); - - if (string[i+1] == LPAREN) - temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */ - else - temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC); - i = si; - if (string[i] == '\0') /* don't increment i past EOS in loop */ - break; - i++; - continue; - } -#if defined (PROCESS_SUBSTITUTION) - else if (skipcmd && noprocsub == 0 && (c == '<' || c == '>') && string[i+1] == LPAREN) - { - si = i + 2; - if (string[si] == '\0') - CQ_RETURN(si); - temp = extract_process_subst (string, (c == '<') ? "<(" : ">(", &si, 0); - free (temp); /* XXX - not using SX_ALLOC here yet */ - i = si; - if (string[i] == '\0') - break; - i++; - continue; - } -#endif /* PROCESS_SUBSTITUTION */ -#if defined (EXTENDED_GLOB) - else if ((flags & SD_EXTGLOB) && extended_glob && string[i+1] == LPAREN && member (c, "?*+!@")) - { - si = i + 2; - if (string[si] == '\0') - CQ_RETURN(si); - - open[0] = c; - open[1] = LPAREN; - open[2] = '\0'; - temp = extract_delimited_string (string, &si, open, "(", ")", SX_NOALLOC); /* ) */ - - i = si; - if (string[i] == '\0') /* don't increment i past EOS in loop */ - break; - i++; - continue; - } -#endif - else if ((flags & SD_GLOB) && c == LBRACK) - { - si = i + 1; - if (string[si] == '\0') - CQ_RETURN(si); - - temp = extract_delimited_string (string, &si, "[", "[", "]", SX_NOALLOC); /* ] */ - - i = si; - if (string[i] == '\0') /* don't increment i past EOS in loop */ - break; - i++; - continue; - } - else if ((skipquote || invert) && (member (c, delims) == 0)) - break; - else - ADVANCE_CHAR (string, slen, i); - } - - CQ_RETURN(i); -} - -#if defined (READLINE) -/* Return 1 if the portion of STRING ending at EINDEX is quoted (there is - an unclosed quoted string), or if the character at EINDEX is quoted - by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various - single and double-quoted string parsing functions should not return an - error if there are unclosed quotes or braces. The characters that this - recognizes need to be the same as the contents of - rl_completer_quote_characters. */ - -int -char_is_quoted (string, eindex) - char *string; - int eindex; -{ - int i, pass_next, c; - size_t slen; - DECLARE_MBSTATE; - - slen = strlen (string); - no_longjmp_on_fatal_error = 1; - i = pass_next = 0; - while (i <= eindex) - { - c = string[i]; - - if (pass_next) - { - pass_next = 0; - if (i >= eindex) /* XXX was if (i >= eindex - 1) */ - CQ_RETURN(1); - ADVANCE_CHAR (string, slen, i); - continue; - } - else if (c == '\\') - { - pass_next = 1; - i++; - continue; - } - else if (c == '\'' || c == '"') - { - i = (c == '\'') ? skip_single_quoted (string, slen, ++i) - : skip_double_quoted (string, slen, ++i); - if (i > eindex) - CQ_RETURN(1); - /* no increment, the skip_xxx functions go one past end */ - } - else - ADVANCE_CHAR (string, slen, i); - } - - CQ_RETURN(0); -} - -int -unclosed_pair (string, eindex, openstr) - char *string; - int eindex; - char *openstr; -{ - int i, pass_next, openc, olen; - size_t slen; - DECLARE_MBSTATE; - - slen = strlen (string); - olen = strlen (openstr); - i = pass_next = openc = 0; - while (i <= eindex) - { - if (pass_next) - { - pass_next = 0; - if (i >= eindex) /* XXX was if (i >= eindex - 1) */ - return 0; - ADVANCE_CHAR (string, slen, i); - continue; - } - else if (string[i] == '\\') - { - pass_next = 1; - i++; - continue; - } - else if (STREQN (string + i, openstr, olen)) - { - openc = 1 - openc; - i += olen; - } - else if (string[i] == '\'' || string[i] == '"') - { - i = (string[i] == '\'') ? skip_single_quoted (string, slen, i) - : skip_double_quoted (string, slen, i); - if (i > eindex) - return 0; - } - else - ADVANCE_CHAR (string, slen, i); - } - return (openc); -} - -/* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the - individual words. If DELIMS is NULL, the current value of $IFS is used - to split the string, and the function follows the shell field splitting - rules. SENTINEL is an index to look for. NWP, if non-NULL, - gets the number of words in the returned list. CWP, if non-NULL, gets - the index of the word containing SENTINEL. Non-whitespace chars in - DELIMS delimit separate fields. */ -WORD_LIST * -split_at_delims (string, slen, delims, sentinel, flags, nwp, cwp) - char *string; - int slen; - char *delims; - int sentinel, flags; - int *nwp, *cwp; -{ - int ts, te, i, nw, cw, ifs_split, dflags; - char *token, *d, *d2; - WORD_LIST *ret, *tl; - - if (string == 0 || *string == '\0') - { - if (nwp) - *nwp = 0; - if (cwp) - *cwp = 0; - return ((WORD_LIST *)NULL); - } - - d = (delims == 0) ? ifs_value : delims; - ifs_split = delims == 0; - - /* Make d2 the non-whitespace characters in delims */ - d2 = 0; - if (delims) - { - size_t slength; -#if defined (HANDLE_MULTIBYTE) - size_t mblength = 1; -#endif - DECLARE_MBSTATE; - - slength = strlen (delims); - d2 = (char *)xmalloc (slength + 1); - i = ts = 0; - while (delims[i]) - { -#if defined (HANDLE_MULTIBYTE) - mbstate_t state_bak; - state_bak = state; - mblength = MBRLEN (delims + i, slength, &state); - if (MB_INVALIDCH (mblength)) - state = state_bak; - else if (mblength > 1) - { - memcpy (d2 + ts, delims + i, mblength); - ts += mblength; - i += mblength; - slength -= mblength; - continue; - } -#endif - if (whitespace (delims[i]) == 0) - d2[ts++] = delims[i]; - - i++; - slength--; - } - d2[ts] = '\0'; - } - - ret = (WORD_LIST *)NULL; - - /* Remove sequences of whitespace characters at the start of the string, as - long as those characters are delimiters. */ - for (i = 0; member (string[i], d) && spctabnl (string[i]); i++) - ; - if (string[i] == '\0') - return (ret); - - ts = i; - nw = 0; - cw = -1; - dflags = flags|SD_NOJMP; - while (1) - { - te = skip_to_delim (string, ts, d, dflags); - - /* If we have a non-whitespace delimiter character, use it to make a - separate field. This is just about what $IFS splitting does and - is closer to the behavior of the shell parser. */ - if (ts == te && d2 && member (string[ts], d2)) - { - te = ts + 1; - /* If we're using IFS splitting, the non-whitespace delimiter char - and any additional IFS whitespace delimits a field. */ - if (ifs_split) - while (member (string[te], d) && spctabnl (string[te])) - te++; - else - while (member (string[te], d2)) - te++; - } - - token = substring (string, ts, te); - - ret = add_string_to_list (token, ret); - free (token); - nw++; - - if (sentinel >= ts && sentinel <= te) - cw = nw; - - /* If the cursor is at whitespace just before word start, set the - sentinel word to the current word. */ - if (cwp && cw == -1 && sentinel == ts-1) - cw = nw; - - /* If the cursor is at whitespace between two words, make a new, empty - word, add it before (well, after, since the list is in reverse order) - the word we just added, and set the current word to that one. */ - if (cwp && cw == -1 && sentinel < ts) - { - tl = make_word_list (make_word (""), ret->next); - ret->next = tl; - cw = nw; - nw++; - } - - if (string[te] == 0) - break; - - i = te; - while (member (string[i], d) && (ifs_split || spctabnl(string[i]))) - i++; - - if (string[i]) - ts = i; - else - break; - } - - /* Special case for SENTINEL at the end of STRING. If we haven't found - the word containing SENTINEL yet, and the index we're looking for is at - the end of STRING (or past the end of the previously-found token, - possible if the end of the line is composed solely of IFS whitespace) - add an additional null argument and set the current word pointer to that. */ - if (cwp && cw == -1 && (sentinel >= slen || sentinel >= te)) - { - if (whitespace (string[sentinel - 1])) - { - token = ""; - ret = add_string_to_list (token, ret); - nw++; - } - cw = nw; - } - - if (nwp) - *nwp = nw; - if (cwp) - *cwp = cw; - - FREE (d2); - - return (REVERSE_LIST (ret, WORD_LIST *)); -} -#endif /* READLINE */ - -#if 0 -/* UNUSED */ -/* Extract the name of the variable to bind to from the assignment string. */ -char * -assignment_name (string) - char *string; -{ - int offset; - char *temp; - - offset = assignment (string, 0); - if (offset == 0) - return (char *)NULL; - temp = substring (string, 0, offset); - return (temp); -} -#endif - -/* **************************************************************** */ -/* */ -/* Functions to convert strings to WORD_LISTs and vice versa */ -/* */ -/* **************************************************************** */ - -/* Return a single string of all the words in LIST. SEP is the separator - to put between individual elements of LIST in the output string. */ -char * -string_list_internal (list, sep) - WORD_LIST *list; - char *sep; -{ - register WORD_LIST *t; - char *result, *r; - int word_len, sep_len, result_size; - - if (list == 0) - return ((char *)NULL); - - /* Short-circuit quickly if we don't need to separate anything. */ - if (list->next == 0) - return (savestring (list->word->word)); - - /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */ - sep_len = STRLEN (sep); - result_size = 0; - - for (t = list; t; t = t->next) - { - if (t != list) - result_size += sep_len; - result_size += strlen (t->word->word); - } - - r = result = (char *)xmalloc (result_size + 1); - - for (t = list; t; t = t->next) - { - if (t != list && sep_len) - { - if (sep_len > 1) - { - FASTCOPY (sep, r, sep_len); - r += sep_len; - } - else - *r++ = sep[0]; - } - - word_len = strlen (t->word->word); - FASTCOPY (t->word->word, r, word_len); - r += word_len; - } - - *r = '\0'; - return (result); -} - -/* Return a single string of all the words present in LIST, separating - each word with a space. */ -char * -string_list (list) - WORD_LIST *list; -{ - return (string_list_internal (list, " ")); -} - -/* An external interface that can be used by the rest of the shell to - obtain a string containing the first character in $IFS. Handles all - the multibyte complications. If LENP is non-null, it is set to the - length of the returned string. */ -char * -ifs_firstchar (lenp) - int *lenp; -{ - char *ret; - int len; - - ret = xmalloc (MB_LEN_MAX + 1); -#if defined (HANDLE_MULTIBYTE) - if (ifs_firstc_len == 1) - { - ret[0] = ifs_firstc[0]; - ret[1] = '\0'; - len = ret[0] ? 1 : 0; - } - else - { - memcpy (ret, ifs_firstc, ifs_firstc_len); - ret[len = ifs_firstc_len] = '\0'; - } -#else - ret[0] = ifs_firstc; - ret[1] = '\0'; - len = ret[0] ? 0 : 1; -#endif - - if (lenp) - *lenp = len; - - return ret; -} - -/* Return a single string of all the words present in LIST, obeying the - quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the - expansion [of $*] appears within a double quoted string, it expands - to a single field with the value of each parameter separated by the - first character of the IFS variable, or by a <space> if IFS is unset." */ -char * -string_list_dollar_star (list) - WORD_LIST *list; -{ - char *ret; -#if defined (HANDLE_MULTIBYTE) -# if defined (__GNUC__) - char sep[MB_CUR_MAX + 1]; -# else - char *sep = 0; -# endif -#else - char sep[2]; -#endif - -#if defined (HANDLE_MULTIBYTE) -# if !defined (__GNUC__) - sep = (char *)xmalloc (MB_CUR_MAX + 1); -# endif /* !__GNUC__ */ - if (ifs_firstc_len == 1) - { - sep[0] = ifs_firstc[0]; - sep[1] = '\0'; - } - else - { - memcpy (sep, ifs_firstc, ifs_firstc_len); - sep[ifs_firstc_len] = '\0'; - } -#else - sep[0] = ifs_firstc; - sep[1] = '\0'; -#endif - - ret = string_list_internal (list, sep); -#if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__) - free (sep); -#endif - return ret; -} - -/* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) - is non-zero, the $@ appears within double quotes, and we should quote - the list before converting it into a string. If IFS is unset, and the - word is not quoted, we just need to quote CTLESC and CTLNUL characters - in the words in the list, because the default value of $IFS is - <space><tab><newline>, IFS characters in the words in the list should - also be split. If IFS is null, and the word is not quoted, we need - to quote the words in the list to preserve the positional parameters - exactly. */ -char * -string_list_dollar_at (list, quoted) - WORD_LIST *list; - int quoted; -{ - char *ifs, *ret; -#if defined (HANDLE_MULTIBYTE) -# if defined (__GNUC__) - char sep[MB_CUR_MAX + 1]; -# else - char *sep = 0; -# endif /* !__GNUC__ */ -#else - char sep[2]; -#endif - WORD_LIST *tlist; - - /* XXX this could just be ifs = ifs_value; */ - ifs = ifs_var ? value_cell (ifs_var) : (char *)0; - -#if defined (HANDLE_MULTIBYTE) -# if !defined (__GNUC__) - sep = (char *)xmalloc (MB_CUR_MAX + 1); -# endif /* !__GNUC__ */ - if (ifs && *ifs) - { - if (ifs_firstc_len == 1) - { - sep[0] = ifs_firstc[0]; - sep[1] = '\0'; - } - else - { - memcpy (sep, ifs_firstc, ifs_firstc_len); - sep[ifs_firstc_len] = '\0'; - } - } - else - { - sep[0] = ' '; - sep[1] = '\0'; - } -#else - sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs; - sep[1] = '\0'; -#endif - - /* XXX -- why call quote_list if ifs == 0? we can get away without doing - it now that quote_escapes quotes spaces */ - tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE)) - ? quote_list (list) - : list_quote_escapes (list); - - ret = string_list_internal (tlist, sep); -#if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__) - free (sep); -#endif - return ret; -} - -/* Turn the positional parameters into a string, understanding quoting and - the various subtleties of using the first character of $IFS as the - separator. Calls string_list_dollar_at, string_list_dollar_star, and - string_list as appropriate. */ -char * -string_list_pos_params (pchar, list, quoted) - int pchar; - WORD_LIST *list; - int quoted; -{ - char *ret; - WORD_LIST *tlist; - - if (pchar == '*' && (quoted & Q_DOUBLE_QUOTES)) - { - tlist = quote_list (list); - word_list_remove_quoted_nulls (tlist); - ret = string_list_dollar_star (tlist); - } - else if (pchar == '*' && (quoted & Q_HERE_DOCUMENT)) - { - tlist = quote_list (list); - word_list_remove_quoted_nulls (tlist); - ret = string_list (tlist); - } - else if (pchar == '*') - { - /* Even when unquoted, string_list_dollar_star does the right thing - making sure that the first character of $IFS is used as the - separator. */ - ret = string_list_dollar_star (list); - } - else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) - /* We use string_list_dollar_at, but only if the string is quoted, since - that quotes the escapes if it's not, which we don't want. We could - use string_list (the old code did), but that doesn't do the right - thing if the first character of $IFS is not a space. We use - string_list_dollar_star if the string is unquoted so we make sure that - the elements of $@ are separated by the first character of $IFS for - later splitting. */ - ret = string_list_dollar_at (list, quoted); - else if (pchar == '@') - ret = string_list_dollar_star (list); - else - ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list); - - return ret; -} - -/* Return the list of words present in STRING. Separate the string into - words at any of the characters found in SEPARATORS. If QUOTED is - non-zero then word in the list will have its quoted flag set, otherwise - the quoted flag is left as make_word () deemed fit. - - This obeys the P1003.2 word splitting semantics. If `separators' is - exactly <space><tab><newline>, then the splitting algorithm is that of - the Bourne shell, which treats any sequence of characters from `separators' - as a delimiter. If IFS is unset, which results in `separators' being set - to "", no splitting occurs. If separators has some other value, the - following rules are applied (`IFS white space' means zero or more - occurrences of <space>, <tab>, or <newline>, as long as those characters - are in `separators'): - - 1) IFS white space is ignored at the start and the end of the - string. - 2) Each occurrence of a character in `separators' that is not - IFS white space, along with any adjacent occurrences of - IFS white space delimits a field. - 3) Any nonzero-length sequence of IFS white space delimits a field. - */ - -/* BEWARE! list_string strips null arguments. Don't call it twice and - expect to have "" preserved! */ - -/* This performs word splitting and quoted null character removal on - STRING. */ -#define issep(c) \ - (((separators)[0]) ? ((separators)[1] ? isifs(c) \ - : (c) == (separators)[0]) \ - : 0) - -WORD_LIST * -list_string (string, separators, quoted) - register char *string, *separators; - int quoted; -{ - WORD_LIST *result; - WORD_DESC *t; - char *current_word, *s; - int sindex, sh_style_split, whitesep, xflags; - size_t slen; - - if (!string || !*string) - return ((WORD_LIST *)NULL); - - sh_style_split = separators && separators[0] == ' ' && - separators[1] == '\t' && - separators[2] == '\n' && - separators[3] == '\0'; - for (xflags = 0, s = ifs_value; s && *s; s++) - { - if (*s == CTLESC) xflags |= SX_NOCTLESC; - else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL; - } - - slen = 0; - /* Remove sequences of whitespace at the beginning of STRING, as - long as those characters appear in IFS. Do not do this if - STRING is quoted or if there are no separator characters. */ - if (!quoted || !separators || !*separators) - { - for (s = string; *s && spctabnl (*s) && issep (*s); s++); - - if (!*s) - return ((WORD_LIST *)NULL); - - string = s; - } - - /* OK, now STRING points to a word that does not begin with white space. - The splitting algorithm is: - extract a word, stopping at a separator - skip sequences of spc, tab, or nl as long as they are separators - This obeys the field splitting rules in Posix.2. */ - slen = (MB_CUR_MAX > 1) ? strlen (string) : 1; - for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; ) - { - /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim - unless multibyte chars are possible. */ - current_word = string_extract_verbatim (string, slen, &sindex, separators, xflags); - if (current_word == 0) - break; - - /* If we have a quoted empty string, add a quoted null argument. We - want to preserve the quoted null character iff this is a quoted - empty string; otherwise the quoted null characters are removed - below. */ - if (QUOTED_NULL (current_word)) - { - t = alloc_word_desc (); - t->word = make_quoted_char ('\0'); - t->flags |= W_QUOTED|W_HASQUOTEDNULL; - result = make_word_list (t, result); - } - else if (current_word[0] != '\0') - { - /* If we have something, then add it regardless. However, - perform quoted null character removal on the current word. */ - remove_quoted_nulls (current_word); - result = add_string_to_list (current_word, result); - result->word->flags &= ~W_HASQUOTEDNULL; /* just to be sure */ - if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) - result->word->flags |= W_QUOTED; - } - - /* If we're not doing sequences of separators in the traditional - Bourne shell style, then add a quoted null argument. */ - else if (!sh_style_split && !spctabnl (string[sindex])) - { - t = alloc_word_desc (); - t->word = make_quoted_char ('\0'); - t->flags |= W_QUOTED|W_HASQUOTEDNULL; - result = make_word_list (t, result); - } - - free (current_word); - - /* Note whether or not the separator is IFS whitespace, used later. */ - whitesep = string[sindex] && spctabnl (string[sindex]); - - /* Move past the current separator character. */ - if (string[sindex]) - { - DECLARE_MBSTATE; - ADVANCE_CHAR (string, slen, sindex); - } - - /* Now skip sequences of space, tab, or newline characters if they are - in the list of separators. */ - while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex])) - sindex++; - - /* If the first separator was IFS whitespace and the current character - is a non-whitespace IFS character, it should be part of the current - field delimiter, not a separate delimiter that would result in an - empty field. Look at POSIX.2, 3.6.5, (3)(b). */ - if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex])) - { - sindex++; - /* An IFS character that is not IFS white space, along with any - adjacent IFS white space, shall delimit a field. (SUSv3) */ - while (string[sindex] && spctabnl (string[sindex]) && isifs (string[sindex])) - sindex++; - } - } - return (REVERSE_LIST (result, WORD_LIST *)); -} - -/* Parse a single word from STRING, using SEPARATORS to separate fields. - ENDPTR is set to the first character after the word. This is used by - the `read' builtin. This is never called with SEPARATORS != $IFS; - it should be simplified. - - XXX - this function is very similar to list_string; they should be - combined - XXX */ -char * -get_word_from_string (stringp, separators, endptr) - char **stringp, *separators, **endptr; -{ - register char *s; - char *current_word; - int sindex, sh_style_split, whitesep, xflags; - size_t slen; - - if (!stringp || !*stringp || !**stringp) - return ((char *)NULL); - - sh_style_split = separators && separators[0] == ' ' && - separators[1] == '\t' && - separators[2] == '\n' && - separators[3] == '\0'; - for (xflags = 0, s = ifs_value; s && *s; s++) - { - if (*s == CTLESC) xflags |= SX_NOCTLESC; - if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL; - } - - s = *stringp; - slen = 0; - - /* Remove sequences of whitespace at the beginning of STRING, as - long as those characters appear in IFS. */ - if (sh_style_split || !separators || !*separators) - { - for (; *s && spctabnl (*s) && isifs (*s); s++); - - /* If the string is nothing but whitespace, update it and return. */ - if (!*s) - { - *stringp = s; - if (endptr) - *endptr = s; - return ((char *)NULL); - } - } - - /* OK, S points to a word that does not begin with white space. - Now extract a word, stopping at a separator, save a pointer to - the first character after the word, then skip sequences of spc, - tab, or nl as long as they are separators. - - This obeys the field splitting rules in Posix.2. */ - sindex = 0; - /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim - unless multibyte chars are possible. */ - slen = (MB_CUR_MAX > 1) ? strlen (s) : 1; - current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags); - - /* Set ENDPTR to the first character after the end of the word. */ - if (endptr) - *endptr = s + sindex; - - /* Note whether or not the separator is IFS whitespace, used later. */ - whitesep = s[sindex] && spctabnl (s[sindex]); - - /* Move past the current separator character. */ - if (s[sindex]) - { - DECLARE_MBSTATE; - ADVANCE_CHAR (s, slen, sindex); - } - - /* Now skip sequences of space, tab, or newline characters if they are - in the list of separators. */ - while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex])) - sindex++; - - /* If the first separator was IFS whitespace and the current character is - a non-whitespace IFS character, it should be part of the current field - delimiter, not a separate delimiter that would result in an empty field. - Look at POSIX.2, 3.6.5, (3)(b). */ - if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex])) - { - sindex++; - /* An IFS character that is not IFS white space, along with any adjacent - IFS white space, shall delimit a field. */ - while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex])) - sindex++; - } - - /* Update STRING to point to the next field. */ - *stringp = s + sindex; - return (current_word); -} - -/* Remove IFS white space at the end of STRING. Start at the end - of the string and walk backwards until the beginning of the string - or we find a character that's not IFS white space and not CTLESC. - Only let CTLESC escape a white space character if SAW_ESCAPE is - non-zero. */ -char * -strip_trailing_ifs_whitespace (string, separators, saw_escape) - char *string, *separators; - int saw_escape; -{ - char *s; - - s = string + STRLEN (string) - 1; - while (s > string && ((spctabnl (*s) && isifs (*s)) || - (saw_escape && *s == CTLESC && spctabnl (s[1])))) - s--; - *++s = '\0'; - return string; -} - -#if 0 -/* UNUSED */ -/* Split STRING into words at whitespace. Obeys shell-style quoting with - backslashes, single and double quotes. */ -WORD_LIST * -list_string_with_quotes (string) - char *string; -{ - WORD_LIST *list; - char *token, *s; - size_t s_len; - int c, i, tokstart, len; - - for (s = string; s && *s && spctabnl (*s); s++) - ; - if (s == 0 || *s == 0) - return ((WORD_LIST *)NULL); - - s_len = strlen (s); - tokstart = i = 0; - list = (WORD_LIST *)NULL; - while (1) - { - c = s[i]; - if (c == '\\') - { - i++; - if (s[i]) - i++; - } - else if (c == '\'') - i = skip_single_quoted (s, s_len, ++i); - else if (c == '"') - i = skip_double_quoted (s, s_len, ++i); - else if (c == 0 || spctabnl (c)) - { - /* We have found the end of a token. Make a word out of it and - add it to the word list. */ - token = substring (s, tokstart, i); - list = add_string_to_list (token, list); - free (token); - while (spctabnl (s[i])) - i++; - if (s[i]) - tokstart = i; - else - break; - } - else - i++; /* normal character */ - } - return (REVERSE_LIST (list, WORD_LIST *)); -} -#endif - -/********************************************************/ -/* */ -/* Functions to perform assignment statements */ -/* */ -/********************************************************/ - -#if defined (ARRAY_VARS) -static SHELL_VAR * -do_compound_assignment (name, value, flags) - char *name, *value; - int flags; -{ - SHELL_VAR *v; - int mklocal, mkassoc, mkglobal; - WORD_LIST *list; - - mklocal = flags & ASS_MKLOCAL; - mkassoc = flags & ASS_MKASSOC; - mkglobal = flags & ASS_MKGLOBAL; - - if (mklocal && variable_context) - { - v = find_variable (name); - list = expand_compound_array_assignment (v, value, flags); - if (mkassoc) - v = make_local_assoc_variable (name); - else if (v == 0 || (array_p (v) == 0 && assoc_p (v) == 0) || v->context != variable_context) - v = make_local_array_variable (name, 0); - if (v) - assign_compound_array_list (v, list, flags); - } - /* In a function but forcing assignment in global context */ - else if (mkglobal && variable_context) - { - v = find_global_variable (name); - list = expand_compound_array_assignment (v, value, flags); - if (v == 0 && mkassoc) - v = make_new_assoc_variable (name); - else if (v && mkassoc && assoc_p (v) == 0) - v = convert_var_to_assoc (v); - else if (v == 0) - v = make_new_array_variable (name); - else if (v && mkassoc == 0 && array_p (v) == 0) - v = convert_var_to_array (v); - if (v) - assign_compound_array_list (v, list, flags); - } - else - v = assign_array_from_string (name, value, flags); - - return (v); -} -#endif - -/* Given STRING, an assignment string, get the value of the right side - of the `=', and bind it to the left side. If EXPAND is true, then - perform parameter expansion, command substitution, and arithmetic - expansion on the right-hand side. Perform tilde expansion in any - case. Do not perform word splitting on the result of expansion. */ -static int -do_assignment_internal (word, expand) - const WORD_DESC *word; - int expand; -{ - int offset, appendop, assign_list, aflags, retval; - char *name, *value, *temp; - SHELL_VAR *entry; -#if defined (ARRAY_VARS) - char *t; - int ni; -#endif - const char *string; - - if (word == 0 || word->word == 0) - return 0; - - appendop = assign_list = aflags = 0; - string = word->word; - offset = assignment (string, 0); - name = savestring (string); - value = (char *)NULL; - - if (name[offset] == '=') - { - if (name[offset - 1] == '+') - { - appendop = 1; - name[offset - 1] = '\0'; - } - - name[offset] = 0; /* might need this set later */ - temp = name + offset + 1; - -#if defined (ARRAY_VARS) - if (expand && (word->flags & W_COMPASSIGN)) - { - assign_list = ni = 1; - value = extract_array_assignment_list (temp, &ni); - } - else -#endif - if (expand && temp[0]) - value = expand_string_if_necessary (temp, 0, expand_string_assignment); - else - value = savestring (temp); - } - - if (value == 0) - { - value = (char *)xmalloc (1); - value[0] = '\0'; - } - - if (echo_command_at_execute) - { - if (appendop) - name[offset - 1] = '+'; - xtrace_print_assignment (name, value, assign_list, 1); - if (appendop) - name[offset - 1] = '\0'; - } - -#define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0) - - if (appendop) - aflags |= ASS_APPEND; - -#if defined (ARRAY_VARS) - if (t = mbschr (name, '[')) /*]*/ - { - if (assign_list) - { - report_error (_("%s: cannot assign list to array member"), name); - ASSIGN_RETURN (0); - } - entry = assign_array_element (name, value, aflags); - if (entry == 0) - ASSIGN_RETURN (0); - } - else if (assign_list) - { - if ((word->flags & W_ASSIGNARG) && (word->flags & W_ASSNGLOBAL) == 0) - aflags |= ASS_MKLOCAL; - if ((word->flags & W_ASSIGNARG) && (word->flags & W_ASSNGLOBAL)) - aflags |= ASS_MKGLOBAL; - if (word->flags & W_ASSIGNASSOC) - aflags |= ASS_MKASSOC; - entry = do_compound_assignment (name, value, aflags); - } - else -#endif /* ARRAY_VARS */ - entry = bind_variable (name, value, aflags); - - stupidly_hack_special_variables (name); - - /* Return 1 if the assignment seems to have been performed correctly. */ - if (entry == 0 || readonly_p (entry)) - retval = 0; /* assignment failure */ - else if (noassign_p (entry)) - { - last_command_exit_value = EXECUTION_FAILURE; - retval = 1; /* error status, but not assignment failure */ - } - else - retval = 1; - - if (entry && retval != 0 && noassign_p (entry) == 0) - VUNSETATTR (entry, att_invisible); - - ASSIGN_RETURN (retval); -} - -/* Perform the assignment statement in STRING, and expand the - right side by doing tilde, command and parameter expansion. */ -int -do_assignment (string) - char *string; -{ - WORD_DESC td; - - td.flags = W_ASSIGNMENT; - td.word = string; - - return do_assignment_internal (&td, 1); -} - -int -do_word_assignment (word, flags) - WORD_DESC *word; - int flags; -{ - return do_assignment_internal (word, 1); -} - -/* Given STRING, an assignment string, get the value of the right side - of the `=', and bind it to the left side. Do not perform any word - expansions on the right hand side. */ -int -do_assignment_no_expand (string) - char *string; -{ - WORD_DESC td; - - td.flags = W_ASSIGNMENT; - td.word = string; - - return (do_assignment_internal (&td, 0)); -} - -/*************************************************** - * * - * Functions to manage the positional parameters * - * * - ***************************************************/ - -/* Return the word list that corresponds to `$*'. */ -WORD_LIST * -list_rest_of_args () -{ - register WORD_LIST *list, *args; - int i; - - /* Break out of the loop as soon as one of the dollar variables is null. */ - for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++) - list = make_word_list (make_bare_word (dollar_vars[i]), list); - - for (args = rest_of_args; args; args = args->next) - list = make_word_list (make_bare_word (args->word->word), list); - - return (REVERSE_LIST (list, WORD_LIST *)); -} - -int -number_of_args () -{ - register WORD_LIST *list; - int n; - - for (n = 0; n < 9 && dollar_vars[n+1]; n++) - ; - for (list = rest_of_args; list; list = list->next) - n++; - return n; -} - -/* Return the value of a positional parameter. This handles values > 10. */ -char * -get_dollar_var_value (ind) - intmax_t ind; -{ - char *temp; - WORD_LIST *p; - - if (ind < 10) - temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL; - else /* We want something like ${11} */ - { - ind -= 10; - for (p = rest_of_args; p && ind--; p = p->next) - ; - temp = p ? savestring (p->word->word) : (char *)NULL; - } - return (temp); -} - -/* Make a single large string out of the dollar digit variables, - and the rest_of_args. If DOLLAR_STAR is 1, then obey the special - case of "$*" with respect to IFS. */ -char * -string_rest_of_args (dollar_star) - int dollar_star; -{ - register WORD_LIST *list; - char *string; - - list = list_rest_of_args (); - string = dollar_star ? string_list_dollar_star (list) : string_list (list); - dispose_words (list); - return (string); -} - -/* Return a string containing the positional parameters from START to - END, inclusive. If STRING[0] == '*', we obey the rules for $*, - which only makes a difference if QUOTED is non-zero. If QUOTED includes - Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise - no quoting chars are added. */ -static char * -pos_params (string, start, end, quoted) - char *string; - int start, end, quoted; -{ - WORD_LIST *save, *params, *h, *t; - char *ret; - int i; - - /* see if we can short-circuit. if start == end, we want 0 parameters. */ - if (start == end) - return ((char *)NULL); - - save = params = list_rest_of_args (); - if (save == 0 && start > 0) - return ((char *)NULL); - - if (start == 0) /* handle ${@:0[:x]} specially */ - { - t = make_word_list (make_word (dollar_vars[0]), params); - save = params = t; - } - - for (i = start ? 1 : 0; params && i < start; i++) - params = params->next; - if (params == 0) - { - dispose_words (save); - return ((char *)NULL); - } - for (h = t = params; params && i < end; i++) - { - t = params; - params = params->next; - } - - t->next = (WORD_LIST *)NULL; - - ret = string_list_pos_params (string[0], h, quoted); - - if (t != params) - t->next = params; - - dispose_words (save); - return (ret); -} - -/******************************************************************/ -/* */ -/* Functions to expand strings to strings or WORD_LISTs */ -/* */ -/******************************************************************/ - -#if defined (PROCESS_SUBSTITUTION) -#define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~') -#else -#define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~') -#endif - -/* If there are any characters in STRING that require full expansion, - then call FUNC to expand STRING; otherwise just perform quote - removal if necessary. This returns a new string. */ -static char * -expand_string_if_necessary (string, quoted, func) - char *string; - int quoted; - EXPFUNC *func; -{ - WORD_LIST *list; - size_t slen; - int i, saw_quote; - char *ret; - DECLARE_MBSTATE; - - /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */ - slen = (MB_CUR_MAX > 1) ? strlen (string) : 0; - i = saw_quote = 0; - while (string[i]) - { - if (EXP_CHAR (string[i])) - break; - else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"') - saw_quote = 1; - ADVANCE_CHAR (string, slen, i); - } - - if (string[i]) - { - list = (*func) (string, quoted); - if (list) - { - ret = string_list (list); - dispose_words (list); - } - else - ret = (char *)NULL; - } - else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0)) - ret = string_quote_removal (string, quoted); - else - ret = savestring (string); - - return ret; -} - -static inline char * -expand_string_to_string_internal (string, quoted, func) - char *string; - int quoted; - EXPFUNC *func; -{ - WORD_LIST *list; - char *ret; - - if (string == 0 || *string == '\0') - return ((char *)NULL); - - list = (*func) (string, quoted); - if (list) - { - ret = string_list (list); - dispose_words (list); - } - else - ret = (char *)NULL; - - return (ret); -} - -char * -expand_string_to_string (string, quoted) - char *string; - int quoted; -{ - return (expand_string_to_string_internal (string, quoted, expand_string)); -} - -char * -expand_string_unsplit_to_string (string, quoted) - char *string; - int quoted; -{ - return (expand_string_to_string_internal (string, quoted, expand_string_unsplit)); -} - -char * -expand_assignment_string_to_string (string, quoted) - char *string; - int quoted; -{ - return (expand_string_to_string_internal (string, quoted, expand_string_assignment)); -} - -char * -expand_arith_string (string, quoted) - char *string; - int quoted; -{ - WORD_DESC td; - WORD_LIST *list, *tlist; - size_t slen; - int i, saw_quote; - char *ret; - DECLARE_MBSTATE; - - /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */ - slen = (MB_CUR_MAX > 1) ? strlen (string) : 0; - i = saw_quote = 0; - while (string[i]) - { - if (EXP_CHAR (string[i])) - break; - else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"') - saw_quote = 1; - ADVANCE_CHAR (string, slen, i); - } - - if (string[i]) - { - /* This is expanded version of expand_string_internal as it's called by - expand_string_leave_quoted */ - td.flags = W_NOPROCSUB; /* don't want process substitution */ - td.word = savestring (string); - list = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL); - /* This takes care of the calls from expand_string_leave_quoted and - expand_string */ - if (list) - { - tlist = word_list_split (list); - dispose_words (list); - list = tlist; - if (list) - dequote_list (list); - } - /* This comes from expand_string_if_necessary */ - if (list) - { - ret = string_list (list); - dispose_words (list); - } - else - ret = (char *)NULL; - FREE (td.word); - } - else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0)) - ret = string_quote_removal (string, quoted); - else - ret = savestring (string); - - return ret; -} - -#if defined (COND_COMMAND) -/* Just remove backslashes in STRING. Returns a new string. */ -char * -remove_backslashes (string) - char *string; -{ - char *r, *ret, *s; - - r = ret = (char *)xmalloc (strlen (string) + 1); - for (s = string; s && *s; ) - { - if (*s == '\\') - s++; - if (*s == 0) - break; - *r++ = *s++; - } - *r = '\0'; - return ret; -} - -/* This needs better error handling. */ -/* Expand W for use as an argument to a unary or binary operator in a - [[...]] expression. If SPECIAL is 1, this is the rhs argument - to the != or == operator, and should be treated as a pattern. In - this case, we quote the string specially for the globbing code. If - SPECIAL is 2, this is an rhs argument for the =~ operator, and should - be quoted appropriately for regcomp/regexec. The caller is responsible - for removing the backslashes if the unquoted word is needed later. */ -char * -cond_expand_word (w, special) - WORD_DESC *w; - int special; -{ - char *r, *p; - WORD_LIST *l; - int qflags; - - if (w->word == 0 || w->word[0] == '\0') - return ((char *)NULL); - - expand_no_split_dollar_star = 1; - w->flags |= W_NOSPLIT2; - l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0); - expand_no_split_dollar_star = 0; - if (l) - { - if (special == 0) /* LHS */ - { - dequote_list (l); - r = string_list (l); - } - else - { - /* Need to figure out whether or not we should call dequote_escapes - or a new dequote_ctlnul function here, and under what - circumstances. */ - qflags = QGLOB_CVTNULL; - if (special == 2) - qflags |= QGLOB_REGEXP; - p = string_list (l); - r = quote_string_for_globbing (p, qflags); - free (p); - } - dispose_words (l); - } - else - r = (char *)NULL; - - return r; -} -#endif - -/* Call expand_word_internal to expand W and handle error returns. - A convenience function for functions that don't want to handle - any errors or free any memory before aborting. */ -static WORD_LIST * -call_expand_word_internal (w, q, i, c, e) - WORD_DESC *w; - int q, i, *c, *e; -{ - WORD_LIST *result; - - result = expand_word_internal (w, q, i, c, e); - if (result == &expand_word_error || result == &expand_word_fatal) - { - /* By convention, each time this error is returned, w->word has - already been freed (it sometimes may not be in the fatal case, - but that doesn't result in a memory leak because we're going - to exit in most cases). */ - w->word = (char *)NULL; - last_command_exit_value = EXECUTION_FAILURE; - exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF); - /* NOTREACHED */ - return (NULL); - } - else - return (result); -} - -/* Perform parameter expansion, command substitution, and arithmetic - expansion on STRING, as if it were a word. Leave the result quoted. - Since this does not perform word splitting, it leaves quoted nulls - in the result. */ -static WORD_LIST * -expand_string_internal (string, quoted) - char *string; - int quoted; -{ - WORD_DESC td; - WORD_LIST *tresult; - - if (string == 0 || *string == 0) - return ((WORD_LIST *)NULL); - - td.flags = 0; - td.word = savestring (string); - - tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL); - - FREE (td.word); - return (tresult); -} - -/* Expand STRING by performing parameter expansion, command substitution, - and arithmetic expansion. Dequote the resulting WORD_LIST before - returning it, but do not perform word splitting. The call to - remove_quoted_nulls () is in here because word splitting normally - takes care of quote removal. */ -WORD_LIST * -expand_string_unsplit (string, quoted) - char *string; - int quoted; -{ - WORD_LIST *value; - - if (string == 0 || *string == '\0') - return ((WORD_LIST *)NULL); - - expand_no_split_dollar_star = 1; - value = expand_string_internal (string, quoted); - expand_no_split_dollar_star = 0; - - if (value) - { - if (value->word) - { - remove_quoted_nulls (value->word->word); - value->word->flags &= ~W_HASQUOTEDNULL; - } - dequote_list (value); - } - return (value); -} - -/* Expand the rhs of an assignment statement */ -WORD_LIST * -expand_string_assignment (string, quoted) - char *string; - int quoted; -{ - WORD_DESC td; - WORD_LIST *value; - - if (string == 0 || *string == '\0') - return ((WORD_LIST *)NULL); - - expand_no_split_dollar_star = 1; - - td.flags = W_ASSIGNRHS; - td.word = savestring (string); - value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL); - FREE (td.word); - - expand_no_split_dollar_star = 0; - - if (value) - { - if (value->word) - { - remove_quoted_nulls (value->word->word); - value->word->flags &= ~W_HASQUOTEDNULL; - } - dequote_list (value); - } - return (value); -} - - -/* Expand one of the PS? prompt strings. This is a sort of combination of - expand_string_unsplit and expand_string_internal, but returns the - passed string when an error occurs. Might want to trap other calls - to jump_to_top_level here so we don't endlessly loop. */ -WORD_LIST * -expand_prompt_string (string, quoted, wflags) - char *string; - int quoted; - int wflags; -{ - WORD_LIST *value; - WORD_DESC td; - - if (string == 0 || *string == 0) - return ((WORD_LIST *)NULL); - - td.flags = wflags; - td.word = savestring (string); - - no_longjmp_on_fatal_error = 1; - value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL); - no_longjmp_on_fatal_error = 0; - - if (value == &expand_word_error || value == &expand_word_fatal) - { - value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL); - return value; - } - FREE (td.word); - if (value) - { - if (value->word) - { - remove_quoted_nulls (value->word->word); - value->word->flags &= ~W_HASQUOTEDNULL; - } - dequote_list (value); - } - return (value); -} - -/* Expand STRING just as if you were expanding a word, but do not dequote - the resultant WORD_LIST. This is called only from within this file, - and is used to correctly preserve quoted characters when expanding - things like ${1+"$@"}. This does parameter expansion, command - substitution, arithmetic expansion, and word splitting. */ -static WORD_LIST * -expand_string_leave_quoted (string, quoted) - char *string; - int quoted; -{ - WORD_LIST *tlist; - WORD_LIST *tresult; - - if (string == 0 || *string == '\0') - return ((WORD_LIST *)NULL); - - tlist = expand_string_internal (string, quoted); - - if (tlist) - { - tresult = word_list_split (tlist); - dispose_words (tlist); - return (tresult); - } - return ((WORD_LIST *)NULL); -} - -/* This does not perform word splitting or dequote the WORD_LIST - it returns. */ -static WORD_LIST * -expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at) - char *string; - int quoted, *dollar_at_p, *has_dollar_at; -{ - WORD_DESC td; - WORD_LIST *tresult; - - if (string == 0 || *string == '\0') - return (WORD_LIST *)NULL; - - td.flags = W_NOSPLIT2; /* no splitting, remove "" and '' */ - td.word = string; - tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at); - return (tresult); -} - -/* Expand STRING just as if you were expanding a word. This also returns - a list of words. Note that filename globbing is *NOT* done for word - or string expansion, just when the shell is expanding a command. This - does parameter expansion, command substitution, arithmetic expansion, - and word splitting. Dequote the resultant WORD_LIST before returning. */ -WORD_LIST * -expand_string (string, quoted) - char *string; - int quoted; -{ - WORD_LIST *result; - - if (string == 0 || *string == '\0') - return ((WORD_LIST *)NULL); - - result = expand_string_leave_quoted (string, quoted); - return (result ? dequote_list (result) : result); -} - -/*************************************************** - * * - * Functions to handle quoting chars * - * * - ***************************************************/ - -/* Conventions: - - A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string. - The parser passes CTLNUL as CTLESC CTLNUL. */ - -/* Quote escape characters in string s, but no other characters. This is - used to protect CTLESC and CTLNUL in variable values from the rest of - the word expansion process after the variable is expanded (word splitting - and filename generation). If IFS is null, we quote spaces as well, just - in case we split on spaces later (in the case of unquoted $@, we will - eventually attempt to split the entire word on spaces). Corresponding - code exists in dequote_escapes. Even if we don't end up splitting on - spaces, quoting spaces is not a problem. This should never be called on - a string that is quoted with single or double quotes or part of a here - document (effectively double-quoted). */ -char * -quote_escapes (string) - char *string; -{ - register char *s, *t; - size_t slen; - char *result, *send; - int quote_spaces, skip_ctlesc, skip_ctlnul; - DECLARE_MBSTATE; - - slen = strlen (string); - send = string + slen; - - quote_spaces = (ifs_value && *ifs_value == 0); - - for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++) - skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL; - - t = result = (char *)xmalloc ((slen * 2) + 1); - s = string; - - while (*s) - { - if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' ')) - *t++ = CTLESC; - COPY_CHAR_P (t, s, send); - } - *t = '\0'; - - return (result); -} - -static WORD_LIST * -list_quote_escapes (list) - WORD_LIST *list; -{ - register WORD_LIST *w; - char *t; - - for (w = list; w; w = w->next) - { - t = w->word->word; - w->word->word = quote_escapes (t); - free (t); - } - return list; -} - -/* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL. - - The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL. - This is necessary to make unquoted CTLESC and CTLNUL characters in the - data stream pass through properly. - - We need to remove doubled CTLESC characters inside quoted strings before - quoting the entire string, so we do not double the number of CTLESC - characters. - - Also used by parts of the pattern substitution code. */ -char * -dequote_escapes (string) - char *string; -{ - register char *s, *t, *s1; - size_t slen; - char *result, *send; - int quote_spaces; - DECLARE_MBSTATE; - - if (string == 0) - return string; - - slen = strlen (string); - send = string + slen; - - t = result = (char *)xmalloc (slen + 1); - - if (strchr (string, CTLESC) == 0) - return (strcpy (result, string)); - - quote_spaces = (ifs_value && *ifs_value == 0); - - s = string; - while (*s) - { - if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' '))) - { - s++; - if (*s == '\0') - break; - } - COPY_CHAR_P (t, s, send); - } - *t = '\0'; - - return result; -} - -static WORD_LIST * -list_dequote_escapes (list) - WORD_LIST *list; -{ - register WORD_LIST *w; - char *t; - - for (w = list; w; w = w->next) - { - t = w->word->word; - w->word->word = dequote_escapes (t); - free (t); - } - return list; -} - -/* Return a new string with the quoted representation of character C. - This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be - set in any resultant WORD_DESC where this value is the word. */ -static char * -make_quoted_char (c) - int c; -{ - char *temp; - - temp = (char *)xmalloc (3); - if (c == 0) - { - temp[0] = CTLNUL; - temp[1] = '\0'; - } - else - { - temp[0] = CTLESC; - temp[1] = c; - temp[2] = '\0'; - } - return (temp); -} - -/* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so - the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where - this value is the word. */ -char * -quote_string (string) - char *string; -{ - register char *t; - size_t slen; - char *result, *send; - - if (*string == 0) - { - result = (char *)xmalloc (2); - result[0] = CTLNUL; - result[1] = '\0'; - } - else - { - DECLARE_MBSTATE; - - slen = strlen (string); - send = string + slen; - - result = (char *)xmalloc ((slen * 2) + 1); - - for (t = result; string < send; ) - { - *t++ = CTLESC; - COPY_CHAR_P (t, string, send); - } - *t = '\0'; - } - return (result); -} - -/* De-quote quoted characters in STRING. */ -char * -dequote_string (string) - char *string; -{ - register char *s, *t; - size_t slen; - char *result, *send; - DECLARE_MBSTATE; - - slen = strlen (string); - - t = result = (char *)xmalloc (slen + 1); - - if (QUOTED_NULL (string)) - { - result[0] = '\0'; - return (result); - } - - /* If no character in the string can be quoted, don't bother examining - each character. Just return a copy of the string passed to us. */ - if (strchr (string, CTLESC) == NULL) - return (strcpy (result, string)); - - send = string + slen; - s = string; - while (*s) - { - if (*s == CTLESC) - { - s++; - if (*s == '\0') - break; - } - COPY_CHAR_P (t, s, send); - } - - *t = '\0'; - return (result); -} - -/* Quote the entire WORD_LIST list. */ -static WORD_LIST * -quote_list (list) - WORD_LIST *list; -{ - register WORD_LIST *w; - char *t; - - for (w = list; w; w = w->next) - { - t = w->word->word; - w->word->word = quote_string (t); - if (*t == 0) - w->word->flags |= W_HASQUOTEDNULL; /* XXX - turn on W_HASQUOTEDNULL here? */ - w->word->flags |= W_QUOTED; - free (t); - } - return list; -} - -/* De-quote quoted characters in each word in LIST. */ -WORD_LIST * -dequote_list (list) - WORD_LIST *list; -{ - register char *s; - register WORD_LIST *tlist; - - for (tlist = list; tlist; tlist = tlist->next) - { - s = dequote_string (tlist->word->word); - if (QUOTED_NULL (tlist->word->word)) - tlist->word->flags &= ~W_HASQUOTEDNULL; - free (tlist->word->word); - tlist->word->word = s; - } - return list; -} - -/* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed - string. */ -char * -remove_quoted_escapes (string) - char *string; -{ - char *t; - - if (string) - { - t = dequote_escapes (string); - strcpy (string, t); - free (t); - } - - return (string); -} - -/* Perform quoted null character removal on STRING. We don't allow any - quoted null characters in the middle or at the ends of strings because - of how expand_word_internal works. remove_quoted_nulls () turns - STRING into an empty string iff it only consists of a quoted null, - and removes all unquoted CTLNUL characters. */ -char * -remove_quoted_nulls (string) - char *string; -{ - register size_t slen; - register int i, j, prev_i; - DECLARE_MBSTATE; - - if (strchr (string, CTLNUL) == 0) /* XXX */ - return string; /* XXX */ - - slen = strlen (string); - i = j = 0; - - while (i < slen) - { - if (string[i] == CTLESC) - { - /* Old code had j++, but we cannot assume that i == j at this - point -- what if a CTLNUL has already been removed from the - string? We don't want to drop the CTLESC or recopy characters - that we've already copied down. */ - i++; string[j++] = CTLESC; - if (i == slen) - break; - } - else if (string[i] == CTLNUL) - { - i++; - continue; - } - - prev_i = i; - ADVANCE_CHAR (string, slen, i); - if (j < prev_i) - { - do string[j++] = string[prev_i++]; while (prev_i < i); - } - else - j = i; - } - string[j] = '\0'; - - return (string); -} - -/* Perform quoted null character removal on each element of LIST. - This modifies LIST. */ -void -word_list_remove_quoted_nulls (list) - WORD_LIST *list; -{ - register WORD_LIST *t; - - for (t = list; t; t = t->next) - { - remove_quoted_nulls (t->word->word); - t->word->flags &= ~W_HASQUOTEDNULL; - } -} - -/* **************************************************************** */ -/* */ -/* Functions for Matching and Removing Patterns */ -/* */ -/* **************************************************************** */ - -#if defined (HANDLE_MULTIBYTE) -#if 0 /* Currently unused */ -static unsigned char * -mb_getcharlens (string, len) - char *string; - int len; -{ - int i, offset, last; - unsigned char *ret; - char *p; - DECLARE_MBSTATE; - - i = offset = 0; - last = 0; - ret = (unsigned char *)xmalloc (len); - memset (ret, 0, len); - while (string[last]) - { - ADVANCE_CHAR (string, len, offset); - ret[last] = offset - last; - last = offset; - } - return ret; -} -#endif -#endif - -/* Remove the portion of PARAM matched by PATTERN according to OP, where OP - can have one of 4 values: - RP_LONG_LEFT remove longest matching portion at start of PARAM - RP_SHORT_LEFT remove shortest matching portion at start of PARAM - RP_LONG_RIGHT remove longest matching portion at end of PARAM - RP_SHORT_RIGHT remove shortest matching portion at end of PARAM -*/ - -#define RP_LONG_LEFT 1 -#define RP_SHORT_LEFT 2 -#define RP_LONG_RIGHT 3 -#define RP_SHORT_RIGHT 4 - -/* Returns its first argument if nothing matched; new memory otherwise */ -static char * -remove_upattern (param, pattern, op) - char *param, *pattern; - int op; -{ - register int len; - register char *end; - register char *p, *ret, c; - - len = STRLEN (param); - end = param + len; - - switch (op) - { - case RP_LONG_LEFT: /* remove longest match at start */ - for (p = end; p >= param; p--) - { - c = *p; *p = '\0'; - if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH) - { - *p = c; - return (savestring (p)); - } - *p = c; - - } - break; - - case RP_SHORT_LEFT: /* remove shortest match at start */ - for (p = param; p <= end; p++) - { - c = *p; *p = '\0'; - if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH) - { - *p = c; - return (savestring (p)); - } - *p = c; - } - break; - - case RP_LONG_RIGHT: /* remove longest match at end */ - for (p = param; p <= end; p++) - { - if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH) - { - c = *p; *p = '\0'; - ret = savestring (param); - *p = c; - return (ret); - } - } - break; - - case RP_SHORT_RIGHT: /* remove shortest match at end */ - for (p = end; p >= param; p--) - { - if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH) - { - c = *p; *p = '\0'; - ret = savestring (param); - *p = c; - return (ret); - } - } - break; - } - - return (param); /* no match, return original string */ -} - -#if defined (HANDLE_MULTIBYTE) -/* Returns its first argument if nothing matched; new memory otherwise */ -static wchar_t * -remove_wpattern (wparam, wstrlen, wpattern, op) - wchar_t *wparam; - size_t wstrlen; - wchar_t *wpattern; - int op; -{ - wchar_t wc, *ret; - int n; - - switch (op) - { - case RP_LONG_LEFT: /* remove longest match at start */ - for (n = wstrlen; n >= 0; n--) - { - wc = wparam[n]; wparam[n] = L'\0'; - if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH) - { - wparam[n] = wc; - return (wcsdup (wparam + n)); - } - wparam[n] = wc; - } - break; - - case RP_SHORT_LEFT: /* remove shortest match at start */ - for (n = 0; n <= wstrlen; n++) - { - wc = wparam[n]; wparam[n] = L'\0'; - if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH) - { - wparam[n] = wc; - return (wcsdup (wparam + n)); - } - wparam[n] = wc; - } - break; - - case RP_LONG_RIGHT: /* remove longest match at end */ - for (n = 0; n <= wstrlen; n++) - { - if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH) - { - wc = wparam[n]; wparam[n] = L'\0'; - ret = wcsdup (wparam); - wparam[n] = wc; - return (ret); - } - } - break; - - case RP_SHORT_RIGHT: /* remove shortest match at end */ - for (n = wstrlen; n >= 0; n--) - { - if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH) - { - wc = wparam[n]; wparam[n] = L'\0'; - ret = wcsdup (wparam); - wparam[n] = wc; - return (ret); - } - } - break; - } - - return (wparam); /* no match, return original string */ -} -#endif /* HANDLE_MULTIBYTE */ - -static char * -remove_pattern (param, pattern, op) - char *param, *pattern; - int op; -{ - char *xret; - - if (param == NULL) - return (param); - if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */ - return (savestring (param)); - -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1) - { - wchar_t *ret, *oret; - size_t n; - wchar_t *wparam, *wpattern; - mbstate_t ps; - - n = xdupmbstowcs (&wpattern, NULL, pattern); - if (n == (size_t)-1) - { - xret = remove_upattern (param, pattern, op); - return ((xret == param) ? savestring (param) : xret); - } - n = xdupmbstowcs (&wparam, NULL, param); - - if (n == (size_t)-1) - { - free (wpattern); - xret = remove_upattern (param, pattern, op); - return ((xret == param) ? savestring (param) : xret); - } - oret = ret = remove_wpattern (wparam, n, wpattern, op); - /* Don't bother to convert wparam back to multibyte string if nothing - matched; just return copy of original string */ - if (ret == wparam) - { - free (wparam); - free (wpattern); - return (savestring (param)); - } - - free (wparam); - free (wpattern); - - n = strlen (param); - xret = (char *)xmalloc (n + 1); - memset (&ps, '\0', sizeof (mbstate_t)); - n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps); - xret[n] = '\0'; /* just to make sure */ - free (oret); - return xret; - } - else -#endif - { - xret = remove_upattern (param, pattern, op); - return ((xret == param) ? savestring (param) : xret); - } -} - -/* Match PAT anywhere in STRING and return the match boundaries. - This returns 1 in case of a successful match, 0 otherwise. SP - and EP are pointers into the string where the match begins and - ends, respectively. MTYPE controls what kind of match is attempted. - MATCH_BEG and MATCH_END anchor the match at the beginning and end - of the string, respectively. The longest match is returned. */ -static int -match_upattern (string, pat, mtype, sp, ep) - char *string, *pat; - int mtype; - char **sp, **ep; -{ - int c, len, mlen; - register char *p, *p1, *npat; - char *end; - int n1; - - /* If the pattern doesn't match anywhere in the string, go ahead and - short-circuit right away. A minor optimization, saves a bunch of - unnecessary calls to strmatch (up to N calls for a string of N - characters) if the match is unsuccessful. To preserve the semantics - of the substring matches below, we make sure that the pattern has - `*' as first and last character, making a new pattern if necessary. */ - /* XXX - check this later if I ever implement `**' with special meaning, - since this will potentially result in `**' at the beginning or end */ - len = STRLEN (pat); - if (pat[0] != '*' || (pat[0] == '*' && pat[1] == LPAREN && extended_glob) || pat[len - 1] != '*') - { - p = npat = (char *)xmalloc (len + 3); - p1 = pat; - if (*p1 != '*' || (*p1 == '*' && p1[1] == LPAREN && extended_glob)) - *p++ = '*'; - while (*p1) - *p++ = *p1++; - if (p1[-1] != '*' || p[-2] == '\\') - *p++ = '*'; - *p = '\0'; - } - else - npat = pat; - c = strmatch (npat, string, FNMATCH_EXTFLAG); - if (npat != pat) - free (npat); - if (c == FNM_NOMATCH) - return (0); - - len = STRLEN (string); - end = string + len; - - mlen = umatchlen (pat, len); - - switch (mtype) - { - case MATCH_ANY: - for (p = string; p <= end; p++) - { - if (match_pattern_char (pat, p)) - { - p1 = (mlen == -1) ? end : p + mlen; - /* p1 - p = length of portion of string to be considered - p = current position in string - mlen = number of characters consumed by match (-1 for entire string) - end = end of string - we want to break immediately if the potential match len - is greater than the number of characters remaining in the - string - */ - if (p1 > end) - break; - for ( ; p1 >= p; p1--) - { - c = *p1; *p1 = '\0'; - if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0) - { - *p1 = c; - *sp = p; - *ep = p1; - return 1; - } - *p1 = c; -#if 1 - /* If MLEN != -1, we have a fixed length pattern. */ - if (mlen != -1) - break; -#endif - } - } - } - - return (0); - - case MATCH_BEG: - if (match_pattern_char (pat, string) == 0) - return (0); - - for (p = (mlen == -1) ? end : string + mlen; p >= string; p--) - { - c = *p; *p = '\0'; - if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0) - { - *p = c; - *sp = string; - *ep = p; - return 1; - } - *p = c; - /* If MLEN != -1, we have a fixed length pattern. */ - if (mlen != -1) - break; - } - - return (0); - - case MATCH_END: - for (p = end - ((mlen == -1) ? len : mlen); p <= end; p++) - { - if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0) - { - *sp = p; - *ep = end; - return 1; - } - /* If MLEN != -1, we have a fixed length pattern. */ - if (mlen != -1) - break; - } - - return (0); - } - - return (0); -} - -#if defined (HANDLE_MULTIBYTE) -/* Match WPAT anywhere in WSTRING and return the match boundaries. - This returns 1 in case of a successful match, 0 otherwise. Wide - character version. */ -static int -match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep) - wchar_t *wstring; - char **indices; - size_t wstrlen; - wchar_t *wpat; - int mtype; - char **sp, **ep; -{ - wchar_t wc, *wp, *nwpat, *wp1; - size_t len; - int mlen; - int n, n1, n2, simple; - - simple = (wpat[0] != L'\\' && wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'['); -#if defined (EXTENDED_GLOB) - if (extended_glob) - simple &= (wpat[1] != L'(' || (wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'+' && wpat[0] != L'!' && wpat[0] != L'@')); /*)*/ -#endif - - /* If the pattern doesn't match anywhere in the string, go ahead and - short-circuit right away. A minor optimization, saves a bunch of - unnecessary calls to strmatch (up to N calls for a string of N - characters) if the match is unsuccessful. To preserve the semantics - of the substring matches below, we make sure that the pattern has - `*' as first and last character, making a new pattern if necessary. */ - len = wcslen (wpat); - if (wpat[0] != L'*' || (wpat[0] == L'*' && wpat[1] == WLPAREN && extended_glob) || wpat[len - 1] != L'*') - { - wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t)); - wp1 = wpat; - if (*wp1 != L'*' || (*wp1 == '*' && wp1[1] == WLPAREN && extended_glob)) - *wp++ = L'*'; - while (*wp1 != L'\0') - *wp++ = *wp1++; - if (wp1[-1] != L'*' || wp1[-2] == L'\\') - *wp++ = L'*'; - *wp = '\0'; - } - else - nwpat = wpat; - len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG); - if (nwpat != wpat) - free (nwpat); - if (len == FNM_NOMATCH) - return (0); - - mlen = wmatchlen (wpat, wstrlen); - -/* itrace("wmatchlen (%ls) -> %d", wpat, mlen); */ - switch (mtype) - { - case MATCH_ANY: - for (n = 0; n <= wstrlen; n++) - { - n2 = simple ? (*wpat == wstring[n]) : match_pattern_wchar (wpat, wstring + n); - if (n2) - { - n1 = (mlen == -1) ? wstrlen : n + mlen; - if (n1 > wstrlen) - break; - - for ( ; n1 >= n; n1--) - { - wc = wstring[n1]; wstring[n1] = L'\0'; - if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0) - { - wstring[n1] = wc; - *sp = indices[n]; - *ep = indices[n1]; - return 1; - } - wstring[n1] = wc; - /* If MLEN != -1, we have a fixed length pattern. */ - if (mlen != -1) - break; - } - } - } - - return (0); - - case MATCH_BEG: - if (match_pattern_wchar (wpat, wstring) == 0) - return (0); - - for (n = (mlen == -1) ? wstrlen : mlen; n >= 0; n--) - { - wc = wstring[n]; wstring[n] = L'\0'; - if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0) - { - wstring[n] = wc; - *sp = indices[0]; - *ep = indices[n]; - return 1; - } - wstring[n] = wc; - /* If MLEN != -1, we have a fixed length pattern. */ - if (mlen != -1) - break; - } - - return (0); - - case MATCH_END: - for (n = wstrlen - ((mlen == -1) ? wstrlen : mlen); n <= wstrlen; n++) - { - if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0) - { - *sp = indices[n]; - *ep = indices[wstrlen]; - return 1; - } - /* If MLEN != -1, we have a fixed length pattern. */ - if (mlen != -1) - break; - } - - return (0); - } - - return (0); -} -#endif /* HANDLE_MULTIBYTE */ - -static int -match_pattern (string, pat, mtype, sp, ep) - char *string, *pat; - int mtype; - char **sp, **ep; -{ -#if defined (HANDLE_MULTIBYTE) - int ret; - size_t n; - wchar_t *wstring, *wpat; - char **indices; - size_t slen, plen, mslen, mplen; -#endif - - if (string == 0 || *string == 0 || pat == 0 || *pat == 0) - return (0); - -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1) - { - if (mbsmbchar (string) == 0 && mbsmbchar (pat) == 0) - return (match_upattern (string, pat, mtype, sp, ep)); - - n = xdupmbstowcs (&wpat, NULL, pat); - if (n == (size_t)-1) - return (match_upattern (string, pat, mtype, sp, ep)); - n = xdupmbstowcs (&wstring, &indices, string); - if (n == (size_t)-1) - { - free (wpat); - return (match_upattern (string, pat, mtype, sp, ep)); - } - ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep); - - free (wpat); - free (wstring); - free (indices); - - return (ret); - } - else -#endif - return (match_upattern (string, pat, mtype, sp, ep)); -} - -static int -getpatspec (c, value) - int c; - char *value; -{ - if (c == '#') - return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT); - else /* c == '%' */ - return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT); -} - -/* Posix.2 says that the WORD should be run through tilde expansion, - parameter expansion, command substitution and arithmetic expansion. - This leaves the result quoted, so quote_string_for_globbing () has - to be called to fix it up for strmatch (). If QUOTED is non-zero, - it means that the entire expression was enclosed in double quotes. - This means that quoting characters in the pattern do not make any - special pattern characters quoted. For example, the `*' in the - following retains its special meaning: "${foo#'*'}". */ -static char * -getpattern (value, quoted, expandpat) - char *value; - int quoted, expandpat; -{ - char *pat, *tword; - WORD_LIST *l; -#if 0 - int i; -#endif - /* There is a problem here: how to handle single or double quotes in the - pattern string when the whole expression is between double quotes? - POSIX.2 says that enclosing double quotes do not cause the pattern to - be quoted, but does that leave us a problem with @ and array[@] and their - expansions inside a pattern? */ -#if 0 - if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword) - { - i = 0; - pat = string_extract_double_quoted (tword, &i, 1); - free (tword); - tword = pat; - } -#endif - - /* expand_string_for_rhs () leaves WORD quoted and does not perform - word splitting. */ - l = *value ? expand_string_for_rhs (value, - (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted, - (int *)NULL, (int *)NULL) - : (WORD_LIST *)0; - pat = string_list (l); - dispose_words (l); - if (pat) - { - tword = quote_string_for_globbing (pat, QGLOB_CVTNULL); - free (pat); - pat = tword; - } - return (pat); -} - -#if 0 -/* Handle removing a pattern from a string as a result of ${name%[%]value} - or ${name#[#]value}. */ -static char * -variable_remove_pattern (value, pattern, patspec, quoted) - char *value, *pattern; - int patspec, quoted; -{ - char *tword; - - tword = remove_pattern (value, pattern, patspec); - - return (tword); -} -#endif - -static char * -list_remove_pattern (list, pattern, patspec, itype, quoted) - WORD_LIST *list; - char *pattern; - int patspec, itype, quoted; -{ - WORD_LIST *new, *l; - WORD_DESC *w; - char *tword; - - for (new = (WORD_LIST *)NULL, l = list; l; l = l->next) - { - tword = remove_pattern (l->word->word, pattern, patspec); - w = alloc_word_desc (); - w->word = tword ? tword : savestring (""); - new = make_word_list (w, new); - } - - l = REVERSE_LIST (new, WORD_LIST *); - tword = string_list_pos_params (itype, l, quoted); - dispose_words (l); - - return (tword); -} - -static char * -parameter_list_remove_pattern (itype, pattern, patspec, quoted) - int itype; - char *pattern; - int patspec, quoted; -{ - char *ret; - WORD_LIST *list; - - list = list_rest_of_args (); - if (list == 0) - return ((char *)NULL); - ret = list_remove_pattern (list, pattern, patspec, itype, quoted); - dispose_words (list); - return (ret); -} - -#if defined (ARRAY_VARS) -static char * -array_remove_pattern (var, pattern, patspec, varname, quoted) - SHELL_VAR *var; - char *pattern; - int patspec; - char *varname; /* so we can figure out how it's indexed */ - int quoted; -{ - ARRAY *a; - HASH_TABLE *h; - int itype; - char *ret; - WORD_LIST *list; - SHELL_VAR *v; - - /* compute itype from varname here */ - v = array_variable_part (varname, &ret, 0); - - /* XXX */ - if (v && invisible_p (var)) - return ((char *)NULL); - - itype = ret[0]; - - a = (v && array_p (v)) ? array_cell (v) : 0; - h = (v && assoc_p (v)) ? assoc_cell (v) : 0; - - list = a ? array_to_word_list (a) : (h ? assoc_to_word_list (h) : 0); - if (list == 0) - return ((char *)NULL); - ret = list_remove_pattern (list, pattern, patspec, itype, quoted); - dispose_words (list); - - return ret; -} -#endif /* ARRAY_VARS */ - -static char * -parameter_brace_remove_pattern (varname, value, ind, patstr, rtype, quoted, flags) - char *varname, *value; - int ind; - char *patstr; - int rtype, quoted, flags; -{ - int vtype, patspec, starsub; - char *temp1, *val, *pattern; - SHELL_VAR *v; - - if (value == 0) - return ((char *)NULL); - - this_command_name = varname; - - vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); - if (vtype == -1) - return ((char *)NULL); - - starsub = vtype & VT_STARSUB; - vtype &= ~VT_STARSUB; - - patspec = getpatspec (rtype, patstr); - if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT) - patstr++; - - /* Need to pass getpattern newly-allocated memory in case of expansion -- - the expansion code will free the passed string on an error. */ - temp1 = savestring (patstr); - pattern = getpattern (temp1, quoted, 1); - free (temp1); - - temp1 = (char *)NULL; /* shut up gcc */ - switch (vtype) - { - case VT_VARIABLE: - case VT_ARRAYMEMBER: - temp1 = remove_pattern (val, pattern, patspec); - if (vtype == VT_VARIABLE) - FREE (val); - if (temp1) - { - val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) - ? quote_string (temp1) - : quote_escapes (temp1); - free (temp1); - temp1 = val; - } - break; -#if defined (ARRAY_VARS) - case VT_ARRAYVAR: - temp1 = array_remove_pattern (v, pattern, patspec, varname, quoted); - if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0)) - { - val = quote_escapes (temp1); - free (temp1); - temp1 = val; - } - break; -#endif - case VT_POSPARMS: - temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted); - if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0)) - { - val = quote_escapes (temp1); - free (temp1); - temp1 = val; - } - break; - } - - FREE (pattern); - return temp1; -} - -/******************************************* - * * - * Functions to expand WORD_DESCs * - * * - *******************************************/ - -/* Expand WORD, performing word splitting on the result. This does - parameter expansion, command substitution, arithmetic expansion, - word splitting, and quote removal. */ - -WORD_LIST * -expand_word (word, quoted) - WORD_DESC *word; - int quoted; -{ - WORD_LIST *result, *tresult; - - tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL); - result = word_list_split (tresult); - dispose_words (tresult); - return (result ? dequote_list (result) : result); -} - -/* Expand WORD, but do not perform word splitting on the result. This - does parameter expansion, command substitution, arithmetic expansion, - and quote removal. */ -WORD_LIST * -expand_word_unsplit (word, quoted) - WORD_DESC *word; - int quoted; -{ - WORD_LIST *result; - - expand_no_split_dollar_star = 1; -#if defined (HANDLE_MULTIBYTE) - if (ifs_firstc[0] == 0) -#else - if (ifs_firstc == 0) -#endif - word->flags |= W_NOSPLIT; - word->flags |= W_NOSPLIT2; - result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL); - expand_no_split_dollar_star = 0; - - return (result ? dequote_list (result) : result); -} - -/* Perform shell expansions on WORD, but do not perform word splitting or - quote removal on the result. Virtually identical to expand_word_unsplit; - could be combined if implementations don't diverge. */ -WORD_LIST * -expand_word_leave_quoted (word, quoted) - WORD_DESC *word; - int quoted; -{ - WORD_LIST *result; - - expand_no_split_dollar_star = 1; -#if defined (HANDLE_MULTIBYTE) - if (ifs_firstc[0] == 0) -#else - if (ifs_firstc == 0) -#endif - word->flags |= W_NOSPLIT; - word->flags |= W_NOSPLIT2; - result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL); - expand_no_split_dollar_star = 0; - - return result; -} - -#if defined (PROCESS_SUBSTITUTION) - -/*****************************************************************/ -/* */ -/* Hacking Process Substitution */ -/* */ -/*****************************************************************/ - -#if !defined (HAVE_DEV_FD) -/* Named pipes must be removed explicitly with `unlink'. This keeps a list - of FIFOs the shell has open. unlink_fifo_list will walk the list and - unlink all of them. add_fifo_list adds the name of an open FIFO to the - list. NFIFO is a count of the number of FIFOs in the list. */ -#define FIFO_INCR 20 - -struct temp_fifo { - char *file; - pid_t proc; -}; - -static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL; -static int nfifo; -static int fifo_list_size; - -void -clear_fifo_list () -{ -} - -char * -copy_fifo_list (sizep) - int *sizep; -{ - if (sizep) - *sizep = 0; - return (char *)NULL; -} - -static void -add_fifo_list (pathname) - char *pathname; -{ - if (nfifo >= fifo_list_size - 1) - { - fifo_list_size += FIFO_INCR; - fifo_list = (struct temp_fifo *)xrealloc (fifo_list, - fifo_list_size * sizeof (struct temp_fifo)); - } - - fifo_list[nfifo].file = savestring (pathname); - nfifo++; -} - -void -unlink_fifo (i) - int i; -{ - if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1)) - { - unlink (fifo_list[i].file); - free (fifo_list[i].file); - fifo_list[i].file = (char *)NULL; - fifo_list[i].proc = -1; - } -} - -void -unlink_fifo_list () -{ - int saved, i, j; - - if (nfifo == 0) - return; - - for (i = saved = 0; i < nfifo; i++) - { - if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1)) - { - unlink (fifo_list[i].file); - free (fifo_list[i].file); - fifo_list[i].file = (char *)NULL; - fifo_list[i].proc = -1; - } - else - saved++; - } - - /* If we didn't remove some of the FIFOs, compact the list. */ - if (saved) - { - for (i = j = 0; i < nfifo; i++) - if (fifo_list[i].file) - { - fifo_list[j].file = fifo_list[i].file; - fifo_list[j].proc = fifo_list[i].proc; - j++; - } - nfifo = j; - } - else - nfifo = 0; -} - -/* Take LIST, which is a bitmap denoting active FIFOs in fifo_list - from some point in the past, and close all open FIFOs in fifo_list - that are not marked as active in LIST. If LIST is NULL, close - everything in fifo_list. LSIZE is the number of elements in LIST, in - case it's larger than fifo_list_size (size of fifo_list). */ -void -close_new_fifos (list, lsize) - char *list; - int lsize; -{ - int i; - - if (list == 0) - { - unlink_fifo_list (); - return; - } - - for (i = 0; i < lsize; i++) - if (list[i] == 0 && i < fifo_list_size && fifo_list[i].proc != -1) - unlink_fifo (i); - - for (i = lsize; i < fifo_list_size; i++) - unlink_fifo (i); -} - -int -fifos_pending () -{ - return nfifo; -} - -int -num_fifos () -{ - return nfifo; -} - -static char * -make_named_pipe () -{ - char *tname; - - tname = sh_mktmpname ("sh-np", MT_USERANDOM|MT_USETMPDIR); - if (mkfifo (tname, 0600) < 0) - { - free (tname); - return ((char *)NULL); - } - - add_fifo_list (tname); - return (tname); -} - -#else /* HAVE_DEV_FD */ - -/* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell - has open to children. NFDS is a count of the number of bits currently - set in DEV_FD_LIST. TOTFDS is a count of the highest possible number - of open files. */ -static char *dev_fd_list = (char *)NULL; -static int nfds; -static int totfds; /* The highest possible number of open files. */ - -void -clear_fifo (i) - int i; -{ - if (dev_fd_list[i]) - { - dev_fd_list[i] = 0; - nfds--; - } -} - -void -clear_fifo_list () -{ - register int i; - - if (nfds == 0) - return; - - for (i = 0; nfds && i < totfds; i++) - clear_fifo (i); - - nfds = 0; -} - -char * -copy_fifo_list (sizep) - int *sizep; -{ - char *ret; - - if (nfds == 0 || totfds == 0) - { - if (sizep) - *sizep = 0; - return (char *)NULL; - } - - if (sizep) - *sizep = totfds; - ret = (char *)xmalloc (totfds); - return (memcpy (ret, dev_fd_list, totfds)); -} - -static void -add_fifo_list (fd) - int fd; -{ - if (dev_fd_list == 0 || fd >= totfds) - { - int ofds; - - ofds = totfds; - totfds = getdtablesize (); - if (totfds < 0 || totfds > 256) - totfds = 256; - if (fd >= totfds) - totfds = fd + 2; - - dev_fd_list = (char *)xrealloc (dev_fd_list, totfds); - memset (dev_fd_list + ofds, '\0', totfds - ofds); - } - - dev_fd_list[fd] = 1; - nfds++; -} - -int -fifos_pending () -{ - return 0; /* used for cleanup; not needed with /dev/fd */ -} - -int -num_fifos () -{ - return nfds; -} - -void -unlink_fifo (fd) - int fd; -{ - if (dev_fd_list[fd]) - { - close (fd); - dev_fd_list[fd] = 0; - nfds--; - } -} - -void -unlink_fifo_list () -{ - register int i; - - if (nfds == 0) - return; - - for (i = 0; nfds && i < totfds; i++) - unlink_fifo (i); - - nfds = 0; -} - -/* Take LIST, which is a snapshot copy of dev_fd_list from some point in - the past, and close all open fds in dev_fd_list that are not marked - as open in LIST. If LIST is NULL, close everything in dev_fd_list. - LSIZE is the number of elements in LIST, in case it's larger than - totfds (size of dev_fd_list). */ -void -close_new_fifos (list, lsize) - char *list; - int lsize; -{ - int i; - - if (list == 0) - { - unlink_fifo_list (); - return; - } - - for (i = 0; i < lsize; i++) - if (list[i] == 0 && i < totfds && dev_fd_list[i]) - unlink_fifo (i); - - for (i = lsize; i < totfds; i++) - unlink_fifo (i); -} - -#if defined (NOTDEF) -print_dev_fd_list () -{ - register int i; - - fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ()); - fflush (stderr); - - for (i = 0; i < totfds; i++) - { - if (dev_fd_list[i]) - fprintf (stderr, " %d", i); - } - fprintf (stderr, "\n"); -} -#endif /* NOTDEF */ - -static char * -make_dev_fd_filename (fd) - int fd; -{ - char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p; - - ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 8); - - strcpy (ret, DEV_FD_PREFIX); - p = inttostr (fd, intbuf, sizeof (intbuf)); - strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p); - - add_fifo_list (fd); - return (ret); -} - -#endif /* HAVE_DEV_FD */ - -/* Return a filename that will open a connection to the process defined by - executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return - a filename in /dev/fd corresponding to a descriptor that is one of the - ends of the pipe. If not defined, we use named pipes on systems that have - them. Systems without /dev/fd and named pipes are out of luck. - - OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or - use the read end of the pipe and dup that file descriptor to fd 0 in - the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for - writing or use the write end of the pipe in the child, and dup that - file descriptor to fd 1 in the child. The parent does the opposite. */ - -static char * -process_substitute (string, open_for_read_in_child) - char *string; - int open_for_read_in_child; -{ - char *pathname; - int fd, result; - pid_t old_pid, pid; -#if defined (HAVE_DEV_FD) - int parent_pipe_fd, child_pipe_fd; - int fildes[2]; -#endif /* HAVE_DEV_FD */ -#if defined (JOB_CONTROL) - pid_t old_pipeline_pgrp; -#endif - - if (!string || !*string || wordexp_only) - return ((char *)NULL); - -#if !defined (HAVE_DEV_FD) - pathname = make_named_pipe (); -#else /* HAVE_DEV_FD */ - if (pipe (fildes) < 0) - { - sys_error (_("cannot make pipe for process substitution")); - return ((char *)NULL); - } - /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of - the pipe in the parent, otherwise the read end. */ - parent_pipe_fd = fildes[open_for_read_in_child]; - child_pipe_fd = fildes[1 - open_for_read_in_child]; - /* Move the parent end of the pipe to some high file descriptor, to - avoid clashes with FDs used by the script. */ - parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64); - - pathname = make_dev_fd_filename (parent_pipe_fd); -#endif /* HAVE_DEV_FD */ - - if (pathname == 0) - { - sys_error (_("cannot make pipe for process substitution")); - return ((char *)NULL); - } - - old_pid = last_made_pid; - -#if defined (JOB_CONTROL) - old_pipeline_pgrp = pipeline_pgrp; - pipeline_pgrp = shell_pgrp; - save_pipeline (1); -#endif /* JOB_CONTROL */ - - pid = make_child ((char *)NULL, 1); - if (pid == 0) - { - reset_terminating_signals (); /* XXX */ - free_pushed_string_input (); - /* Cancel traps, in trap.c. */ - restore_original_signals (); /* XXX - what about special builtins? bash-4.2 */ - setup_async_signals (); - subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB; - } - -#if defined (JOB_CONTROL) - set_sigchld_handler (); - stop_making_children (); - /* XXX - should we only do this in the parent? (as in command subst) */ - pipeline_pgrp = old_pipeline_pgrp; -#endif /* JOB_CONTROL */ - - if (pid < 0) - { - sys_error (_("cannot make child for process substitution")); - free (pathname); -#if defined (HAVE_DEV_FD) - close (parent_pipe_fd); - close (child_pipe_fd); -#endif /* HAVE_DEV_FD */ - return ((char *)NULL); - } - - if (pid > 0) - { -#if defined (JOB_CONTROL) - restore_pipeline (1); -#endif - -#if !defined (HAVE_DEV_FD) - fifo_list[nfifo-1].proc = pid; -#endif - - last_made_pid = old_pid; - -#if defined (JOB_CONTROL) && defined (PGRP_PIPE) - close_pgrp_pipe (); -#endif /* JOB_CONTROL && PGRP_PIPE */ - -#if defined (HAVE_DEV_FD) - close (child_pipe_fd); -#endif /* HAVE_DEV_FD */ - - return (pathname); - } - - set_sigint_handler (); - -#if defined (JOB_CONTROL) - set_job_control (0); -#endif /* JOB_CONTROL */ - -#if !defined (HAVE_DEV_FD) - /* Open the named pipe in the child. */ - fd = open (pathname, open_for_read_in_child ? O_RDONLY : O_WRONLY); - if (fd < 0) - { - /* Two separate strings for ease of translation. */ - if (open_for_read_in_child) - sys_error (_("cannot open named pipe %s for reading"), pathname); - else - sys_error (_("cannot open named pipe %s for writing"), pathname); - - exit (127); - } - if (open_for_read_in_child) - { - if (sh_unset_nodelay_mode (fd) < 0) - { - sys_error (_("cannot reset nodelay mode for fd %d"), fd); - exit (127); - } - } -#else /* HAVE_DEV_FD */ - fd = child_pipe_fd; -#endif /* HAVE_DEV_FD */ - - if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0) - { - sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname, - open_for_read_in_child ? 0 : 1); - exit (127); - } - - if (fd != (open_for_read_in_child ? 0 : 1)) - close (fd); - - /* Need to close any files that this process has open to pipes inherited - from its parent. */ - if (current_fds_to_close) - { - close_fd_bitmap (current_fds_to_close); - current_fds_to_close = (struct fd_bitmap *)NULL; - } - -#if defined (HAVE_DEV_FD) - /* Make sure we close the parent's end of the pipe and clear the slot - in the fd list so it is not closed later, if reallocated by, for - instance, pipe(2). */ - close (parent_pipe_fd); - dev_fd_list[parent_pipe_fd] = 0; -#endif /* HAVE_DEV_FD */ - - /* subshells shouldn't have this flag, which controls using the temporary - environment for variable lookups. */ - expanding_redir = 0; - - result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST)); - -#if !defined (HAVE_DEV_FD) - /* Make sure we close the named pipe in the child before we exit. */ - close (open_for_read_in_child ? 0 : 1); -#endif /* !HAVE_DEV_FD */ - - last_command_exit_value = result; - result = run_exit_trap (); - exit (result); - /*NOTREACHED*/ -} -#endif /* PROCESS_SUBSTITUTION */ - -/***********************************/ -/* */ -/* Command Substitution */ -/* */ -/***********************************/ - -static char * -read_comsub (fd, quoted, rflag) - int fd, quoted; - int *rflag; -{ - char *istring, buf[128], *bufp, *s; - int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul; - ssize_t bufn; - - istring = (char *)NULL; - istring_index = istring_size = bufn = tflag = 0; - - for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++) - skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL; - - /* Read the output of the command through the pipe. This may need to be - changed to understand multibyte characters in the future. */ - while (1) - { - if (fd < 0) - break; - if (--bufn <= 0) - { - bufn = zread (fd, buf, sizeof (buf)); - if (bufn <= 0) - break; - bufp = buf; - } - c = *bufp++; - - if (c == 0) - { -#if 0 - internal_warning ("read_comsub: ignored null byte in input"); -#endif - continue; - } - - /* Add the character to ISTRING, possibly after resizing it. */ - RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE); - - /* This is essentially quote_string inline */ - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */) - istring[istring_index++] = CTLESC; - /* Escape CTLESC and CTLNUL in the output to protect those characters - from the rest of the word expansions (word splitting and globbing.) - This is essentially quote_escapes inline. */ - else if (skip_ctlesc == 0 && c == CTLESC) - { - tflag |= W_HASCTLESC; - istring[istring_index++] = CTLESC; - } - else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0))) - istring[istring_index++] = CTLESC; - - istring[istring_index++] = c; - -#if 0 -#if defined (__CYGWIN__) - if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r') - { - istring_index--; - istring[istring_index - 1] = '\n'; - } -#endif -#endif - } - - if (istring) - istring[istring_index] = '\0'; - - /* If we read no output, just return now and save ourselves some - trouble. */ - if (istring_index == 0) - { - FREE (istring); - if (rflag) - *rflag = tflag; - return (char *)NULL; - } - - /* Strip trailing newlines from the output of the command. */ - if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) - { - while (istring_index > 0) - { - if (istring[istring_index - 1] == '\n') - { - --istring_index; - - /* If the newline was quoted, remove the quoting char. */ - if (istring[istring_index - 1] == CTLESC) - --istring_index; - } - else - break; - } - istring[istring_index] = '\0'; - } - else - strip_trailing (istring, istring_index - 1, 1); - - if (rflag) - *rflag = tflag; - return istring; -} - -/* Perform command substitution on STRING. This returns a WORD_DESC * with the - contained string possibly quoted. */ -WORD_DESC * -command_substitute (string, quoted) - char *string; - int quoted; -{ - pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid; - char *istring; - int result, fildes[2], function_value, pflags, rc, tflag; - WORD_DESC *ret; - - istring = (char *)NULL; - - /* Don't fork () if there is no need to. In the case of no command to - run, just return NULL. */ - if (!string || !*string || (string[0] == '\n' && !string[1])) - return ((WORD_DESC *)NULL); - - if (wordexp_only && read_but_dont_execute) - { - last_command_exit_value = EX_WEXPCOMSUB; - jump_to_top_level (EXITPROG); - } - - /* We're making the assumption here that the command substitution will - eventually run a command from the file system. Since we'll run - maybe_make_export_env in this subshell before executing that command, - the parent shell and any other shells it starts will have to remake - the environment. If we make it before we fork, other shells won't - have to. Don't bother if we have any temporary variable assignments, - though, because the export environment will be remade after this - command completes anyway, but do it if all the words to be expanded - are variable assignments. */ - if (subst_assign_varlist == 0 || garglist == 0) - maybe_make_export_env (); /* XXX */ - - /* Flags to pass to parse_and_execute() */ - pflags = (interactive && sourcelevel == 0) ? SEVAL_RESETLINE : 0; - - /* Pipe the output of executing STRING into the current shell. */ - if (pipe (fildes) < 0) - { - sys_error (_("cannot make pipe for command substitution")); - goto error_exit; - } - - old_pid = last_made_pid; -#if defined (JOB_CONTROL) - old_pipeline_pgrp = pipeline_pgrp; - /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */ - if ((subshell_environment & SUBSHELL_PIPE) == 0) - pipeline_pgrp = shell_pgrp; - cleanup_the_pipeline (); -#endif /* JOB_CONTROL */ - - old_async_pid = last_asynchronous_pid; - pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC); - last_asynchronous_pid = old_async_pid; - - if (pid == 0) - { - /* Reset the signal handlers in the child, but don't free the - trap strings. Set a flag noting that we have to free the - trap strings if we run trap to change a signal disposition. */ - reset_signal_handlers (); - subshell_environment |= SUBSHELL_RESETTRAP; - } - -#if defined (JOB_CONTROL) - /* XXX DO THIS ONLY IN PARENT ? XXX */ - set_sigchld_handler (); - stop_making_children (); - if (pid != 0) - pipeline_pgrp = old_pipeline_pgrp; -#else - stop_making_children (); -#endif /* JOB_CONTROL */ - - if (pid < 0) - { - sys_error (_("cannot make child for command substitution")); - error_exit: - - last_made_pid = old_pid; - - FREE (istring); - close (fildes[0]); - close (fildes[1]); - return ((WORD_DESC *)NULL); - } - - if (pid == 0) - { - set_sigint_handler (); /* XXX */ - - free_pushed_string_input (); - - if (dup2 (fildes[1], 1) < 0) - { - sys_error (_("command_substitute: cannot duplicate pipe as fd 1")); - exit (EXECUTION_FAILURE); - } - - /* If standard output is closed in the parent shell - (such as after `exec >&-'), file descriptor 1 will be - the lowest available file descriptor, and end up in - fildes[0]. This can happen for stdin and stderr as well, - but stdout is more important -- it will cause no output - to be generated from this command. */ - if ((fildes[1] != fileno (stdin)) && - (fildes[1] != fileno (stdout)) && - (fildes[1] != fileno (stderr))) - close (fildes[1]); - - if ((fildes[0] != fileno (stdin)) && - (fildes[0] != fileno (stdout)) && - (fildes[0] != fileno (stderr))) - close (fildes[0]); - -#ifdef __CYGWIN__ - /* Let stdio know the fd may have changed from text to binary mode, and - make sure to preserve stdout line buffering. */ - freopen (NULL, "w", stdout); - sh_setlinebuf (stdout); -#endif /* __CYGWIN__ */ - - /* The currently executing shell is not interactive. */ - interactive = 0; - - /* This is a subshell environment. */ - subshell_environment |= SUBSHELL_COMSUB; - - change_flag ('v', FLAG_OFF); - - /* When not in POSIX mode, command substitution does not inherit - the -e flag. */ - if (posixly_correct == 0) - { - builtin_ignoring_errexit = 0; - change_flag ('e', FLAG_OFF); - set_shellopts (); - } - - remove_quoted_escapes (string); - - startup_state = 2; /* see if we can avoid a fork */ - /* Give command substitution a place to jump back to on failure, - so we don't go back up to main (). */ - result = setjmp_nosigs (top_level); - - /* If we're running a command substitution inside a shell function, - trap `return' so we don't return from the function in the subshell - and go off to never-never land. */ - if (result == 0 && return_catch_flag) - function_value = setjmp_nosigs (return_catch); - else - function_value = 0; - - if (result == ERREXIT) - rc = last_command_exit_value; - else if (result == EXITPROG) - rc = last_command_exit_value; - else if (result) - rc = EXECUTION_FAILURE; - else if (function_value) - rc = return_catch_value; - else - { - subshell_level++; - rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST); - subshell_level--; - } - - last_command_exit_value = rc; - rc = run_exit_trap (); -#if defined (PROCESS_SUBSTITUTION) - unlink_fifo_list (); -#endif - exit (rc); - } - else - { -#if defined (JOB_CONTROL) && defined (PGRP_PIPE) - close_pgrp_pipe (); -#endif /* JOB_CONTROL && PGRP_PIPE */ - - close (fildes[1]); - - tflag = 0; - istring = read_comsub (fildes[0], quoted, &tflag); - - close (fildes[0]); - - current_command_subst_pid = pid; - last_command_exit_value = wait_for (pid); - last_command_subst_pid = pid; - last_made_pid = old_pid; - -#if defined (JOB_CONTROL) - /* If last_command_exit_value > 128, then the substituted command - was terminated by a signal. If that signal was SIGINT, then send - SIGINT to ourselves. This will break out of loops, for instance. */ - if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT) - kill (getpid (), SIGINT); - - /* wait_for gives the terminal back to shell_pgrp. If some other - process group should have it, give it away to that group here. - pipeline_pgrp is non-zero only while we are constructing a - pipeline, so what we are concerned about is whether or not that - pipeline was started in the background. A pipeline started in - the background should never get the tty back here. */ - if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0) - give_terminal_to (pipeline_pgrp, 0); -#endif /* JOB_CONTROL */ - - ret = alloc_word_desc (); - ret->word = istring; - ret->flags = tflag; - - return ret; - } -} - -/******************************************************** - * * - * Utility functions for parameter expansion * - * * - ********************************************************/ - -#if defined (ARRAY_VARS) - -static arrayind_t -array_length_reference (s) - char *s; -{ - int len; - arrayind_t ind; - char *akey; - char *t, c; - ARRAY *array; - HASH_TABLE *h; - SHELL_VAR *var; - - var = array_variable_part (s, &t, &len); - - /* If unbound variables should generate an error, report one and return - failure. */ - if ((var == 0 || invisible_p (var) || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error) - { - c = *--t; - *t = '\0'; - last_command_exit_value = EXECUTION_FAILURE; - err_unboundvar (s); - *t = c; - return (-1); - } - else if (var == 0 || invisible_p (var)) - return 0; - - /* We support a couple of expansions for variables that are not arrays. - We'll return the length of the value for v[0], and 1 for v[@] or - v[*]. Return 0 for everything else. */ - - array = array_p (var) ? array_cell (var) : (ARRAY *)NULL; - h = assoc_p (var) ? assoc_cell (var) : (HASH_TABLE *)NULL; - - if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']') - { - if (assoc_p (var)) - return (h ? assoc_num_elements (h) : 0); - else if (array_p (var)) - return (array ? array_num_elements (array) : 0); - else - return (var_isset (var) ? 1 : 0); - } - - if (assoc_p (var)) - { - t[len - 1] = '\0'; - akey = expand_assignment_string_to_string (t, 0); /* [ */ - t[len - 1] = ']'; - if (akey == 0 || *akey == 0) - { - err_badarraysub (t); - FREE (akey); - return (-1); - } - t = assoc_reference (assoc_cell (var), akey); - free (akey); - } - else - { - ind = array_expand_index (var, t, len); - /* negative subscripts to indexed arrays count back from end */ - if (var && array_p (var) && ind < 0) - ind = array_max_index (array_cell (var)) + 1 + ind; - if (ind < 0) - { - err_badarraysub (t); - return (-1); - } - if (array_p (var)) - t = array_reference (array, ind); - else - t = (ind == 0) ? value_cell (var) : (char *)NULL; - } - - len = MB_STRLEN (t); - return (len); -} -#endif /* ARRAY_VARS */ - -static int -valid_brace_expansion_word (name, var_is_special) - char *name; - int var_is_special; -{ - if (DIGIT (*name) && all_digits (name)) - return 1; - else if (var_is_special) - return 1; -#if defined (ARRAY_VARS) - else if (valid_array_reference (name)) - return 1; -#endif /* ARRAY_VARS */ - else if (legal_identifier (name)) - return 1; - else - return 0; -} - -static int -chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at) - char *name; - int quoted; - int *quoted_dollar_atp, *contains_dollar_at; -{ - char *temp1; - - if (name == 0) - { - if (quoted_dollar_atp) - *quoted_dollar_atp = 0; - if (contains_dollar_at) - *contains_dollar_at = 0; - return 0; - } - - /* check for $@ and $* */ - if (name[0] == '@' && name[1] == 0) - { - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) - *quoted_dollar_atp = 1; - if (contains_dollar_at) - *contains_dollar_at = 1; - return 1; - } - else if (name[0] == '*' && name[1] == '\0' && quoted == 0) - { - if (contains_dollar_at) - *contains_dollar_at = 1; - return 1; - } - - /* Now check for ${array[@]} and ${array[*]} */ -#if defined (ARRAY_VARS) - else if (valid_array_reference (name)) - { - temp1 = mbschr (name, '['); - if (temp1 && temp1[1] == '@' && temp1[2] == ']') - { - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) - *quoted_dollar_atp = 1; - if (contains_dollar_at) - *contains_dollar_at = 1; - return 1; - } /* [ */ - /* ${array[*]}, when unquoted, should be treated like ${array[@]}, - which should result in separate words even when IFS is unset. */ - if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0) - { - if (contains_dollar_at) - *contains_dollar_at = 1; - return 1; - } - } -#endif - return 0; -} - -/* Parameter expand NAME, and return a new string which is the expansion, - or NULL if there was no expansion. - VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in - the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that - NAME was found inside of a double-quoted expression. */ -static WORD_DESC * -parameter_brace_expand_word (name, var_is_special, quoted, pflags, indp) - char *name; - int var_is_special, quoted, pflags; - arrayind_t *indp; -{ - WORD_DESC *ret; - char *temp, *tt; - intmax_t arg_index; - SHELL_VAR *var; - int atype, rflags; - arrayind_t ind; - - ret = 0; - temp = 0; - rflags = 0; - - if (indp) - *indp = INTMAX_MIN; - - /* Handle multiple digit arguments, as in ${11}. */ - if (legal_number (name, &arg_index)) - { - tt = get_dollar_var_value (arg_index); - if (tt) - temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) - ? quote_string (tt) - : quote_escapes (tt); - else - temp = (char *)NULL; - FREE (tt); - } - else if (var_is_special) /* ${@} */ - { - int sindex; - tt = (char *)xmalloc (2 + strlen (name)); - tt[sindex = 0] = '$'; - strcpy (tt + 1, name); - - ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL, - (int *)NULL, (int *)NULL, pflags); - free (tt); - } -#if defined (ARRAY_VARS) - else if (valid_array_reference (name)) - { -expand_arrayref: - /* XXX - does this leak if name[@] or name[*]? */ - if (pflags & PF_ASSIGNRHS) - { - temp = array_variable_name (name, &tt, (int *)0); - if (ALL_ELEMENT_SUB (tt[0]) && tt[1] == ']') - temp = array_value (name, quoted|Q_DOUBLE_QUOTES, 0, &atype, &ind); - else - temp = array_value (name, quoted, 0, &atype, &ind); - } - else - temp = array_value (name, quoted, 0, &atype, &ind); - if (atype == 0 && temp) - { - temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) - ? quote_string (temp) - : quote_escapes (temp); - rflags |= W_ARRAYIND; - if (indp) - *indp = ind; - } - else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) - rflags |= W_HASQUOTEDNULL; - } -#endif - else if (var = find_variable (name)) - { - if (var_isset (var) && invisible_p (var) == 0) - { -#if defined (ARRAY_VARS) - if (assoc_p (var)) - temp = assoc_reference (assoc_cell (var), "0"); - else if (array_p (var)) - temp = array_reference (array_cell (var), 0); - else - temp = value_cell (var); -#else - temp = value_cell (var); -#endif - - if (temp) - temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) - ? quote_string (temp) - : quote_escapes (temp); - } - else - temp = (char *)NULL; - } - else if (var = find_variable_last_nameref (name)) - { - temp = nameref_cell (var); -#if defined (ARRAY_VARS) - /* Handle expanding nameref whose value is x[n] */ - if (temp && *temp && valid_array_reference (temp)) - { - name = temp; - goto expand_arrayref; - } - else -#endif - /* y=2 ; typeset -n x=y; echo ${x} is not the same as echo ${2} in ksh */ - if (temp && *temp && legal_identifier (temp) == 0) - { - last_command_exit_value = EXECUTION_FAILURE; - report_error (_("%s: invalid variable name for name reference"), temp); - temp = &expand_param_error; - } - else - temp = (char *)NULL; - } - else - temp = (char *)NULL; - - if (ret == 0) - { - ret = alloc_word_desc (); - ret->word = temp; - ret->flags |= rflags; - } - return ret; -} - -static char * -parameter_brace_find_indir (name, var_is_special, quoted, find_nameref) - char *name; - int var_is_special, quoted, find_nameref; -{ - char *temp, *t; - WORD_DESC *w; - SHELL_VAR *v; - - if (find_nameref && var_is_special == 0 && (v = find_variable_last_nameref (name)) && - nameref_p (v) && (t = nameref_cell (v)) && *t) - return (savestring (t)); - - /* If var_is_special == 0, and name is not an array reference, this does - more expansion than necessary. It should really look up the variable's - value and not try to expand it. */ - w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND, 0); - t = w->word; - /* Have to dequote here if necessary */ - if (t) - { - temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) - ? dequote_string (t) - : dequote_escapes (t); - free (t); - t = temp; - } - dispose_word_desc (w); - - return t; -} - -/* Expand an indirect reference to a variable: ${!NAME} expands to the - value of the variable whose name is the value of NAME. */ -static WORD_DESC * -parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at) - char *name; - int var_is_special, quoted; - int *quoted_dollar_atp, *contains_dollar_at; -{ - char *temp, *t; - WORD_DESC *w; - SHELL_VAR *v; - - /* See if it's a nameref first, behave in ksh93-compatible fashion. - There is at least one incompatibility: given ${!foo[0]} where foo=bar, - bash performs an indirect lookup on foo[0] and expands the result; - ksh93 expands bar[0]. We could do that here -- there are enough usable - primitives to do that -- but do not at this point. */ - if (var_is_special == 0 && (v = find_variable_last_nameref (name))) - { - if (nameref_p (v) && (t = nameref_cell (v)) && *t) - { - w = alloc_word_desc (); - w->word = savestring (t); - w->flags = 0; - return w; - } - } - - t = parameter_brace_find_indir (name, var_is_special, quoted, 0); - - chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at); - if (t == 0) - return (WORD_DESC *)NULL; - - w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0, 0); - free (t); - - return w; -} - -/* Expand the right side of a parameter expansion of the form ${NAMEcVALUE}, - depending on the value of C, the separating character. C can be one of - "-", "+", or "=". QUOTED is true if the entire brace expression occurs - between double quotes. */ -static WORD_DESC * -parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat) - char *name, *value; - int c, quoted, *qdollaratp, *hasdollarat; -{ - WORD_DESC *w; - WORD_LIST *l; - char *t, *t1, *temp, *vname; - int hasdol; - - /* If the entire expression is between double quotes, we want to treat - the value as a double-quoted string, with the exception that we strip - embedded unescaped double quotes (for sh backwards compatibility). */ - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value) - { - hasdol = 0; - temp = string_extract_double_quoted (value, &hasdol, 1); - } - else - temp = value; - - w = alloc_word_desc (); - hasdol = 0; - /* XXX was 0 not quoted */ - l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL) - : (WORD_LIST *)0; - if (hasdollarat) - *hasdollarat = hasdol || (l && l->next); - if (temp != value) - free (temp); - if (l) - { - /* The expansion of TEMP returned something. We need to treat things - slightly differently if HASDOL is non-zero. If we have "$@", the - individual words have already been quoted. We need to turn them - into a string with the words separated by the first character of - $IFS without any additional quoting, so string_list_dollar_at won't - do the right thing. We use string_list_dollar_star instead. */ - temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l); - - /* If l->next is not null, we know that TEMP contained "$@", since that - is the only expansion that creates more than one word. */ - if (qdollaratp && ((hasdol && quoted) || l->next)) - *qdollaratp = 1; - /* If we have a quoted null result (QUOTED_NULL(temp)) and the word is - a quoted null (l->next == 0 && QUOTED_NULL(l->word->word)), the - flags indicate it (l->word->flags & W_HASQUOTEDNULL), and the - expansion is quoted (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) - (which is more paranoia than anything else), we need to return the - quoted null string and set the flags to indicate it. */ - if (l->next == 0 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL (temp) && QUOTED_NULL (l->word->word) && (l->word->flags & W_HASQUOTEDNULL)) - { - w->flags |= W_HASQUOTEDNULL; - } - dispose_words (l); - } - else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol) - { - /* The brace expansion occurred between double quotes and there was - a $@ in TEMP. It does not matter if the $@ is quoted, as long as - it does not expand to anything. In this case, we want to return - a quoted empty string. */ - temp = make_quoted_char ('\0'); - w->flags |= W_HASQUOTEDNULL; - } - else - temp = (char *)NULL; - - if (c == '-' || c == '+') - { - w->word = temp; - return w; - } - - /* c == '=' */ - t = temp ? savestring (temp) : savestring (""); - t1 = dequote_string (t); - free (t); - - /* bash-4.4/5.0 */ - vname = name; - if (*name == '!' && - (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1]) || VALID_INDIR_PARAM (name[1]))) - { - vname = parameter_brace_find_indir (name + 1, SPECIAL_VAR (name, 1), quoted, 1); - if (vname == 0 || *vname == 0) - { - report_error (_("%s: invalid indirect expansion"), name); - free (vname); - dispose_word (w); - return &expand_wdesc_error; - } - if (legal_identifier (vname) == 0) - { - report_error (_("%s: invalid variable name"), vname); - free (vname); - dispose_word (w); - return &expand_wdesc_error; - } - } - -#if defined (ARRAY_VARS) - if (valid_array_reference (vname)) - assign_array_element (vname, t1, 0); - else -#endif /* ARRAY_VARS */ - bind_variable (vname, t1, 0); -#if 0 - if (STREQ (vname, "IFS") == 0) -#endif - stupidly_hack_special_variables (vname); - - if (vname != name) - free (vname); - - /* From Posix group discussion Feb-March 2010. Issue 7 0000221 */ - free (temp); - - w->word = t1; - return w; -} - -/* Deal with the right hand side of a ${name:?value} expansion in the case - that NAME is null or not set. If VALUE is non-null it is expanded and - used as the error message to print, otherwise a standard message is - printed. */ -static void -parameter_brace_expand_error (name, value) - char *name, *value; -{ - WORD_LIST *l; - char *temp; - - last_command_exit_value = EXECUTION_FAILURE; /* ensure it's non-zero */ - if (value && *value) - { - l = expand_string (value, 0); - temp = string_list (l); - report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */ - FREE (temp); - dispose_words (l); - } - else - report_error (_("%s: parameter null or not set"), name); - - /* Free the data we have allocated during this expansion, since we - are about to longjmp out. */ - free (name); - FREE (value); -} - -/* Return 1 if NAME is something for which parameter_brace_expand_length is - OK to do. */ -static int -valid_length_expression (name) - char *name; -{ - return (name[1] == '\0' || /* ${#} */ - ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */ - (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */ -#if defined (ARRAY_VARS) - valid_array_reference (name + 1) || /* ${#a[7]} */ -#endif - legal_identifier (name + 1)); /* ${#PS1} */ -} - -/* Handle the parameter brace expansion that requires us to return the - length of a parameter. */ -static intmax_t -parameter_brace_expand_length (name) - char *name; -{ - char *t, *newname; - intmax_t number, arg_index; - WORD_LIST *list; -#if defined (ARRAY_VARS) - SHELL_VAR *var; -#endif - - if (name[1] == '\0') /* ${#} */ - number = number_of_args (); - else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */ - number = number_of_args (); - else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') - { - /* Take the lengths of some of the shell's special parameters. */ - switch (name[1]) - { - case '-': - t = which_set_flags (); - break; - case '?': - t = itos (last_command_exit_value); - break; - case '$': - t = itos (dollar_dollar_pid); - break; - case '!': - if (last_asynchronous_pid == NO_PID) - t = (char *)NULL; /* XXX - error if set -u set? */ - else - t = itos (last_asynchronous_pid); - break; - case '#': - t = itos (number_of_args ()); - break; - } - number = STRLEN (t); - FREE (t); - } -#if defined (ARRAY_VARS) - else if (valid_array_reference (name + 1)) - number = array_length_reference (name + 1); -#endif /* ARRAY_VARS */ - else - { - number = 0; - - if (legal_number (name + 1, &arg_index)) /* ${#1} */ - { - t = get_dollar_var_value (arg_index); - if (t == 0 && unbound_vars_is_error) - return INTMAX_MIN; - number = MB_STRLEN (t); - FREE (t); - } -#if defined (ARRAY_VARS) - else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var))) - { - if (assoc_p (var)) - t = assoc_reference (assoc_cell (var), "0"); - else - t = array_reference (array_cell (var), 0); - if (t == 0 && unbound_vars_is_error) - return INTMAX_MIN; - number = MB_STRLEN (t); - } -#endif - else /* ${#PS1} */ - { - newname = savestring (name); - newname[0] = '$'; - list = expand_string (newname, Q_DOUBLE_QUOTES); - t = list ? string_list (list) : (char *)NULL; - free (newname); - if (list) - dispose_words (list); - - number = t ? MB_STRLEN (t) : 0; - FREE (t); - } - } - - return (number); -} - -/* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression, - so we do some ad-hoc parsing of an arithmetic expression to find - the first DELIM, instead of using strchr(3). Two rules: - 1. If the substring contains a `(', read until closing `)'. - 2. If the substring contains a `?', read past one `:' for each `?'. -*/ - -static char * -skiparith (substr, delim) - char *substr; - int delim; -{ - size_t sublen; - int skipcol, pcount, i; - DECLARE_MBSTATE; - - sublen = strlen (substr); - i = skipcol = pcount = 0; - while (substr[i]) - { - /* Balance parens */ - if (substr[i] == LPAREN) - { - pcount++; - i++; - continue; - } - if (substr[i] == RPAREN && pcount) - { - pcount--; - i++; - continue; - } - if (pcount) - { - ADVANCE_CHAR (substr, sublen, i); - continue; - } - - /* Skip one `:' for each `?' */ - if (substr[i] == ':' && skipcol) - { - skipcol--; - i++; - continue; - } - if (substr[i] == delim) - break; - if (substr[i] == '?') - { - skipcol++; - i++; - continue; - } - ADVANCE_CHAR (substr, sublen, i); - } - - return (substr + i); -} - -/* Verify and limit the start and end of the desired substring. If - VTYPE == 0, a regular shell variable is being used; if it is 1, - then the positional parameters are being used; if it is 2, then - VALUE is really a pointer to an array variable that should be used. - Return value is 1 if both values were OK, 0 if there was a problem - with an invalid expression, or -1 if the values were out of range. */ -static int -verify_substring_values (v, value, substr, vtype, e1p, e2p) - SHELL_VAR *v; - char *value, *substr; - int vtype; - intmax_t *e1p, *e2p; -{ - char *t, *temp1, *temp2; - arrayind_t len; - int expok; -#if defined (ARRAY_VARS) - ARRAY *a; - HASH_TABLE *h; -#endif - - /* duplicate behavior of strchr(3) */ - t = skiparith (substr, ':'); - if (*t && *t == ':') - *t = '\0'; - else - t = (char *)0; - - temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES); - *e1p = evalexp (temp1, &expok); - free (temp1); - if (expok == 0) - return (0); - - len = -1; /* paranoia */ - switch (vtype) - { - case VT_VARIABLE: - case VT_ARRAYMEMBER: - len = MB_STRLEN (value); - break; - case VT_POSPARMS: - len = number_of_args () + 1; - if (*e1p == 0) - len++; /* add one arg if counting from $0 */ - break; -#if defined (ARRAY_VARS) - case VT_ARRAYVAR: - /* For arrays, the first value deals with array indices. Negative - offsets count from one past the array's maximum index. Associative - arrays treat the number of elements as the maximum index. */ - if (assoc_p (v)) - { - h = assoc_cell (v); - len = assoc_num_elements (h) + (*e1p < 0); - } - else - { - a = (ARRAY *)value; - len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */ - } - break; -#endif - } - - if (len == -1) /* paranoia */ - return -1; - - if (*e1p < 0) /* negative offsets count from end */ - *e1p += len; - - if (*e1p > len || *e1p < 0) - return (-1); - -#if defined (ARRAY_VARS) - /* For arrays, the second offset deals with the number of elements. */ - if (vtype == VT_ARRAYVAR) - len = assoc_p (v) ? assoc_num_elements (h) : array_num_elements (a); -#endif - - if (t) - { - t++; - temp2 = savestring (t); - temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES); - free (temp2); - t[-1] = ':'; - *e2p = evalexp (temp1, &expok); - free (temp1); - if (expok == 0) - return (0); -#if 1 - if ((vtype == VT_ARRAYVAR || vtype == VT_POSPARMS) && *e2p < 0) -#else - /* bash-4.3: allow positional parameter length < 0 to count backwards - from end of positional parameters */ - if (vtype == VT_ARRAYVAR && *e2p < 0) -#endif - { - internal_error (_("%s: substring expression < 0"), t); - return (0); - } -#if defined (ARRAY_VARS) - /* In order to deal with sparse arrays, push the intelligence about how - to deal with the number of elements desired down to the array- - specific functions. */ - if (vtype != VT_ARRAYVAR) -#endif - { - if (*e2p < 0) - { - *e2p += len; - if (*e2p < 0 || *e2p < *e1p) - { - internal_error (_("%s: substring expression < 0"), t); - return (0); - } - } - else - *e2p += *e1p; /* want E2 chars starting at E1 */ - if (*e2p > len) - *e2p = len; - } - } - else - *e2p = len; - - return (1); -} - -/* Return the type of variable specified by VARNAME (simple variable, - positional param, or array variable). Also return the value specified - by VARNAME (value of a variable or a reference to an array element). - QUOTED is the standard description of quoting state, using Q_* defines. - FLAGS is currently a set of flags to pass to array_value. If IND is - non-null and not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is - passed to array_value so the array index is not computed again. - If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL - characters in the value are quoted with CTLESC and takes appropriate - steps. For convenience, *VALP is set to the dequoted VALUE. */ -static int -get_var_and_type (varname, value, ind, quoted, flags, varp, valp) - char *varname, *value; - arrayind_t ind; - int quoted, flags; - SHELL_VAR **varp; - char **valp; -{ - int vtype, want_indir; - char *temp, *vname; - WORD_DESC *wd; -#if defined (ARRAY_VARS) - SHELL_VAR *v; -#endif - arrayind_t lind; - - want_indir = *varname == '!' && - (legal_variable_starter ((unsigned char)varname[1]) || DIGIT (varname[1]) - || VALID_INDIR_PARAM (varname[1])); - if (want_indir) - vname = parameter_brace_find_indir (varname+1, SPECIAL_VAR (varname, 1), quoted, 1); - /* XXX - what if vname == 0 || *vname == 0 ? */ - else - vname = varname; - - /* This sets vtype to VT_VARIABLE or VT_POSPARMS */ - vtype = (vname[0] == '@' || vname[0] == '*') && vname[1] == '\0'; - if (vtype == VT_POSPARMS && vname[0] == '*') - vtype |= VT_STARSUB; - *varp = (SHELL_VAR *)NULL; - -#if defined (ARRAY_VARS) - if (valid_array_reference (vname)) - { - v = array_variable_part (vname, &temp, (int *)0); - /* If we want to signal array_value to use an already-computed index, - set LIND to that index */ - lind = (ind != INTMAX_MIN && (flags & AV_USEIND)) ? ind : 0; - if (v && invisible_p (v)) - { - vtype = VT_ARRAYMEMBER; - *varp = (SHELL_VAR *)NULL; - *valp = (char *)NULL; - } - if (v && (array_p (v) || assoc_p (v))) - { /* [ */ - if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']') - { - /* Callers have to differentiate between indexed and associative */ - vtype = VT_ARRAYVAR; - if (temp[0] == '*') - vtype |= VT_STARSUB; - *valp = array_p (v) ? (char *)array_cell (v) : (char *)assoc_cell (v); - } - else - { - vtype = VT_ARRAYMEMBER; - *valp = array_value (vname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind); - } - *varp = v; - } - else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')) - { - vtype = VT_VARIABLE; - *varp = v; - if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) - *valp = dequote_string (value); - else - *valp = dequote_escapes (value); - } - else - { - vtype = VT_ARRAYMEMBER; - *varp = v; - *valp = array_value (vname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind); - } - } - else if ((v = find_variable (vname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v))) - { - vtype = VT_ARRAYMEMBER; - *varp = v; - *valp = assoc_p (v) ? assoc_reference (assoc_cell (v), "0") : array_reference (array_cell (v), 0); - } - else -#endif - { - if (value && vtype == VT_VARIABLE) - { - if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) - *valp = dequote_string (value); - else - *valp = dequote_escapes (value); - } - else - *valp = value; - } - - if (want_indir) - free (vname); - - return vtype; -} - -/******************************************************/ -/* */ -/* Functions to extract substrings of variable values */ -/* */ -/******************************************************/ - -#if defined (HANDLE_MULTIBYTE) -/* Character-oriented rather than strictly byte-oriented substrings. S and - E, rather being strict indices into STRING, indicate character (possibly - multibyte character) positions that require calculation. - Used by the ${param:offset[:length]} expansion. */ -static char * -mb_substring (string, s, e) - char *string; - int s, e; -{ - char *tt; - int start, stop, i, slen; - DECLARE_MBSTATE; - - start = 0; - /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */ - slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0; - - i = s; - while (string[start] && i--) - ADVANCE_CHAR (string, slen, start); - stop = start; - i = e - s; - while (string[stop] && i--) - ADVANCE_CHAR (string, slen, stop); - tt = substring (string, start, stop); - return tt; -} -#endif - -/* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME - is `@', use the positional parameters; otherwise, use the value of - VARNAME. If VARNAME is an array variable, use the array elements. */ - -static char * -parameter_brace_substring (varname, value, ind, substr, quoted, flags) - char *varname, *value; - int ind; - char *substr; - int quoted, flags; -{ - intmax_t e1, e2; - int vtype, r, starsub; - char *temp, *val, *tt, *oname; - SHELL_VAR *v; - - if (value == 0 && ((varname[0] != '@' && varname[0] != '*') || varname[1])) - return ((char *)NULL); - - oname = this_command_name; - this_command_name = varname; - - vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); - if (vtype == -1) - { - this_command_name = oname; - return ((char *)NULL); - } - - starsub = vtype & VT_STARSUB; - vtype &= ~VT_STARSUB; - - r = verify_substring_values (v, val, substr, vtype, &e1, &e2); - this_command_name = oname; - if (r <= 0) - { - if (vtype == VT_VARIABLE) - FREE (val); - return ((r == 0) ? &expand_param_error : (char *)NULL); - } - - switch (vtype) - { - case VT_VARIABLE: - case VT_ARRAYMEMBER: -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1) - tt = mb_substring (val, e1, e2); - else -#endif - tt = substring (val, e1, e2); - - if (vtype == VT_VARIABLE) - FREE (val); - if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) - temp = quote_string (tt); - else - temp = tt ? quote_escapes (tt) : (char *)NULL; - FREE (tt); - break; - case VT_POSPARMS: - tt = pos_params (varname, e1, e2, quoted); - if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0) - { - temp = tt ? quote_escapes (tt) : (char *)NULL; - FREE (tt); - } - else - temp = tt; - break; -#if defined (ARRAY_VARS) - case VT_ARRAYVAR: - if (assoc_p (v)) - /* we convert to list and take first e2 elements starting at e1th - element -- officially undefined for now */ - temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted); - else - /* We want E2 to be the number of elements desired (arrays can be sparse, - so verify_substring_values just returns the numbers specified and we - rely on array_subrange to understand how to deal with them). */ - temp = array_subrange (array_cell (v), e1, e2, starsub, quoted); - /* array_subrange now calls array_quote_escapes as appropriate, so the - caller no longer needs to. */ - break; -#endif - default: - temp = (char *)NULL; - } - - return temp; -} - -/****************************************************************/ -/* */ -/* Functions to perform pattern substitution on variable values */ -/* */ -/****************************************************************/ - -static int -shouldexp_replacement (s) - char *s; -{ - register char *p; - - for (p = s; p && *p; p++) - { - if (*p == '\\') - p++; - else if (*p == '&') - return 1; - } - return 0; -} - -char * -pat_subst (string, pat, rep, mflags) - char *string, *pat, *rep; - int mflags; -{ - char *ret, *s, *e, *str, *rstr, *mstr; - int rsize, rptr, l, replen, mtype, rxpand, rslen, mlen; - - if (string == 0) - return (savestring ("")); - - mtype = mflags & MATCH_TYPEMASK; - -#if 0 /* bash-4.2 ? */ - rxpand = (rep && *rep) ? shouldexp_replacement (rep) : 0; -#else - rxpand = 0; -#endif - - /* Special cases: - * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING - * with REP and return the result. - * 2. A null pattern with mtype == MATCH_END means to append REP to - * STRING and return the result. - * These don't understand or process `&' in the replacement string. - */ - if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END)) - { - replen = STRLEN (rep); - l = STRLEN (string); - ret = (char *)xmalloc (replen + l + 2); - if (replen == 0) - strcpy (ret, string); - else if (mtype == MATCH_BEG) - { - strcpy (ret, rep); - strcpy (ret + replen, string); - } - else - { - strcpy (ret, string); - strcpy (ret + l, rep); - } - return (ret); - } - - ret = (char *)xmalloc (rsize = 64); - ret[0] = '\0'; - - for (replen = STRLEN (rep), rptr = 0, str = string;;) - { - if (match_pattern (str, pat, mtype, &s, &e) == 0) - break; - l = s - str; - - if (rxpand) - { - int x; - mlen = e - s; - mstr = xmalloc (mlen + 1); - for (x = 0; x < mlen; x++) - mstr[x] = s[x]; - mstr[mlen] = '\0'; - rstr = strcreplace (rep, '&', mstr, 0); - rslen = strlen (rstr); - } - else - { - rstr = rep; - rslen = replen; - } - - RESIZE_MALLOCED_BUFFER (ret, rptr, (l + rslen), rsize, 64); - - /* OK, now copy the leading unmatched portion of the string (from - str to s) to ret starting at rptr (the current offset). Then copy - the replacement string at ret + rptr + (s - str). Increment - rptr (if necessary) and str and go on. */ - if (l) - { - strncpy (ret + rptr, str, l); - rptr += l; - } - if (replen) - { - strncpy (ret + rptr, rstr, rslen); - rptr += rslen; - } - str = e; /* e == end of match */ - - if (rstr != rep) - free (rstr); - - if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY) - break; - - if (s == e) - { - /* On a zero-length match, make sure we copy one character, since - we increment one character to avoid infinite recursion. */ - RESIZE_MALLOCED_BUFFER (ret, rptr, 1, rsize, 64); - ret[rptr++] = *str++; - e++; /* avoid infinite recursion on zero-length match */ - } - } - - /* Now copy the unmatched portion of the input string */ - if (str && *str) - { - RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64); - strcpy (ret + rptr, str); - } - else - ret[rptr] = '\0'; - - return ret; -} - -/* Do pattern match and replacement on the positional parameters. */ -static char * -pos_params_pat_subst (string, pat, rep, mflags) - char *string, *pat, *rep; - int mflags; -{ - WORD_LIST *save, *params; - WORD_DESC *w; - char *ret; - int pchar, qflags; - - save = params = list_rest_of_args (); - if (save == 0) - return ((char *)NULL); - - for ( ; params; params = params->next) - { - ret = pat_subst (params->word->word, pat, rep, mflags); - w = alloc_word_desc (); - w->word = ret ? ret : savestring (""); - dispose_word (params->word); - params->word = w; - } - - pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@'; - qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0; - - ret = string_list_pos_params (pchar, save, qflags); - - dispose_words (save); - - return (ret); -} - -/* Perform pattern substitution on VALUE, which is the expansion of - VARNAME. PATSUB is an expression supplying the pattern to match - and the string to substitute. QUOTED is a flags word containing - the type of quoting currently in effect. */ -static char * -parameter_brace_patsub (varname, value, ind, patsub, quoted, flags) - char *varname, *value; - int ind; - char *patsub; - int quoted, flags; -{ - int vtype, mflags, starsub, delim; - char *val, *temp, *pat, *rep, *p, *lpatsub, *tt; - SHELL_VAR *v; - - if (value == 0) - return ((char *)NULL); - - this_command_name = varname; - - vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); - if (vtype == -1) - return ((char *)NULL); - - starsub = vtype & VT_STARSUB; - vtype &= ~VT_STARSUB; - - mflags = 0; - /* PATSUB is never NULL when this is called. */ - if (*patsub == '/') - { - mflags |= MATCH_GLOBREP; - patsub++; - } - - /* Malloc this because expand_string_if_necessary or one of the expansion - functions in its call chain may free it on a substitution error. */ - lpatsub = savestring (patsub); - - if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) - mflags |= MATCH_QUOTED; - - if (starsub) - mflags |= MATCH_STARSUB; - - /* If the pattern starts with a `/', make sure we skip over it when looking - for the replacement delimiter. */ - delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0); - if (lpatsub[delim] == '/') - { - lpatsub[delim] = 0; - rep = lpatsub + delim + 1; - } - else - rep = (char *)NULL; - - if (rep && *rep == '\0') - rep = (char *)NULL; - - /* Perform the same expansions on the pattern as performed by the - pattern removal expansions. */ - pat = getpattern (lpatsub, quoted, 1); - - if (rep) - { - /* We want to perform quote removal on the expanded replacement even if - the entire expansion is double-quoted because the parser and string - extraction functions treated quotes in the replacement string as - special. THIS IS NOT BACKWARDS COMPATIBLE WITH BASH-4.2. */ - if (shell_compatibility_level > 42) - rep = expand_string_if_necessary (rep, quoted & ~(Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT), expand_string_unsplit); - /* This is the bash-4.2 code. */ - else if ((mflags & MATCH_QUOTED) == 0) - rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit); - else - rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit); - } - - /* ksh93 doesn't allow the match specifier to be a part of the expanded - pattern. This is an extension. Make sure we don't anchor the pattern - at the beginning or end of the string if we're doing global replacement, - though. */ - p = pat; - if (mflags & MATCH_GLOBREP) - mflags |= MATCH_ANY; - else if (pat && pat[0] == '#') - { - mflags |= MATCH_BEG; - p++; - } - else if (pat && pat[0] == '%') - { - mflags |= MATCH_END; - p++; - } - else - mflags |= MATCH_ANY; - - /* OK, we now want to substitute REP for PAT in VAL. If - flags & MATCH_GLOBREP is non-zero, the substitution is done - everywhere, otherwise only the first occurrence of PAT is - replaced. The pattern matching code doesn't understand - CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable - values passed in (VT_VARIABLE) so the pattern substitution - code works right. We need to requote special chars after - we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the - other cases if QUOTED == 0, since the posparams and arrays - indexed by * or @ do special things when QUOTED != 0. */ - - switch (vtype) - { - case VT_VARIABLE: - case VT_ARRAYMEMBER: - temp = pat_subst (val, p, rep, mflags); - if (vtype == VT_VARIABLE) - FREE (val); - if (temp) - { - tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp); - free (temp); - temp = tt; - } - break; - case VT_POSPARMS: - temp = pos_params_pat_subst (val, p, rep, mflags); - if (temp && (mflags & MATCH_QUOTED) == 0) - { - tt = quote_escapes (temp); - free (temp); - temp = tt; - } - break; -#if defined (ARRAY_VARS) - case VT_ARRAYVAR: - temp = assoc_p (v) ? assoc_patsub (assoc_cell (v), p, rep, mflags) - : array_patsub (array_cell (v), p, rep, mflags); - /* Don't call quote_escapes anymore; array_patsub calls - array_quote_escapes as appropriate before adding the - space separators; ditto for assoc_patsub. */ - break; -#endif - } - - FREE (pat); - FREE (rep); - free (lpatsub); - - return temp; -} - -/****************************************************************/ -/* */ -/* Functions to perform case modification on variable values */ -/* */ -/****************************************************************/ - -/* Do case modification on the positional parameters. */ - -static char * -pos_params_modcase (string, pat, modop, mflags) - char *string, *pat; - int modop; - int mflags; -{ - WORD_LIST *save, *params; - WORD_DESC *w; - char *ret; - int pchar, qflags; - - save = params = list_rest_of_args (); - if (save == 0) - return ((char *)NULL); - - for ( ; params; params = params->next) - { - ret = sh_modcase (params->word->word, pat, modop); - w = alloc_word_desc (); - w->word = ret ? ret : savestring (""); - dispose_word (params->word); - params->word = w; - } - - pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@'; - qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0; - - ret = string_list_pos_params (pchar, save, qflags); - dispose_words (save); - - return (ret); -} - -/* Perform case modification on VALUE, which is the expansion of - VARNAME. MODSPEC is an expression supplying the type of modification - to perform. QUOTED is a flags word containing the type of quoting - currently in effect. */ -static char * -parameter_brace_casemod (varname, value, ind, modspec, patspec, quoted, flags) - char *varname, *value; - int ind, modspec; - char *patspec; - int quoted, flags; -{ - int vtype, starsub, modop, mflags, x; - char *val, *temp, *pat, *p, *lpat, *tt; - SHELL_VAR *v; - - if (value == 0) - return ((char *)NULL); - - this_command_name = varname; - - vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); - if (vtype == -1) - return ((char *)NULL); - - starsub = vtype & VT_STARSUB; - vtype &= ~VT_STARSUB; - - modop = 0; - mflags = 0; - if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) - mflags |= MATCH_QUOTED; - if (starsub) - mflags |= MATCH_STARSUB; - - p = patspec; - if (modspec == '^') - { - x = p && p[0] == modspec; - modop = x ? CASE_UPPER : CASE_UPFIRST; - p += x; - } - else if (modspec == ',') - { - x = p && p[0] == modspec; - modop = x ? CASE_LOWER : CASE_LOWFIRST; - p += x; - } - else if (modspec == '~') - { - x = p && p[0] == modspec; - modop = x ? CASE_TOGGLEALL : CASE_TOGGLE; - p += x; - } - - lpat = p ? savestring (p) : 0; - /* Perform the same expansions on the pattern as performed by the - pattern removal expansions. FOR LATER */ - pat = lpat ? getpattern (lpat, quoted, 1) : 0; - - /* OK, now we do the case modification. */ - switch (vtype) - { - case VT_VARIABLE: - case VT_ARRAYMEMBER: - temp = sh_modcase (val, pat, modop); - if (vtype == VT_VARIABLE) - FREE (val); - if (temp) - { - tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp); - free (temp); - temp = tt; - } - break; - - case VT_POSPARMS: - temp = pos_params_modcase (val, pat, modop, mflags); - if (temp && (mflags & MATCH_QUOTED) == 0) - { - tt = quote_escapes (temp); - free (temp); - temp = tt; - } - break; - -#if defined (ARRAY_VARS) - case VT_ARRAYVAR: - temp = assoc_p (v) ? assoc_modcase (assoc_cell (v), pat, modop, mflags) - : array_modcase (array_cell (v), pat, modop, mflags); - /* Don't call quote_escapes; array_modcase calls array_quote_escapes - as appropriate before adding the space separators; ditto for - assoc_modcase. */ - break; -#endif - } - - FREE (pat); - free (lpat); - - return temp; -} - -/* Check for unbalanced parens in S, which is the contents of $(( ... )). If - any occur, this must be a nested command substitution, so return 0. - Otherwise, return 1. A valid arithmetic expression must always have a - ( before a matching ), so any cases where there are more right parens - means that this must not be an arithmetic expression, though the parser - will not accept it without a balanced total number of parens. */ -static int -chk_arithsub (s, len) - const char *s; - int len; -{ - int i, count; - DECLARE_MBSTATE; - - i = count = 0; - while (i < len) - { - if (s[i] == LPAREN) - count++; - else if (s[i] == RPAREN) - { - count--; - if (count < 0) - return 0; - } - - switch (s[i]) - { - default: - ADVANCE_CHAR (s, len, i); - break; - - case '\\': - i++; - if (s[i]) - ADVANCE_CHAR (s, len, i); - break; - - case '\'': - i = skip_single_quoted (s, len, ++i); - break; - - case '"': - i = skip_double_quoted ((char *)s, len, ++i); - break; - } - } - - return (count == 0); -} - -/****************************************************************/ -/* */ -/* Functions to perform parameter expansion on a string */ -/* */ -/****************************************************************/ - -/* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */ -static WORD_DESC * -parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, contains_dollar_at) - char *string; - int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at, pflags; -{ - int check_nullness, var_is_set, var_is_null, var_is_special; - int want_substring, want_indir, want_patsub, want_casemod; - char *name, *value, *temp, *temp1; - WORD_DESC *tdesc, *ret; - int t_index, sindex, c, tflag, modspec; - intmax_t number; - arrayind_t ind; - - temp = temp1 = value = (char *)NULL; - var_is_set = var_is_null = var_is_special = check_nullness = 0; - want_substring = want_indir = want_patsub = want_casemod = 0; - - sindex = *indexp; - t_index = ++sindex; - /* ${#var} doesn't have any of the other parameter expansions on it. */ - if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */ - name = string_extract (string, &t_index, "}", SX_VARNAME); - else -#if defined (CASEMOD_EXPANSIONS) - /* To enable case-toggling expansions using the `~' operator character - change the 1 to 0. */ -# if defined (CASEMOD_CAPCASE) - name = string_extract (string, &t_index, "#%^,~:-=?+/}", SX_VARNAME); -# else - name = string_extract (string, &t_index, "#%^,:-=?+/}", SX_VARNAME); -# endif /* CASEMOD_CAPCASE */ -#else - name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME); -#endif /* CASEMOD_EXPANSIONS */ - - ret = 0; - tflag = 0; - - ind = INTMAX_MIN; - - /* If the name really consists of a special variable, then make sure - that we have the entire name. We don't allow indirect references - to special variables except `#', `?', `@' and `*'. */ - if ((sindex == t_index && VALID_SPECIAL_LENGTH_PARAM (string[t_index])) || - (sindex == t_index - 1 && string[sindex] == '!' && VALID_INDIR_PARAM (string[t_index]))) - { - t_index++; - temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0); - name = (char *)xrealloc (name, 3 + (strlen (temp1))); - *name = string[sindex]; - if (string[sindex] == '!') - { - /* indirect reference of $#, $?, $@, or $* */ - name[1] = string[sindex + 1]; - strcpy (name + 2, temp1); - } - else - strcpy (name + 1, temp1); - free (temp1); - } - sindex = t_index; - - /* Find out what character ended the variable name. Then - do the appropriate thing. */ - if (c = string[sindex]) - sindex++; - - /* If c is followed by one of the valid parameter expansion - characters, move past it as normal. If not, assume that - a substring specification is being given, and do not move - past it. */ - if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex])) - { - check_nullness++; - if (c = string[sindex]) - sindex++; - } - else if (c == ':' && string[sindex] != RBRACE) - want_substring = 1; - else if (c == '/' /* && string[sindex] != RBRACE */) /* XXX */ - want_patsub = 1; -#if defined (CASEMOD_EXPANSIONS) - else if (c == '^' || c == ',' || c == '~') - { - modspec = c; - want_casemod = 1; - } -#endif - - /* Catch the valid and invalid brace expressions that made it through the - tests above. */ - /* ${#-} is a valid expansion and means to take the length of $-. - Similarly for ${#?} and ${##}... */ - if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 && - VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE) - { - name = (char *)xrealloc (name, 3); - name[1] = c; - name[2] = '\0'; - c = string[sindex++]; - } - - /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */ - if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 && - member (c, "%:=+/") && string[sindex] == RBRACE) - { - temp = (char *)NULL; - goto bad_substitution; - } - - /* Indirect expansion begins with a `!'. A valid indirect expansion is - either a variable name, one of the positional parameters or a special - variable that expands to one of the positional parameters. */ - want_indir = *name == '!' && - (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1]) - || VALID_INDIR_PARAM (name[1])); - - /* Determine the value of this variable. */ - - /* Check for special variables, directly referenced. */ - if (SPECIAL_VAR (name, want_indir)) - var_is_special++; - - /* Check for special expansion things, like the length of a parameter */ - if (*name == '#' && name[1]) - { - /* If we are not pointing at the character just after the - closing brace, then we haven't gotten all of the name. - Since it begins with a special character, this is a bad - substitution. Also check NAME for validity before trying - to go on. */ - if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0)) - { - temp = (char *)NULL; - goto bad_substitution; - } - - number = parameter_brace_expand_length (name); - if (number == INTMAX_MIN && unbound_vars_is_error) - { - last_command_exit_value = EXECUTION_FAILURE; - err_unboundvar (name+1); - free (name); - return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); - } - free (name); - - *indexp = sindex; - if (number < 0) - return (&expand_wdesc_error); - else - { - ret = alloc_word_desc (); - ret->word = itos (number); - return ret; - } - } - - /* ${@} is identical to $@. */ - if (name[0] == '@' && name[1] == '\0') - { - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) - *quoted_dollar_atp = 1; - - if (contains_dollar_at) - *contains_dollar_at = 1; - - tflag |= W_DOLLARAT; - } - - /* Process ${!PREFIX*} expansion. */ - if (want_indir && string[sindex - 1] == RBRACE && - (string[sindex - 2] == '*' || string[sindex - 2] == '@') && - legal_variable_starter ((unsigned char) name[1])) - { - char **x; - WORD_LIST *xlist; - - temp1 = savestring (name + 1); - number = strlen (temp1); - temp1[number - 1] = '\0'; - x = all_variables_matching_prefix (temp1); - xlist = strvec_to_word_list (x, 0, 0); - if (string[sindex - 2] == '*') - temp = string_list_dollar_star (xlist); - else - { - temp = string_list_dollar_at (xlist, quoted); - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) - *quoted_dollar_atp = 1; - if (contains_dollar_at) - *contains_dollar_at = 1; - - tflag |= W_DOLLARAT; - } - free (x); - dispose_words (xlist); - free (temp1); - *indexp = sindex; - - free (name); - - ret = alloc_word_desc (); - ret->word = temp; - ret->flags = tflag; /* XXX */ - return ret; - } - -#if defined (ARRAY_VARS) - /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */ - if (want_indir && string[sindex - 1] == RBRACE && - string[sindex - 2] == ']' && valid_array_reference (name+1)) - { - char *x, *x1; - - temp1 = savestring (name + 1); - x = array_variable_name (temp1, &x1, (int *)0); /* [ */ - FREE (x); - if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']') - { - temp = array_keys (temp1, quoted); /* handles assoc vars too */ - if (x1[0] == '@') - { - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) - *quoted_dollar_atp = 1; - if (contains_dollar_at) - *contains_dollar_at = 1; - - tflag |= W_DOLLARAT; - } - - free (temp1); - *indexp = sindex; - - ret = alloc_word_desc (); - ret->word = temp; - ret->flags = tflag; /* XXX */ - return ret; - } - - free (temp1); - } -#endif /* ARRAY_VARS */ - - /* Make sure that NAME is valid before trying to go on. */ - if (valid_brace_expansion_word (want_indir ? name + 1 : name, - var_is_special) == 0) - { - temp = (char *)NULL; - goto bad_substitution; - } - - if (want_indir) - tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at); - else - tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND|(pflags&(PF_NOSPLIT2|PF_ASSIGNRHS)), &ind); - - if (tdesc) - { - temp = tdesc->word; - tflag = tdesc->flags; - dispose_word_desc (tdesc); - } - else - temp = (char *)0; - - if (temp == &expand_param_error || temp == &expand_param_fatal) - { - FREE (name); - FREE (value); - return (temp == &expand_param_error ? &expand_wdesc_error : &expand_wdesc_fatal); - } - -#if defined (ARRAY_VARS) - if (valid_array_reference (name)) - chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at); -#endif - - var_is_set = temp != (char *)0; - var_is_null = check_nullness && (var_is_set == 0 || *temp == 0); - /* XXX - this may not need to be restricted to special variables */ - if (check_nullness) - var_is_null |= var_is_set && var_is_special && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL (temp); - - /* Get the rest of the stuff inside the braces. */ - if (c && c != RBRACE) - { - /* Extract the contents of the ${ ... } expansion - according to the Posix.2 rules. */ - value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#' || c =='/' || c == '^' || c == ',' || c ==':') ? SX_POSIXEXP|SX_WORD : SX_WORD); - if (string[sindex] == RBRACE) - sindex++; - else - goto bad_substitution; - } - else - value = (char *)NULL; - - *indexp = sindex; - - /* All the cases where an expansion can possibly generate an unbound - variable error. */ - if (want_substring || want_patsub || want_casemod || c == '#' || c == '%' || c == RBRACE) - { - if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1])) - { - last_command_exit_value = EXECUTION_FAILURE; - err_unboundvar (name); - FREE (value); - FREE (temp); - free (name); - return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); - } - } - - /* If this is a substring spec, process it and add the result. */ - if (want_substring) - { - temp1 = parameter_brace_substring (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0); - FREE (name); - FREE (value); - FREE (temp); - - if (temp1 == &expand_param_error) - return (&expand_wdesc_error); - else if (temp1 == &expand_param_fatal) - return (&expand_wdesc_fatal); - - ret = alloc_word_desc (); - ret->word = temp1; - /* We test quoted_dollar_atp because we want variants with double-quoted - "$@" to take a different code path. In fact, we make sure at the end - of expand_word_internal that we're only looking at these flags if - quoted_dollar_at == 0. */ - if (temp1 && - (quoted_dollar_atp == 0 || *quoted_dollar_atp == 0) && - QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) - ret->flags |= W_QUOTED|W_HASQUOTEDNULL; - return ret; - } - else if (want_patsub) - { - temp1 = parameter_brace_patsub (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0); - FREE (name); - FREE (value); - FREE (temp); - - if (temp1 == &expand_param_error) - return (&expand_wdesc_error); - else if (temp1 == &expand_param_fatal) - return (&expand_wdesc_fatal); - - ret = alloc_word_desc (); - ret->word = temp1; - if (temp1 && - (quoted_dollar_atp == 0 || *quoted_dollar_atp == 0) && - QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) - ret->flags |= W_QUOTED|W_HASQUOTEDNULL; - return ret; - } -#if defined (CASEMOD_EXPANSIONS) - else if (want_casemod) - { - temp1 = parameter_brace_casemod (name, temp, ind, modspec, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0); - FREE (name); - FREE (value); - FREE (temp); - - if (temp1 == &expand_param_error) - return (&expand_wdesc_error); - else if (temp1 == &expand_param_fatal) - return (&expand_wdesc_fatal); - - ret = alloc_word_desc (); - ret->word = temp1; - if (temp1 && - (quoted_dollar_atp == 0 || *quoted_dollar_atp == 0) && - QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) - ret->flags |= W_QUOTED|W_HASQUOTEDNULL; - return ret; - } -#endif - - /* Do the right thing based on which character ended the variable name. */ - switch (c) - { - default: - case '\0': - bad_substitution: - last_command_exit_value = EXECUTION_FAILURE; - report_error (_("%s: bad substitution"), string ? string : "??"); - FREE (value); - FREE (temp); - free (name); - return &expand_wdesc_error; - - case RBRACE: - break; - - case '#': /* ${param#[#]pattern} */ - case '%': /* ${param%[%]pattern} */ - if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0') - { - FREE (value); - break; - } - temp1 = parameter_brace_remove_pattern (name, temp, ind, value, c, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0); - free (temp); - free (value); - free (name); - - ret = alloc_word_desc (); - ret->word = temp1; - if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) - ret->flags |= W_QUOTED|W_HASQUOTEDNULL; - return ret; - - case '-': - case '=': - case '?': - case '+': - if (var_is_set && var_is_null == 0) - { - /* If the operator is `+', we don't want the value of the named - variable for anything, just the value of the right hand side. */ - if (c == '+') - { - /* XXX -- if we're double-quoted and the named variable is "$@", - we want to turn off any special handling of "$@" -- - we're not using it, so whatever is on the rhs applies. */ - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) - *quoted_dollar_atp = 0; - if (contains_dollar_at) - *contains_dollar_at = 0; - - FREE (temp); - if (value) - { - /* From Posix discussion on austin-group list. Issue 221 - requires that backslashes escaping `}' inside - double-quoted ${...} be removed. */ - if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) - quoted |= Q_DOLBRACE; - ret = parameter_brace_expand_rhs (name, value, c, - quoted, - quoted_dollar_atp, - contains_dollar_at); - /* XXX - fix up later, esp. noting presence of - W_HASQUOTEDNULL in ret->flags */ - free (value); - } - else - temp = (char *)NULL; - } - else - { - FREE (value); - } - /* Otherwise do nothing; just use the value in TEMP. */ - } - else /* VAR not set or VAR is NULL. */ - { - FREE (temp); - temp = (char *)NULL; - if (c == '=' && var_is_special) - { - last_command_exit_value = EXECUTION_FAILURE; - report_error (_("$%s: cannot assign in this way"), name); - free (name); - free (value); - return &expand_wdesc_error; - } - else if (c == '?') - { - parameter_brace_expand_error (name, value); - return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); - } - else if (c != '+') - { - /* XXX -- if we're double-quoted and the named variable is "$@", - we want to turn off any special handling of "$@" -- - we're not using it, so whatever is on the rhs applies. */ - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp) - *quoted_dollar_atp = 0; - if (contains_dollar_at) - *contains_dollar_at = 0; - - /* From Posix discussion on austin-group list. Issue 221 requires - that backslashes escaping `}' inside double-quoted ${...} be - removed. */ - if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) - quoted |= Q_DOLBRACE; - ret = parameter_brace_expand_rhs (name, value, c, quoted, - quoted_dollar_atp, - contains_dollar_at); - /* XXX - fix up later, esp. noting presence of - W_HASQUOTEDNULL in tdesc->flags */ - } - free (value); - } - - break; - } - free (name); - - if (ret == 0) - { - ret = alloc_word_desc (); - ret->flags = tflag; - ret->word = temp; - } - return (ret); -} - -/* Expand a single ${xxx} expansion. The braces are optional. When - the braces are used, parameter_brace_expand() does the work, - possibly calling param_expand recursively. */ -static WORD_DESC * -param_expand (string, sindex, quoted, expanded_something, - contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p, - pflags) - char *string; - int *sindex, quoted, *expanded_something, *contains_dollar_at; - int *quoted_dollar_at_p, *had_quoted_null_p, pflags; -{ - char *temp, *temp1, uerror[3]; - int zindex, t_index, expok; - unsigned char c; - intmax_t number; - SHELL_VAR *var; - WORD_LIST *list; - WORD_DESC *tdesc, *ret; - int tflag; - - zindex = *sindex; - c = string[++zindex]; - - temp = (char *)NULL; - ret = tdesc = (WORD_DESC *)NULL; - tflag = 0; - - /* Do simple cases first. Switch on what follows '$'. */ - switch (c) - { - /* $0 .. $9? */ - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - temp1 = dollar_vars[TODIGIT (c)]; - if (unbound_vars_is_error && temp1 == (char *)NULL) - { - uerror[0] = '$'; - uerror[1] = c; - uerror[2] = '\0'; - last_command_exit_value = EXECUTION_FAILURE; - err_unboundvar (uerror); - return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); - } - if (temp1) - temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) - ? quote_string (temp1) - : quote_escapes (temp1); - else - temp = (char *)NULL; - - break; - - /* $$ -- pid of the invoking shell. */ - case '$': - temp = itos (dollar_dollar_pid); - break; - - /* $# -- number of positional parameters. */ - case '#': - temp = itos (number_of_args ()); - break; - - /* $? -- return value of the last synchronous command. */ - case '?': - temp = itos (last_command_exit_value); - break; - - /* $- -- flags supplied to the shell on invocation or by `set'. */ - case '-': - temp = which_set_flags (); - break; - - /* $! -- Pid of the last asynchronous command. */ - case '!': - /* If no asynchronous pids have been created, expand to nothing. - If `set -u' has been executed, and no async processes have - been created, this is an expansion error. */ - if (last_asynchronous_pid == NO_PID) - { - if (expanded_something) - *expanded_something = 0; - temp = (char *)NULL; - if (unbound_vars_is_error) - { - uerror[0] = '$'; - uerror[1] = c; - uerror[2] = '\0'; - last_command_exit_value = EXECUTION_FAILURE; - err_unboundvar (uerror); - return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); - } - } - else - temp = itos (last_asynchronous_pid); - break; - - /* The only difference between this and $@ is when the arg is quoted. */ - case '*': /* `$*' */ - list = list_rest_of_args (); - -#if 0 - /* According to austin-group posix proposal by Geoff Clare in - <20090505091501.GA10097@squonk.masqnet> of 5 May 2009: - - "The shell shall write a message to standard error and - immediately exit when it tries to expand an unset parameter - other than the '@' and '*' special parameters." - */ - - if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0) - { - uerror[0] = '$'; - uerror[1] = '*'; - uerror[2] = '\0'; - last_command_exit_value = EXECUTION_FAILURE; - err_unboundvar (uerror); - return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); - } -#endif - - /* If there are no command-line arguments, this should just - disappear if there are other characters in the expansion, - even if it's quoted. */ - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0) - temp = (char *)NULL; - else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE)) - { - /* If we have "$*" we want to make a string of the positional - parameters, separated by the first character of $IFS, and - quote the whole string, including the separators. If IFS - is unset, the parameters are separated by ' '; if $IFS is - null, the parameters are concatenated. */ - temp = (quoted & (Q_DOUBLE_QUOTES|Q_PATQUOTE)) ? string_list_dollar_star (list) : string_list (list); - if (temp) - { - temp1 = quote_string (temp); - if (*temp == 0) - tflag |= W_HASQUOTEDNULL; - free (temp); - temp = temp1; - } - } - else - { - /* We check whether or not we're eventually going to split $* here, - for example when IFS is empty and we are processing the rhs of - an assignment statement. In that case, we don't separate the - arguments at all. Otherwise, if the $* is not quoted it is - identical to $@ */ -# if defined (HANDLE_MULTIBYTE) - if (expand_no_split_dollar_star && ifs_firstc[0] == 0) -# else - if (expand_no_split_dollar_star && ifs_firstc == 0) -# endif - temp = string_list_dollar_star (list); - else - { - temp = string_list_dollar_at (list, quoted); - if (quoted == 0 && (ifs_is_set == 0 || ifs_is_null)) - tflag |= W_SPLITSPACE; - } - - if (expand_no_split_dollar_star == 0 && contains_dollar_at) - *contains_dollar_at = 1; - } - - dispose_words (list); - break; - - /* When we have "$@" what we want is "$1" "$2" "$3" ... This - means that we have to turn quoting off after we split into - the individually quoted arguments so that the final split - on the first character of $IFS is still done. */ - case '@': /* `$@' */ - list = list_rest_of_args (); - -#if 0 - /* According to austin-group posix proposal by Geoff Clare in - <20090505091501.GA10097@squonk.masqnet> of 5 May 2009: - - "The shell shall write a message to standard error and - immediately exit when it tries to expand an unset parameter - other than the '@' and '*' special parameters." - */ - - if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0) - { - uerror[0] = '$'; - uerror[1] = '@'; - uerror[2] = '\0'; - last_command_exit_value = EXECUTION_FAILURE; - err_unboundvar (uerror); - return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); - } -#endif - - /* We want to flag the fact that we saw this. We can't turn - off quoting entirely, because other characters in the - string might need it (consider "\"$@\""), but we need some - way to signal that the final split on the first character - of $IFS should be done, even though QUOTED is 1. */ - /* XXX - should this test include Q_PATQUOTE? */ - if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) - *quoted_dollar_at_p = 1; - if (contains_dollar_at) - *contains_dollar_at = 1; - - /* We want to separate the positional parameters with the first - character of $IFS in case $IFS is something other than a space. - We also want to make sure that splitting is done no matter what -- - according to POSIX.2, this expands to a list of the positional - parameters no matter what IFS is set to. */ - /* XXX - what to do when in a context where word splitting is not - performed? Even when IFS is not the default, posix seems to imply - that we behave like unquoted $* ? Maybe we should use PF_NOSPLIT2 - here. */ - temp = string_list_dollar_at (list, (pflags & PF_ASSIGNRHS) ? (quoted|Q_DOUBLE_QUOTES) : quoted); - - tflag |= W_DOLLARAT; - dispose_words (list); - break; - - case LBRACE: - tdesc = parameter_brace_expand (string, &zindex, quoted, pflags, - quoted_dollar_at_p, - contains_dollar_at); - - if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal) - return (tdesc); - temp = tdesc ? tdesc->word : (char *)0; - - /* XXX */ - /* Quoted nulls should be removed if there is anything else - in the string. */ - /* Note that we saw the quoted null so we can add one back at - the end of this function if there are no other characters - in the string, discard TEMP, and go on. The exception to - this is when we have "${@}" and $1 is '', since $@ needs - special handling. */ - if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp)) - { - if (had_quoted_null_p) - *had_quoted_null_p = 1; - if (*quoted_dollar_at_p == 0) - { - free (temp); - tdesc->word = temp = (char *)NULL; - } - - } - - ret = tdesc; - goto return0; - - /* Do command or arithmetic substitution. */ - case LPAREN: - /* We have to extract the contents of this paren substitution. */ - t_index = zindex + 1; - temp = extract_command_subst (string, &t_index, 0); - zindex = t_index; - - /* For Posix.2-style `$(( ))' arithmetic substitution, - extract the expression and pass it to the evaluator. */ - if (temp && *temp == LPAREN) - { - char *temp2; - temp1 = temp + 1; - temp2 = savestring (temp1); - t_index = strlen (temp2) - 1; - - if (temp2[t_index] != RPAREN) - { - free (temp2); - goto comsub; - } - - /* Cut off ending `)' */ - temp2[t_index] = '\0'; - - if (chk_arithsub (temp2, t_index) == 0) - { - free (temp2); -#if 0 - internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution")); -#endif - goto comsub; - } - - /* Expand variables found inside the expression. */ - temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES); - free (temp2); - -arithsub: - /* No error messages. */ - this_command_name = (char *)NULL; - number = evalexp (temp1, &expok); - free (temp); - free (temp1); - if (expok == 0) - { - if (interactive_shell == 0 && posixly_correct) - { - last_command_exit_value = EXECUTION_FAILURE; - return (&expand_wdesc_fatal); - } - else - return (&expand_wdesc_error); - } - temp = itos (number); - break; - } - -comsub: - if (pflags & PF_NOCOMSUB) - /* we need zindex+1 because string[zindex] == RPAREN */ - temp1 = substring (string, *sindex, zindex+1); - else - { - tdesc = command_substitute (temp, quoted); - temp1 = tdesc ? tdesc->word : (char *)NULL; - if (tdesc) - dispose_word_desc (tdesc); - } - FREE (temp); - temp = temp1; - break; - - /* Do POSIX.2d9-style arithmetic substitution. This will probably go - away in a future bash release. */ - case '[': - /* Extract the contents of this arithmetic substitution. */ - t_index = zindex + 1; - temp = extract_arithmetic_subst (string, &t_index); - zindex = t_index; - if (temp == 0) - { - temp = savestring (string); - if (expanded_something) - *expanded_something = 0; - goto return0; - } - - /* Do initial variable expansion. */ - temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES); - - goto arithsub; - - default: - /* Find the variable in VARIABLE_LIST. */ - temp = (char *)NULL; - - for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++) - ; - temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL; - - /* If this isn't a variable name, then just output the `$'. */ - if (temp1 == 0 || *temp1 == '\0') - { - FREE (temp1); - temp = (char *)xmalloc (2); - temp[0] = '$'; - temp[1] = '\0'; - if (expanded_something) - *expanded_something = 0; - goto return0; - } - - /* If the variable exists, return its value cell. */ - var = find_variable (temp1); - - if (var && invisible_p (var) == 0 && var_isset (var)) - { -#if defined (ARRAY_VARS) - if (assoc_p (var) || array_p (var)) - { - temp = array_p (var) ? array_reference (array_cell (var), 0) - : assoc_reference (assoc_cell (var), "0"); - if (temp) - temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) - ? quote_string (temp) - : quote_escapes (temp); - else if (unbound_vars_is_error) - goto unbound_variable; - } - else -#endif - { - temp = value_cell (var); - - temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) - ? quote_string (temp) - : quote_escapes (temp); - } - - free (temp1); - - goto return0; - } - else if (var = find_variable_last_nameref (temp1)) - { - temp = nameref_cell (var); -#if defined (ARRAY_VARS) - if (temp && *temp && valid_array_reference (temp)) - { - tdesc = parameter_brace_expand_word (temp, SPECIAL_VAR (temp, 0), quoted, pflags, (arrayind_t *)NULL); - if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal) - return (tdesc); - ret = tdesc; - goto return0; - } - else -#endif - /* y=2 ; typeset -n x=y; echo $x is not the same as echo $2 in ksh */ - if (temp && *temp && legal_identifier (temp) == 0) - { - last_command_exit_value = EXECUTION_FAILURE; - report_error (_("%s: invalid variable name for name reference"), temp); - return (&expand_wdesc_error); /* XXX */ - } - else - temp = (char *)NULL; - } - - temp = (char *)NULL; - -unbound_variable: - if (unbound_vars_is_error) - { - last_command_exit_value = EXECUTION_FAILURE; - err_unboundvar (temp1); - } - else - { - free (temp1); - goto return0; - } - - free (temp1); - last_command_exit_value = EXECUTION_FAILURE; - return ((unbound_vars_is_error && interactive_shell == 0) - ? &expand_wdesc_fatal - : &expand_wdesc_error); - } - - if (string[zindex]) - zindex++; - -return0: - *sindex = zindex; - - if (ret == 0) - { - ret = alloc_word_desc (); - ret->flags = tflag; /* XXX */ - ret->word = temp; - } - return ret; -} - -/* Make a word list which is the result of parameter and variable - expansion, command substitution, arithmetic substitution, and - quote removal of WORD. Return a pointer to a WORD_LIST which is - the result of the expansion. If WORD contains a null word, the - word list returned is also null. - - QUOTED contains flag values defined in shell.h. - - ISEXP is used to tell expand_word_internal that the word should be - treated as the result of an expansion. This has implications for - how IFS characters in the word are treated. - - CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null - they point to an integer value which receives information about expansion. - CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero. - EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions, - else zero. - - This only does word splitting in the case of $@ expansion. In that - case, we split on ' '. */ - -/* Values for the local variable quoted_state. */ -#define UNQUOTED 0 -#define PARTIALLY_QUOTED 1 -#define WHOLLY_QUOTED 2 - -static WORD_LIST * -expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something) - WORD_DESC *word; - int quoted, isexp; - int *contains_dollar_at; - int *expanded_something; -{ - WORD_LIST *list; - WORD_DESC *tword; - - /* The intermediate string that we build while expanding. */ - char *istring; - - /* The current size of the above object. */ - int istring_size; - - /* Index into ISTRING. */ - int istring_index; - - /* Temporary string storage. */ - char *temp, *temp1; - - /* The text of WORD. */ - register char *string; - - /* The size of STRING. */ - size_t string_size; - - /* The index into STRING. */ - int sindex; - - /* This gets 1 if we see a $@ while quoted. */ - int quoted_dollar_at; - - /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on - whether WORD contains no quoting characters, a partially quoted - string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */ - int quoted_state; - - /* State flags */ - int had_quoted_null; - int has_dollar_at, temp_has_dollar_at; - int split_on_spaces; - int tflag; - int pflags; /* flags passed to param_expand */ - - int assignoff; /* If assignment, offset of `=' */ - - register unsigned char c; /* Current character. */ - int t_index; /* For calls to string_extract_xxx. */ - - char twochars[2]; - - DECLARE_MBSTATE; - - istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE); - istring[istring_index = 0] = '\0'; - quoted_dollar_at = had_quoted_null = has_dollar_at = 0; - split_on_spaces = 0; - quoted_state = UNQUOTED; - - string = word->word; - if (string == 0) - goto finished_with_string; - /* Don't need the string length for the SADD... and COPY_ macros unless - multibyte characters are possible. */ - string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1; - - if (contains_dollar_at) - *contains_dollar_at = 0; - - assignoff = -1; - - /* Begin the expansion. */ - - for (sindex = 0; ;) - { - c = string[sindex]; - - /* Case on top-level character. */ - switch (c) - { - case '\0': - goto finished_with_string; - - case CTLESC: - sindex++; -#if HANDLE_MULTIBYTE - if (MB_CUR_MAX > 1 && string[sindex]) - { - SADD_MBQCHAR_BODY(temp, string, sindex, string_size); - } - else -#endif - { - temp = (char *)xmalloc (3); - temp[0] = CTLESC; - temp[1] = c = string[sindex]; - temp[2] = '\0'; - } - -dollar_add_string: - if (string[sindex]) - sindex++; - -add_string: - if (temp) - { - istring = sub_append_string (temp, istring, &istring_index, &istring_size); - temp = (char *)0; - } - - break; - -#if defined (PROCESS_SUBSTITUTION) - /* Process substitution. */ - case '<': - case '>': - { - /* bash-4.4/bash-5.0 - XXX - technically this should only be expanded at the start - of a word */ - if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct) - { - sindex--; /* add_character: label increments sindex */ - goto add_character; - } - else - t_index = sindex + 1; /* skip past both '<' and LPAREN */ - - temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index, 0); /*))*/ - sindex = t_index; - - /* If the process substitution specification is `<()', we want to - open the pipe for writing in the child and produce output; if - it is `>()', we want to open the pipe for reading in the child - and consume input. */ - temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0; - - FREE (temp1); - - goto dollar_add_string; - } -#endif /* PROCESS_SUBSTITUTION */ - - case '=': - /* Posix.2 section 3.6.1 says that tildes following `=' in words - which are not assignment statements are not expanded. If the - shell isn't in posix mode, though, we perform tilde expansion - on `likely candidate' unquoted assignment statements (flags - include W_ASSIGNMENT but not W_QUOTED). A likely candidate - contains an unquoted :~ or =~. Something to think about: we - now have a flag that says to perform tilde expansion on arguments - to `assignment builtins' like declare and export that look like - assignment statements. We now do tilde expansion on such words - even in POSIX mode. */ - if (word->flags & (W_ASSIGNRHS|W_NOTILDE)) - { - if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c)) - goto add_ifs_character; - else - goto add_character; - } - /* If we're not in posix mode or forcing assignment-statement tilde - expansion, note where the `=' appears in the word and prepare to - do tilde expansion following the first `='. */ - if ((word->flags & W_ASSIGNMENT) && - (posixly_correct == 0 || (word->flags & W_TILDEEXP)) && - assignoff == -1 && sindex > 0) - assignoff = sindex; - if (sindex == assignoff && string[sindex+1] == '~') /* XXX */ - word->flags |= W_ITILDE; -#if 0 - else if ((word->flags & W_ASSIGNMENT) && - (posixly_correct == 0 || (word->flags & W_TILDEEXP)) && - string[sindex+1] == '~') - word->flags |= W_ITILDE; -#endif - if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c)) - goto add_ifs_character; - else - goto add_character; - - case ':': - if (word->flags & W_NOTILDE) - { - if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c)) - goto add_ifs_character; - else - goto add_character; - } - - if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) && - string[sindex+1] == '~') - word->flags |= W_ITILDE; - - if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c)) - goto add_ifs_character; - else - goto add_character; - - case '~': - /* If the word isn't supposed to be tilde expanded, or we're not - at the start of a word or after an unquoted : or = in an - assignment statement, we don't do tilde expansion. */ - if ((word->flags & (W_NOTILDE|W_DQUOTE)) || - (sindex > 0 && ((word->flags & W_ITILDE) == 0)) || - (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) - { - word->flags &= ~W_ITILDE; - if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0) - goto add_ifs_character; - else - goto add_character; - } - - if (word->flags & W_ASSIGNRHS) - tflag = 2; - else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP)) - tflag = 1; - else - tflag = 0; - - temp = bash_tilde_find_word (string + sindex, tflag, &t_index); - - word->flags &= ~W_ITILDE; - - if (temp && *temp && t_index > 0) - { - temp1 = bash_tilde_expand (temp, tflag); - if (temp1 && *temp1 == '~' && STREQ (temp, temp1)) - { - FREE (temp); - FREE (temp1); - goto add_character; /* tilde expansion failed */ - } - free (temp); - temp = temp1; - sindex += t_index; - goto add_quoted_string; /* XXX was add_string */ - } - else - { - FREE (temp); - goto add_character; - } - - case '$': - if (expanded_something) - *expanded_something = 1; - - temp_has_dollar_at = 0; - pflags = (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0; - if (word->flags & W_NOSPLIT2) - pflags |= PF_NOSPLIT2; - if (word->flags & W_ASSIGNRHS) - pflags |= PF_ASSIGNRHS; - tword = param_expand (string, &sindex, quoted, expanded_something, - &temp_has_dollar_at, "ed_dollar_at, - &had_quoted_null, pflags); - has_dollar_at += temp_has_dollar_at; - split_on_spaces += (tword->flags & W_SPLITSPACE); - - if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal) - { - free (string); - free (istring); - return ((tword == &expand_wdesc_error) ? &expand_word_error - : &expand_word_fatal); - } - if (contains_dollar_at && has_dollar_at) - *contains_dollar_at = 1; - - if (tword && (tword->flags & W_HASQUOTEDNULL)) - had_quoted_null = 1; - - temp = tword ? tword->word : (char *)NULL; - dispose_word_desc (tword); - - /* Kill quoted nulls; we will add them back at the end of - expand_word_internal if nothing else in the string */ - if (had_quoted_null && temp && QUOTED_NULL (temp)) - { - FREE (temp); - temp = (char *)NULL; - } - - goto add_string; - break; - - case '`': /* Backquoted command substitution. */ - { - t_index = sindex++; - - temp = string_extract (string, &sindex, "`", SX_REQMATCH); - /* The test of sindex against t_index is to allow bare instances of - ` to pass through, for backwards compatibility. */ - if (temp == &extract_string_error || temp == &extract_string_fatal) - { - if (sindex - 1 == t_index) - { - sindex = t_index; - goto add_character; - } - last_command_exit_value = EXECUTION_FAILURE; - report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index); - free (string); - free (istring); - return ((temp == &extract_string_error) ? &expand_word_error - : &expand_word_fatal); - } - - if (expanded_something) - *expanded_something = 1; - - if (word->flags & W_NOCOMSUB) - /* sindex + 1 because string[sindex] == '`' */ - temp1 = substring (string, t_index, sindex + 1); - else - { - de_backslash (temp); - tword = command_substitute (temp, quoted); - temp1 = tword ? tword->word : (char *)NULL; - if (tword) - dispose_word_desc (tword); - } - FREE (temp); - temp = temp1; - goto dollar_add_string; - } - - case '\\': - if (string[sindex + 1] == '\n') - { - sindex += 2; - continue; - } - - c = string[++sindex]; - - if (quoted & Q_HERE_DOCUMENT) - tflag = CBSHDOC; - else if (quoted & Q_DOUBLE_QUOTES) - tflag = CBSDQUOTE; - else - tflag = 0; - - /* From Posix discussion on austin-group list: Backslash escaping - a } in ${...} is removed. Issue 0000221 */ - if ((quoted & Q_DOLBRACE) && c == RBRACE) - { - SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size); - } - /* This is the fix for " $@\ " */ - else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0) && isexp == 0 && isifs (c)) - { - RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, - DEFAULT_ARRAY_SIZE); - istring[istring_index++] = CTLESC; - istring[istring_index++] = '\\'; - istring[istring_index] = '\0'; - - SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size); - } - else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0)) - { - SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size); - } - else if (c == 0) - { - c = CTLNUL; - sindex--; /* add_character: label increments sindex */ - goto add_character; - } - else - { - SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size); - } - - sindex++; -add_twochars: - /* BEFORE jumping here, we need to increment sindex if appropriate */ - RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, - DEFAULT_ARRAY_SIZE); - istring[istring_index++] = twochars[0]; - istring[istring_index++] = twochars[1]; - istring[istring_index] = '\0'; - - break; - - case '"': - if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) - goto add_character; - - t_index = ++sindex; - temp = string_extract_double_quoted (string, &sindex, 0); - - /* If the quotes surrounded the entire string, then the - whole word was quoted. */ - quoted_state = (t_index == 1 && string[sindex] == '\0') - ? WHOLLY_QUOTED - : PARTIALLY_QUOTED; - - if (temp && *temp) - { - tword = alloc_word_desc (); - tword->word = temp; - - temp = (char *)NULL; - - temp_has_dollar_at = 0; /* XXX */ - /* Need to get W_HASQUOTEDNULL flag through this function. */ - list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &temp_has_dollar_at, (int *)NULL); - has_dollar_at += temp_has_dollar_at; - - if (list == &expand_word_error || list == &expand_word_fatal) - { - free (istring); - free (string); - /* expand_word_internal has already freed temp_word->word - for us because of the way it prints error messages. */ - tword->word = (char *)NULL; - dispose_word (tword); - return list; - } - - dispose_word (tword); - - /* "$@" (a double-quoted dollar-at) expands into nothing, - not even a NULL word, when there are no positional - parameters. */ - if (list == 0 && has_dollar_at) - { - quoted_dollar_at++; - break; - } - - /* If we get "$@", we know we have expanded something, so we - need to remember it for the final split on $IFS. This is - a special case; it's the only case where a quoted string - can expand into more than one word. It's going to come back - from the above call to expand_word_internal as a list with - a single word, in which all characters are quoted and - separated by blanks. What we want to do is to turn it back - into a list for the next piece of code. */ - if (list) - dequote_list (list); - - if (list && list->word && (list->word->flags & W_HASQUOTEDNULL)) - had_quoted_null = 1; /* XXX */ - - if (has_dollar_at) - { - quoted_dollar_at++; - if (contains_dollar_at) - *contains_dollar_at = 1; - if (expanded_something) - *expanded_something = 1; - } - } - else - { - /* What we have is "". This is a minor optimization. */ - FREE (temp); - list = (WORD_LIST *)NULL; - } - - /* The code above *might* return a list (consider the case of "$@", - where it returns "$1", "$2", etc.). We can't throw away the - rest of the list, and we have to make sure each word gets added - as quoted. We test on tresult->next: if it is non-NULL, we - quote the whole list, save it to a string with string_list, and - add that string. We don't need to quote the results of this - (and it would be wrong, since that would quote the separators - as well), so we go directly to add_string. */ - if (list) - { - if (list->next) - { - /* Testing quoted_dollar_at makes sure that "$@" is - split correctly when $IFS does not contain a space. */ - temp = quoted_dollar_at - ? string_list_dollar_at (list, Q_DOUBLE_QUOTES) - : string_list (quote_list (list)); - dispose_words (list); - goto add_string; - } - else - { - temp = savestring (list->word->word); - tflag = list->word->flags; - dispose_words (list); - - /* If the string is not a quoted null string, we want - to remove any embedded unquoted CTLNUL characters. - We do not want to turn quoted null strings back into - the empty string, though. We do this because we - want to remove any quoted nulls from expansions that - contain other characters. For example, if we have - x"$*"y or "x$*y" and there are no positional parameters, - the $* should expand into nothing. */ - /* We use the W_HASQUOTEDNULL flag to differentiate the - cases: a quoted null character as above and when - CTLNUL is contained in the (non-null) expansion - of some variable. We use the had_quoted_null flag to - pass the value through this function to its caller. */ - if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0) - remove_quoted_nulls (temp); /* XXX */ - } - } - else - temp = (char *)NULL; - - /* We do not want to add quoted nulls to strings that are only - partially quoted; we can throw them away. The exception to - this is when we are going to be performing word splitting, - since we have to preserve a null argument if the next character - will cause word splitting. */ - if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2))) - continue; - - add_quoted_string: - - if (temp) - { - temp1 = temp; - temp = quote_string (temp); - free (temp1); - goto add_string; - } - else - { - /* Add NULL arg. */ - c = CTLNUL; - sindex--; /* add_character: label increments sindex */ - goto add_character; - } - - /* break; */ - - case '\'': - if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) - goto add_character; - - t_index = ++sindex; - temp = string_extract_single_quoted (string, &sindex); - - /* If the entire STRING was surrounded by single quotes, - then the string is wholly quoted. */ - quoted_state = (t_index == 1 && string[sindex] == '\0') - ? WHOLLY_QUOTED - : PARTIALLY_QUOTED; - - /* If all we had was '', it is a null expansion. */ - if (*temp == '\0') - { - free (temp); - temp = (char *)NULL; - } - else - remove_quoted_escapes (temp); /* ??? */ - - /* We do not want to add quoted nulls to strings that are only - partially quoted; such nulls are discarded. */ - if (temp == 0 && (quoted_state == PARTIALLY_QUOTED)) - continue; - - /* If we have a quoted null expansion, add a quoted NULL to istring. */ - if (temp == 0) - { - c = CTLNUL; - sindex--; /* add_character: label increments sindex */ - goto add_character; - } - else - goto add_quoted_string; - - /* break; */ - - default: - /* This is the fix for " $@ " */ - add_ifs_character: - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c))) - { - if (string[sindex]) /* from old goto dollar_add_string */ - sindex++; - if (c == 0) - { - c = CTLNUL; - goto add_character; - } - else - { -#if HANDLE_MULTIBYTE - if (MB_CUR_MAX > 1) - sindex--; - - if (MB_CUR_MAX > 1) - { - SADD_MBQCHAR_BODY(temp, string, sindex, string_size); - } - else -#endif - { - twochars[0] = CTLESC; - twochars[1] = c; - goto add_twochars; - } - } - } - - SADD_MBCHAR (temp, string, sindex, string_size); - - add_character: - RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size, - DEFAULT_ARRAY_SIZE); - istring[istring_index++] = c; - istring[istring_index] = '\0'; - - /* Next character. */ - sindex++; - } - } - -finished_with_string: - /* OK, we're ready to return. If we have a quoted string, and - quoted_dollar_at is not set, we do no splitting at all; otherwise - we split on ' '. The routines that call this will handle what to - do if nothing has been expanded. */ - - /* Partially and wholly quoted strings which expand to the empty - string are retained as an empty arguments. Unquoted strings - which expand to the empty string are discarded. The single - exception is the case of expanding "$@" when there are no - positional parameters. In that case, we discard the expansion. */ - - /* Because of how the code that handles "" and '' in partially - quoted strings works, we need to make ISTRING into a QUOTED_NULL - if we saw quoting characters, but the expansion was empty. - "" and '' are tossed away before we get to this point when - processing partially quoted strings. This makes "" and $xxx"" - equivalent when xxx is unset. We also look to see whether we - saw a quoted null from a ${} expansion and add one back if we - need to. */ - - /* If we expand to nothing and there were no single or double quotes - in the word, we throw it away. Otherwise, we return a NULL word. - The single exception is for $@ surrounded by double quotes when - there are no positional parameters. In that case, we also throw - the word away. */ - - if (*istring == '\0') - { - if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED)) - { - istring[0] = CTLNUL; - istring[1] = '\0'; - tword = make_bare_word (istring); - tword->flags |= W_HASQUOTEDNULL; /* XXX */ - list = make_word_list (tword, (WORD_LIST *)NULL); - if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) - tword->flags |= W_QUOTED; - } - /* According to sh, ksh, and Posix.2, if a word expands into nothing - and a double-quoted "$@" appears anywhere in it, then the entire - word is removed. */ - else if (quoted_state == UNQUOTED || quoted_dollar_at) - list = (WORD_LIST *)NULL; -#if 0 - else - { - tword = make_bare_word (istring); - if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) - tword->flags |= W_QUOTED; - list = make_word_list (tword, (WORD_LIST *)NULL); - } -#else - else - list = (WORD_LIST *)NULL; -#endif - } - else if (word->flags & W_NOSPLIT) - { - tword = make_bare_word (istring); - if (word->flags & W_ASSIGNMENT) - tword->flags |= W_ASSIGNMENT; /* XXX */ - if (word->flags & W_COMPASSIGN) - tword->flags |= W_COMPASSIGN; /* XXX */ - if (word->flags & W_NOGLOB) - tword->flags |= W_NOGLOB; /* XXX */ - if (word->flags & W_NOBRACE) - tword->flags |= W_NOBRACE; /* XXX */ - if (word->flags & W_NOEXPAND) - tword->flags |= W_NOEXPAND; /* XXX */ - if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) - tword->flags |= W_QUOTED; - if (had_quoted_null && QUOTED_NULL (istring)) - tword->flags |= W_HASQUOTEDNULL; - list = make_word_list (tword, (WORD_LIST *)NULL); - } - else - { - char *ifs_chars; - char *tstring; - - ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL; - - /* If we have $@, we need to split the results no matter what. If - IFS is unset or NULL, string_list_dollar_at has separated the - positional parameters with a space, so we split on space (we have - set ifs_chars to " \t\n" above if ifs is unset). If IFS is set, - string_list_dollar_at has separated the positional parameters - with the first character of $IFS, so we split on $IFS. If - SPLIT_ON_SPACES is set, we expanded $* (unquoted) with IFS either - unset or null, and we want to make sure that we split on spaces - regardless of what else has happened to IFS since the expansion. */ - if (split_on_spaces) - list = list_string (istring, " ", 1); /* XXX quoted == 1? */ - /* If we have $@ (has_dollar_at != 0) and we are in a context where we - don't want to split the result (W_NOSPLIT2), and we are not quoted, - we have already separated the arguments with the first character of - $IFS. In this case, we want to return a list with a single word - with the separator possibly replaced with a space (it's what other - shells seem to do). - quoted_dollar_at is internal to this function and is set if we are - passed an argument that is unquoted (quoted == 0) but we encounter a - double-quoted $@ while expanding it. */ - else if (has_dollar_at && quoted_dollar_at == 0 && ifs_chars && quoted == 0 && (word->flags & W_NOSPLIT2)) - { - /* Only split and rejoin if we have to */ - if (*ifs_chars && *ifs_chars != ' ') - { - list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1); - tstring = string_list (list); - } - else - tstring = istring; - tword = make_bare_word (tstring); - if (tstring != istring) - free (tstring); - goto set_word_flags; - } - else if (has_dollar_at && ifs_chars) - list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1); - else - { - tword = make_bare_word (istring); -set_word_flags: - if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED)) - tword->flags |= W_QUOTED; - if (word->flags & W_ASSIGNMENT) - tword->flags |= W_ASSIGNMENT; - if (word->flags & W_COMPASSIGN) - tword->flags |= W_COMPASSIGN; - if (word->flags & W_NOGLOB) - tword->flags |= W_NOGLOB; - if (word->flags & W_NOBRACE) - tword->flags |= W_NOBRACE; - if (word->flags & W_NOEXPAND) - tword->flags |= W_NOEXPAND; - if (had_quoted_null && QUOTED_NULL (istring)) - tword->flags |= W_HASQUOTEDNULL; /* XXX */ - list = make_word_list (tword, (WORD_LIST *)NULL); - } - } - - free (istring); - return (list); -} - -/* **************************************************************** */ -/* */ -/* Functions for Quote Removal */ -/* */ -/* **************************************************************** */ - -/* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the - backslash quoting rules for within double quotes or a here document. */ -char * -string_quote_removal (string, quoted) - char *string; - int quoted; -{ - size_t slen; - char *r, *result_string, *temp, *send; - int sindex, tindex, dquote; - unsigned char c; - DECLARE_MBSTATE; - - /* The result can be no longer than the original string. */ - slen = strlen (string); - send = string + slen; - - r = result_string = (char *)xmalloc (slen + 1); - - for (dquote = sindex = 0; c = string[sindex];) - { - switch (c) - { - case '\\': - c = string[++sindex]; - if (c == 0) - { - *r++ = '\\'; - break; - } - if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0) - *r++ = '\\'; - /* FALLTHROUGH */ - - default: - SCOPY_CHAR_M (r, string, send, sindex); - break; - - case '\'': - if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) - { - *r++ = c; - sindex++; - break; - } - tindex = sindex + 1; - temp = string_extract_single_quoted (string, &tindex); - if (temp) - { - strcpy (r, temp); - r += strlen (r); - free (temp); - } - sindex = tindex; - break; - - case '"': - dquote = 1 - dquote; - sindex++; - break; - } - } - *r = '\0'; - return (result_string); -} - -#if 0 -/* UNUSED */ -/* Perform quote removal on word WORD. This allocates and returns a new - WORD_DESC *. */ -WORD_DESC * -word_quote_removal (word, quoted) - WORD_DESC *word; - int quoted; -{ - WORD_DESC *w; - char *t; - - t = string_quote_removal (word->word, quoted); - w = alloc_word_desc (); - w->word = t ? t : savestring (""); - return (w); -} - -/* Perform quote removal on all words in LIST. If QUOTED is non-zero, - the members of the list are treated as if they are surrounded by - double quotes. Return a new list, or NULL if LIST is NULL. */ -WORD_LIST * -word_list_quote_removal (list, quoted) - WORD_LIST *list; - int quoted; -{ - WORD_LIST *result, *t, *tresult, *e; - - for (t = list, result = (WORD_LIST *)NULL; t; t = t->next) - { - tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL); -#if 0 - result = (WORD_LIST *) list_append (result, tresult); -#else - if (result == 0) - result = e = tresult; - else - { - e->next = tresult; - while (e->next) - e = e->next; - } -#endif - } - return (result); -} -#endif - -/******************************************* - * * - * Functions to perform word splitting * - * * - *******************************************/ - -void -setifs (v) - SHELL_VAR *v; -{ - char *t; - unsigned char uc; - - ifs_var = v; - ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n"; - - ifs_is_set = ifs_var != 0; - ifs_is_null = ifs_is_set && (*ifs_value == 0); - - /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet - handle multibyte chars in IFS */ - memset (ifs_cmap, '\0', sizeof (ifs_cmap)); - for (t = ifs_value ; t && *t; t++) - { - uc = *t; - ifs_cmap[uc] = 1; - } - -#if defined (HANDLE_MULTIBYTE) - if (ifs_value == 0) - { - ifs_firstc[0] = '\0'; - ifs_firstc_len = 1; - } - else - { - size_t ifs_len; - ifs_len = strnlen (ifs_value, MB_CUR_MAX); - ifs_firstc_len = MBLEN (ifs_value, ifs_len); - if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len)) - { - ifs_firstc[0] = ifs_value[0]; - ifs_firstc[1] = '\0'; - ifs_firstc_len = 1; - } - else - memcpy (ifs_firstc, ifs_value, ifs_firstc_len); - } -#else - ifs_firstc = ifs_value ? *ifs_value : 0; -#endif -} - -char * -getifs () -{ - return ifs_value; -} - -/* This splits a single word into a WORD LIST on $IFS, but only if the word - is not quoted. list_string () performs quote removal for us, even if we - don't do any splitting. */ -WORD_LIST * -word_split (w, ifs_chars) - WORD_DESC *w; - char *ifs_chars; -{ - WORD_LIST *result; - - if (w) - { - char *xifs; - - xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars; - result = list_string (w->word, xifs, w->flags & W_QUOTED); - } - else - result = (WORD_LIST *)NULL; - - return (result); -} - -/* Perform word splitting on LIST and return the RESULT. It is possible - to return (WORD_LIST *)NULL. */ -static WORD_LIST * -word_list_split (list) - WORD_LIST *list; -{ - WORD_LIST *result, *t, *tresult, *e; - - for (t = list, result = (WORD_LIST *)NULL; t; t = t->next) - { - tresult = word_split (t->word, ifs_value); - if (result == 0) - result = e = tresult; - else - { - e->next = tresult; - while (e->next) - e = e->next; - } - } - return (result); -} - -/************************************************** - * * - * Functions to expand an entire WORD_LIST * - * * - **************************************************/ - -/* Do any word-expansion-specific cleanup and jump to top_level */ -static void -exp_jump_to_top_level (v) - int v; -{ - set_pipestatus_from_exit (last_command_exit_value); - - /* Cleanup code goes here. */ - expand_no_split_dollar_star = 0; /* XXX */ - expanding_redir = 0; - assigning_in_environment = 0; - - if (parse_and_execute_level == 0) - top_level_cleanup (); /* from sig.c */ - - jump_to_top_level (v); -} - -/* Put NLIST (which is a WORD_LIST * of only one element) at the front of - ELIST, and set ELIST to the new list. */ -#define PREPEND_LIST(nlist, elist) \ - do { nlist->next = elist; elist = nlist; } while (0) - -/* Separate out any initial variable assignments from TLIST. If set -k has - been executed, remove all assignment statements from TLIST. Initial - variable assignments and other environment assignments are placed - on SUBST_ASSIGN_VARLIST. */ -static WORD_LIST * -separate_out_assignments (tlist) - WORD_LIST *tlist; -{ - register WORD_LIST *vp, *lp; - - if (tlist == 0) - return ((WORD_LIST *)NULL); - - if (subst_assign_varlist) - dispose_words (subst_assign_varlist); /* Clean up after previous error */ - - subst_assign_varlist = (WORD_LIST *)NULL; - vp = lp = tlist; - - /* Separate out variable assignments at the start of the command. - Loop invariant: vp->next == lp - Loop postcondition: - lp = list of words left after assignment statements skipped - tlist = original list of words - */ - while (lp && (lp->word->flags & W_ASSIGNMENT)) - { - vp = lp; - lp = lp->next; - } - - /* If lp != tlist, we have some initial assignment statements. - We make SUBST_ASSIGN_VARLIST point to the list of assignment - words and TLIST point to the remaining words. */ - if (lp != tlist) - { - subst_assign_varlist = tlist; - /* ASSERT(vp->next == lp); */ - vp->next = (WORD_LIST *)NULL; /* terminate variable list */ - tlist = lp; /* remainder of word list */ - } - - /* vp == end of variable list */ - /* tlist == remainder of original word list without variable assignments */ - if (!tlist) - /* All the words in tlist were assignment statements */ - return ((WORD_LIST *)NULL); - - /* ASSERT(tlist != NULL); */ - /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */ - - /* If the -k option is in effect, we need to go through the remaining - words, separate out the assignment words, and place them on - SUBST_ASSIGN_VARLIST. */ - if (place_keywords_in_env) - { - WORD_LIST *tp; /* tp == running pointer into tlist */ - - tp = tlist; - lp = tlist->next; - - /* Loop Invariant: tp->next == lp */ - /* Loop postcondition: tlist == word list without assignment statements */ - while (lp) - { - if (lp->word->flags & W_ASSIGNMENT) - { - /* Found an assignment statement, add this word to end of - subst_assign_varlist (vp). */ - if (!subst_assign_varlist) - subst_assign_varlist = vp = lp; - else - { - vp->next = lp; - vp = lp; - } - - /* Remove the word pointed to by LP from TLIST. */ - tp->next = lp->next; - /* ASSERT(vp == lp); */ - lp->next = (WORD_LIST *)NULL; - lp = tp->next; - } - else - { - tp = lp; - lp = lp->next; - } - } - } - return (tlist); -} - -#define WEXP_VARASSIGN 0x001 -#define WEXP_BRACEEXP 0x002 -#define WEXP_TILDEEXP 0x004 -#define WEXP_PARAMEXP 0x008 -#define WEXP_PATHEXP 0x010 - -/* All of the expansions, including variable assignments at the start of - the list. */ -#define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP) - -/* All of the expansions except variable assignments at the start of - the list. */ -#define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP) - -/* All of the `shell expansions': brace expansion, tilde expansion, parameter - expansion, command substitution, arithmetic expansion, word splitting, and - quote removal. */ -#define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP) - -/* Take the list of words in LIST and do the various substitutions. Return - a new list of words which is the expanded list, and without things like - variable assignments. */ - -WORD_LIST * -expand_words (list) - WORD_LIST *list; -{ - return (expand_word_list_internal (list, WEXP_ALL)); -} - -/* Same as expand_words (), but doesn't hack variable or environment - variables. */ -WORD_LIST * -expand_words_no_vars (list) - WORD_LIST *list; -{ - return (expand_word_list_internal (list, WEXP_NOVARS)); -} - -WORD_LIST * -expand_words_shellexp (list) - WORD_LIST *list; -{ - return (expand_word_list_internal (list, WEXP_SHELLEXP)); -} - -static WORD_LIST * -glob_expand_word_list (tlist, eflags) - WORD_LIST *tlist; - int eflags; -{ - char **glob_array, *temp_string; - register int glob_index; - WORD_LIST *glob_list, *output_list, *disposables, *next; - WORD_DESC *tword; - - output_list = disposables = (WORD_LIST *)NULL; - glob_array = (char **)NULL; - while (tlist) - { - /* For each word, either globbing is attempted or the word is - added to orig_list. If globbing succeeds, the results are - added to orig_list and the word (tlist) is added to the list - of disposable words. If globbing fails and failed glob - expansions are left unchanged (the shell default), the - original word is added to orig_list. If globbing fails and - failed glob expansions are removed, the original word is - added to the list of disposable words. orig_list ends up - in reverse order and requires a call to REVERSE_LIST to - be set right. After all words are examined, the disposable - words are freed. */ - next = tlist->next; - - /* If the word isn't an assignment and contains an unquoted - pattern matching character, then glob it. */ - if ((tlist->word->flags & W_NOGLOB) == 0 && - unquoted_glob_pattern_p (tlist->word->word)) - { - glob_array = shell_glob_filename (tlist->word->word); - - /* Handle error cases. - I don't think we should report errors like "No such file - or directory". However, I would like to report errors - like "Read failed". */ - - if (glob_array == 0 || GLOB_FAILED (glob_array)) - { - glob_array = (char **)xmalloc (sizeof (char *)); - glob_array[0] = (char *)NULL; - } - - /* Dequote the current word in case we have to use it. */ - if (glob_array[0] == NULL) - { - temp_string = dequote_string (tlist->word->word); - free (tlist->word->word); - tlist->word->word = temp_string; - } - - /* Make the array into a word list. */ - glob_list = (WORD_LIST *)NULL; - for (glob_index = 0; glob_array[glob_index]; glob_index++) - { - tword = make_bare_word (glob_array[glob_index]); - glob_list = make_word_list (tword, glob_list); - } - - if (glob_list) - { - output_list = (WORD_LIST *)list_append (glob_list, output_list); - PREPEND_LIST (tlist, disposables); - } - else if (fail_glob_expansion != 0) - { - last_command_exit_value = EXECUTION_FAILURE; - report_error (_("no match: %s"), tlist->word->word); - exp_jump_to_top_level (DISCARD); - } - else if (allow_null_glob_expansion == 0) - { - /* Failed glob expressions are left unchanged. */ - PREPEND_LIST (tlist, output_list); - } - else - { - /* Failed glob expressions are removed. */ - PREPEND_LIST (tlist, disposables); - } - } - else - { - /* Dequote the string. */ - temp_string = dequote_string (tlist->word->word); - free (tlist->word->word); - tlist->word->word = temp_string; - PREPEND_LIST (tlist, output_list); - } - - strvec_dispose (glob_array); - glob_array = (char **)NULL; - - tlist = next; - } - - if (disposables) - dispose_words (disposables); - - if (output_list) - output_list = REVERSE_LIST (output_list, WORD_LIST *); - - return (output_list); -} - -#if defined (BRACE_EXPANSION) -static WORD_LIST * -brace_expand_word_list (tlist, eflags) - WORD_LIST *tlist; - int eflags; -{ - register char **expansions; - char *temp_string; - WORD_LIST *disposables, *output_list, *next; - WORD_DESC *w; - int eindex; - - for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next) - { - next = tlist->next; - - if (tlist->word->flags & W_NOBRACE) - { -/*itrace("brace_expand_word_list: %s: W_NOBRACE", tlist->word->word);*/ - PREPEND_LIST (tlist, output_list); - continue; - } - - if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG)) - { -/*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/ - PREPEND_LIST (tlist, output_list); - continue; - } - - /* Only do brace expansion if the word has a brace character. If - not, just add the word list element to BRACES and continue. In - the common case, at least when running shell scripts, this will - degenerate to a bunch of calls to `mbschr', and then what is - basically a reversal of TLIST into BRACES, which is corrected - by a call to REVERSE_LIST () on BRACES when the end of TLIST - is reached. */ - if (mbschr (tlist->word->word, LBRACE)) - { - expansions = brace_expand (tlist->word->word); - - for (eindex = 0; temp_string = expansions[eindex]; eindex++) - { - w = alloc_word_desc (); - w->word = temp_string; - - /* If brace expansion didn't change the word, preserve - the flags. We may want to preserve the flags - unconditionally someday -- XXX */ - if (STREQ (temp_string, tlist->word->word)) - w->flags = tlist->word->flags; - else - w = make_word_flags (w, temp_string); - - output_list = make_word_list (w, output_list); - } - free (expansions); - - /* Add TLIST to the list of words to be freed after brace - expansion has been performed. */ - PREPEND_LIST (tlist, disposables); - } - else - PREPEND_LIST (tlist, output_list); - } - - if (disposables) - dispose_words (disposables); - - if (output_list) - output_list = REVERSE_LIST (output_list, WORD_LIST *); - - return (output_list); -} -#endif - -#if defined (ARRAY_VARS) -/* Take WORD, a compound associative array assignment, and internally run - 'declare -A w', where W is the variable name portion of WORD. */ -static int -make_internal_declare (word, option) - char *word; - char *option; -{ - int t; - WORD_LIST *wl; - WORD_DESC *w; - - w = make_word (word); - - t = assignment (w->word, 0); - w->word[t] = '\0'; - - wl = make_word_list (w, (WORD_LIST *)NULL); - wl = make_word_list (make_word (option), wl); - - return (declare_builtin (wl)); -} -#endif - -static WORD_LIST * -shell_expand_word_list (tlist, eflags) - WORD_LIST *tlist; - int eflags; -{ - WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list; - int expanded_something, has_dollar_at; - char *temp_string; - - /* We do tilde expansion all the time. This is what 1003.2 says. */ - new_list = (WORD_LIST *)NULL; - for (orig_list = tlist; tlist; tlist = next) - { - temp_string = tlist->word->word; - - next = tlist->next; - -#if defined (ARRAY_VARS) - /* If this is a compound array assignment to a builtin that accepts - such assignments (e.g., `declare'), take the assignment and perform - it separately, handling the semantics of declarations inside shell - functions. This avoids the double-evaluation of such arguments, - because `declare' does some evaluation of compound assignments on - its own. */ - if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG)) - { - int t; - char opts[8], opti; - - opti = 0; - if (tlist->word->flags & (W_ASSIGNASSOC|W_ASSNGLOBAL|W_ASSIGNARRAY)) - opts[opti++] = '-'; - - if ((tlist->word->flags & (W_ASSIGNASSOC|W_ASSNGLOBAL)) == (W_ASSIGNASSOC|W_ASSNGLOBAL)) - { - opts[opti++] = 'g'; - opts[opti++] = 'A'; - } - else if (tlist->word->flags & W_ASSIGNASSOC) - opts[opti++] = 'A'; - else if ((tlist->word->flags & (W_ASSIGNARRAY|W_ASSNGLOBAL)) == (W_ASSIGNARRAY|W_ASSNGLOBAL)) - { - opts[opti++] = 'g'; - opts[opti++] = 'a'; - } - else if (tlist->word->flags & W_ASSIGNARRAY) - opts[opti++] = 'a'; - else if (tlist->word->flags & W_ASSNGLOBAL) - opts[opti++] = 'g'; - -#if 0 - /* If we have special handling note the integer attribute */ - if (opti > 0 && (tlist->word->flags & W_ASSIGNINT)) - opts[opti++] = 'i'; -#endif - - opts[opti] = '\0'; - if (opti > 0) - make_internal_declare (tlist->word->word, opts); - - t = do_word_assignment (tlist->word, 0); - if (t == 0) - { - last_command_exit_value = EXECUTION_FAILURE; - exp_jump_to_top_level (DISCARD); - } - - /* Now transform the word as ksh93 appears to do and go on */ - t = assignment (tlist->word->word, 0); - tlist->word->word[t] = '\0'; - tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC|W_ASSIGNARRAY); - } -#endif - - expanded_something = 0; - expanded = expand_word_internal - (tlist->word, 0, 0, &has_dollar_at, &expanded_something); - - if (expanded == &expand_word_error || expanded == &expand_word_fatal) - { - /* By convention, each time this error is returned, - tlist->word->word has already been freed. */ - tlist->word->word = (char *)NULL; - - /* Dispose our copy of the original list. */ - dispose_words (orig_list); - /* Dispose the new list we're building. */ - dispose_words (new_list); - - last_command_exit_value = EXECUTION_FAILURE; - if (expanded == &expand_word_error) - exp_jump_to_top_level (DISCARD); - else - exp_jump_to_top_level (FORCE_EOF); - } - - /* Don't split words marked W_NOSPLIT. */ - if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0) - { - temp_list = word_list_split (expanded); - dispose_words (expanded); - } - else - { - /* If no parameter expansion, command substitution, process - substitution, or arithmetic substitution took place, then - do not do word splitting. We still have to remove quoted - null characters from the result. */ - word_list_remove_quoted_nulls (expanded); - temp_list = expanded; - } - - expanded = REVERSE_LIST (temp_list, WORD_LIST *); - new_list = (WORD_LIST *)list_append (expanded, new_list); - } - - if (orig_list) - dispose_words (orig_list); - - if (new_list) - new_list = REVERSE_LIST (new_list, WORD_LIST *); - - return (new_list); -} - -/* The workhorse for expand_words () and expand_words_no_vars (). - First arg is LIST, a WORD_LIST of words. - Second arg EFLAGS is a flags word controlling which expansions are - performed. - - This does all of the substitutions: brace expansion, tilde expansion, - parameter expansion, command substitution, arithmetic expansion, - process substitution, word splitting, and pathname expansion, according - to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits - set, or for which no expansion is done, do not undergo word splitting. - Words with the W_NOGLOB bit set do not undergo pathname expansion; words - with W_NOBRACE set do not undergo brace expansion (see - brace_expand_word_list above). */ -static WORD_LIST * -expand_word_list_internal (list, eflags) - WORD_LIST *list; - int eflags; -{ - WORD_LIST *new_list, *temp_list; - int tint; - - tempenv_assign_error = 0; - if (list == 0) - return ((WORD_LIST *)NULL); - - garglist = new_list = copy_word_list (list); - if (eflags & WEXP_VARASSIGN) - { - garglist = new_list = separate_out_assignments (new_list); - if (new_list == 0) - { - if (subst_assign_varlist) - { - /* All the words were variable assignments, so they are placed - into the shell's environment. */ - for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next) - { - this_command_name = (char *)NULL; /* no arithmetic errors */ - tint = do_word_assignment (temp_list->word, 0); - /* Variable assignment errors in non-interactive shells - running in Posix.2 mode cause the shell to exit. */ - if (tint == 0) - { - last_command_exit_value = EXECUTION_FAILURE; - if (interactive_shell == 0 && posixly_correct) - exp_jump_to_top_level (FORCE_EOF); - else - exp_jump_to_top_level (DISCARD); - } - } - dispose_words (subst_assign_varlist); - subst_assign_varlist = (WORD_LIST *)NULL; - } - return ((WORD_LIST *)NULL); - } - } - - /* Begin expanding the words that remain. The expansions take place on - things that aren't really variable assignments. */ - -#if defined (BRACE_EXPANSION) - /* Do brace expansion on this word if there are any brace characters - in the string. */ - if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list) - new_list = brace_expand_word_list (new_list, eflags); -#endif /* BRACE_EXPANSION */ - - /* Perform the `normal' shell expansions: tilde expansion, parameter and - variable substitution, command substitution, arithmetic expansion, - and word splitting. */ - new_list = shell_expand_word_list (new_list, eflags); - - /* Okay, we're almost done. Now let's just do some filename - globbing. */ - if (new_list) - { - if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0) - /* Glob expand the word list unless globbing has been disabled. */ - new_list = glob_expand_word_list (new_list, eflags); - else - /* Dequote the words, because we're not performing globbing. */ - new_list = dequote_list (new_list); - } - - if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist) - { - sh_wassign_func_t *assign_func; - int is_special_builtin, is_builtin_or_func; - - /* If the remainder of the words expand to nothing, Posix.2 requires - that the variable and environment assignments affect the shell's - environment. */ - assign_func = new_list ? assign_in_env : do_word_assignment; - tempenv_assign_error = 0; - - is_builtin_or_func = (new_list && new_list->word && (find_shell_builtin (new_list->word->word) || find_function (new_list->word->word))); - /* Posix says that special builtins exit if a variable assignment error - occurs in an assignment preceding it. */ - is_special_builtin = (posixly_correct && new_list && new_list->word && find_special_builtin (new_list->word->word)); - - for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next) - { - this_command_name = (char *)NULL; - assigning_in_environment = (assign_func == assign_in_env); - tint = (*assign_func) (temp_list->word, is_builtin_or_func); - assigning_in_environment = 0; - /* Variable assignment errors in non-interactive shells running - in Posix.2 mode cause the shell to exit. */ - if (tint == 0) - { - if (assign_func == do_word_assignment) - { - last_command_exit_value = EXECUTION_FAILURE; - if (interactive_shell == 0 && posixly_correct && is_special_builtin) - exp_jump_to_top_level (FORCE_EOF); - else - exp_jump_to_top_level (DISCARD); - } - else - tempenv_assign_error++; - } - } - - dispose_words (subst_assign_varlist); - subst_assign_varlist = (WORD_LIST *)NULL; - } - - return (new_list); -} diff --git a/tests/RUN-ONE-TEST~ b/tests/RUN-ONE-TEST~ deleted file mode 100755 index 3efcf32d..00000000 --- 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/array.tests~ b/tests/array.tests~ deleted file mode 100644 index bed63708..00000000 --- a/tests/array.tests~ +++ /dev/null @@ -1,402 +0,0 @@ -# this is needed so that the bad assignments (b[]=bcde, for example) do not -# cause fatal shell errors when in posix mode -set +o posix - -set +a -# The calls to egrep -v are to filter out builtin array variables that are -# automatically set and possibly contain values that vary. - -# first make sure we handle the basics -x=() -echo ${x[@]} -unset x - -# this should be an error -test=(first & second) -echo $? -unset test - -# make sure declare -a converts an existing variable to an array -unset a -a=abcde -declare -a a -echo ${a[0]} - -unset a -a=abcde -a[2]=bdef - -unset b -declare -a b[256] - -unset c[2] -unset c[*] - -a[1]= - -_ENV=/bin/true -x=${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]} - -declare -r c[100] - -echo ${a[0]} ${a[4]} -echo ${a[@]} - -echo ${a[*]} - -# this should print out values, too -declare -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS|FUNCNAME)' - -unset a[7] -echo ${a[*]} - -unset a[4] -echo ${a[*]} - -echo ${a} -echo "${a}" -echo $a - -unset a[0] -echo ${a} - -echo ${a[@]} - -a[5]="hello world" -echo ${a[5]} -echo ${#a[5]} - -echo ${#a[@]} - -a[4+5/2]="test expression" -declare a["7 + 8"]="test 2" -a[7 + 8]="test 2" -echo ${a[@]} - -readonly a[5] -readonly a -# these two lines should output `declare' commands -readonly -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' -declare -ar | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' -# this line should output `readonly' commands, even for arrays -set -o posix -readonly -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' -set +o posix - -declare -a d='([1]="" [2]="bdef" [5]="hello world" "test")' -d[9]="ninth element" - -declare -a e[10]=test # this works in post-bash-2.05 versions -declare -a e[10]='(test)' - -pass=/etc/passwd -declare -a f='("${d[@]}")' -b=([0]=this [1]=is [2]=a [3]=test [4]="$PS1" [5]=$pass) - -echo ${b[@]:2:3} - -declare -pa | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' - -a[3]="this is a test" - -b[]=bcde -b[*]=aaa -echo ${b[ ]} - -c[-2]=4 -echo ${c[-4]} - -d[7]=(abdedfegeee) - -d=([]=abcde [1]="test test" [*]=last [-65]=negative ) - -unset d[12] -unset e[*] - -declare -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' - -ps1='hello' -unset ps1[2] -unset ${ps1[2]} - -declare +a ps1 -declare +a c - -# the prompt should not print when using a here doc -read -p "array test: " -a rv <<! -this is a test of read using arrays -! - -echo ${rv[0]} ${rv[4]} -echo ${rv[@]} - -# the variable should be converted to an array when `read -a' is done -vv=1 -read -a vv <<! -this is a test of arrays -! -echo ${vv[0]} ${vv[3]} -echo ${vv[@]} -unset vv - -declare -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' - -export rv -#set - -x[4]=bbb -x=abde -echo $x -echo ${x[0]} -echo ${x[4]} -echo efgh | ( read x[1] ; echo ${x[1]} ) -echo wxyz | ( declare -a x ; read x ; echo $x ; echo ${x[0]} ) - -# Make sure that arrays can be used to save the positional paramters verbatim -set -- a 'b c' d 'e f g' h - -ARGV=( [0]=$0 "$@" ) - -for z in "${ARGV[@]}" -do - echo "$z" -done - -echo "$0" -for z in "$@" -do - echo "$z" -done - -# do various pattern removal and length tests -XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin - -xpath=( $( IFS=: ; echo $XPATH ) ) - -echo ${xpath[@]} -echo ${xpath[@]##*/} -echo ${xpath[0]##*/} -echo ${xpath[@]%%[!/]*} -echo ${xpath[0]%%[!/]*} -recho ${xpath##*/} -recho ${xpath%%[!/]*} -recho ${xpath[5]##*/} -recho ${xpath[5]%%[!/]*} - -# let's try to make it a DOS-style path - -zecho "${xpath[@]/\//\\}" -zecho "${xpath[@]//\//\\}" -zecho "${xpath[@]//[\/]/\\}" - -# length of the first element of the array, since array without subscript -# is equivalent to referencing first element -echo ${#xpath} -- ${#xpath[0]} - -# number of elements in the array -nelem=${#xpath[@]} -echo ${#xpath[@]} -- $nelem - -# total length of all elements in the array, including space separators -xx="${xpath[*]}" -echo ${#xx} - -# total length of all elements in the array -xx=$( IFS='' ; echo "${xpath[*]}" ) -echo ${#xx} - -unset xpath[nelem-1] - -nelem=${#xpath[@]} -echo ${#xpath[@]} -- $nelem - -# arrays and things that look like index assignments -array=(42 [1]=14 [2]=44) - -array2=(grep [ 123 ] \*) - -echo ${array[@]} -echo "${array2[@]}" - -# arrays and implicit arithmetic evaluation -declare -i -a iarray - -iarray=( 2+4 1+6 7+2 ) -echo ${iarray[@]} - -iarray[4]=4+1 -echo ${iarray[@]} - -# make sure assignment using the compound assignment syntax removes all -# of the old elements from the array value -barray=(old1 old2 old3 old4 old5) -barray=(new1 new2 new3) -echo "length = ${#barray[@]}" -echo "value = ${barray[*]}" - -# make sure the array code behaves correctly with respect to unset variables -set -u -( echo ${#narray[4]} ) - -${THIS_SH} ./array1.sub -${THIS_SH} ./array2.sub - -# some old bugs and ksh93 compatibility tests -${THIS_SH} ./array3.sub - -# some compound assingment parsing problems that showed up in bash-3.1-release -${THIS_SH} ./array4.sub - -set +u -cd /tmp - -touch 1=bar -foo=([10]="bar") -echo ${foo[0]} -rm 1=bar - -cd $OLDPWD - -foo=(a b c d e f g) -echo ${foo[@]} - -# quoted reserved words are ok -foo=(\for \case \if \then \else) -echo ${foo[@]} - -# quoted metacharacters are ok -foo=( [1]='<>' [2]='<' [3]='>' [4]='!' ) -echo ${foo[@]} - -# numbers are just words when not in a redirection context -foo=( 12 14 16 18 20 ) -echo ${foo[@]} - -foo=( 4414758999202 ) -echo ${foo[@]} - -# this was a bug in all versions of bash 2.x up to and including bash-2.04 -declare -a ddd=(aaa -bbb) -echo ${ddd[@]} - -# errors until post-bash-2.05a; now reserved words are OK -foo=(a b c for case if then else) - -foo=(for case if then else) - -# errors -metas=( <> < > ! ) -metas=( [1]=<> [2]=< [3]=> [4]=! ) - -# various expansions that didn't really work right until post-bash-2.04 -foo='abc' -echo ${foo[0]} ${#foo[0]} -echo ${foo[1]} ${#foo[1]} -echo ${foo[@]} ${#foo[@]} -echo ${foo[*]} ${#foo[*]} - -foo='' -echo ${foo[0]} ${#foo[0]} -echo ${foo[1]} ${#foo[1]} -echo ${foo[@]} ${#foo[@]} -echo ${foo[*]} ${#foo[*]} - -# new expansions added after bash-2.05b -x[0]=zero -x[1]=one -x[4]=four -x[10]=ten - -recho ${!x[@]} -recho "${!x[@]}" -recho ${!x[*]} -recho "${!x[*]}" - -# sparse array tests for code fixed in bash-3.0 -unset av -av[1]='one' -av[2]='' - -av[3]=three -av[5]=five -av[7]=seven - -echo include null element -- expect one -echo ${av[@]:1:2} # what happens when we include a null element? -echo include unset element -- expect three five -echo ${av[@]:3:2} # what happens when we include an unset element? -echo start at unset element -- expect five seven -echo ${av[@]:4:2} # what happens when we start at an unset element? - -echo too many elements -- expect three five seven -echo ${av[@]:3:5} # how about too many elements? - -echo positive offset - expect five seven -echo ${av[@]:5:2} -echo negative offset to unset element - expect seven -echo ${av[@]: -2:2} - -echo positive offset 2 - expect seven -echo ${av[@]: 6:2} -echo negative offset 2 - expect seven -echo ${av[@]: -1:2} - -echo out-of-range offset -echo ${av[@]:12} - -# parsing problems and other inconsistencies not fixed until post bash-3.0 -unset x -declare -a x=(')' $$) -[ ${x[1]} -eq $$ ] || echo bad - -unset x -declare -a x=(a b c d e) -echo ${x[4]} - -z=([1]=one [4]=four [7]=seven [10]=ten) - -echo ${#z[@]} - -echo ${!z[@]} - -unset x -declare -a x=(a \'b c\') - -echo "${x[1]}" - -unset x -declare -a x=(a 'b c') - -echo "${x[1]}" - -unset x -declare -a x=($0) -[ "${x[@]}" = $0 ] || echo double expansion of \$0 -declare -a x=(\$0) -echo "${x[@]}" - -# tests for bash-3.1 problems -${THIS_SH} ./array5.sub - -# tests for post-bash-3.2 problems, most fixed in bash-3.2 patches -${THIS_SH} ./array6.sub -${THIS_SH} ./array7.sub - -${THIS_SH} ./array8.sub - -${THIS_SH} ./array9.sub - -${THIS_SH} ./array10.sub - -${THIS_SH} ./array11.sub - -${THIS_SH} ./array12.sub - -${THIS_SH} ./array13.sub - -${THIS_SH} ./array14.sub - -${THIS_SH} ./array15.sub - -${THIS_SH} ./array16.sub diff --git a/tests/mapfile.tests~ b/tests/mapfile.tests~ deleted file mode 100644 index a9170c13..00000000 --- a/tests/mapfile.tests~ +++ /dev/null @@ -1,42 +0,0 @@ -declare -a A -mapfile A < mapfile.data -for (( i = 0 ; i < ${#A[@]} ; i++ )); do - echo -n "${A[${i}]}" -done - -declare -a B -mapfile -t B < mapfile.data -for (( i = 0 ; i < ${#B[@]} ; i++ )); do - echo "${B[${i}]}" -done - -mapfile -C "echo" -c 1 A < mapfile.data -mapfile -C "echo" -c 3 A < mapfile.data -mapfile -C "echo" -c 19 A < mapfile.data - -declare -a C -mapfile -t -u 3 C 3< mapfile.data < mapfile.tests -for (( i = 0 ; i < ${#C[@]} ; i++ )); do - echo "${C[${i}]}" -done - - -declare -a D -for (( i = 0 ; i < 30; i++ )); do - D[${i}]="[$i] aaa" -done -mapfile -O 10 -t D < mapfile.data -for (( i = 0 ; i < ${#D[@]} ; i++ )); do - echo "${D[${i}]}" -done - -declare -a E -for (( i = 0 ; i < 30; i++ )); do - E[${i}]="[$i] aaa" -done -mapfile -O 10 -n 5 -t E < mapfile.data -for (( i = 0 ; i < ${#E[@]} ; i++ )); do - echo "${E[${i}]}" -done - -${THIS_SH} ./mapfile1.sub diff --git a/tests/misc/regress/log.orig b/tests/misc/regress/log.orig deleted file mode 100644 index c1f1e199..00000000 --- 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 4b3bf2b8..00000000 --- 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 diff --git a/unwind_prot.c~ b/unwind_prot.c~ deleted file mode 100644 index fef1d993..00000000 --- a/unwind_prot.c~ +++ /dev/null @@ -1,372 +0,0 @@ -/* unwind_prot.c - a simple unwind-protect system for internal variables */ - -/* I can't stand it anymore! Please can't we just write the - whole Unix system in lisp or something? */ - -/* 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 <http://www.gnu.org/licenses/>. -*/ - -/* **************************************************************** */ -/* */ -/* Unwind Protection Scheme for Bash */ -/* */ -/* **************************************************************** */ -#include "config.h" - -#include "bashtypes.h" -#include "bashansi.h" - -#if defined (HAVE_UNISTD_H) -# include <unistd.h> -#endif - -#if STDC_HEADERS -# include <stddef.h> -#endif - -#ifndef offsetof -# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) -#endif - -#include "command.h" -#include "general.h" -#include "unwind_prot.h" -#include "sig.h" -#include "quit.h" -#include "error.h" /* for internal_warning */ - -/* Structure describing a saved variable and the value to restore it to. */ -typedef struct { - char *variable; - int size; - char desired_setting[1]; /* actual size is `size' */ -} SAVED_VAR; - -/* If HEAD.CLEANUP is null, then ARG.V contains a tag to throw back to. - If HEAD.CLEANUP is restore_variable, then SV.V contains the saved - variable. Otherwise, call HEAD.CLEANUP (ARG.V) to clean up. */ -typedef union uwp { - struct uwp_head { - union uwp *next; - Function *cleanup; - } head; - struct { - struct uwp_head uwp_head; - char *v; - } arg; - struct { - struct uwp_head uwp_head; - SAVED_VAR v; - } sv; -} UNWIND_ELT; - - -static void without_interrupts __P((VFunction *, char *, char *)); -static void unwind_frame_discard_internal __P((char *, char *)); -static void unwind_frame_run_internal __P((char *, char *)); -static void add_unwind_protect_internal __P((Function *, char *)); -static void remove_unwind_protect_internal __P((char *, char *)); -static void run_unwind_protects_internal __P((char *, char *)); -static void clear_unwind_protects_internal __P((char *, char *)); -static inline void restore_variable __P((SAVED_VAR *)); -static void unwind_protect_mem_internal __P((char *, char *)); - -static UNWIND_ELT *unwind_protect_list = (UNWIND_ELT *)NULL; - -#define uwpalloc(elt) (elt) = (UNWIND_ELT *)xmalloc (sizeof (UNWIND_ELT)) -#define uwpfree(elt) free(elt) - -/* Run a function without interrupts. This relies on the fact that the - FUNCTION cannot change the value of interrupt_immediately. (I.e., does - not call QUIT (). */ -static void -without_interrupts (function, arg1, arg2) - VFunction *function; - char *arg1, *arg2; -{ - int old_interrupt_immediately; - - old_interrupt_immediately = interrupt_immediately; - interrupt_immediately = 0; - - (*function)(arg1, arg2); - - interrupt_immediately = old_interrupt_immediately; -} - -/* Start the beginning of a region. */ -void -begin_unwind_frame (tag) - char *tag; -{ - add_unwind_protect ((Function *)NULL, tag); -} - -/* Discard the unwind protects back to TAG. */ -void -discard_unwind_frame (tag) - char *tag; -{ - if (unwind_protect_list) - without_interrupts (unwind_frame_discard_internal, tag, (char *)NULL); -} - -/* Run the unwind protects back to TAG. */ -void -run_unwind_frame (tag) - char *tag; -{ - if (unwind_protect_list) - without_interrupts (unwind_frame_run_internal, tag, (char *)NULL); -} - -/* Add the function CLEANUP with ARG to the list of unwindable things. */ -void -add_unwind_protect (cleanup, arg) - Function *cleanup; - char *arg; -{ - without_interrupts (add_unwind_protect_internal, (char *)cleanup, arg); -} - -/* Remove the top unwind protect from the list. */ -void -remove_unwind_protect () -{ - if (unwind_protect_list) - without_interrupts - (remove_unwind_protect_internal, (char *)NULL, (char *)NULL); -} - -/* Run the list of cleanup functions in unwind_protect_list. */ -void -run_unwind_protects () -{ - if (unwind_protect_list) - without_interrupts - (run_unwind_protects_internal, (char *)NULL, (char *)NULL); -} - -/* Erase the unwind-protect list. If flags is 1, free the elements. */ -void -clear_unwind_protect_list (flags) - int flags; -{ - char *flag; - - if (unwind_protect_list) - { - flag = flags ? "" : (char *)NULL; - without_interrupts - (clear_unwind_protects_internal, flag, (char *)NULL); - } -} - -int -have_unwind_protects () -{ - return (unwind_protect_list != 0); -} - -int -unwind_protect_tag_on_stack (tag) - const char *tag; -{ - UNWIND_ELT *elt; - - elt = unwind_protect_list; - while (elt) - { - if (elt->head.cleanup == 0 && STREQ (elt->arg.v, tag)) - return 1; - elt = unwind_protect_list->head.next; - } - return 0; -} - -/* **************************************************************** */ -/* */ -/* The Actual Functions */ -/* */ -/* **************************************************************** */ - -static void -add_unwind_protect_internal (cleanup, arg) - Function *cleanup; - char *arg; -{ - UNWIND_ELT *elt; - - uwpalloc (elt); - elt->head.next = unwind_protect_list; - elt->head.cleanup = cleanup; - elt->arg.v = arg; - unwind_protect_list = elt; -} - -static void -remove_unwind_protect_internal (ignore1, ignore2) - char *ignore1, *ignore2; -{ - UNWIND_ELT *elt; - - elt = unwind_protect_list; - if (elt) - { - unwind_protect_list = unwind_protect_list->head.next; - uwpfree (elt); - } -} - -static void -run_unwind_protects_internal (ignore1, ignore2) - char *ignore1, *ignore2; -{ - unwind_frame_run_internal ((char *) NULL, (char *) NULL); -} - -static void -clear_unwind_protects_internal (flag, ignore) - char *flag, *ignore; -{ - if (flag) - { - while (unwind_protect_list) - remove_unwind_protect_internal ((char *)NULL, (char *)NULL); - } - unwind_protect_list = (UNWIND_ELT *)NULL; -} - -static void -unwind_frame_discard_internal (tag, ignore) - char *tag, *ignore; -{ - UNWIND_ELT *elt; - int found; - - found = 0; - while (elt = unwind_protect_list) - { - unwind_protect_list = unwind_protect_list->head.next; - if (elt->head.cleanup == 0 && (STREQ (elt->arg.v, tag))) - { - uwpfree (elt); - found = 1; - break; - } - else - uwpfree (elt); - } - - if (found == 0) - internal_warning ("unwind_frame_discard: %s: frame not found", tag); -} - -/* Restore the value of a variable, based on the contents of SV. - sv->desired_setting is a block of memory SIZE bytes long holding the - value itself. This block of memory is copied back into the variable. */ -static inline void -restore_variable (sv) - SAVED_VAR *sv; -{ - FASTCOPY (sv->desired_setting, sv->variable, sv->size); -} - -static void -unwind_frame_run_internal (tag, ignore) - char *tag, *ignore; -{ - UNWIND_ELT *elt; - int found; - - found = 0; - while (elt = unwind_protect_list) - { - unwind_protect_list = elt->head.next; - - /* If tag, then compare. */ - if (elt->head.cleanup == 0) - { - if (tag && STREQ (elt->arg.v, tag)) - { - uwpfree (elt); - found = 1; - break; - } - } - else - { - if (elt->head.cleanup == (Function *) restore_variable) - restore_variable (&elt->sv.v); - else - (*(elt->head.cleanup)) (elt->arg.v); - } - - uwpfree (elt); - } - if (tag && found == 0) - internal_warning ("unwind_frame_run: %s: frame not found", tag); -} - -static void -unwind_protect_mem_internal (var, psize) - char *var; - char *psize; -{ - int size, allocated; - UNWIND_ELT *elt; - - size = *(int *) psize; - allocated = size + offsetof (UNWIND_ELT, sv.v.desired_setting[0]); - elt = (UNWIND_ELT *)xmalloc (allocated); - elt->head.next = unwind_protect_list; - elt->head.cleanup = (Function *) restore_variable; - elt->sv.v.variable = var; - elt->sv.v.size = size; - FASTCOPY (var, elt->sv.v.desired_setting, size); - unwind_protect_list = elt; -} - -/* Save the value of a variable so it will be restored when unwind-protects - are run. VAR is a pointer to the variable. SIZE is the size in - bytes of VAR. */ -void -unwind_protect_mem (var, size) - char *var; - int size; -{ - without_interrupts (unwind_protect_mem_internal, var, (char *) &size); -} - -#if defined (DEBUG) -#include <stdio.h> - -void -print_unwind_protect_tags () -{ - UNWIND_ELT *elt; - - elt = unwind_protect_list; - while (elt) - { - if (elt->head.cleanup == 0) - fprintf(stderr, "tag: %s\n", elt->arg.v); - elt = elt->head.next; - } -} -#endif diff --git a/unwind_prot.h~ b/unwind_prot.h~ deleted file mode 100644 index cc556f74..00000000 --- a/unwind_prot.h~ +++ /dev/null @@ -1,49 +0,0 @@ -/* unwind_prot.h - Macros and functions for hacking unwind protection. */ - -/* 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 <http://www.gnu.org/licenses/>. -*/ - -#if !defined (_UNWIND_PROT_H) -#define _UNWIND_PROT_H - -/* Run a function without interrupts. */ -extern void begin_unwind_frame __P((char *)); -extern void discard_unwind_frame __P((char *)); -extern void run_unwind_frame __P((char *)); -extern void add_unwind_protect (); /* Not portable to arbitrary C99 hosts. */ -extern void remove_unwind_protect __P((void)); -extern void run_unwind_protects __P((void)); -extern void clear_unwind_protect_list __P((int)); -extern int have_unwind_protects __P((void)); -extern void uwp_init __P((void)); - -/* Define for people who like their code to look a certain way. */ -#define end_unwind_frame() - -/* How to protect a variable. */ -#define unwind_protect_var(X) unwind_protect_mem ((char *)&(X), sizeof (X)) -extern void unwind_protect_mem __P((char *, int)); - -/* Backwards compatibility */ -#define unwind_protect_int unwind_protect_var -#define unwind_protect_short unwind_protect_var -#define unwind_protect_string unwind_protect_var -#define unwind_protect_pointer unwind_protect_var -#define unwind_protect_jmp_buf unwind_protect_var - -#endif /* _UNWIND_PROT_H */ |