diff -Nrc2 bash-2.01.1/CHANGES bash-2.02/CHANGES *** bash-2.01.1/CHANGES Mon Sep 22 12:53:08 1997 --- bash-2.02/CHANGES Wed Apr 15 10:26:03 1998 *************** *** 1,2 **** --- 1,385 ---- + This document details the changes between this version, bash-2.02-beta2, + and the previous version, bash-2.02-beta1. + + 1. Changes to Bash + + a. A bug was fixed that caused the terminal process group to be set + incorrectly when performing command substitution of builtins in a + pipeline. + + ------------------------------------------------------------------------------ + This document details the changes between this version, bash-2.02-beta2, + and the previous version, bash-2.02-beta1. + + 1. Changes to Bash + + a. Attempting to `wait' for stopped jobs now generates a warning message. + + b. Pipelines which exit due to SIGPIPE in non-interactive shells are now + not reported if the shell is compiled -DDONT_REPORT_SIGPIPE. + + c. Some changes were made to builtins/psize.sh and support/bashbug.sh to + attempt to avoid some /tmp file races and surreptitious file + substitutions. + + d. Fixed a bug that caused the shell not to compile if configured with + dparen arithmetic but without aliases. + + e. Fixed a bug that caused the input stream to be switched when assigning + empty arrays with `bash -c'. + + f. A bug was fixed in the readline expansion glue code that caused bash to + dump core when expanding lines with an unclosed single quote. + + g. A fix was made to the `cd' builtin so that using a non-empty directory + from $CDPATH results in an absolute pathname of the new current working + directory to be displayed after the current directory is changed. + + h. Fixed a bug in the variable assignment code that caused the shell to + dump core when referencing an unset variable with `set -u' enabled in + an assignment statement preceding a command. + + i. Fixed a bug in the exit trap code that caused reserved words to not be + recognized under certain circumstances. + + j. Fixed a bug in the parameter pattern substitution code so that quote + removal is performed. + + k. The shell should now configure correctly on Apple Rhapsody systems. + + l. The `kill' builtin now prints a usage message if it is not passed any + arguments. + + ------------------------------------------------------------------------------ + This document details the changes between this version, bash-2.02-beta1, + and the previous version, bash-2.02-alpha1. + + 1. Changes to Bash + + a. A few compilation bugs were fixed in the new extended globbing code. + + b. Executing arithmetic commands now sets the command name to `((' so + error messages look right. + + c. Fixed some build problems with various configuration options. + + d. The `printf' builtin now aborts immediately if an illegal format + character is encountered. + + e. The code that creates here-documents now behaves better if the file it's + trying to create already exists for some reason. + + f. Fixed a problem with the extended globbing code that made patterns like + `x+*' expand incorrectly. + + g. The prompt string expansion code no longer quotes tildes with backslashes. + + h. The bash getcwd() implementation in lib/sh/getcwd.c now behaves better in + the presence of lstat(2) failures. + + i. Fixed a bug with strsub() that caused core dumps when executing `fc -s'. + + j. The mail checking code now ensures that it has a valid default mailpath. + + k. A bug was fixed that caused local variables to be unset inappropriately + when sourcing a script from within another sourced script. + + l. A bug was fixed in the history saving code so that functions are saved + in the history list correctly if `cmdhist' is enabled, but `lithist' + is not. + + m. A bug was fixed that caused printf overflows when displaying error + messages. + + n. It should be easier to build the loadble builtins in examples/loadables, + though some manual editing of the generated Makefile is still required. + + o. The user's primary group is now always ${GROUPS[0]}. + + p. Some updates were made to support/config.guess from the GNU master copy. + + q. Some changes were made to the autoconf support for Solaris 2.6 large + files. + + r. The `command' builtins now does the right thing when confstr(3) cannot + find a value for _CS_PATH. + + s. Extended globbing expressions like `*.!(c)' are not history expanded if + `extglob' is enabled. + + t. Using the `-P' option to `cd' will force the value that is assigned to + PWD to not contain any symbolic links. + + 2. Changes to Readline + + a. The code that prints completion listings now behaves better if one or + more of the filenames contains non-printable characters. + + b. The time delay when showing matching parentheses is now 0.5 seconds. + + ------------------------------------------------------------------------------ + This document details the changes between this version, bash-2.02-alpha1, + and the previous version, bash-2.01.1-release. + + 1. Changes to Bash + + a. OS-specific configuration changes for: BSD/OS 3.x, Minix 2.x, + Solaris 2.6, SINIX SVR4. + + b. Changes were made to the generated `info' files so that `install-info' + works correctly. + + c. PWD is now auto-exported. + + d. A fix was made to the pipeline code to make sure that the shell forks + to execute simple commands consisting solely of assignment statements. + + e. Changes to the test suite for systems with 14-character filenames. + + f. The default sizes of some internal hash tables have been made smaller + to reduce the shell's memory footprint. + + g. The `((...))' arithmetic command is now executed directly instead of + being translated into `let "..."'. + + h. Fixes were made to the expansion code so that "$*", "$@", "${array[@]}", + and "${array[@]}" expand correctly when IFS does not contain a space + character, is unset, or is set to NULL. + + i. The indirect expansion code (${!var}) was changed so that the only + valid values of `var' are variable names, positional parameters, `#', + `@', and `*'. + + j. An arithmetic expression error in a $((...)) expansion now causes a + non-interactive shell running in posix mode to exit. + + k. Compound array assignment now splits the words within the parentheses + on shell metacharacters like the parser would before expansing them + and performing the assignment. This is for compatibility with ksh-93. + + l. The internal shell backslash-quoting code (used in the output of `set' + and completion) now quotes tildes if they appear at the start of the + string or after a `=' or `:'. + + m. A couple of bugs with `shopt -o' were fixed. + + n. `bash +o' now displays the same output as `set +o' before starting an + interactive shell. + + o. A bug that caused command substitution and the `eval' builtin to + occasionally free memory twice when an error was encountered was fixed. + + p. The filename globbing code no longer requires read permission for a + directory when the filename to be matched does not contain any globbing + characters, as POSIX.2 specifies. + + q. A bug was fixed so that the job containing the last asynchronous + process is not removed from the job table until a `wait' is executed + for that process or another asynchronous process is started. This + satisfies a POSIX.2 requirement. + + r. A `select' bug was fixed so that a non-numeric user response is treated + the same as a numeric response that is out of range. + + s. The shell no longer parses the value of SHELLOPTS from the environment + if it is restricted, running setuid, or running in `privileged mode'. + + t. Fixes were made to enable large file support on systems such as + Solaris 2.6, where the size of a file may be larger than can be held + in an `int'. + + u. The filename hashing code was fixed to not add `./' to the beginning of + filenames which already begin with `./'. + + v. The configure script was changed so that the GNU termcap library is not + compiled in if `prefer-curses' has been specified. + + w. HISTCONTROL and HISTIGNORE are no longer applied to the second and + subsequent lines of a multi-line command. + + x. A fix was made to `disown' so that it does a better job of catching + out-of-range jobs. + + y. Non-interactive shells no longer report the status of processes terminated + due to SIGINT, even if the standard output is a terminal. + + z. A bug that caused the output of `jobs' to have extra carriage returns + was fixed. + + aa. A bug that caused PIPESTATUS to not be set when builtins or shell + functions were executed in the foreground was fixed. + + bb. Bash now attempts to detect when it is being run by sshd, and treats + that case identically to being run by rshd. + + cc. A bug that caused `set -a' to export SHELLOPTS when one of the shell + options was changed was fixed. + + dd. The `kill' builtin now disallows empty or missing process id arguments + instead of treating them as identical to `0', which means the current + process. + + ee. `var=value declare -x var' now behaves identically to + `var=value export var'. Similarly for `var=value declare -r var' and + `var=value readonly var'. + + ff. A few memory leaks were fixed. + + gg. `alias' and `unalias' now print error messages when passed an argument + that is not an alias for printing or deletion, even when the shell is + not interactive, as POSIX.2 specifies. + + hh. `alias' and `alias -p' now return a status of 0 when no aliases are + defined, as POSIX.2 specifes. + + ii. `cd -' now prints the pathname of the new working directory if the shell + is interactive. + + jj. A fix was made so that the code that binds $PWD now copes with getcwd() + returning NULL. + + kk. `unset' now checks whether or not a function name it's trying to unset + is a valid shell identifier only when the shell is running in posix mode. + + ll. A change was made to the code that generates filenames for here documents + to make them less prone to name collisions. + + mm. The parser was changed so that `time' is recognized as a reserved word + only at the beginning of a pipeline. + + nn. The pathname canonicalization code was changed so that `//' is converted + into `/', but all other pathnames beginning with `//' are left alone, as + POSIX.2 specifies. + + oo. The `logout' builtin will no longer exit a non-interactive non-login + shell. + + 2. Changes to Readline + + a. Fixed a problem in the readline test program rltest.c that caused a core + dump. + + b. The code that handles parser directives in inputrc files now displays + more error messages. + + c. The history expansion code was fixed so that the appearance of the + history comment character at the beginning of a word inhibits history + expansion for that word and the rest of the input line. + + 3. New Features in Bash + + a. A new version of malloc, based on the older GNU malloc, that has many + changes, is more page-based, is more conservative with memory usage, + and does not `orphan' large blocks when they are freed. + + b. A new version of gmalloc, based on the old GLIBC malloc, with many + changes and range checking included by default. + + c. A new implementation of fnmatch(3) that includes full POSIX.2 Basic + Regular Expression matching, including character classes, collating + symbols, equivalence classes, and support for case-insensitive pattern + matching. + + d. ksh-88 egrep-style extended pattern matching ([@+*?!](patlist)) has been + implemented, controlled by a new `shopt' option, `extglob'. + + e. There is a new ksh-like `[[' compound command, which implements + extended `test' functionality. + + f. There is a new `printf' builtin, implemented according to the POSIX.2 + specification. + + g. There is a new feature for command substitution: $(< filename) now expands + to the contents of `filename', with any trailing newlines removed + (equivalent to $(cat filename)). + + h. There are new tilde prefixes which expand to directories from the + directory stack. + + i. There is a new `**' arithmetic operator to do exponentiation. + + j. There are new configuration options to control how bash is linked: + `--enable-profiling', to allow bash to be profiled with gprof, and + `--enable-static-link', to allow bash to be linked statically. + + k. There is a new configuration option, `--enable-cond-command', which + controls whether or not the `[[' command is included. It is on by + default. + + l. There is a new configuration option, `--enable-extended-glob', which + controls whether or not the ksh extended globbing feature is included. + It is enabled by default. + + m. There is a new configuration #define in config.h.top that, when enabled, + will cause all login shells to source /etc/profile and one of the user- + specific login shell startup files, whether or not the shell is + interactive. + + n. There is a new invocation option, `--dump-po-strings', to dump + a shell script's translatable strings ($"...") in GNU `po' format. + + o. There is a new `shopt' option, `nocaseglob', to enable case-insensitive + pattern matching when globbing filenames and using the `case' construct. + + p. There is a new `shopt' option, `huponexit', which, when enabled, causes + the shell to send SIGHUP to all jobs when an interactive login shell + exits. + + q. `bind' has a new `-u' option, which takes a readline function name as an + argument and unbinds all key sequences bound to that function in a + specified keymap. + + r. `disown' now has `-a' and `-r' options, to limit operation to all jobs + and running jobs, respectively. + + s. The `shopt' `-p' option now causes output to be displayed in a reusable + format. + + t. `test' has a new `-N' option, which returns true if the filename argument + has been modified since it was last accessed. + + u. `umask' now has a `-p' option to print output in a reusable format. + + v. A new escape sequence, `\xNNN', has been added to the `echo -e' and $'...' + translation code. It expands to the character whose ascii code is NNN + in hexadecimal. + + w. The prompt string expansion code has a new `\r' escape sequence. + + x. The shell may now be cross-compiled for the CYGWIN32 environment on + a Unix machine. + + 4. New Features in Readline + + a. There is now an option for `iterative' yank-last-arg handline, so a user + can keep entering `M-.', yanking the last argument of successive history + lines. + + b. New variable, `print-completions-horizontally', which causes completion + matches to be displayed across the screen (like `ls -x') rather than up + and down the screen (like `ls'). + + c. New variable, `completion-ignore-case', which causes filename completion + and matching to be performed case-insensitively. + + d. There is a new bindable command, `magic-space', which causes history + expansion to be performed on the current readline buffer and a space to + be inserted into the result. + + e. There is a new bindable command, `menu-complete', which enables tcsh-like + menu completion (successive executions of menu-complete insert a single + completion match, cycling through the list of possible completions). + + f. There is a new bindable command, `paste-from-clipboard', for use on Win32 + systems, to insert the text from the Win32 clipboard into the editing + buffer. + + g. The key sequence translation code now understands printf-style backslash + escape sequences, including \NNN octal escapes. These escape sequences + may be used in key sequence definitions or macro values. + + h. An `$include' inputrc file parser directive has been added. + + ------------------------------------------------------------------------------ This document details the changes between this version, bash-2.01.1-release, and the previous version, bash-2.01-release. diff -Nrc2 bash-2.01.1/COMPAT bash-2.02/COMPAT *** bash-2.01.1/COMPAT Fri Apr 11 16:58:48 1997 --- bash-2.02/COMPAT Mon Jul 28 13:36:52 1997 *************** *** 102,103 **** --- 102,117 ---- alias ulimit="ulimit -S" + 9. Bash-2.01 uses a new quoting syntax, $'...' to do ANSI-C string + translation. Backslash-escaped characters in ... are expanded and + replaced as specified by the ANSI C standard. + + 10. The sourcing of startup files has changed somewhat. This is explained + more completely in the INVOCATION section of the manual page. + + A non-interactive shell not named `sh' and not in posix mode reads + and executes commands from the file named by $BASH_ENV. A + non-interactive shell started by `su' and not in posix mode will read + startup files. No other non-interactive shells read any startup files. + + An interactive shell started in posix mode reads and executes commands + from the file named by $ENV. diff -Nrc2 bash-2.01.1/COPYING bash-2.02/COPYING *** bash-2.01.1/COPYING Tue Jun 18 11:55:38 1996 --- bash-2.02/COPYING Mon Jul 7 17:03:17 1997 *************** *** 3,7 **** Copyright (C) 1989, 1991 Free Software Foundation, Inc. ! 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. --- 3,7 ---- Copyright (C) 1989, 1991 Free Software Foundation, Inc. ! 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff -Nrc2 bash-2.01.1/CWRU/PLATFORMS bash-2.02/CWRU/PLATFORMS *** bash-2.01.1/CWRU/PLATFORMS Tue Mar 11 13:52:20 1997 --- bash-2.02/CWRU/PLATFORMS Wed Jun 4 11:02:58 1997 *************** *** 7,11 **** SunOS 5.5 BSDI BSD/OS 2.1 ! FreeBSD 2.1.7 NetBSD 1.2 AIX 4.2 --- 7,11 ---- SunOS 5.5 BSDI BSD/OS 2.1 ! FreeBSD 2.2 NetBSD 1.2 AIX 4.2 diff -Nrc2 bash-2.01.1/CWRU/POSIX.NOTES bash-2.02/CWRU/POSIX.NOTES *** bash-2.01.1/CWRU/POSIX.NOTES Tue Mar 25 11:39:25 1997 --- bash-2.02/CWRU/POSIX.NOTES Tue Sep 23 13:39:25 1997 *************** *** 22,27 **** 5. The POSIX.2 `PS1' and `PS2' expansions of `!' to the history number and `!!' to `!' 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 --- 22,27 ---- 5. The POSIX.2 `PS1' and `PS2' expansions of `!' to the history number and `!!' to `!' are enabled, and parameter expansion is ! performed on the values of `PS1' and `PS2' regardless of the ! setting of the `promptvars' option. 6. Interactive comments are enabled by default. (Note that Bash has *************** *** 43,58 **** found. ! 12. Redirection operators do not perform filename expansion on the word in the redirection unless the shell is interactive. ! 13. Function names must be valid shell `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 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 --- 43,61 ---- found. ! 12. Non-interactive shells exit if a syntax error in an arithmetic ! expansion results in an invalid expression. ! ! 13. Redirection operators do not perform filename expansion on the word in the redirection unless the shell is interactive. ! 14. Function names must be valid shell `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. ! 15. POSIX.2 `special' builtins are found before shell functions during command lookup. ! 16. 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 *************** *** 60,82 **** assignments preceding the command name, and so on. ! 16. If the `cd' builtin finds a directory to change to using `$CDPATH', the value it assigns to the `PWD' variable does not contain any symbolic links, as if `cd -P' had been executed. ! 17. 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. ! 18. 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. ! 19. Process substitution is not available. ! 20. Assignment statements preceding POSIX.2 `special' builtins persist in the shell environment after the builtin completes. ! 21. The `export' and `readonly' builtin commands display their output in the format required by POSIX.2. --- 63,91 ---- assignments preceding the command name, and so on. ! 17. If the `cd' builtin finds a directory to change to using `$CDPATH', the value it assigns to the `PWD' variable does not contain any symbolic links, as if `cd -P' had been executed. ! 18. If `$CDPATH' is set, the `cd' builtin will not implicitly append ! the current directory to it. This means that `cd' will fail if no ! valid directory name can be constructed from any of the entries in ! `$CDPATH', even if the a directory with the same name as the name ! given as an argument to `cd' exists in the current directory. ! ! 19. 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. ! 20. 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 readonly variable. ! 21. Process substitution is not available. ! 22. Assignment statements preceding POSIX.2 special builtins persist in the shell environment after the builtin completes. ! 23. The `export' and `readonly' builtin commands display their output in the format required by POSIX.2. diff -Nrc2 bash-2.01.1/CWRU/changelog bash-2.02/CWRU/changelog *** bash-2.01.1/CWRU/changelog Tue Jun 3 11:27:48 1997 --- bash-2.02/CWRU/changelog Wed Apr 15 10:26:18 1998 *************** *** 1718,1719 **** --- 1718,3734 ---- [bash-2.01-release frozen] + + 6/6 + --- + configure.in + - force shlicc2 and libc malloc for BSD/OS 3.0 + + 6/9 + --- + doc/Makefile.in + - don't create ${man3dir}, since we're not installing the readline + manual page + + lib/readline/readline.h + - rl_dispatching should be declared `extern' + [in bash-2.01.1] + + 6/10 + ---- + lib/malloc/Makefile.in + - make sure ${ALLOCA_SOURCE} is preceded by ${srcdir} so that things + work when building in a directory other than the source directory + [in bash-2.01.1] + + 6/30 + ---- + lib/readline/examples/rltest.c + - don't free the value returned by history_list() + + lib/readline/histfile.c + - open the history file for writing with mode 0600 for better + security + [in bash-2.01.1] + + execute_cmd.c + - select_query now uses legal_number to decide whether the user's + selection is a valid number, and just executes the loop again if + invalid input is entered + [in bash-2.01.1] + + 7/1 + --- + builtins/evalstring.c + - fix to parse_and_execute so `bash -c 'time [-p] zzz'' works right + [in bash-2.01.1] + + execute_cmd.c + - fix to execute_command_internal so that `bash -c time [-p] (zzz)'' + works right + [in bash-2.01.1] + - print_formatted_time should pass a long as the fourth parameter + to mkfmt + [in bash-2.01.1] + + externs.h, shell.c + - `exit_shell' is now a void function + + hashlib.c + - print_table_stats is now a void function + + mailcheck.c + - made add_mail_file check for the filename in the mail file list + using the expanded filename, since that is what it puts into + the list + [in bash-2.01.1] + + variables.c + - for the time being, PWD will be auto-exported, since some systems + seem to expect it + + doc/bashref.texi, lib/readline/doc/{hist,rlman}.texinfo + - added necessary `dircategory' and `direntry' commands to make + `install-info' work correctly + + Makefile.in + - move $(LDFLAGS) after $(BUILTINS_LDFLAGS) and $(LIBRARY_LDFLAGS) on + the line that links bash + + doc/texinfo.tex + - upgraded to version 2.185 from the texinfo-3.9 distribution + + lib/tilde/tilde.c + - fixed a bug in tilde_expand so that enough space is allocated for + the string and terminating null byte if a `~' does not appear. + This was masked before by the bash malloc() + [in bash-2.01.1] + + 7/3 + --- + aclocal.m4 + - new test, BASH_TYPE_INT32_T, to check which builtin C type is + 32 bits wide + - new test, BASH_TYPE_PTRDIFF_T, to check which builtin C type is + appropriate for pointer arithmetic + + configure.in + - check sizes of int and long, and for the existence of an int32_t + basic system type. Call BASH_TYPE_INT32_T if int32_t is not + defined anywhere in the system header files + - check size of (char *), and for the existence of a ptrdiff_t + basic system type. Call BASH_TYPE_PTRDIFF_T if ptrdiff_t is not + defined anywhere in the system header files + - added a check for + + config.h.in + - add lines for SIZEOF_INT, SIZEOF_LONG, SIZEOF_CHAR_P, int32_t, + u_int32_t, and ptrdiff_t + - added line for HAVE_STDDEF_H + + lib/malloc/malloc.c + - new version, with many changes and much better memory usage; old + (bash-2.01) version is lib/malloc/omalloc.c + + lib/malloc/gmalloc.c + - new version, with a number of changes and range checking included + by default; old (bash-2.01) version is lib/malloc/ogmalloc.c + + execute_cmd.c + - applied patch from 5/27 to make execute_simple_command fork early + if it's part of a pipeline. This keeps assignment statements or + other commands that don't require a builtin, function, or disk + command to be executed from modifying the shell's environment + + tests/exec?.sub + - renamed from tests/execscript.sub? because those filenames are + too long for System V 14-char filename systems + + tests/source?.sub + - renamed from tests/source.sub? because those filenames are bad + for DOS/Windows + + tests/getopts?.sub + - renamed from tests/getopts.sub? because those filenames are bad + for DOS/Windows + + tests/histexp.{tests,right} + - renamed from histexpand.{tests,right} because those filenames are + too long for System V 14-char filename systems + + tests/trap1.sub + - renamed from trap.sub1 because that filename was bad for DOS/Windows + + tests/ifs-[123].right + - renamed from ifs.[123].right because those filenames were bad for + DOS/Windows + + tests/ifs-[123].test + - renamed from ifs-test-[123].sh because those filenames were bad + for DOS/Windows + + examples/startup-files/Bashrc.bfox + - renamed from examples/startup-files/Bashrc because that filename + conflicts with examples/startup-files/bashrc on case-insensitive + file systems + + tests/exec.right + - renamed from execscript.right because that filename is too long + for System V 14-char filename systems + + tests/run-set-e + - renamed from run-set-e-test + + tests/misc/perftest + - renamed from tests/misc/haertel.perftest because that filename is + too long for System V 14-char filename systems + + lib/glob/fnmatch.c + - new version with full POSIX.2 BRE matching (character classes, + collating symbols, equivalence classes), full support for + strcoll(3), and case-insensitive pattern matching + + lib/glob/fnmatch.h + - new version, with necessary symbols for the new fnmatch.c + + tests/posixpat.{tests,right}, tests/run-posixpat + - test suite for the POSIX.2 BRE pattern matching code + + variables.c + - make sure that array assignment using the compound syntax empties + the array before doing the assignment + [in bash-2.01.1] + + trap.c + - new function, trap_to_sighandler(sig), which returns the correct + trap handler for SIG depending on the information in sigmodes[sig] + [in bash-2.01.1] + + sig.h + - extern declarations for trap_handler and trap_to_sighandler + [in bash-2.01.1] + + jobs.c + - if we get an interrupt while waiting for a command to complete, + and there was a trap set on SIGINT that resets the handler to + SIG_DFL, the value that waitchld uses for old_trap_handler will + be wrong (it will be trap_handler, but trap_handler no longer + knows anything about SIGINT). If old_signal_handler is trap_handler, + but signal_is_trapped(SIGINT) returns 0, we need to call + trap_to_sighandler to decide what to do + [in bash-2.01.1] + + 7/7 + --- + locale.c + - fix to set_locale_var to handle an assignment to LC_ALL (e.g., as + the result of `unset LANG') when default_locale is null + [in bash-2.01.1] + + 7/8 + --- + builtins/umask.def, doc/{bash.{1,html},bashref.texi} + - added `-p' option for umask to print output in a reusable form + + 7/9 + --- + doc/{bash.{1,html},bashref.texi} + - removed descriptions of `-type', `-path', and `-all' options to + the `type' builtin in preparation for removing them in the next + release + + builtins/type.def + - removed mention of `-type', `-path', and `-all' options from the + long help description + + error.c, error.h + - new function: internal_warning, for warning messages + + variables.c + - changed a call to internal_error to use internal_warning + - modified change of 7/3 so that arrays are not emptied until + just before the shell is about to assign the new values, so + the old value can be used to generate the rhs of the assignment, + if necessary. This is how `normal' shell variables work + [in bash-2.01.1] + + jobs.c, jobs.h + - delete_job now takes a second int argument and prints a warning + message when deleting a stopped job if the second argument is + non-zero + + jobs.c, builtins/jobs.def + - changed all calls to delete_job to provide a proper second arg + + lib/readline/bind.c + - broke rl_read_init_file into an `upper' and `lower' half in + preparation for adding file inclusion capability to inputrc + parsing + - handle_parser_directive now displays an error message if an + unknown directive is encountered + - parser_endif now prints an error message if an $endif without + a matching $if is found + - added `$include' parser directive to read bindings and commands + from another file at that point + + lib/readline/doc/rluser.texinfo, doc/{bash.{1,html},readline.3} + - documented new readline `$include' parser directive + + shell.c, parse.y + - added a new invocation option, --dump-po-strings, and code to + make it dump translatable strings ($"...") in GNU gettext + `po' format + + doc/{bash.{1,html},bashref.texi} + - documented new `--dump-po-strings' invocation option + + lib/readline/{{kill,funmap}.c,readline.h} + - added `rl_paste_from_clipboard()', bound to `paste-from-clipboard' + for CYGWIN32 users + + lib/readline/kill.c + - incorporated bfox's patches for `iterative' yank-last-arg handling. + This means that one can keep pressing M-. and move backwards in + the history, yanking the last argument of successive history lines + + lib/readline/rlwinsize.h + - new file, encapsulates various locations of the definition for + `struct winsize' + + aclocal.m4 + - augmented BASH_STRUCT_WINSIZE to look in termios.h as well as + sys/ioctl.h for definition of `struct winsize' + + lib/readline/rltty.h + - include "rlwinsize.h" after including tty-driver-specific header + file + + 7/10 + ---- + support/config.guess + - add better support for SunOS on M68K (old Sun3 machines) + + parse.y + - check for compound array assignment in read_token_word only if + there are characters before the `=' (which would make it a legal + assignment statement). This fixes the problem with defining a + function named `=' with `=() { echo foo; }' + [in bash-2.01.1] + + jobs.c, jobs.h + - nohup_all_jobs and delete_all_jobs now take a parameter which + says whether or not to restrict their operation to only running + jobs + + jobs.c + - changed all calls to delete_all_jobs + + builtins/jobs.def + - added `-a' (all jobs) and `-r' (running jobs only) options to + `disown' + + doc/{bash.{1,html},bashref.texi} + - documented new `-a' and `-r' options to `disown' + + findcmd.c, findcmd.h + - new files with command searching code from execute_cmd.c and + function declarations from execute_cmd.h + + Makefile.in, builtins/Makefile.in + - updated dependencies to account for new findcmd.[ch] + - updated dependencies to account for new redir.[ch] + + redir.c, redir.h + - new files with code that sets up lists and performs redirections + from execute_cmd.c and execute_cmd.h + + execute_cmd.c + - include new findcmd.h, redir.h + + 7/11 + ---- + Makefile.in, configure.in + - PROFILE_FLAGS is now substituted into the Makefile by configure + + 7/14 + ---- + print_cmd.c + - make sure single_quote is called from xtrace_print_word_list + to correctly quote each word of trace output, especially those + with embedded quotes + [in bash-2.01.1] + + aclocal.m4 + - extended BASH_CHECK_GETPW_FUNCS so that it checks that getpwuid + and getpwnam can also be declared, as well as getpwent + [in bash-2.01.1] + - in BASH_FUNC_PRINTF, cast printf to type `_bashfunc' before trying + to assign it to `pf' to avoid any prototype problems in the + declaration + [in bash-2.01.1] + + trap.c + - include before any of the bash-specific header files, + but after config.h + [in bash-2.01.1] + + test.c + - include and declare `extern int errno' before including + any of the bash-specific include files, but after + [in bash-2.01.1] + + builtins/Makefile.in + - PROFILE_FLAGS is now substituted into the Makefile by configure + + configure.in + - new options, --enable-profiling and --enable-static-link, to turn + on profiling with gprof and link bash statically (if using gcc) + for use as a root shell. The former implies the latter. If + we're linking statically, dynamic loading of new builtins is not + available + + doc/bashref.texi + - documented new --enable-profiling and --enable-static-link + options in installation section; regenerated INSTALL + + lib/glob/glob.[ch] + - new global variable, glob_ignore_case, turns on case-insensitive + filename matching in fnmatch() using the FNM_CASEFOLD flag + + doc/{bash.{1,html},bashref.texi} + - documented new shopt `nocaseglob' option + + 7/15 + ---- + bashline.c + - when glob_complete_word is called with state == 0, make sure we + set rl_filename_completion_desired so that proper quoting of + the resultant filenames is performed + [in bash-2.01.1] + + 7/16 + ---- + externs.h, oslib.c + - strcasecmp and strncasecmp replacements should have `const char *' + as the first two arguments, to match OS definitions + [in bash-2.01.1] + + 7/17 + ---- + (many files) + - changes for minix-2.0, mostly just adding #ifndef _MINIX around + include files that minix doesn't provide, like and + + + lib/readline/terminal.c + - removed `outchar' function; use _rl_output_character_function in + its place + + support/config.guess + - changes to recognize HP_ARCH of `hppa2.0' + + test.c + - new `-N' option: `test -N file' returns true if FILE exists and + has been modified since it was last accessed + + doc/{bash.{1,html},bashref.texi} + - documented new `test -N' option + + 7/22 + ---- + aclocal.m4 + - prefer /var/spool/mail to /usr/spool/mail in BASH_DEFAULT_MAIL_DIR + [in bash-2.01.1] + + lib/readline/{complete,bind}.c + - new readline variable, print-completions-horizontally, which causes + matches to be printed across the screen (like `ls -x') rather than + up-and-down (like `ls') + - new readline variable, completion-ignore-case, which causes filename + completion and matching to be performed case-insensitively + + doc/{bash.{1,html},readline.3}, lib/readline/doc/rluser.texinfo + - documented new print-completions-horizontally variable + - documented new completion-ignore-case variable + + _distribution, Makefile.in + - bumped the version number up to 2.02-alpha1 + + bracecomp.c + - fixes so that the braces are not quoted by the filename quoting + function when complete-into-braces is executed with M-{. The + brace completion functions do filename quoting themselves + [in bash-2.01.1] + + pathexp.c + - changed quote_string_for_globbing so that it takes a flags word + as its second argument + + pathexp.h + - defines for flags passed to quote_string_for_globbing + + subst.c,execute_cmd.c + - changed calls to quote_string_for_globbing to pass the correct + flag arguments + + expr.c + - added a `**' binary operator to do exponentiation (2**16 == 65536). + precedence is lower than arithmetic operators, higher than unary + operators (2**16-1 == 65535) + + doc/{bash.{1,html},bashref.texi} + - documented new `**' arithmetic binary operator + + 7/24 + ---- + shell.c + - added new (currently undocumented) `--wordexp' option to do the + job required by POSIX.2 wordexp(). If -n is supplied along with + --wordexp, command substitution is disallowed and the shell + exits with a status of 125 if one is attempted. If there is an + expansion error, the shell exits with a status of 127. If there + is a shell parsing error, the shell exits with a status of 126. + Otherwise, the exit status is 0. The current output is + + number of words\n + number of bytes\n + expanded words, one per line, separated by newlines + + This will have to be changed when an interface to glibc is coded + + 7/28 + ---- + hashcmd.h + - reduced the default size of the filename hash table from 631 + to 107 + + sig.c + - don't call initialize_siglist if HAVE_UNDER_SYS_SIGLIST is defined + [in bash-2.01.1] + + siglist.c + - don't compile this file if HAVE_UNDER_SYS_SIGLIST is defined + [in bash-2.01.1] + + variables.c + - fix to make $RANDOM work better in subshells + [in bash-2.01.1] + + aclocal.m4 + - new macro, BASH_DECL_UNDER_SYS_SIGLIST, looks for _sys_siglist in + and , defines UNDER_SYS_SIGLIST_DECLARED if + found + [in bash-2.01.1] + - change BASH_UNDER_SYS_SIGLIST to require BASH_DECL_UNDER_SYS_SIGLIST, + like BASH_SYS_SIGLIST requires AC_DECL_SYS_SIGLIST + [in bash-2.01.1] + + config.h.in + - add a line for UNDER_SYS_SIGLIST_DECLARED + [in bash-2.01.1] + + configure.in + - make sure that SVR4_2 is defined for machines that have $host_os + sysv4.2* (e.g., sysv4.2MP) as well as $host == sysv4.2 + [in bash-2.01.1] + + 7/29 + ---- + command.h + - new command type, ARITH_COM, used to create and execute a ((...)) + command without translating it into let "..." + + parse.y + - changes to the grammar and lexer so that ((...)) is parsed as a + command of type ARITH_CMD. An ARITH_CMD is a WORD_LIST, for + future expansion, even though only the first word is used + + make_cmd.c, make_cmd.h + - definition and declaration of a function to build an arithmetic + command + + dispose_cmd.c + - added code to dispose of arithmetic commands + + print_cmd.c + - added code to print arithmetic commands, both `regularly' and + when they're being traced with `set -x' + + externs.h + - extern declaration for xtrace_print_arith_cmd + + copy_cmd.c + - added code to copy arithmetic commands + + execute_cmd.c + - added code to directly execute arithmetic commands -- they are + a shell_control_structure, so just about everything like + redirections and piping is taken care of by the boilerplate code. + All that's needed is to expand the expression (which is within + double quotes -- added by parse.y:parse_arith_cmd()), print it + if tracing is enabled, call the expression evaluator, and return + an appropriate result + + 7/30 + ---- + input.c + - new function, set_buffered_stream(fd, bp), sets the buffered stream + associated with FD to BP and returns the old buffered stream + + input.h + - extern declaration for set_buffered_stream + + parse.y + - call set_buffered_stream rather than manipulating the BUFFERS array + directly + + shell.c + - unset_bash_input now takes an argument, CHECK_ZERO. This tells it + whether to check whether default_buffered_input is >= 0 or just > 0 + + externs.h + - changed extern declaration for unset_bash_input + + execute_cmd.c, jobs.c, nojobs.c + - changed calls to unset_bash_input to add appropriate argument + + input.h + - #undef B_* before defining them as flag values for b_flags. Some + systems, like SVR4, have a B_ERROR define in a file included by + jobs.c and nojobs.c, and it causes a warning + + 7/31 + ---- + fnmatch.c + - rewrote most of fnmatch(), so that it now implements ksh-88 style + pattern matching (`[@+*?!](patlist)') if the FNM_EXTMATCH flag + is set + + fnmatch.h + - added a define for FNM_EXTMATCH + + 8/4 + --- + lib/readline/display.c + - fixed _rl_redisplay_after_sigwinch () so that it really redisplays + only the portion after the final newline of a multi-line prompt + [in bash-2.01.1] + + bashline.c + - attempt_shell_completion no longer returns matches if a glob pattern + matches more than one filename -- it caused too many problems + [in bash-2.01.1] + + 8/5 + --- + lib/glob/glob.c + - updated glob_pattern_p so that the extended matching operators + are recognized + + pathexp.c + - udpated unquoted_glob_pattern_p so that the extended matching + operators are recognized + - udpated quote_globbing_chars so that the extended matching + operators are recognized and quoted appropriately + + subst.c + - updated match_pattern_char so that the extended matching operators + are recognized + + parse.y + - updated read_token_word so that it parses an extended matching + pattern as a single word + + jobs.c + - if a job is suspended with SIGTSTP, and the user has set + checkwinsize with `shopt', update the window size + [in bash-2.01.1] + + pathexp.c, pathexp.h + - new global variable, extended_glob, controls whether the extended + pattern matching features are enabled + + pathexp.h + - new define, FNMATCH_EXTFLAG, to be OR'd with other values for + flags argument to fnmatch to enable the extended pattern matching + features if extended_glob is set + + {pathexp,execute_cmd,bashhist,subst,test}.c, builtins/help.def + - changed calls to fnmatch to add FNMATCH_EXTFLAG to the flags arg if + extended_glob is non-zero + + lib/glob/glob.c + - changed flags arg passed to fnmatch to include FNM_EXTMATCH if + extended_glob is non-zero (#ifdef SHELL) + + 8/6 + --- + builtins/shopt.def + - added a new `extglob' shell option, controls the value of + extended_glob + + 8/7 + --- + doc/{bash.{1,html},bashref.texi} + - documented new extended pattern matching operators and the `extglob' + shell option + + tests/{extglob.{tests,right},run-extglob} + - test suite for the new extended globbing features + + 8/8 + --- + parse.y, pathexp.h, lib/glob/fnmatch.c + - made the extended globbing code #ifdef EXTENDED_GLOB + + config.h.in + - added a line for EXTENDED_GLOB, controlled by configure + + configure.in + - new option, --enable-extended-glob, controls defining of + EXTENDED_GLOB (on by default) + + doc/bashref.texi + - documented new `configure' `--enable-extended-glob' option + + 8/11 + ---- + builtins/printf.def + - new `printf' builtin, implemented according to POSIX.2 spec + for printf(1) + + Makefile.in,builtins/Makefile.in + - added necessary stuff for new printf builtin + + 8/12 + ---- + lib/readline/isearch.c + - change to make ^G interrupt the incremental search correctly + [in bash-2.01.1] + + configure.in, config.h.in + - configure now checks for the availability of strtoul(3) + + builtins/printf.def + - use strtoul for the `%o', `%u', `%x', and `%X' formats if it + is available + + 8/13 + ---- + tests/{printf.{right,tests},run-printf} + - extensive test suite for the new `printf' builtin + + builtins/Makefile.in + - change so that `builtext.h' is not recreated every time the source + file for a builtin is changed if the contents are the same. This + keeps many files from being recompiled + + 8/14 + ---- + subst.c + - changed verify_substring_values so that it returns -1 for substring + range errors, 0 for expression errors, and 1 for success + [in bash-2.01.1] + - changed parameter_brace_substring to return an error if + verify_substring_values returns 0, and a null string if it returns + -1. This matches the ksh93 behavior + [in bash-2.01.1] + + trap.c + - changed decode_signal so that it makes sure the first three + characters of a signal name are `SIG' before allowing the `SIG' + prefix to be omitted. This is so a signal spec of `T' does not + match `EXIT', for instance + [in bash-2.01.1] + + builtins/trap.def + - make sure that showtrap() displays traps for signals with unknown + names using the signal number + [in bash-2.01.1] + shell.c + - make sure that `bash -r' doesn't turn on the restricted mode until + after the startup files are executed + [in bash-2.01.1] + + doc/{bash.{1,html},bashref.texi} + - documented printf builtin + + 8/15 + ---- + general.c + - added \xNNN escape to ansicstr -- NNN are up to three hex digits. + This affects $'...', `echo -e', and printf + + builtins/printf.def + - added \xNNN escape to bexpand -- NNN are up to three hex digits. + This affects printf's `%b' conversion specifier + + doc/{bash.{1,html},bashref.texi} + - documented new \xNNN escape sequence for echo, $'...', and printf + + builtins/setattr.def + - make sure that a variable found in the temp environment does not + cause a null string to be assigned by bind_variable (e.g., + foo="" export foo + ) + [in bash-2.01.1] + + 8/18 + ---- + subst.c + - fixed a bug that sometimes caused bad memory (pointer into an + allocated block) to be passed to free when doing arithmetic + substitution. Bug report from stevet@myofb.org + [in bash-2.01.1] + + 8/19 + ---- + subst.c + - considerable changes: moved the code that expands a single + $... parameter expansion into a separate function: param_expand() + This function returns a string, which may contain characters + quoted with CTLESC or CTLNUL without doing word splitting + - changed expand_word_internal to not remove the expansion of "$*" + if the number of positional parameters is > 0 + - changed the '"' case of expand_word_internal to remove quoted + nulls from the resultant word if the expansion was not "$@", and + the word is not a quoted null string ([] == CTLNUL, [1] == '\0') + + subst.c, variables.c + - moved the code that handles special variables from subst.c to + variables.c + + 8/20 + ---- + subst.c + - rearranged the source a bit to group functions with similar + operation together + - fixed parameter_brace_expand so that it no longer allows + indirect expansion of `special' variables + - fixed parameter_brace_expand so taking the length of some of + the shell's special parameters works again + - moved all of the code that computes the length of a shell + parameter (the ${#xxx} expansion) into parameter_brace_expand_length. + Previously, the code that handled the lengths of the shell's + special parameters was in parameter_brace_expand_word + - valid indirect expansions are now only variable names or positional + parameters + + 8/21 + ---- + subst.c + - fixed param_expand to raise an expansion error if $! is being + expanded and no asynchronous processes have been created + - an expression error in a $((...)) arithmetic expansion now causes + a non-interactive shell running in POSIX mode to exit + - relaxed change of 8/20 to allow indirect references to $#, $@, $* + + builtins/bashref.texi + - documented new posix-mode exit on invalid expressions in $((...)) + + lib/readline/complete.c + - don't call rl_strpbrk unless rl_filename_quote_characters is not + NULL -- strpbrk requires non-NULL arguments + [in bash-2.01.1] + + 8/22 + ---- + bashline.c + - don't make `history-expand-line' a bindable command unless + BANG_HISTORY is defined, and don't compile the code for that + command in unless BANG_HISTORY is defined + - make history_expand_line(), tcsh_magic_space(), alias_expand_line(), + and history_and_alias_expand_line() int-returning functions that + return 0 for success and non-zero on error. This allows + tcsh_magic_space() to just call history_expand_line() and insert + a space if that returns successfully + - `magic-space' is now a bindable readline command + + doc/bash.{1,html}, lib/readline/doc/rluser.texinfo + - documented new `magic-space' bindable readline command + + 8/25 + ---- + parse.y + - fixed decode_prompt_string so that values of $PWD longer than + PATH_MAX don't cause buffer overruns (char t_string[PATH_MAX]) + [in bash-2.01.1] + + general.c + - fixed polite_directory_format so that values of $HOME longer + than PATH_MAX don't cause buffer overruns (char tdir[PATH_MAX]) + [in bash-2.01.1] + + subst.c + - fix to expansion of $* so that the positional parameters are + separated by the first character of $IFS, even when the expansion + is not within double quotes, so the correct split is still + performed even when IFS does not contain a space. Works for + ${*}, too + - fix to expansion of $@ so that the positional parameters are + separated by the first character of $IFS, even when the expansion + is not within double quotes, so the correct split is still + performed even when IFS does not contain a space. Works for + ${@}, too + - new function, string_list_dollar_at(), which is to $@ as + string_list_dollar_star is to $* + - fixed expansion of $@ so that splitting is still done even if + IFS is unset or NULL, as POSIX.2 specifies (section 3.5.2) + - fixed expansion of $* so that it expands to multiple words if there + is more than one positional parameter, just like $@, even if + IFS is unset or NULL + - new function list_quote_escapes, quotes (with CTLESC) all + CTLESC and CTLNUL characters in each member of the list + + tests/dollar-{at,star}.sh + - combined into dollar-at-star, changed run-dollars accordingly + + 8/26 + ---- + Makefile.in + - make the `tests' target use $(SHELL) instead of hardcoding `sh' + + 8/29 + ---- + subst.c + - expand_word_list_internal now takes a flags word as the second + argument, telling which expansions to perform on the WORD_LIST + - broke expand_word_list_internal into several functions: one + each to do brace expansion, glob expansion, and the `normal' + shell expansions + - new extern function: expand_words_shellexp() to perform the + `normal' shell expansions on a WORD_LIST + + subst.h + - extern declaration for expand_words_shellexp + + bashline.c + - fixed a problem with attempt_shell_completion where it attempted + to refer to rl_line_buffer[-1] (completion at the start of the + line, which means that ti == -1, which means that the test for + rl_line_buffer[ti] at line 715 was an array bounds error + [in bash-2.01.1] + + eval.c + - new function, parse_string_to_word_list(), which takes a string + and runs it through the parser, returning the resultant word + list + + externs.h + - new extern declaration for parse_string_to_word_list() + + variables.c + - change assign_array_var_from_string to first split the string + between the parens on whitespace, then expand the resultant + list of words with all the shell expansions before doing the + assignment + + 9/4 + --- + redir.c, redir.h + - redirection_error is no longer a static function + + builtins/evalstring.c + - changes to handle $( < filename ) (equivalent to $(cat filename)) + as in ksh + + lib/readline/bind.c + - added two new functions: rl_unbind_function_in_map(func, map), + which unbinds all keys that execute FUNC in MAP; and + rl_unbind_command_in_map(command, map), which unbinds all keys + bound to COMMAND in MAP + + lib/readline/readline.h + - extern declarations for rl_unbind_{function,command}_in_map + + lib/readline/doc/rltech.texi + - documented rl_unbind_{function,command}_in_map + + builtins/bind.def + - added a new option, -u FUNCNAME, which unbinds all key sequences + bound to FUNCNAME in the specified (or current) keymap + + doc/{bash.{1,html},bashref.texi} + - documented new $( < filename ) command substitution + - documented new bind -u FUNCNAME option + + 9/5 + --- + shell.c + - send SIGHUP to all jobs when an interactive login shell exits if + the variable `hup_on_exit' is non-zero + - modified run_startup_files so that if `NON_INTERACTIVE_LOGIN_SHELLS' + is #define'd (perhaps in config.h.top, though there is nothing there + for it), all login shells (interactive and non-interactive) run + /etc/profile and one of the per-user login shell startup files + + builtins/shopt.def + - new shopt option `huponexit' to control the value of hup_on_exit + + doc/{bash.{1,html},bashref.texi} + - documented new `huponexit' shell option + + 9/8 + --- + builtins/common.c + - changed contains_shell_metas to return 1 if a tilde appears at the + start of a string or after a `=' or `:' + - changed backslash_quote to quote a tilde if it appears at the start + of a string or after a `=' or `:' + + lib/readline/complete.c + - moved rl_tilde_expand to util.c; it doesn't really have anything + to do with completion + - moved insert_text to readline.c, renamed it _rl_replace_text (since + that's really what it does), changed callers + - moved code that postprocesses the list of completion matches into + a new function: postprocess_matches + - new implementation of tcsh-like menu completion in a single new + function: rl_menu_complete + + lib/readline/{funmap.c,readline.h} + - necessary declarations for binding rl_menu_complete to the + new `menu-complete' command + + doc/{bash.{1,html},readline.3}, lib/readline/doc/rluser.texinfo + - documented new `menu-complete' bindable readline command + + 9/9 + --- + jobs.c + - delete_job should print a warning only if subshell_environment + is 0, so we don't print bogus warnings when shell scripts without + a leading #! are executed + + 9/10 + ---- + builtins/read.def + - fixed the code so that the `read' is automatically restarted when + it returns -1 with errno == EINTR. SIGINT is handled by the + interrupt handler, since interrupt_immediately is set to 1, so + this handles things like SIGCHLD + [in bash-2.01.1] + + 9/11 + ---- + test.c + - reorganized the code slightly to make it easier to add the ksh-like + [[...]] compound command + + test.h + - new file, with extern declarations for functions available in test.c + + externs.h + - moved declaration of test_command to test.h + + builtins/test.def + - include `test.h' + + 9/16 + ---- + {command,make_cmd,dispose_cmd,externs,subst}.h + parse.y, subst.c + {make,dispose,copy,print,execute}_cmd.c + - changes to add the new ksh-93 compatible [[...]] conditional command + + configure.in + - new enable option, --enable-cond-command, to compile in the [[...]] + command code + + config.h.in + - new #define, COND_COMMAND, to compile in the [[...]] command code + + tests/{run-cond,cond.{tests,right}} + - test suite for the new [[...]] command + + {builtins,lib/{readline,glob,tilde}}/Makefile.in + - explicit dependencies for .o files on .c files for losing makes + like Solaris + + doc/{bash.{1,html},bashref.texi} + - documented the new `[[' compound command + - documented the test/[ builtin behavior based on the number of + arguments in the description of the builtin + - made a new section for conditional expressions that just lists + the available primaries -- the connectives and other operators + are listed in the description of the [[ command and the test/[ + builtin + + 9/18 + ---- + builtins/set.def + - minus_o_option_commands is now a global function so the shopt + code can use it + - minus_o_option_commands now takes an argument telling it which + options to print, just like list_minus_o_options + - new function, print_minus_o_option, which prints the value of + a `set -o' option either in the traditional format or in the + format used by `set +o' + - changed list_minus_o_opts and minus_o_option_commands to call + print_minus_o_option + + builtins/shopt.def + - `shopt -p' now causes output to be printed in a format reusable + as input (the format is a series of shopt commands, like the + output of `set +o') + - fixed a bug that made `shopt -so' and `shopt -uo' not work + - fixed list_shopt_o_options so that `shopt -op' acts like `set +o' + - fixed list_shopt_o_options to that `shopt -op optname' prints the + value of optname in a reusable format + - fixed list_some_o_options so that `shopt -ops' and `shopt -opu' + work and display output in a reusable format + + 9/19 + ---- + doc/{bash.{1,html},bashref.texi} + - documented new `shopt -p' behavior + + shell.c + - made `bash +o' display the same output as `set +o' and then + start an interactive shell (previously `bash -o' and `bash +o' + displayed the same thing) + + builtins/common.h + - added prototypes to the extern function declarations + + 9/22 + ---- + builtins/evalstring.c + - fixed the DISCARD case of the jump_to_top_level so that it + doesn't try to call dispose_command(command) after the + `pe_dispose' unwind frame gets run, since that disposes the + command + + 9/23 + ---- + test.[ch] + - test_eaccess is now a global function so that globbing code can + use it + + lib/glob/glob.c + - rewrote glob_vector to be slightly more efficient and to not + read the directory if the filename pattern does not contain + any globbing chars. This satisfies the POSIX requirement that + read permission is not required for a directory when the + pathname component does not contain a pattern character (bug + reported by jsm28@cam.ac.uk) + + subst.c + - fixed parameter_brace_expand so that ${array[@]} and ${array[*]} + behave correctly when IFS is unset or set to something that does + not contain a space (they should result in separate words, just + like $@ and $*) + + tests/{run-array2,array-at-star,array2.right} + - tests for the expansions of ${array[@]} and ${array[*]}, derived + from the tests in dollar-at-star + + 9/24 + ---- + jobs.c + - fixed cleanup_dead_jobs so that it doesn't remove the job + containing last_asynchronous_pid from the job table. This + fixes the POSIX.2 `wait' requirement problem + + 9/25 + ---- + parse.y + - added `\r' escape sequence to the prompt expansion code + + lib/readline/chardefs.h + - added defines for ISOCTAL, OCTVALUE, isxdigit (if not defined), + and HEXVALUE + + lib/readline/bind.c + - added `normal' echo/printf-like backslash escapes to the + key sequence translation code, with the addition that \d + expands to RUBOUT. This means that key sequence definitions + (before the `:') and macro values may contain these special + backslash-escape sequences + - now that we can translate octal escape sequences in key bindings, + change _rl_get_keyname so that it turns characters with values + 128-159 inclusive into octal escape sequences (\200-\237), since + those characters are not ASCII or ISO Latin 1 + + doc/{bash.{1,html},readline.3}, lib/readline/doc/rluser.texinfo + - documented new backslash escapes for readline key sequence and + macro translation + + builtins/pushd.def + - new function, get_dirstack_from_string(char *string), returns an + element from the directory stack or null, treating the argument + exactly as `dirs string' would, with the exception that if + the first character of `string' is not `+' or `-', a `+' is + assumed + + builtins/common.h + - new extern declaration for get_dirstack_from_string + + general.c + - added code to bash_special_tilde_expansions to get the expansion + using get_dirstack_from_string() if the first character of the + tilde-prefix is a digit or the first character is a `+' or `-' + and the second is a digit + + tests/dstack.{tests,right} + - renamed from dirstack.{tests,right} + + tests/dtack2.{tests,right} + - new tests for the directory stack tilde expansion code + + tests/run-dirstack + - now runs both dstack and dstack2 + + 10/3 + ---- + trap.c + - reordered header file inclusion for irix 4 + + execute_cmd.c + - fixed select_query so that a reply that is not a number is treated + the same as a numeric reply that is out of range + + lib/readline/util.c + - added a backwards-compatibility definition of _rl_savestring() + + builtins/set.def + - initialize_shell_options now takes an argument saying whether or + not we should parse $SHELLOPTS from the environment. The shell + does not parse the value if it's restricted, running setuid, or + running in `privileged mode' + + shell.c + - change call to initialize_shell_options to add the correct argument + + builtins/common.h + - changed extern declaration for initialize_shell_options + + doc/{bash.{1,html},bashref.texi} + - added note that the shell ignores $SHELLOPTS in the environment at + startup if running in privileged mode + - added note that the restricted shell does not parse $SHELLOPTS from + the environment at startup + + 10/6 + ---- + aclocal.m4 + - change BASH_RLIMIT_TYPE so that it looks for rlim_t in + as well as , for Solaris 2.6 + - new macro, BASH_LARGE_FILE_SUPPORT, to enable special compilation + options for large files on Solaris 2.6 (from eggert@twinsun.com) + + mailcheck.c + - the `file_size' member of the FILEINFO struct should be of + type `off_t' + - the `size' variable in file_has_grown should be of type `off_t' + - the RESET_MAIL_FILE macro should initialize file_size to 0, not 0L + + builtins/Makefile.in + - LDFLAGS and LOCAL_LDFLAGS are now set by configure + - `mkbuiltins' is now created from `mkbuiltins.o' instead of directly + from the source to the executable + + builtins/evalfile.c + - fixed _evalfile so that it handles large files correctly on + systems where the st_size member of `struct stat' will not fit + into an `int' + + builtins/mkbuiltins.c + - don't assume that st_size fits into an int + + input.[ch] + - the `b_size' member of a struct BSTREAM is now of type `size_t' + - changed third argument to make_buffered_stream to size_t; changed + caller + - changed `size' variable in fd_to_buffered_stream to type `size_t' + + general.h + - include if HAVE_SYS_RESOURCE_H and RLIMTYPE are + both defined, for possible necessary definition of RLIMTYPE + (e.g., on Solaris 2.6) + + {execute_cmd,jobs}.c, builtins/times.def + - don't include explicitly if RLIMTYPE is defined, + since general.h will include it in that case + + lib/readline/bind.c + - new function, char *_rl_read_file(filename, sizep), which reads + FILENAME into a malloced buffer, returning the buffer and the + size of the buffer in *SIZEP + + lib/readline/histfile.c + - changed read_history_range and history_truncate_file to handle + large files + + hashcmd.c + - find_hashed_filename should not add `./' to the front of a pathname + that already begins with `./' + + 10/8 + ---- + support/config.sub + - recognize `hppa2.0' as a valid machine architecture + + aclocal.m4 + - changed BASH_CHECK_LIB_TERMCAP so that `gnutermcap' is not chosen + if `$prefer_curses' is set to something + + bashhist.c + - don't use HISTCONTROL or HISTIGNORE to remove lines from the + second and subsequent lines of a multi-line command + (current_command_line_count > 1). Old code did this only when + command-oriented-history was enabled + + doc/{bash.{1,html},bashref.texi} + - changed descriptions of HISTCONTROL and HISTIGNORE to state that + these variables are not applied to the second and subsequent + lines of a multi-line command + + builtins/hash.def, {copy,dispose}_cmd.c + - include "bashtypes.h" -- cray machines need it because of their + oddball definition of `word' + + configure.in + - changed check of ${host_cpu} to check for `*cray*' and `*Cray*' + when deciding whether to include the GNU malloc, since it + seems that ${host_cpu} gets set to `CrayYMP' + + 10/9 + ---- + configure.in + - look for strtod and strtol in libc + - make lib/sh directory in build directory if not there + - create lib/sh/Makefile + + config.h.in + - added HAVE_STRTOD and HAVE_STRTOL + + Makefile.in + - changes for lib/sh/libsh.a (shell library) + + builtins/printf.def + - took out the `#ifdef STRTOUL' code, since strtoul is in libsh.a, + and will be resolved from there if it's not in libc + + variables.c + - call strtol() instead of string_to_long() + + general.c, general.h + - removed string_to_long + - changed legal_number to use strtol so it correctly sets errno + to ERANGE on overflow + - moved bash_getcwd_errstr here from lib/sh/oslib.c + + externs.h + - moved extern declarations for functions defined in libsh to a + separate section of the file, added extern declarations for + other functions in libsh + + builtins/ulimit.def + - changed macro definition for string_to_rlimtype to call strtol + directly instead of string_to_long + + lib/sh/clktck.c + - moved get_clock_tck to its own file, since it's compiled in + unconditionally + + 10/10 + ----- + lib/sh/getenv.c + - moved getenv() and __getenv() here from lib/sh/oslib.c + + lib/sh/{setlinebuf,strerror,strcasecmp}.c + - moved {setlinebuf,strerror,strcasecmp}() from oslib.c to + individual files + + lib/sh/Makefile.in, Makefile.in + - changes for new files in lib/sh + + aclocal.m4 + - new macro BASH_SYS_RESTARTABLE_SYSCALLS, which does what + AC_SYS_RESTARTABLE_SYSCALLS does, but using posix sigaction() + + configure.in + - call BASH_SYS_RESTARTABLE_SYSCALLS if ac_cv_sys_restartable_syscalls + is `no' + + 10/13 + ----- + builtins/jobs.def + - catch out-of-range jobs better in disown_builtin + + configure.in + - don't build with GNU malloc on cygwin32 + + trap.c + - change signal_name to handle the case where signal_names[sig] is + NULL, which can happen on cygwin32 + + execute_cmd.c + - changes to do_piping to make pipes text mode (O_TEXT) on cygwin32 + + cross-build + - new directory with cache files and other stuff for cross-compiling + bash (currently only for building for cygwin32 on a Unix machine) + + cross-build/cygwin32.cache + - new file containing configuration variable assignments for + cygwin32 that would otherwise require a default case for AC_TRY_RUN + + configure.in + - source ${srcdir}/cross-build/cygwin32.cache on CYGWIN32 systems + if we're cross-compiling on a unix machine + - set $CC_FOR_BUILD for cygwin32 cross-compiling environment + + Makefile.in + - CC_FOR_BUILD is now a variable set by configure + + builtins/mkbuiltins.c + - only check for read(2) returning <= 0 in extract_info() (error + and exit on < 0, warning and return on == 0) + + builtins/evalfile.c + - only check for read(2) returning <= 0 in _evalfile() (error and + and failure return on < 0, success on == 0 while short-circuting + rest of operation) + + 10/14 + ----- + + vprint.c + - moved to lib/sh/vprint.c + + lib/sh/Makefile.in + - added entries for vprint.[co] in the appropriate places + + cross-build/win32sig.h + - a version of signames.h for cross-compiling for the CYGWIN32 + environment on a Unix machine (from noer@cygnus.com) + + aclocal.m4 + - made all cases of AC_TRY_RUN and AC_TRY_COMPILE have reasonable + default cases for cross-compiling, and tell the user what they are + + Makefile.in + - removed vprint.c from shell sources and vprint.o from shell + objects + - added a level of indirection for signames.h -- the variable + SIGNAMES_H is set by configure to either `lsignames.h' or + a file for a cross-compilation environment (currently only + the cygwin32 stuff is supported). Then that file is copied + to `signames.h'. `lsignames.h' is created by `mksignames' as + was previously used to create signames.h directly + + configure.in + - set SIGNAMES_H to either `$(srcdir)/cross-build/win32sig.h' or + `lsignames.h' as appropriate, substitute into Makefile + + 10/15 + ----- + builtins/Makefile.in + - CC_FOR_BUILD is now set by configure and used to build mkbuiltins + and psize.aux + + variables.h + - new variable attribute `att_tempvar', set if the SHELL_VAR * was + constructed on the fly from the temporary environment + + variables.c + - find_name_in_env_array now sets the `att_tempvar' attribute on + the SHELL_VAR it creates + + findcmd.c + - search_for_command now disposes the SHELL_VAR created by searching + the temporary environment for $PATH, if it is found there + - _find_user_command_internal also disposes of the SHELL_VAR if it + has the `att_tempvar' attribute set + + builtins/setattr.c + - show_name_attributes looks in the temporary environemnt, so it needs + to dispose the SHELL_VAR if it has the att_tempvar attribute set + + subst.c + - parameter_brace_expand_word now disposes of the SHELL_VAR returned + by find_variable if it has the att_tempvar attribute set + - ditto for param_expand and word_split + + builtins/kill.def + - disallow null pid arguments instead of treating them as 0 + - display a usage message and return failure if no pid or job + arguments are supplied + + 10/16 + ----- + builtins/declare.def + - make `var=value declare -x var' behave the same as + `var=value export var' and `var=value declare -r var' behave the + same as `var=value readonly var', now that we have the `tempvar' + attribute + + 10/22 + ----- + jobs.c + - non-interactive shells shouldn't report jobs killed by a SIGINT, + even if the standard output is to a terminal + - pretty_print_job should add a CR at the end of its output if the + shell is interactive and asynchronous notification is being + performed. This fixes the problem with extra CRs in the output + of $(jobs) + + general.c + - changed canonicalize_pathname to change `//' into `/', but leave + other pathnames starting with two consecutive slashes alone + + 10/27 + ----- + + lib/readline/histexpand.c + - fixed history_expand so that the appearance of the history + comment character at the beginning of a word inhibits history + expansion for the rest of the line + + 10/29 + ----- + jobs.c,variables.c + - moved set_pipestatus_array to variables.c + + variables.c + - new function, set_pipestatus_from_exit(int), which sets the + PIPESTATUS variable from a command's exit status + + variables.h + - extern declarations for set_pipestatus_from_exit and + set_pipestatus_array + + execute_cmd.c + - fixed execute_simple_command to call set_pipestatus_from_exit + if a foreground builtin or function, or a foreground null + command is executed + + 10/31 + ----- + shell.c + - fixed run_startup_files to detect being run by sshd, and treat + that case as equivalent to being run by rshd + + 11/3 + ---- + builtins/set.def + - make sure `set -a' doesn't cause SHELLOPTS to be exported when + a change is made to one of the shell options + + 11/4 + ---- + pathexp.c + - fix to shell_glob_filename in the code that uses a POSIX glob + library + + 11/5 + ---- + jobs.c + - fix cleanup_dead_jobs to hang onto the job corresponding to + last_asynchronous_pid only if the shell is not interactive + (this still has the problem that until a new async process + is started, the job will stay in the jobs table) + + configure.in,aclocal.m4 + - added a new macro, BASH_TYPE_U_INT32_T, to check for u_int32_t + separately from int32_t, since there are systems (HP-UX 10.20) + that have a define for the latter but not the former + + 11/6 + ---- + jobs.c + - cleanup_dead_jobs no longer checks whether the job it is deleting + corresponds to last_asynchronous_pid + - notify_of_job_status and mark_dead_jobs_as_notified now will not + mark the job corresponding to last_asynchronous_pid as notified + if the shell is not interactive + - wait_for_single_pid, if told to wait for last_asynchronous_pid, + or the job of which it is a member, will take care of marking + the job as notified after calling wait_for and collecting the + status. This means that two successive `wait' calls for $! will + succeed the first time and fail the second, as POSIX.2 specifies + (take this code out if it causes problems) + + 11/7 + ---- + jobs.c + - wait_for_job, if told to wait for the job corresponding to the + last async pid, will mark the job as notified after waiting for + it and collecting the status + + general.h + - fixed MEMBER macro to avoid reading past end of S (it used to + test s[1] before s[0], which is an error if s == "") + + subst.c + - expand_word_internal should free ISTRING before returning if + param_expand returns an error + - parameter_brace_expand_word should free the memory it allocates + and passes to param_expand + + execute_cmd.c + - execute_arith_command should call dispose_words on the list + returned by expand_words + + parse.y + - after calling parse_arith_command, read_token needs to free the + string value that parse_arith_command fills in, since make_word + makes a copy of the string it's passed + + 11/10 + ----- + subst.c + - cond_expand_word needs to free the value returned by string_list + after it is run through quote_string_for_globbing + + parse.y + - make sure cond_term frees yylval.word if it is just a `!' and + it's parsed as a term negation operator + + variables.c + - assign_array_var_from_string needs to free the word list returned + by parse_string_to_word_list after calling expand_words_shellexp + on it + + execute_cmd.c + - changed execute_simple_command to avoid saving the_printed_command + into command_line until just before it's needed. This should save + time and prevent memory leaks on errors, but it must be watched + closely to make sure that the_printed_command doesn't change out + from under execute_simple_command before we copy it + + 11/12 + ----- + builtins/alias.def + - alias and unalias should print error messages when passed an + argument that is not an alias for printing or deletion, + respectively, even if the shell is not interactive + + builtins/exit.def + - `logout' will no longer exit a non-login non-interactive shell + + 11/17 + ----- + lib/readline/nls.c + - add `koi8-r' as a legal LANG value + + builtins/alias.def + - if `alias' or `alias -p' is executed when no aliases are defined, + the return status should be 0, according to POSIX.2 + + 11/18 + ----- + subst.c + - changed a couple of calls to make_word_list (make_word(z), ...) + to add_string_to_list (z, ...) + + execute_cmd.c + - execute_cond_command now sets this_command_name to `[[' + + 11/21 + ----- + variables.c + - all_visible_{function,variable}s and the functions they call + should be compiled in only if READLINE is defined + + 11/24 + ----- + aclocal.m4 + - remove some leading whitespace before preprocessor statements in + BASH_KERNEL_RLIMIT_CHECK + + general.[ch] + - fix declarations for group_member so the extern declaration in + general.h agrees with the definition in general.c (fix from + Andreas Schwab ) + + builtins/cd.def + - print the new working directory if the shell is interactive + and `cd -' succeeds + - don't print the new working directory if it's found in $CDPATH + if the shell is not interactive + + 11/25 + ----- + builtins/cd.def + - fixes to bindpwd so that it copes with get_working_directory + returning NULL (bug from schwab@issan.informatik.uni-dortmund.de) + + 12/2 + ---- + support/config.guess + - add support for new OS name for SINIX SVR4 systems + + 12/3 + ---- + + builtins/set.def + - `unset' should check that a function it's trying to unset is a + legal identifier only when in POSIX mode + + redir.c + - changed here_document_to_fd to try and make sure the filename + used for the here document is `more unique', since the old + version would fail if two here documents were created in less + than a second + + 12/4 + ---- + builtins/cd.def + - POSIX.2 says that if CDPATH is used to find the new directory, + and it's not relative to the current directory, the new directory + name should be displayed on stdout even if the shell is not + interactive + + 12/5 + ---- + parse.y + - changes so that `time' is recognized as a reserved word only at + the beginning of a pipeline (the last read token is one of 0, + `;', `\n', `&&', `||', or `&'): + + o add clause to special_case_tokens that does the check + and returns TIME if the conditions are met + o take check for `TIME' out of CHECK_FOR_RESERVED_WORD, but + leave it in the word_token_alist so that `type' still + reports it as a `keyword' + o new function, time_command_acceptable(), encapsulates the + necessary conditions for `time' to be returned as a + reserved word + + [bash-2.02-alpha1 frozen] + + 1/6/98 + ------ + lib/glob/fnmatch.c + - fix define for isgraph so that it does not return success for space + - fix strcompare() so that the call to strcoll is surrounded by + #ifdef HAVE_STRCOLL + + 1/7 + --- + lib/glob/fnmatch.c + - the `test' argument to brackmatch() should be of type `unsigned char' + + 1/11 + ---- + execute_cmd.c + - make sure execute_arith_command sets this_command_name to `((' + + 1/29 + ---- + parse.y + - make sure the code for pushing and popping strings is compiled in + if either ALIAS or DPAREN_ARITHMETIC is defined, because the (( + code uses push_string in the case of a nested subshell + - fix cond_skip_newlines so it resets the prompt to $PS2 while + parsing an unfinished conditional command + + dispose_cmd.c, copy_cmd.c, builtins/hash.def + - fixes to not use `word' as a variable name or the name of a + function parameter to get around stuff in the Cray Unix include + files + + builtins/printf.def + - return failure immediately if an illegal format character is + encountered + + redir.c + - make the code that creates here-documents behave better if the + file it's trying to create already exists for some reason + + lib/readline/complete.c + - changed print_filename to return the number of characters it + outputs; changed callers to use that value. This makes columns + line up when printing completion listings with filenames + containing control characters + + doc/bash.{1,html} + - fixed a typo in the quote removal section + + 1/30 + ---- + parse.y + - free_string_list() needs to check that t->expander is not NULL + before trying to dereference it + - reset_parser() doesn't need to set pushed_string_list to NULL + after calling free_string_list(), since free_string_list does it + + configure.in,cross-build/cygwin32.cache + - fixes from Geoff Noer for better cygwin32 cross-compilation + + tests/printf.{tests,right} + - removed test for integer overflow, since error messages differ + across systems + + pathexp.c + - fixed a problem with unquoted_glob_pattern_p that made things + like `x+*' not expand correctly + + lib/glob/glob.c + - fixed a problem with glob_pattern_p that made things like `x+*' + not expand correctly + + builtins/cd.def + - if `cd -P' is executed, or `set -o physical' has been executed, + the value of $PWD after a successful cd will not contain any + symlinks, regardless of whether or not the shell is in posix mode + + 2/3 + --- + lib/readline/shell.c + - include or as appropriate + + 2/4 + --- + builtins/common.c + - take out the code in backslash_quote() that looks for tildes to + quote, for the time being + - if getcwd() fails, get_working_directory now prints the error + message corresponding to errno in addition to the rest of the + information -- TENTATIVE CHANGE + + lib/sh/getcwd.c + - fix from Paul Smith to make getcwd() behave better in the presence + of lstat(2) failures + + stringlib.c + - when copying the replacement string into the output string being + constructed, strsub() needs to make sure enough space for the + replacement string is allocated, not the length of the pattern + (use REPLEN, not PATLEN) + + mailcheck.c + - make sure make_default_mailpath() has a valid current_user struct + before trying to construct the default mailpath + + 2/5 + --- + execute_cmd.c + - execute_builtin needs to call run_unwind_frame if the builtin is + `source' or `eval' and we're not in a subshell rather than just + calling dispose_builtin_env, because not all invocations copy + the temporary_env to builtin_env, and nested calls to `.' require + that the temporary env given to the first persist until that first + call to `.' finishes + + parse.y + - fix to history_delimiting_chars so that function definitions like + + function xyz + { + echo a + } + + are saved to the history correctly when command_oriented_history + is enabled, but literal_history is not + + bashhist.c + - when calling internal_error from pre_process_line, use "%s" as + the format with history_value as the argument to avoid the + problem with the failed history event containing printf escape + sequences + + 2/13 + ---- + shell.c + - if shell_initialized is non-zero, don't line-buffer stderr and + stdout in shell_initialize on SunOS5 -- see if this fixes the + crashing problems for scripts without a leading `#! /bin/sh' + + 2/17 + ---- + bashline.c + - added diffs to _ignore_completion_names from Andreas Schwab to + complete names that would otherwise be ignored with FIGNORE if + they are the only possible completions. Define NO_FORCE_FIGNORE + if you want this; it is not defined by default + + 2/19 + ---- + support/bashbug.sh + - changed the bug-bash address to bug-bash@gnu.org + + examples/loadables/Makefile.in + - converted from `Makefile' with some boilerplate configure variables + to find the source and build directories -- still requires some + hand-editing to get the right CFLAGS and LDFLAGS for shared object + creation + + Makefile.in + - create examples/loadables/Makefile with `make makefiles' + + configure.in + - create examples/loadables directory so `make makefiles' can write a + makefile there + + general.c + - make sure initialize_groups_array always sets things up so that + ${GROUPS[0]} is the user's primary group (current_user.gid) + + 2/20 + ---- + lib/readline/parens.c + - change the time delay when showing matching parens from 1.5 sec to + 0.5 sec + + 2/23 + ---- + shell.c + - isnetconn() should call getpeername(fd,...) instead of using 0 + (though fileno(stdin) should always be 0) + + support/config.guess + - updates from master FSF copy + + 2/24 + ---- + support/man2html.c + - modified version of man2html to convert bash.1 into bash.html + + support/Makefile.in + - simple Makefile to create man2html + + configure.in + - make sure support/Makefile is created + + Makefile.in + - make sure support/Makefile is created and cleaned + + doc/Makefile.in + - changes to suffix rules to say how to make .html from .1 + - `bash.html' is now a makefile target, created by man2html from + bash.1 rather than being hand-modified + + lib/sh/itos.c, general.c + - new file, itos() from general.c. This is here because the + implementation of strerror in lib/sh/strerror.c uses itos() + + Makefile.in, lib/sh/Makefile.in + - changes to add itos.c in libsh.a + + externs.h, general.h + - moved extern declaration of itos() from general.h to externs.h + + aclocal.m4 + - changes to BASH_LARGE_FILE_SUPPORT for the LFS64_* variables in + Solaris 2.6 + + Makefile.in + - make sure configure sets CPPFLAGS in this file + + 2/27 + ---- + + builtins/command.def + - make sure get_standard_path returns the value of + STANDARD_UTILS_PATH if _CS_PATH is defined, but confstr(3) + returns 0, indicating that _CS_PATH does not have a defined + value + + bashhist.c + - fixed bash_history_inhibit_expansion() so that extended globbing + expressions like *.!(c) are not history expanded if extended_glob + is non-zero (shopt -s extglob has been executed) + + 3/2 + --- + Makefile.in + - changed release status to `beta1' + + [bash-2.02-beta1 frozen] + + 3/17 + ---- + lib/readline/vi_mode.c + - make sure _rl_vi_save_insert() gets a non-null UNDO_LIST pointer + before trying to do anything with it + + jobs.c + - add a call to internal_warning from wait_for_job if the job is + stopped + - changed notify_of_job_status to not report pipelines exiting due to + SIGPIPE in non-interactive shells if the shell is compiled with + -DDONT_REPORT_SIGPIPE + + builtins/psize.sh + - some fixes to try to avoid /tmp file races and surreptitious + substitutions + + version.c + - changed the extended version info to show 1998 as the copyright year + + parse.y + - fixes from Andreas Schwab + for compilation errors when the shell is configured --disable-alias + but with dparen arithmetic enabled + + eval.c + - fixes from Andreas Schwab to + make sure the input stream is popped correctly when performing an + array assignment in the command argument to `bash -c', e.g., + `bash -c 'A=()'' + + builtins/kill.def + - make `kill' with no arguments print a usage message and return a + failure status + + alias.c + - fix so that rd_token doesn't dump core when trying to do alias + expansion on a line containing an unclosed single quote (fix from + Vasco Pedro ) + + builtins/cd.def + - fix so that using a non-empty directory from CDPATH to construct + the name of the directory to change to results in an absolute + pathname of the new current working directory being displayed, + as POSIX.2 specifies + + support/bashbug.sh + - a couple of small fixes to minimize /tmp file races -- the script + is still raceable, the window is just smaller + + 3/24 + ---- + variables.c + - make sure assign_in_env passes a malloc'd string to + expand_string_unsplit, because some of the error code assumes that + it is malloc'd and frees it (bug reported by Marko.Makela@HUT.FI) + + 3/25 + ---- + doc/bashref.texi + - changed the email addresses to use the @email texinfo tag + + trap.c + - call reset_parser from the exit trap code before calling + parse_and_execute, so reserved words are parsed correctly + + subst.c + - make sure parameter_brace_patsub expands the pattern string as if + the expression were not in double quotes, even if the entire + expansion is enclosed in double quotes, so that quote removal + on embedded double quotes is performed correctly (bug report from + schwab@issan.informatik.uni-dortmund.de) + + 3/27 + ---- + support/config.guess + - changes to allow Power PCs running Apple's Rhapsody to configure + + 3/31 + ---- + + Makefile.in + - changed release status to `beta2' + + [bash-2.02-beta2 frozen] + + 4/6 + --- + subst.c + - make sure command_substitute does not try to set the terminal's + process group to a background job + + [bash-2.02 frozen] diff -Nrc2 bash-2.01.1/INSTALL bash-2.02/INSTALL *** bash-2.01.1/INSTALL Fri Apr 25 14:16:16 1997 --- bash-2.02/INSTALL Thu Sep 18 15:44:39 1997 *************** *** 198,203 **** `--with-glibc-malloc' Use the GNU libc version of `malloc' in `lib/malloc/gmalloc.c'. ! This is somewhat slower than the default `malloc', but wastes ! considerably less space. `--with-gnu-malloc' --- 198,206 ---- `--with-glibc-malloc' Use the GNU libc version of `malloc' in `lib/malloc/gmalloc.c'. ! This is not the version of `malloc' that appears in glibc version ! 2, but a modified version of the `malloc' from glibc version 1. ! This is somewhat slower than the default `malloc', but wastes less ! space on a per-allocation basis, and will return memory to the ! operating system under some circumstances. `--with-gnu-malloc' *************** *** 205,212 **** not the same `malloc' that appears in GNU libc, but an older version derived from the 4.2 BSD `malloc'. This `malloc' is very ! fast, but wastes a lot of space. This option is enabled by ! default. The `NOTES' file contains a list of systems for which ! this should be turned off, and `configure' disables this option ! automatically for a number of systems. `--with-purify' --- 208,215 ---- not the same `malloc' that appears in GNU libc, but an older version derived from the 4.2 BSD `malloc'. This `malloc' is very ! fast, but wastes some space on each allocation. This option is ! enabled by default. The `NOTES' file contains a list of systems ! for which this should be turned off, and `configure' disables this ! option automatically for a number of systems. `--with-purify' *************** *** 218,221 **** --- 221,235 ---- historical Bourne shell. + There are several `--enable-' options that alter how Bash is compiled + and linked, rather than changing run-time features. + + `--enable-profiling' + This builds a Bash binary that produces profiling information to be + processed by `gprof' each time it is executed. + + `--enable-static-link' + This causes Bash to be linked statically, if `gcc' is being used. + This could be used to build a version to use as root's shell. + The `minimal-config' option can be used to disable all of the following options, but it is processed first, so individual options may be *************** *** 245,248 **** --- 259,265 ---- be timed. + `--enable-cond-command' + Include support for the `[[' conditional command. + `--enable-directory-stack' Include support for a `csh'-like directory stack and the `pushd', *************** *** 257,260 **** --- 274,281 ---- `--enable-dparen-arithmetic' Include support for the `ksh' `((...))' command. + + `--enable-extended-glob' + Include support for the extended pattern matching features + described above under *Note Pattern Matching::. `--enable-help-builtin' diff -Nrc2 bash-2.01.1/MANIFEST bash-2.02/MANIFEST *** bash-2.01.1/MANIFEST Mon Jun 2 16:35:37 1997 --- bash-2.02/MANIFEST Tue Mar 3 15:03:27 1998 *************** *** 8,11 **** --- 8,12 ---- CWRU/misc d builtins d + cross-build d doc d examples d *************** *** 26,29 **** --- 27,31 ---- lib/readline/doc d lib/readline/examples d + lib/sh d lib/termcap d lib/termcap/grot d *************** *** 56,60 **** locale.c f stringlib.c f - oslib.c f variables.c f make_cmd.c f --- 58,61 ---- *************** *** 62,66 **** unwind_prot.c f dispose_cmd.c f - getcwd.c f bashhist.c f hashcmd.c f --- 63,66 ---- *************** *** 82,90 **** alias.c f execute_cmd.c f bashline.c f braces.c f bracecomp.c f nojobs.c f - vprint.c f error.c f xmalloc.c f --- 82,91 ---- 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 *************** *** 98,101 **** --- 99,103 ---- maxpath.h f filecntl.h f + findcmd.h f hashlib.h f quit.h f *************** *** 105,108 **** --- 107,111 ---- parser.h f sig.h f + test.h f trap.h f general.h f *************** *** 122,125 **** --- 125,129 ---- make_cmd.h f execute_cmd.h f + redir.h f bashtypes.h f mailcheck.h f *************** *** 166,169 **** --- 170,174 ---- builtins/kill.def f builtins/mkbuiltins.c f + builtins/printf.def f builtins/pushd.def f builtins/read.def f *************** *** 189,192 **** --- 194,199 ---- builtins/common.h f builtins/bashgetopt.h f + cross-build/cygwin32.cache f + cross-build/win32sig.h f lib/glob/ChangeLog f lib/glob/Makefile.in f *************** *** 195,198 **** --- 202,206 ---- lib/glob/glob.c f lib/glob/glob.h f + lib/glob/collsyms.h f lib/glob/doc/Makefile f lib/glob/doc/glob.texi f *************** *** 204,207 **** --- 212,217 ---- lib/malloc/gmalloc.c f lib/malloc/xmalloc.c f + lib/malloc/ogmalloc.c f + lib/malloc/omalloc.c f lib/malloc/stub.c f lib/malloc/i386-alloca.s f *************** *** 252,255 **** --- 262,266 ---- lib/readline/rlconf.h f lib/readline/rltty.h f + lib/readline/rlwinsize.h f lib/readline/readline.h f lib/readline/tcap.h f *************** *** 276,279 **** --- 287,303 ---- lib/readline/examples/rl.c f lib/readline/examples/Inputrc f + lib/sh/Makefile.in f + lib/sh/clktck.c f + lib/sh/getcwd.c f + lib/sh/getenv.c f + lib/sh/itos.c f + lib/sh/oslib.c f + lib/sh/setlinebuf.c f + lib/sh/strcasecmp.c f + lib/sh/strerror.c f + lib/sh/strtod.c f + lib/sh/strtol.c f + lib/sh/strtoul.c f + lib/sh/vprint.c f lib/termcap/Makefile.in f lib/termcap/termcap.c f *************** *** 325,328 **** --- 349,354 ---- doc/builtins.1 f doc/article.ms f + doc/htmlpost.sh f 755 + support/Makefile.in f support/config.guess f support/config.sub f *************** *** 336,339 **** --- 362,366 ---- support/mksignames.c f support/bashbug.sh f + support/man2html.c f support/recho.c f support/zecho.c f *************** *** 350,357 **** examples/bashdb/bashdb.pre f examples/loadables/README f ! examples/loadables/Makefile f examples/loadables/necho.c f examples/loadables/hello.c f - examples/loadables/printf.c f examples/loadables/print.c f examples/loadables/sprintf.c f --- 377,383 ---- examples/bashdb/bashdb.pre f examples/loadables/README f ! examples/loadables/Makefile.in f examples/loadables/necho.c f examples/loadables/hello.c f examples/loadables/print.c f examples/loadables/sprintf.c f *************** *** 370,415 **** examples/loadables/rmdir.c f examples/loadables/head.c f - examples/functions/substr f - examples/functions/kshenv f examples/functions/autoload f examples/functions/autoload.v2 f examples/functions/csh-compat f - examples/functions/shcat f - examples/functions/substr2 f - examples/functions/term f - examples/functions/whatis f - examples/functions/whence f - examples/functions/func f - examples/functions/dirname f examples/functions/dirfuncs f ! examples/functions/basename f examples/functions/exitstat f examples/functions/external f examples/functions/fact f - examples/functions/manpage f examples/functions/fstty f ! examples/functions/jj.bash f ! examples/functions/notify.bash f examples/functions/inpath f ! examples/functions/login f examples/functions/keep f ! examples/functions/seq f examples/functions/mhfold f examples/functions/repeat2 f ! examples/functions/lowercase f examples/functions/xalias.bash f - examples/scripts/shprompt f examples/scripts/adventure.sh f - examples/scripts/precedence f examples/scripts/bcsh.sh f examples/scripts/inpath f examples/scripts/nohup.bash f ! examples/scripts/vtree2 f ! examples/scripts/vtree3 f examples/scripts/scrollbar f examples/scripts/spin.bash f examples/scripts/zprintf f examples/startup-files/README f ! examples/startup-files/Bashrc f examples/startup-files/Bash_aliases f examples/startup-files/Bash_profile f --- 396,456 ---- examples/loadables/rmdir.c f examples/loadables/head.c f examples/functions/autoload f examples/functions/autoload.v2 f + examples/functions/basename f + examples/functions/basename2 f examples/functions/csh-compat f examples/functions/dirfuncs f ! examples/functions/dirname f examples/functions/exitstat f examples/functions/external f examples/functions/fact f examples/functions/fstty f ! examples/functions/func 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/jdate.bash f ! examples/functions/jj.bash f examples/functions/keep f ! examples/functions/kshenv f ! examples/functions/login f ! examples/functions/lowercase f ! examples/functions/manpage f examples/functions/mhfold f + examples/functions/notify.bash f + examples/functions/pathfuncs f examples/functions/repeat2 f ! examples/functions/seq f ! examples/functions/shcat f ! examples/functions/shcat2 f ! examples/functions/substr f ! examples/functions/substr2 f ! examples/functions/term f ! examples/functions/whatis f ! examples/functions/whence f examples/functions/xalias.bash f examples/scripts/adventure.sh f examples/scripts/bcsh.sh f + examples/scripts/fixfiles.bash f + examples/scripts/hanoi.bash f examples/scripts/inpath f + examples/scripts/krand.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/showperm.bash f + examples/scripts/shprompt f examples/scripts/spin.bash f + examples/scripts/timeout f + examples/scripts/vtree2 f + examples/scripts/vtree3 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 *************** *** 417,422 **** examples/startup-files/bashrc f examples/misc/suncmd.termcap f ! examples/misc/alias-conv.sh f ! examples/misc/alias-conv.bash f examples/misc/cshtobash f tests/README f --- 458,463 ---- examples/startup-files/bashrc f examples/misc/suncmd.termcap f ! examples/misc/aliasconv.sh f ! examples/misc/aliasconv.bash f examples/misc/cshtobash f tests/README f *************** *** 425,428 **** --- 466,471 ---- tests/array.tests f tests/array.right f + tests/array-at-star f + tests/array2.right f tests/braces-tests f tests/braces.right f *************** *** 430,487 **** tests/builtins.right f tests/builtins.sub1 f ! tests/source.sub1 f ! tests/source.sub2 f ! tests/source.sub3 f ! tests/source.sub4 f ! tests/dirstack.tests f ! tests/dirstack.right f ! tests/dollar-at.sh f ! tests/dollar-star.sh f tests/dollar.right f tests/errors.tests f tests/errors.right f tests/execscript f ! tests/execscript.right f ! tests/execscript.sub f 755 ! tests/execscript.sub2 f ! tests/execscript.sub3 f ! tests/execscript.sub4 f tests/exp-tests f tests/exp.right f tests/func.tests f tests/func.right f tests/getopts.tests f tests/getopts.right f ! tests/getopts.sub1 f ! tests/getopts.sub2 f ! tests/getopts.sub3 f ! tests/getopts.sub4 f ! tests/getopts.sub5 f ! tests/getopts.sub6 f ! tests/getopts.sub7 f tests/glob-test f tests/glob.right f tests/heredoc.tests f tests/heredoc.right f ! tests/histexpand.tests f ! tests/histexpand.right f tests/history.tests f tests/history.right f tests/history.list f ! tests/ifs-test-1.sh f ! tests/ifs-test-2.sh f ! tests/ifs-test-3.sh f ! tests/ifs.1.right f ! tests/ifs.2.right f ! tests/ifs.3.right f tests/input-line.sh f tests/input-line.sub f tests/input.right f tests/jobs.tests f tests/jobs.right f tests/more-exp.tests f tests/more-exp.right f tests/new-exp.tests f ! tests/new-exp.sub1 f tests/new-exp.right f tests/nquote.tests f --- 473,541 ---- tests/builtins.right f tests/builtins.sub1 f ! tests/source1.sub f ! tests/source2.sub f ! tests/source3.sub f ! tests/source4.sub f ! tests/source5.sub f ! tests/cond.tests f ! tests/cond.right f ! tests/dollar-at-star 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/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/exp-tests f tests/exp.right f + tests/extglob.tests f + tests/extglob.right f tests/func.tests f tests/func.right 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-test f + tests/glob1.sub f tests/glob.right f tests/heredoc.tests f tests/heredoc.right f ! tests/histexp.tests f ! tests/histexp.right f tests/history.tests f tests/history.right f tests/history.list f ! tests/ifs-1.test f ! tests/ifs-2.test f ! tests/ifs-3.test f ! tests/ifs-1.right f ! tests/ifs-2.right f ! tests/ifs-3.right f tests/input-line.sh f tests/input-line.sub f tests/input.right f tests/jobs.tests f + tests/jobs1.sub f + tests/jobs2.sub f tests/jobs.right f tests/more-exp.tests f tests/more-exp.right f tests/new-exp.tests f ! tests/new-exp1.sub f ! tests/new-exp2.sub f tests/new-exp.right f tests/nquote.tests f *************** *** 489,494 **** --- 543,552 ---- tests/posix2.tests f tests/posix2.right f + tests/posixpat.tests f + tests/posixpat.right f tests/prec.right f tests/precedence f + tests/printf.tests f + tests/printf.right f tests/quote.tests f tests/quote.right f *************** *** 512,517 **** --- 570,577 ---- tests/run-arith f tests/run-array f + tests/run-array2 f tests/run-braces f tests/run-builtins f + tests/run-cond f tests/run-dirstack f tests/run-dollars f *************** *** 519,522 **** --- 579,583 ---- tests/run-execscript f tests/run-exp-tests f + tests/run-extglob f tests/run-func f tests/run-getopts f *************** *** 532,536 **** --- 593,599 ---- tests/run-nquote f tests/run-posix2 f + tests/run-posixpat f tests/run-precedence f + tests/run-printf f tests/run-quote f tests/run-read f *************** *** 538,542 **** tests/run-rhs-exp f tests/run-rsh f ! tests/run-set-e-test f tests/run-strip f tests/run-test f --- 601,606 ---- tests/run-rhs-exp f tests/run-rsh f ! tests/run-set-e f ! tests/run-shopt f tests/run-strip f tests/run-test f *************** *** 547,550 **** --- 611,616 ---- tests/set-e-test f tests/set-e.right f + tests/shopt.tests f + tests/shopt.right f tests/strip.tests f tests/strip.right f *************** *** 555,559 **** tests/trap.tests f tests/trap.right f ! tests/trap.sub1 f 755 tests/type.tests f tests/type.right f --- 621,625 ---- tests/trap.tests f tests/trap.right f ! tests/trap1.sub f 755 tests/type.tests f tests/type.right f *************** *** 562,573 **** tests/version f tests/version.mini f ! tests/misc/haertel.perftest f ! tests/misc/perf-script f ! tests/misc/redir.t2.sh f ! tests/misc/run.r2.sh f ! tests/misc/sigint.t1.sh f ! tests/misc/sigint.t2.sh f ! tests/misc/sigint.t3.sh f ! tests/misc/sigint.t4.sh f tests/misc/test-minus-e.1 f tests/misc/test-minus-e.2 f --- 628,639 ---- tests/version f tests/version.mini f ! tests/misc/perftest f ! tests/misc/perf-script 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 *************** *** 576,579 **** --- 642,646 ---- 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 diff -Nrc2 bash-2.01.1/Makefile.in bash-2.02/Makefile.in *** bash-2.01.1/Makefile.in Wed May 28 13:34:27 1997 --- bash-2.02/Makefile.in Thu Apr 16 11:35:05 1998 *************** *** 1,3 **** ! # Makefile for bash-2.01, version 2.32 # # Make sure the first target in the makefile is the right one --- 1,3 ---- ! # Makefile for bash-2.02, version 2.84 # # Make sure the first target in the makefile is the right one *************** *** 28,31 **** --- 28,32 ---- @SET_MAKE@ CC = @CC@ + CC_FOR_BUILD = @CC_FOR_BUILD@ YACC = @YACC@ SHELL=/bin/sh *************** *** 69,73 **** # PROFILE_FLAGS is either -pg, to generate profiling info for use # with gprof, or nothing (the default). ! PROFILE_FLAGS= # The GNU coding standards don't recognize the possibility that --- 70,74 ---- # PROFILE_FLAGS is either -pg, to generate profiling info for use # with gprof, or nothing (the default). ! PROFILE_FLAGS= @PROFILE_FLAGS@ # The GNU coding standards don't recognize the possibility that *************** *** 75,78 **** --- 76,80 ---- # passed to cc. A different name should have been used. CFLAGS = @CFLAGS@ + CPPFLAGS = @CPPFLAGS@ LOCAL_CFLAGS = @LOCAL_CFLAGS@ DEFS = @DEFS@ *************** *** 106,109 **** --- 108,132 ---- SUBDIR_INCLUDES = -I. -I$(topdir) -I$(topdir)/$(LIBSUBDIR) -I$(includedir) + # the bash library + # the library is a mix of functions that the C library does not provide on + # some platforms and general shell utility functions + SH_LIBSRC = $(LIBSRC)/sh + SH_LIBDIR = $(dot)/${LIBSUBDIR}/sh + SH_ABSSRC = ${topdir}/${SH_LIBSRC} + + SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \ + ${SH_LIBSRC}/getenv.c ${SH_LIBSRC}/oslib.c \ + ${SH_LIBSRC}/setlinebuf.c \ + ${SH_LIBSRC}/strcasecmp.c ${SH_LIBSRC}/strerror.c \ + ${SH_LIBSRC}/strtod.c ${SH_LIBSRC}/strtol.c \ + ${SH_LIBSRC}/strtoul.c ${SH_LIBSRC}/vprint.c \ + ${SH_LIBSRC}/itos.c + + SHLIB_LIB = -lsh + SHLIB_LIBNAME = libsh.a + SHLIB_LIBRARY = ${SH_LIBDIR}/${SHLIB_LIBNAME} + SHLIB_LDFLAGS = -L${SH_LIBDIR} + SHLIB_DEP = ${SHLIB_LIBRARY} + # we assume for now that readline source is being shipped with bash RL_LIBSRC = $(LIBSRC)/readline *************** *** 241,251 **** LIBRARIES = $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) $(GLOB_LIB) \ ! $(TILDE_LIB) $(MALLOC_LIB) $(LOCAL_LIBS) LIBDEP = $(READLINE_DEP) $(TERMCAP_DEP) $(GLOB_DEP) $(HISTORY_DEP) \ ! $(TILDE_DEP) $(MALLOC_DEP) LIBRARY_LDFLAGS = $(READLINE_LDFLAGS) $(HISTORY_LDFLAGS) $(TILDE_LDFLAGS) \ ! $(GLOB_LDFLAGS) $(MALLOC_LDFLAGS) # --- 264,274 ---- LIBRARIES = $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) $(GLOB_LIB) \ ! $(TILDE_LIB) $(MALLOC_LIB) $(SHLIB_LIB) $(LOCAL_LIBS) LIBDEP = $(READLINE_DEP) $(TERMCAP_DEP) $(GLOB_DEP) $(HISTORY_DEP) \ ! $(TILDE_DEP) $(MALLOC_DEP) $(SHLIB_DEP) LIBRARY_LDFLAGS = $(READLINE_LDFLAGS) $(HISTORY_LDFLAGS) $(TILDE_LDFLAGS) \ ! $(GLOB_LDFLAGS) $(MALLOC_LDFLAGS) $(SHLIB_LDFLAGS) # *************** *** 258,264 **** expr.c copy_cmd.c flags.c subst.c hashcmd.c hashlib.c mailcheck.c \ test.c trap.c alias.c jobs.c nojobs.c $(ALLOC_FILES) braces.c \ ! vprint.c input.c bashhist.c array.c sig.c pathexp.c oslib.c \ ! unwind_prot.c siglist.c getcwd.c bashline.c bracecomp.c error.c \ ! list.c stringlib.c locale.c xmalloc.c HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ --- 281,287 ---- expr.c copy_cmd.c flags.c subst.c hashcmd.c hashlib.c mailcheck.c \ test.c trap.c alias.c jobs.c nojobs.c $(ALLOC_FILES) braces.c \ ! input.c bashhist.c array.c sig.c pathexp.c \ ! unwind_prot.c siglist.c bashline.c bracecomp.c error.c \ ! list.c stringlib.c locale.c findcmd.c redir.c xmalloc.c HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ *************** *** 273,276 **** --- 296,302 ---- SOURCES = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS) + # header files chosen based on running of configure + SIGNAMES_H = @SIGNAMES_H@ + # object files chosen based on running of configure JOBS_O = @JOBS_O@ *************** *** 282,287 **** trap.o input.o unwind_prot.o pathexp.o sig.o test.o version.o \ alias.o array.o braces.o bracecomp.o bashhist.o bashline.o \ ! getcwd.o siglist.o vprint.o oslib.o list.o stringlib.o \ ! locale.o xmalloc.o # Where the source code of the shell builtins resides. --- 308,312 ---- trap.o input.o unwind_prot.o pathexp.o sig.o test.o version.o \ alias.o array.o braces.o bracecomp.o bashhist.o bashline.o \ ! siglist.o list.o stringlib.o locale.o findcmd.o redir.o xmalloc.o # Where the source code of the shell builtins resides. *************** *** 304,308 **** $(DEFSRC)/ulimit.def $(DEFSRC)/umask.def $(DEFSRC)/wait.def \ $(DEFSRC)/getopts.def $(DEFSRC)/reserved.def \ ! $(DEFSRC)/pushd.def $(DEFSRC)/shopt.def BUILTIN_C_SRC = $(DEFSRC)/mkbuiltins.c $(DEFSRC)/common.c \ $(DEFSRC)/evalstring.c $(DEFSRC)/evalfile.c \ --- 329,333 ---- $(DEFSRC)/ulimit.def $(DEFSRC)/umask.def $(DEFSRC)/wait.def \ $(DEFSRC)/getopts.def $(DEFSRC)/reserved.def \ ! $(DEFSRC)/pushd.def $(DEFSRC)/shopt.def $(DEFSRC)/printf.def BUILTIN_C_SRC = $(DEFSRC)/mkbuiltins.c $(DEFSRC)/common.c \ $(DEFSRC)/evalstring.c $(DEFSRC)/evalfile.c \ *************** *** 318,322 **** $(DEFDIR)/history.o $(DEFDIR)/jobs.o $(DEFDIR)/kill.o \ $(DEFDIR)/let.o $(DEFDIR)/pushd.o $(DEFDIR)/read.o \ ! $(DEFDIR)/return.o $(DEFDIR)/shopt.o \ $(DEFDIR)/set.o $(DEFDIR)/setattr.o $(DEFDIR)/shift.o \ $(DEFDIR)/source.o $(DEFDIR)/suspend.o $(DEFDIR)/test.o \ --- 343,347 ---- $(DEFDIR)/history.o $(DEFDIR)/jobs.o $(DEFDIR)/kill.o \ $(DEFDIR)/let.o $(DEFDIR)/pushd.o $(DEFDIR)/read.o \ ! $(DEFDIR)/return.o $(DEFDIR)/shopt.o $(DEFDIR)/printf.o \ $(DEFDIR)/set.o $(DEFDIR)/setattr.o $(DEFDIR)/shift.o \ $(DEFDIR)/source.o $(DEFDIR)/suspend.o $(DEFDIR)/test.o \ *************** *** 343,353 **** TESTS_SUPPORT = recho zecho printenv CREATED_SUPPORT = signames.h recho zecho printenv tests/recho tests/zecho \ ! tests/printenv mksignames CREATED_CONFIGURE = config.h config.cache config.status config.log \ stamp-h CREATED_MAKEFILES = Makefile builtins/Makefile doc/Makefile \ lib/readline/Makefile lib/glob/Makefile \ ! lib/tilde/Makefile lib/malloc/Makefile \ ! lib/termcap/Makefile # Keep GNU Make from exporting the entire environment for small machines. --- 368,379 ---- TESTS_SUPPORT = recho zecho printenv CREATED_SUPPORT = signames.h recho zecho printenv tests/recho tests/zecho \ ! tests/printenv mksignames lsignames.h CREATED_CONFIGURE = config.h config.cache config.status config.log \ stamp-h CREATED_MAKEFILES = Makefile builtins/Makefile doc/Makefile \ lib/readline/Makefile lib/glob/Makefile \ ! lib/sh/Makefile lib/tilde/Makefile lib/malloc/Makefile \ ! lib/termcap/Makefile examples/loadables/Makefile \ ! support/Makefile # Keep GNU Make from exporting the entire environment for small machines. *************** *** 359,363 **** $(Program): .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP) $(RM) $@ ! $(PURIFY) $(CC) $(LDFLAGS) $(BUILTINS_LDFLAGS) $(LIBRARY_LDFLAGS) -o $(Program) $(OBJECTS) $(LIBS) ls -l $(Program) size $(Program) --- 385,389 ---- $(Program): .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP) $(RM) $@ ! $(PURIFY) $(CC) $(BUILTINS_LDFLAGS) $(LIBRARY_LDFLAGS) $(LDFLAGS) -o $(Program) $(OBJECTS) $(LIBS) ls -l $(Program) size $(Program) *************** *** 433,443 **** $(MAKE) $(MFLAGS) libtermcap.a) || exit 1 mksignames: $(SUPPORT_SRC)mksignames.c $(CC) $(CCFLAGS) $(CPPFLAGS) -o $@ $(SUPPORT_SRC)mksignames.c ! signames.h: mksignames $(RM) $@ ./mksignames $@ $(BUILTINS_LIBRARY): $(BUILTIN_DEFS) $(BUILTIN_C_SRC) config.h memalloc.h @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) libbuiltins.a ) || exit 1 --- 459,480 ---- $(MAKE) $(MFLAGS) libtermcap.a) || exit 1 + $(SHLIB_LIBRARY): config.h ${SHLIB_SOURCE} + @echo making $@ in ${SH_LIBDIR} + @(cd ${SH_LIBDIR} && \ + $(MAKE) $(MFLAGS) ${SHLIB_LIBNAME}) || exit 1 + mksignames: $(SUPPORT_SRC)mksignames.c $(CC) $(CCFLAGS) $(CPPFLAGS) -o $@ $(SUPPORT_SRC)mksignames.c ! # make a list of signals for the local system -- this is done when we're ! # *not* cross-compiling ! lsignames.h: mksignames $(RM) $@ ./mksignames $@ + # copy the correct signames header file to signames.h + signames.h: $(SIGNAMES_H) + -if cmp -s $(SIGNAMES_H) $@ ; then :; else $(RM) $@ ; $(CP) $(SIGNAMES_H) $@ ; fi + $(BUILTINS_LIBRARY): $(BUILTIN_DEFS) $(BUILTIN_C_SRC) config.h memalloc.h @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) libbuiltins.a ) || exit 1 *************** *** 588,592 **** @cp $(TESTS_SUPPORT) tests @( cd $(srcdir)/tests && \ ! PATH=$$PATH:$(BUILD_DIR)/tests THIS_SH=$(THIS_SH) sh ${TESTSCRIPT} ) symlinks: --- 625,629 ---- @cp $(TESTS_SUPPORT) tests @( cd $(srcdir)/tests && \ ! PATH=$$PATH:$(BUILD_DIR)/tests THIS_SH=$(THIS_SH) $(SHELL) ${TESTSCRIPT} ) symlinks: *************** *** 634,639 **** dispose_cmd.o: quit.h maxpath.h unwind_prot.h dispose_cmd.h dispose_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h - getcwd.o: config.h bashtypes.h bashansi.h - getcwd.o: maxpath.h posixstat.h posixdir.h memalloc.h error.o: config.h bashtypes.h bashansi.h ansi_stdlib.h flags.h stdc.h error.h error.o: command.h general.h externs.h input.h bashhist.h --- 671,674 ---- *************** *** 650,655 **** execute_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h execute_cmd.o: memalloc.h ${GRAM_H} flags.h builtins.h jobs.h quit.h siglist.h ! execute_cmd.o: execute_cmd.h trap.h pathexp.h $(DEFSRC)/common.h ! execute_cmd.o: ${DEFDIR}/builtext.h ${GLOB_LIBSRC}/fnmatch.h expr.o: config.h bashansi.h ansi_stdlib.h expr.o: shell.h config.h bashjmp.h posixjmp.h command.h stdc.h error.h --- 685,690 ---- execute_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h execute_cmd.o: memalloc.h ${GRAM_H} flags.h builtins.h jobs.h quit.h siglist.h ! execute_cmd.o: execute_cmd.h findcmd.h redir.h trap.h test.h pathexp.h ! execute_cmd.o: $(DEFSRC)/common.h ${DEFDIR}/builtext.h ${GLOB_LIBSRC}/fnmatch.h expr.o: config.h bashansi.h ansi_stdlib.h expr.o: shell.h config.h bashjmp.h posixjmp.h command.h stdc.h error.h *************** *** 657,660 **** --- 692,700 ---- expr.o: quit.h maxpath.h unwind_prot.h dispose_cmd.h expr.o: make_cmd.h subst.h sig.h pathnames.h externs.h + findcmd.o: config.h bashtypes.h filecntl.h posixstat.h bashansi.h + findcmd.o: ansi_stdlib.h memalloc.h shell.h bashjmp.h posixjmp.h command.h + findcmd.o: stdc.h error.h general.h variables.h quit.h maxpath.h unwind_prot.h + findcmd.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h + findcmd.o: flags.h hashlib.h pathexp.h hashcmd.h flags.o: config.h flags.h flags.o: shell.h config.h bashjmp.h posixjmp.h command.h stdc.h error.h *************** *** 671,675 **** hashcmd.o: shell.h config.h bashjmp.h posixjmp.h command.h stdc.h error.h hashcmd.o: general.h bashtypes.h variables.h array.h hashcmd.h ! hashcmd.o: execute_cmd.h stdc.h hashlib.o: config.h bashansi.h ansi_stdlib.h hashlib.o: shell.h config.h bashjmp.h posixjmp.h command.h stdc.h error.h --- 711,715 ---- hashcmd.o: shell.h config.h bashjmp.h posixjmp.h command.h stdc.h error.h hashcmd.o: general.h bashtypes.h variables.h array.h hashcmd.h ! hashcmd.o: execute_cmd.h findcmd.h stdc.h hashlib.o: config.h bashansi.h ansi_stdlib.h hashlib.o: shell.h config.h bashjmp.h posixjmp.h command.h stdc.h error.h *************** *** 698,706 **** make_cmd.o: variables.h array.h hashlib.h subst.h input.h externs.h make_cmd.o: jobs.h quit.h siglist.h - oslib.o: config.h bashtypes.h posixstat.h filecntl.h bashansi.h maxpath.h - oslib.o: shell.h config.h bashjmp.h posixjmp.h command.h stdc.h error.h - oslib.o: general.h bashtypes.h variables.h array.h hashlib.h - oslib.o: quit.h maxpath.h unwind_prot.h dispose_cmd.h - oslib.o: make_cmd.h subst.h sig.h pathnames.h externs.h y.tab.o: config.h bashtypes.h bashansi.h ansi_stdlib.h memalloc.h y.tab.o: shell.h config.h bashjmp.h posixjmp.h command.h stdc.h error.h --- 738,741 ---- *************** *** 723,726 **** --- 758,766 ---- print_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h print_cmd.o: ${GRAM_H} $(DEFSRC)/common.h + redir.o: config.h bashtypes.h posixstat.h bashansi.h ansi_stdlib.h filecntl.h + redir.o: memalloc.h shell.h bashjmp.h posixjmp.h command.h stdc.h error.h + redir.o: general.h variables.h array.h hashlib.h quit.h maxpath.h unwind_prot.h + redir.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h + redir.o: flags.h execute_cmd.h redir.h input.h shell.o: config.h bashtypes.h posixstat.h bashansi.h ansi_stdlib.h filecntl.h shell.o: shell.h config.h bashjmp.h posixjmp.h command.h stdc.h error.h *************** *** 729,733 **** shell.o: make_cmd.h subst.h sig.h pathnames.h externs.h shell.o: flags.h trap.h mailcheck.h builtins.h $(DEFSRC)/common.h ! shell.o: jobs.h siglist.h input.h execute_cmd.h bashhist.h shell.o: ${GLOB_LIBSRC}/fnmatch.h sig.o: config.h bashtypes.h --- 769,773 ---- shell.o: make_cmd.h subst.h sig.h pathnames.h externs.h shell.o: flags.h trap.h mailcheck.h builtins.h $(DEFSRC)/common.h ! shell.o: jobs.h siglist.h input.h execute_cmd.h findcmd.h bashhist.h shell.o: ${GLOB_LIBSRC}/fnmatch.h sig.o: config.h bashtypes.h *************** *** 755,759 **** test.o: general.h bashtypes.h variables.h array.h hashlib.h test.o: quit.h maxpath.h unwind_prot.h dispose_cmd.h ! test.o: make_cmd.h subst.h sig.h pathnames.h externs.h test.o: ${DEFSRC}/common.h trap.o: config.h bashtypes.h trap.h bashansi.h ansi_stdlib.h --- 795,799 ---- test.o: general.h bashtypes.h variables.h array.h hashlib.h test.o: quit.h maxpath.h unwind_prot.h dispose_cmd.h ! test.o: make_cmd.h subst.h sig.h pathnames.h externs.h test.h test.o: ${DEFSRC}/common.h trap.o: config.h bashtypes.h trap.h bashansi.h ansi_stdlib.h *************** *** 770,777 **** variables.o: quit.h maxpath.h unwind_prot.h dispose_cmd.h variables.o: make_cmd.h subst.h sig.h pathnames.h externs.h ! varibales.o: flags.h execute_cmd.h mailcheck.h input.h $(DEFSRC)/common.h ! variables.o: bashhist.h version.o: version.h .build - vprint.o: config.h xmalloc.o: config.h bashtypes.h ansi_stdlib.h error.h --- 810,816 ---- variables.o: quit.h maxpath.h unwind_prot.h dispose_cmd.h variables.o: make_cmd.h subst.h sig.h pathnames.h externs.h ! variables.o: flags.h execute_cmd.h mailcheck.h input.h $(DEFSRC)/common.h ! variables.o: findcmd.h bashhist.h version.o: version.h .build xmalloc.o: config.h bashtypes.h ansi_stdlib.h error.h *************** *** 820,824 **** bashline.o: quit.h maxpath.h unwind_prot.h dispose_cmd.h bashline.o: make_cmd.h subst.h sig.h pathnames.h externs.h ! bashline.o: builtins.h bashhist.h bashline.h execute_cmd.h pathexp.h bashline.o: $(DEFSRC)/common.h $(GLOB_LIBSRC)/glob.h alias.h bracecomp.o: config.h bashansi.h ansi_stdlib.h --- 859,863 ---- bashline.o: quit.h maxpath.h unwind_prot.h dispose_cmd.h bashline.o: make_cmd.h subst.h sig.h pathnames.h externs.h ! bashline.o: builtins.h bashhist.h bashline.h execute_cmd.h findcmd.h pathexp.h bashline.o: $(DEFSRC)/common.h $(GLOB_LIBSRC)/glob.h alias.h bracecomp.o: config.h bashansi.h ansi_stdlib.h *************** *** 930,934 **** builtins/exec.o: shell.h bashjmp.h posixjmp.h sig.h unwind_prot.h variables.h builtins/exec.o: dispose_cmd.h make_cmd.h subst.h externs.h execute_cmd.h ! builtins/exec.o: flags.h quit.h $(DEFSRC)/common.h stdc.h builtins/exit.o: bashtypes.h builtins/exit.o: command.h config.h memalloc.h error.h general.h maxpath.h --- 969,973 ---- builtins/exec.o: shell.h bashjmp.h posixjmp.h sig.h unwind_prot.h variables.h builtins/exec.o: dispose_cmd.h make_cmd.h subst.h externs.h execute_cmd.h ! builtins/exec.o: findcmd.h flags.h quit.h $(DEFSRC)/common.h stdc.h builtins/exit.o: bashtypes.h builtins/exit.o: command.h config.h memalloc.h error.h general.h maxpath.h *************** *** 949,953 **** builtins/getopts.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h builtins/hash.o: bashtypes.h ! builtins/hash.o: builtins.h command.h execute_cmd.h stdc.h $(DEFSRC)/common.h builtins/hash.o: command.h config.h memalloc.h error.h general.h maxpath.h builtins/hash.o: shell.h bashjmp.h posixjmp.h sig.h unwind_prot.h variables.h quit.h --- 988,992 ---- builtins/getopts.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h builtins/hash.o: bashtypes.h ! builtins/hash.o: builtins.h command.h findcmd.h stdc.h $(DEFSRC)/common.h builtins/hash.o: command.h config.h memalloc.h error.h general.h maxpath.h builtins/hash.o: shell.h bashjmp.h posixjmp.h sig.h unwind_prot.h variables.h quit.h *************** *** 974,977 **** --- 1013,1020 ---- builtins/let.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h builtins/let.o: shell.h bashjmp.h posixjmp.h sig.h unwind_prot.h variables.h + builtins/printf.o: config.h memalloc.h bashjmp.h command.h error.h + builtins/printf.o: general.h quit.h dispose_cmd.h make_cmd.h subst.h + builtins/printf.o: externs.h sig.h pathnames.h shell.h unwind_prot.h + builtins/printf.o: variables.h stdc.h $(DEFSRC)/bashgetopt.h builtins/pushd.o: command.h config.h memalloc.h error.h general.h maxpath.h builtins/pushd.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h *************** *** 1001,1005 **** builtins/source.o: command.h config.h memalloc.h error.h general.h maxpath.h builtins/source.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h ! builtins/source.o: shell.h bashjmp.h posixjmp.h sig.h unwind_prot.h variables.h builtins/suspend.o: command.h config.h memalloc.h error.h general.h maxpath.h builtins/suspend.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h --- 1044,1049 ---- builtins/source.o: command.h config.h memalloc.h error.h general.h maxpath.h builtins/source.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h ! builtins/source.o: shell.h bashjmp.h posixjmp.h sig.h unwind_prot.h variables.h ! builtins/source.o: findcmd.h builtins/suspend.o: command.h config.h memalloc.h error.h general.h maxpath.h builtins/suspend.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h *************** *** 1008,1011 **** --- 1052,1056 ---- builtins/test.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h builtins/test.o: shell.h bashjmp.h posixjmp.h sig.h unwind_prot.h variables.h + builtins/test.o: test.h builtins/times.o: command.h config.h memalloc.h error.h general.h maxpath.h builtins/times.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h stdc.h *************** *** 1016,1020 **** builtins/trap.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h builtins/type.o: command.h config.h memalloc.h error.h general.h maxpath.h ! builtins/type.o: quit.h $(DEFSRC)/common.h execute_cmd.h builtins/type.o: shell.h bashjmp.h posixjmp.h sig.h unwind_prot.h variables.h builtins/type.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h --- 1061,1065 ---- builtins/trap.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h builtins/type.o: command.h config.h memalloc.h error.h general.h maxpath.h ! builtins/type.o: quit.h $(DEFSRC)/common.h findcmd.h builtins/type.o: shell.h bashjmp.h posixjmp.h sig.h unwind_prot.h variables.h builtins/type.o: dispose_cmd.h make_cmd.h subst.h externs.h stdc.h diff -Nrc2 bash-2.01.1/NEWS bash-2.02/NEWS *** bash-2.01.1/NEWS Wed Feb 12 12:12:47 1997 --- bash-2.02/NEWS Fri Apr 17 15:52:44 1998 *************** *** 1,2 **** --- 1,121 ---- + This is a terse description of the new features added to bash-2.02 since + the release of bash-2.01.1. As always, the manual page (doc/bash.1) is + the place to look for complete descriptions. + + 1. New Features in Bash + + a. A new version of malloc, based on the older GNU malloc, that has many + changes, is more page-based, is more conservative with memory usage, + and does not `orphan' large blocks when they are freed. + + b. A new version of gmalloc, based on the old GLIBC malloc, with many + changes and range checking included by default. + + c. A new implementation of fnmatch(3) that includes full POSIX.2 Basic + Regular Expression matching, including character classes, collating + symbols, equivalence classes, and support for case-insensitive pattern + matching. + + d. ksh-88 egrep-style extended pattern matching ([@+*?!](patlist)) has been + implemented, controlled by a new `shopt' option, `extglob'. + + e. There is a new ksh-like `[[' compound command, which implements + extended `test' functionality. + + f. There is a new `printf' builtin, implemented according to the POSIX.2 + specification. + + g. There is a new feature for command substitution: $(< filename) now expands + to the contents of `filename', with any trailing newlines removed + (equivalent to $(cat filename)). + + h. There are new tilde prefixes which expand to directories from the + directory stack. + + i. There is a new `**' arithmetic operator to do exponentiation. + + j. There are new configuration options to control how bash is linked: + `--enable-profiling', to allow bash to be profiled with gprof, and + `--enable-static-link', to allow bash to be linked statically. + + k. There is a new configuration option, `--enable-cond-command', which + controls whether or not the `[[' command is included. It is on by + default. + + l. There is a new configuration option, `--enable-extended-glob', which + controls whether or not the ksh extended globbing feature is included. + It is enabled by default. + + m. There is a new configuration #define in config.h.top that, when enabled, + will cause all login shells to source /etc/profile and one of the user- + specific login shell startup files, whether or not the shell is + interactive. + + n. There is a new invocation option, `--dump-po-strings', to dump + a shell script's translatable strings ($"...") in GNU `po' format. + + o. There is a new `shopt' option, `nocaseglob', to enable case-insensitive + pattern matching when globbing filenames and using the `case' construct. + + p. There is a new `shopt' option, `huponexit', which, when enabled, causes + the shell to send SIGHUP to all jobs when an interactive login shell + exits. + + q. `bind' has a new `-u' option, which takes a readline function name as an + argument and unbinds all key sequences bound to that function in a + specified keymap. + + r. `disown' now has `-a' and `-r' options, to limit operation to all jobs + and running jobs, respectively. + + s. The `shopt' `-p' option now causes output to be displayed in a reusable + format. + + t. `test' has a new `-N' option, which returns true if the filename argument + has been modified since it was last accessed. + + u. `umask' now has a `-p' option to print output in a reusable format. + + v. A new escape sequence, `\xNNN', has been added to the `echo -e' and $'...' + translation code. It expands to the character whose ascii code is NNN + in hexadecimal. + + w. The prompt string expansion code has a new `\r' escape sequence. + + x. The shell may now be cross-compiled for the CYGWIN32 environment on + a Unix machine. + + 2. New Features in Readline + + a. There is now an option for `iterative' yank-last-arg handline, so a user + can keep entering `M-.', yanking the last argument of successive history + lines. + + b. New variable, `print-completions-horizontally', which causes completion + matches to be displayed across the screen (like `ls -x') rather than up + and down the screen (like `ls'). + + c. New variable, `completion-ignore-case', which causes filename completion + and matching to be performed case-insensitively. + + d. There is a new bindable command, `magic-space', which causes history + expansion to be performed on the current readline buffer and a space to + be inserted into the result. + + e. There is a new bindable command, `menu-complete', which enables tcsh-like + menu completion (successive executions of menu-complete insert a single + completion match, cycling through the list of possible completions). + + f. There is a new bindable command, `paste-from-clipboard', for use on Win32 + systems, to insert the text from the Win32 clipboard into the editing + buffer. + + g. The key sequence translation code now understands printf-style backslash + escape sequences, including \NNN octal escapes. These escape sequences + may be used in key sequence definitions or macro values. + + h. An `$include' inputrc file parser directive has been added. + + ------------------------------------------------------------------------------- This is a terse description of the new features added to bash-2.01 since the release of bash-2.0. As always, the manual page (doc/bash.1) is the diff -Nrc2 bash-2.01.1/NOTES bash-2.02/NOTES *** bash-2.01.1/NOTES Fri Apr 11 17:00:00 1997 --- bash-2.02/NOTES Tue Apr 14 13:36:37 1998 *************** *** 138,139 **** --- 138,196 ---- /* Need to get the argument to a -c option processed in the + 8. Some people have asked about binding all of the keys in a PC-keyboard- + style numeric keypad to readline functions. Here's something I + received from the gnu-win32 list that may help. Insert the following + lines into ~/.inputrc: + + # home key + "\e[1~":beginning-of-line + # insert key + "\e[2~":kill-whole-line + # del key + "\e[3~":delete-char + # end key + "\e[4~":end-of-line + # pgup key + "\e[5~":history-search-forward + # pgdn key + "\e[6~":history-search-backward + + 9. Hints for building under Minix 2.0 (Contributed by Terry R. McConnell, + ) + + The version of /bin/sh distributed with Minix is not up to the job of + running the configure script. The easiest solution is to swap /bin/sh + with /usr/bin/ash. Then use chmem(1) to increase the memory allocated + to /bin/sh. The following settings are known to work: + + text data bss stack memory + 63552 9440 3304 65536 141832 /bin/sh + + If you have problems with make or yacc it may be worthwhile first to + install the GNU versions of these utilities before attempting to build + bash. (As of this writing, all of these utilities are available for the + i386 as pre-built binaries via anonymous ftp at math.syr.edu in the + pub/mcconnell/minix directory. Note that the GNU version of yacc is called + bison.) + + Unless you want to see lots of warnings about old-style declarations, + do LOCAL_CFLAGS=-wo; export LOCAL_CFLAGS before running configure. + (These warnings are harmless, but annoying.) + + configure will insist that you supply a host type. For example, do + ./configure --host=i386-pc-minix. + + Minix does not support the system calls required for a proper + implementation of ulimit(). The `ulimit' builtin will not be available. + + Configure will fail to notice that many things like uid_t are indeed + typedef'd in , because it uses egrep for this purpose + and minix has no egrep. You could try making a link /usr/bin/egrep --> + /usr/bin/grep. Better is to install the GNU version of grep in + /usr/local/bin and make the link /usr/local/bin/egrep -->/usr/local/bin/grep. + (These must be hard links, of course, since Minix does not support + symbolic links.) + + You will see many warnings of the form: + warning: unknown s_type: 98 + I have no idea what this means, but it doesn't seem to matter. diff -Nrc2 bash-2.01.1/aclocal.m4 bash-2.02/aclocal.m4 *** bash-2.01.1/aclocal.m4 Tue Jul 29 10:52:17 1997 --- bash-2.02/aclocal.m4 Fri Mar 27 12:04:31 1998 *************** *** 27,31 **** } ], bash_cv_dup2_broken=yes, bash_cv_dup2_broken=no, ! AC_MSG_ERROR(cannot check dup2 if cross compiling)) ]) AC_MSG_RESULT($bash_cv_dup2_broken) --- 27,32 ---- } ], bash_cv_dup2_broken=yes, bash_cv_dup2_broken=no, ! [AC_MSG_ERROR(cannot check dup2 if cross compiling -- defaulting to no) ! bash_cv_dup2_broken=no]) ]) AC_MSG_RESULT($bash_cv_dup2_broken) *************** *** 129,133 **** } ], bash_cv_pgrp_pipe=no,bash_cv_pgrp_pipe=yes, ! AC_MSG_ERROR(cannot check pgrp synchronization if cross compiling)) ]) AC_MSG_RESULT($bash_cv_pgrp_pipe) --- 130,135 ---- } ], bash_cv_pgrp_pipe=no,bash_cv_pgrp_pipe=yes, ! [AC_MSG_ERROR(cannot check pgrp synchronization if cross compiling -- defaulting to no) ! bash_cv_pgrp_pipe=no]) ]) AC_MSG_RESULT($bash_cv_pgrp_pipe) *************** *** 170,174 **** [AC_MSG_CHECKING(for size and type of struct rlimit fields) AC_CACHE_VAL(bash_cv_type_rlimit, ! [AC_TRY_COMPILE([#include ], [rlim_t xxx;], bash_cv_type_rlimit=rlim_t,[ AC_TRY_RUN([ --- 172,177 ---- [AC_MSG_CHECKING(for size and type of struct rlimit fields) AC_CACHE_VAL(bash_cv_type_rlimit, ! [AC_TRY_COMPILE([#include ! #include ], [rlim_t xxx;], bash_cv_type_rlimit=rlim_t,[ AC_TRY_RUN([ *************** *** 185,189 **** exit(1); }], bash_cv_type_rlimit=quad_t, bash_cv_type_rlimit=long, ! AC_MSG_ERROR(cannot check quad_t if cross compiling))]) ]) AC_MSG_RESULT($bash_cv_type_rlimit) --- 188,193 ---- exit(1); }], bash_cv_type_rlimit=quad_t, bash_cv_type_rlimit=long, ! [AC_MSG_ERROR(cannot check quad_t if cross compiling -- defaulting to long) ! bash_cv_type_rlimit=long])]) ]) AC_MSG_RESULT($bash_cv_type_rlimit) *************** *** 208,212 **** #endif], [ char *msg = _sys_siglist[2]; ], bash_cv_decl_under_sys_siglist=yes, bash_cv_decl_under_sys_siglist=no, ! AC_MSG_ERROR(cannot check for _sys_siglist[] if cross compiling))])dnl AC_MSG_RESULT($bash_cv_decl_under_sys_siglist) if test $bash_cv_decl_under_sys_siglist = yes; then --- 212,216 ---- #endif], [ char *msg = _sys_siglist[2]; ], bash_cv_decl_under_sys_siglist=yes, bash_cv_decl_under_sys_siglist=no, ! [AC_MSG_ERROR(cannot check for _sys_siglist[] if cross compiling -- defaulting to no)])])dnl AC_MSG_RESULT($bash_cv_decl_under_sys_siglist) if test $bash_cv_decl_under_sys_siglist = yes; then *************** *** 233,238 **** exit(msg == 0); }], ! bash_cv_under_sys_siglist=yes, bash_cv_under_sys_siglist=no, ! AC_MSG_ERROR(cannot check for _sys_siglist[] if cross compiling))])dnl AC_MSG_RESULT($bash_cv_under_sys_siglist) if test $bash_cv_under_sys_siglist = yes; then --- 237,243 ---- exit(msg == 0); }], ! bash_cv_under_sys_siglist=yes, bash_cv_under_sys_siglist=no, ! [AC_MSG_ERROR(cannot check for _sys_siglist[] if cross compiling -- defaulting to no) ! bash_cv_under_sys_siglist=no])]) AC_MSG_RESULT($bash_cv_under_sys_siglist) if test $bash_cv_under_sys_siglist = yes; then *************** *** 259,264 **** exit(msg == 0); }], ! bash_cv_sys_siglist=yes, bash_cv_sys_siglist=no, ! AC_MSG_ERROR(cannot check for sys_siglist if cross compiling))])dnl AC_MSG_RESULT($bash_cv_sys_siglist) if test $bash_cv_sys_siglist = yes; then --- 264,270 ---- exit(msg == 0); }], ! bash_cv_sys_siglist=yes, bash_cv_sys_siglist=no, ! [AC_MSG_ERROR(cannot check for sys_siglist if cross compiling -- defaulting to no) ! bash_cv_sys_siglist=no])]) AC_MSG_RESULT($bash_cv_sys_siglist) if test $bash_cv_sys_siglist = yes; then *************** *** 320,324 **** exit (dir == 0); }], bash_cv_opendir_not_robust=yes,bash_cv_opendir_not_robust=no, ! AC_MSG_ERROR(cannot check opendir if cross compiling))]) AC_MSG_RESULT($bash_cv_opendir_not_robust) if test $bash_cv_opendir_not_robust = yes; then --- 326,332 ---- exit (dir == 0); }], bash_cv_opendir_not_robust=yes,bash_cv_opendir_not_robust=no, ! [AC_MSG_ERROR(cannot check opendir if cross compiling -- defaulting to no) ! bash_cv_opendir_not_robust=no] ! )]) AC_MSG_RESULT($bash_cv_opendir_not_robust) if test $bash_cv_opendir_not_robust = yes; then *************** *** 347,352 **** ]) AC_DEFUN(BASH_FUNC_STRSIGNAL, ! [AC_MSG_CHECKING([for the existance of strsignal]) AC_CACHE_VAL(bash_cv_have_strsignal, [AC_TRY_LINK([#include --- 355,468 ---- ]) + AC_DEFUN(BASH_TYPE_INT32_T, + [ + if test "X$bash_cv_type_int32_t" = "X"; then + _bash_needmsg=yes + else + AC_MSG_CHECKING(which builtin C type is 32 bits wide) + _bash_needmsg= + fi + AC_CACHE_VAL(bash_cv_type_int32_t, + [AC_TRY_RUN([ + main() + { + #if SIZEOF_INT == 4 + exit (0); + #else + # if SIZEOF_LONG == 4 + exit (1); + # else + # error cannot find 32 bit type... + # endif + #endif + }], bash_cv_type_int32_t=int, bash_cv_type_int32_t=long, + [AC_MSG_ERROR(cannot check type sizes if cross-compiling -- defaulting to int) + bash_cv_type_int32_t=int] + )]) + if test "X$_bash_needmsg" = "Xyes"; then + AC_MSG_CHECKING(which builtin C type is 32 bits wide) + fi + AC_MSG_RESULT($bash_cv_type_int32_t); + if test "$bash_cv_type_int32_t" = "int"; then + AC_DEFINE(int32_t, int) + else + AC_DEFINE(int32_t, long) + fi + ]) + + AC_DEFUN(BASH_TYPE_U_INT32_T, + [ + if test "X$bash_cv_type_u_int32_t" = "X"; then + _bash_needmsg=yes + else + AC_MSG_CHECKING(which unsigned builtin C type is 32 bits wide) + _bash_needmsg= + fi + AC_CACHE_VAL(bash_cv_type_u_int32_t, + [AC_TRY_RUN([ + main() + { + #if SIZEOF_INT == 4 + exit (0); + #else + # if SIZEOF_LONG == 4 + exit (1); + # else + # error cannot find 32 bit type... + # endif + #endif + }], bash_cv_type_u_int32_t=int, bash_cv_type_u_int32_t=long, + [AC_MSG_ERROR(cannot check type sizes if cross-compiling -- defaulting to int) + bash_cv_type_u_int32_t=int] + )]) + if test "X$_bash_needmsg" = "Xyes"; then + AC_MSG_CHECKING(which unsigned builtin C type is 32 bits wide) + fi + AC_MSG_RESULT($bash_cv_type_u_int32_t); + if test "$bash_cv_type_u_int32_t" = "int"; then + AC_DEFINE(u_int32_t, unsigned int) + else + AC_DEFINE(u_int32_t, unsigned long) + fi + ]) + + AC_DEFUN(BASH_TYPE_PTRDIFF_T, + [ + if test "X$bash_cv_type_ptrdiff_t" = "X"; then + _bash_needmsg=yes + else + AC_MSG_CHECKING(which builtin C type is correct for ptrdiff_t) + _bash_needmsg= + fi + AC_CACHE_VAL(bash_cv_type_ptrdiff_t, + [AC_TRY_RUN([ + main() + { + #if SIZEOF_CHAR_P == SIZEOF_INT + exit (0); + #else + # if SIZEOF_CHAR_P == SIZEOF_LONG + exit (1); + # else + # error cannot find type for pointer arithmetic... + # endif + #endif + }], bash_cv_type_ptrdiff_t=int, bash_cv_type_ptrdiff_t=long, + [AC_MSG_ERROR(cannot check type sizes if cross-compiling -- defaulting to int) + bash_cv_type_ptrdiff_t=int] + )]) + if test "X$_bash_needmsg" = "Xyes"; then + AC_MSG_CHECKING(which builtin C type is correct for ptrdiff_t) + fi + AC_MSG_RESULT($bash_cv_type_ptrdiff_t); + if test "$bash_cv_type_ptrdiff_t" = "int"; then + AC_DEFINE(ptrdiff_t, int) + else + AC_DEFINE(ptrdiff_t, long) + fi + ]) + AC_DEFUN(BASH_FUNC_STRSIGNAL, ! [AC_MSG_CHECKING([for the existence of strsignal]) AC_CACHE_VAL(bash_cv_have_strsignal, [AC_TRY_LINK([#include *************** *** 367,371 **** #include #include ! ],[ lstat("",(struct stat *)0); ], bash_cv_func_lstat=yes, bash_cv_func_lstat=no)]) if test $bash_cv_func_lstat = yes; then --- 483,487 ---- #include #include ! ],[ lstat(".",(struct stat *)0); ], bash_cv_func_lstat=yes, bash_cv_func_lstat=no)]) if test $bash_cv_func_lstat = yes; then *************** *** 433,437 **** } ], bash_cv_getenv_redef=yes, bash_cv_getenv_redef=no, ! AC_MSG_ERROR(cannot check getenv redefinition if cross compiling))]) AC_MSG_RESULT($bash_cv_getenv_redef) if test $bash_cv_getenv_redef = yes; then --- 549,555 ---- } ], bash_cv_getenv_redef=yes, bash_cv_getenv_redef=no, ! [AC_MSG_ERROR(cannot check getenv redefinition if cross compiling -- defaulting to yes) ! bash_cv_getenv_redef=yes] ! )]) AC_MSG_RESULT($bash_cv_getenv_redef) if test $bash_cv_getenv_redef = yes; then *************** *** 456,461 **** exit(pf == 0); } ! ],bash_cv_printf_declared=yes, bash_cv_printf_declared=no, ! AC_MSG_ERROR(cannot check printf declaration if cross compiling))]) AC_MSG_RESULT($bash_cv_printf_declared) if test $bash_cv_printf_declared = yes; then --- 574,581 ---- exit(pf == 0); } ! ], bash_cv_printf_declared=yes, bash_cv_printf_declared=no, ! [AC_MSG_ERROR(cannot check printf declaration if cross compiling -- defaulting to yes) ! bash_cv_printf_declared=yes] ! )]) AC_MSG_RESULT($bash_cv_printf_declared) if test $bash_cv_printf_declared = yes; then *************** *** 473,478 **** exit (maxfds == -1L); } ! ],bash_cv_ulimit_maxfds=yes, bash_cv_ulimit_maxfds=no, ! AC_MSG_ERROR(cannot check ulimit if cross compiling))]) AC_MSG_RESULT($bash_cv_ulimit_maxfds) if test $bash_cv_ulimit_maxfds = yes; then --- 593,600 ---- exit (maxfds == -1L); } ! ], bash_cv_ulimit_maxfds=yes, bash_cv_ulimit_maxfds=no, ! [AC_MSG_ERROR(cannot check ulimit if cross compiling -- defaulting to no) ! bash_cv_ulimit_maxfds=no] ! )]) AC_MSG_RESULT($bash_cv_ulimit_maxfds) if test $bash_cv_ulimit_maxfds = yes; then *************** *** 498,502 **** fi AC_MSG_RESULT(using $bash_cv_termcap_lib) ! if test $bash_cv_termcap_lib = gnutermcap; then LDFLAGS="$LDFLAGS -L./lib/termcap" TERMCAP_LIB="./lib/termcap/libtermcap.a" --- 620,624 ---- fi AC_MSG_RESULT(using $bash_cv_termcap_lib) ! if test $bash_cv_termcap_lib = gnutermcap && test -z "$prefer_curses"; then LDFLAGS="$LDFLAGS -L./lib/termcap" TERMCAP_LIB="./lib/termcap/libtermcap.a" *************** *** 569,573 **** } ], bash_cv_getcwd_calls_popen=no, bash_cv_getcwd_calls_popen=yes, ! AC_MSG_ERROR(cannot check whether getcwd calls popen if cross compiling))]) AC_MSG_RESULT($bash_cv_getcwd_calls_popen) if test $bash_cv_getcwd_calls_popen = yes; then --- 691,697 ---- } ], bash_cv_getcwd_calls_popen=no, bash_cv_getcwd_calls_popen=yes, ! [AC_MSG_ERROR(cannot check whether getcwd calls popen if cross compiling -- defaulting to no) ! bash_cv_getcwd_calls_popen=no] ! )]) AC_MSG_RESULT($bash_cv_getcwd_calls_popen) if test $bash_cv_getcwd_calls_popen = yes; then *************** *** 691,695 **** } ], bash_cv_must_reinstall_sighandlers=no, bash_cv_must_reinstall_sighandlers=yes, ! AC_MSG_ERROR(cannot check signal handling if cross compiling))]) AC_MSG_RESULT($bash_cv_must_reinstall_sighandlers) if test $bash_cv_must_reinstall_sighandlers = yes; then --- 815,821 ---- } ], bash_cv_must_reinstall_sighandlers=no, bash_cv_must_reinstall_sighandlers=yes, ! [AC_MSG_ERROR(cannot check signal handling if cross compiling -- defaulting to no) ! bash_cv_must_reinstall_sighandlers=no] ! )]) AC_MSG_RESULT($bash_cv_must_reinstall_sighandlers) if test $bash_cv_must_reinstall_sighandlers = yes; then *************** *** 757,763 **** exit(0); ! }],bash_cv_job_control_missing=present, bash_cv_job_control_missing=missing, ! AC_MSG_ERROR(cannot check job control if cross-compiling)) ! ]) AC_MSG_RESULT($bash_cv_job_control_missing) if test $bash_cv_job_control_missing = missing; then --- 883,890 ---- exit(0); ! }], bash_cv_job_control_missing=present, bash_cv_job_control_missing=missing, ! [AC_MSG_ERROR(cannot check job control if cross-compiling -- defaulting to missing) ! bash_cv_job_control_missing=missing] ! )]) AC_MSG_RESULT($bash_cv_job_control_missing) if test $bash_cv_job_control_missing = missing; then *************** *** 801,807 **** unlink ("/tmp/sh-np-autoconf"); exit(0); ! }],bash_cv_sys_named_pipes=present, bash_cv_sys_named_pipes=missing, ! AC_MSG_ERROR(cannot check for named pipes if cross-compiling)) ! ]) AC_MSG_RESULT($bash_cv_sys_named_pipes) if test $bash_cv_sys_named_pipes = missing; then --- 928,935 ---- unlink ("/tmp/sh-np-autoconf"); exit(0); ! }], bash_cv_sys_named_pipes=present, bash_cv_sys_named_pipes=missing, ! [AC_MSG_ERROR(cannot check for named pipes if cross-compiling -- defaulting to missing) ! bash_cv_sys_named_pipes=missing] ! )]) AC_MSG_RESULT($bash_cv_sys_named_pipes) if test $bash_cv_sys_named_pipes = missing; then *************** *** 851,857 **** exit(1); #endif ! }],bash_cv_func_sigsetjmp=present, bash_cv_func_sigsetjmp=missing, ! AC_MSG_ERROR(cannot check for sigsetjmp/siglongjmp if cross-compiling)) ! ]) AC_MSG_RESULT($bash_cv_func_sigsetjmp) if test $bash_cv_func_sigsetjmp = present; then --- 979,986 ---- exit(1); #endif ! }], bash_cv_func_sigsetjmp=present, bash_cv_func_sigsetjmp=missing, ! [AC_MSG_ERROR(cannot check for sigsetjmp/siglongjmp if cross-compiling -- defaulting to missing) ! bash_cv_func_sigsetjmp=missing] ! )]) AC_MSG_RESULT($bash_cv_func_sigsetjmp) if test $bash_cv_func_sigsetjmp = present; then *************** *** 873,884 **** AC_DEFUN(BASH_STRUCT_WINSIZE, ! [AC_MSG_CHECKING(for struct winsize in sys/ioctl.h) ! AC_CACHE_VAL(bash_cv_struct_winsize_in_ioctl, [AC_TRY_COMPILE([#include #include ], [struct winsize x;], ! bash_cv_struct_winsize_in_ioctl=yes,bash_cv_struct_winsize_in_ioctl=no)]) ! AC_MSG_RESULT($bash_cv_struct_winsize_in_ioctl) ! if test $bash_cv_struct_winsize_in_ioctl = yes; then ! AC_DEFINE(STRUCT_WINSIZE_IN_SYS_IOCTL) fi ]) --- 1002,1022 ---- AC_DEFUN(BASH_STRUCT_WINSIZE, ! [AC_MSG_CHECKING(for struct winsize in sys/ioctl.h and termios.h) ! AC_CACHE_VAL(bash_cv_struct_winsize_header, [AC_TRY_COMPILE([#include #include ], [struct winsize x;], ! bash_cv_struct_winsize_header=ioctl_h, ! [AC_TRY_COMPILE([#include ! #include ], [struct winsize x;], ! bash_cv_struct_winsize_header=termios_h, bash_cv_struct_winsize_header=other) ! ])]) ! if test $bash_cv_struct_winsize_header = ioctl_h; then ! AC_MSG_RESULT(sys/ioctl.h) ! AC_DEFINE(STRUCT_WINSIZE_IN_SYS_IOCTL) ! elif test $bash_cv_struct_winsize_header = termios_h; then ! AC_MSG_RESULT(termios.h) ! AC_DEFINE(STRUCT_WINSIZE_IN_TERMIOS) ! else ! AC_MSG_RESULT(not found) fi ]) *************** *** 1052,1065 **** f = RLIMIT_DATA; ], bash_cv_kernel_rlimit=no, ! [AC_TRY_COMPILE([ ! #include ! #define _KERNEL ! #include ! #undef _KERNEL ! ], ! [ int f; f = RLIMIT_DATA; ! ], bash_cv_kernel_rlimit=yes, bash_cv_kernel_rlimit=no)] )]) AC_MSG_RESULT($bash_cv_kernel_rlimit) --- 1190,1203 ---- f = RLIMIT_DATA; ], bash_cv_kernel_rlimit=no, ! [AC_TRY_COMPILE([ ! #include ! #define _KERNEL ! #include ! #undef _KERNEL ! ], ! [ int f; f = RLIMIT_DATA; ! ], bash_cv_kernel_rlimit=yes, bash_cv_kernel_rlimit=no)] )]) AC_MSG_RESULT($bash_cv_kernel_rlimit) *************** *** 1109,1117 **** } ], bash_cv_func_strcoll_broken=yes, bash_cv_func_strcoll_broken=no, ! AC_MSG_ERROR(cannot check strcoll if cross compiling)) ! ]) AC_MSG_RESULT($bash_cv_func_strcoll_broken) if test $bash_cv_func_strcoll_broken = yes; then AC_DEFINE(STRCOLL_BROKEN) fi ]) --- 1247,1344 ---- } ], bash_cv_func_strcoll_broken=yes, bash_cv_func_strcoll_broken=no, ! [AC_MSG_ERROR(cannot check strcoll if cross compiling -- defaulting to no) ! bash_cv_func_strcoll_broken=no] ! )]) AC_MSG_RESULT($bash_cv_func_strcoll_broken) if test $bash_cv_func_strcoll_broken = yes; then AC_DEFINE(STRCOLL_BROKEN) + fi + ]) + + dnl + dnl If available, use support for large files unless the user specified + dnl one of the CPPFLAGS, LDFLAGS, or LIBS variables ( + dnl via GNU patch 2.5) + dnl + AC_DEFUN(BASH_LARGE_FILE_SUPPORT, + [AC_MSG_CHECKING(whether large file support needs explicit enabling) + ac_getconfs='' + ac_result=yes + ac_set='' + ac_shellvars='CPPFLAGS LDFLAGS LIBS' + for ac_shellvar in $ac_shellvars; do + case $ac_shellvar in + CPPFLAGS) ac_lfsvar=LFS_CFLAGS ac_lfs64var=LFS64_CFLAGS ;; + *) ac_lfsvar=LFS_$ac_shellvar ac_lfs64var=LFS64_$ac_shellvar ;; + esac + eval test '"${'$ac_shellvar'+set}"' = set && ac_set=$ac_shellvar + (getconf $ac_lfsvar) >/dev/null 2>&1 || { ac_result=no; break; } + ac_getconf=`getconf $ac_lfsvar` + ac_getconf64=`getconf $ac_lfs64var` + ac_getconfs=$ac_getconfs$ac_getconf\ $ac_getconf64 + eval ac_test_$ac_shellvar="\$ac_getconf\ \$ac_getconf64" + done + case "$ac_result$ac_getconfs" in + yes) ac_result=no ;; + esac + case "$ac_result$ac_set" in + yes?*) ac_result="yes, but $ac_set is already set, so use its settings" + esac + AC_MSG_RESULT($ac_result) + case $ac_result in + yes) + for ac_shellvar in $ac_shellvars; do + eval $ac_shellvar=\$ac_test_$ac_shellvar + done ;; + esac + ]) + + dnl + dnl AC_SYS_RESTARTABLE_SYSCALLS tests only for restarted system calls + dnl after a signal handler has been installed with signal(). Since + dnl Bash uses sigaction() if it is available, we need to check whether + dnl or not a signal handler installed with sigaction and SA_RESTART + dnl causes system calls to be restarted after the signal is caught + dnl + AC_DEFUN(BASH_SYS_RESTARTABLE_SYSCALLS, + [AC_REQUIRE([BASH_SIGNAL_CHECK]) + AC_CACHE_CHECK(for restartable system calls with posix sigaction, + bash_cv_sys_restartable_syscalls, + [AC_TRY_RUN( + [/* Exit 0 (true) if wait returns something other than -1, + i.e. the pid of the child, which means that wait was restarted + after getting the signal. */ + #include + #include + static int caught = 0; + void ucatch (isig) int isig; { caught = 1; } + main () + { + #if !defined (_POSIX_VERSION) || !defined (HAVE_POSIX_SIGNALS) + exit (1); + #else + struct sigaction act, oact; + int i, status; + + act.sa_handler = ucatch; + /* Might want to add SA_RESTART here, but bash's set_signal_handler + does not. */ + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + sigemptyset(&oact.sa_mask); + i = fork (); + /* A possible race condition here, but in practice it never happens. */ + if (i == 0) { sleep (3); kill (getppid (), SIGINT); sleep (3); exit (0); } + sigaction(SIGINT, &act, &oact); + status = wait(&i); + if (status == -1) wait(&i); + exit (status == -1); + #endif + } + ], bash_cv_sys_restartable_syscalls=yes, bash_cv_sys_restartable_syscalls=no, + AC_MSG_ERROR(cannot check restartable syscalls if cross compiling)) + ]) + if test $bash_cv_sys_restartable_syscalls = yes; then + AC_DEFINE(HAVE_RESTARTABLE_SYSCALLS) fi ]) diff -Nrc2 bash-2.01.1/alias.c bash-2.02/alias.c *** bash-2.01.1/alias.c Mon Apr 14 15:58:00 1997 --- bash-2.02/alias.c Tue Mar 17 13:30:34 1998 *************** *** 25,28 **** --- 25,31 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 412,415 **** --- 415,424 ---- { i = skipquotes (string, i); + /* This could be a line that contains a single quote character, + in which case skipquotes () terminates with string[i] == '\0' + (the end of the string). Check for that here. */ + if (string[i] == '\0') + break; + /* Now string[i] is the matching quote character, and the quoted portion of the token has been scanned. */ diff -Nrc2 bash-2.01.1/array.c bash-2.02/array.c *** bash-2.01.1/array.c Wed Feb 26 17:01:36 1997 --- bash-2.02/array.c Fri Nov 21 12:49:40 1997 *************** *** 14,17 **** --- 14,20 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 152,155 **** --- 155,159 ---- #endif + #ifdef INCLUDE_UNUSED ARRAY_ELEMENT * copy_array_element(ae) *************** *** 159,162 **** --- 163,167 ---- : (ARRAY_ELEMENT *) NULL); } + #endif /* *************** *** 249,252 **** --- 254,258 ---- } + #ifdef TEST_ARRAY /* * Walk the array, calling FUNC once for each element, with the array *************** *** 265,268 **** --- 271,275 ---- (*func)(ae); } + #endif /* diff -Nrc2 bash-2.01.1/bashhist.c bash-2.02/bashhist.c *** bash-2.01.1/bashhist.c Wed May 14 14:08:52 1997 --- bash-2.02/bashhist.c Fri Feb 27 12:34:33 1998 *************** *** 24,27 **** --- 24,30 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 175,178 **** --- 178,185 ---- member ('}', string + i + 1)) return (1); + #if defined (EXTENDED_GLOB) + else if (extended_glob && i > 1 && string[i+1] == '(' && member (')', string + i + 2)) + return (1); + #endif else return (0); *************** *** 400,404 **** { if (expanded < 0) ! internal_error (history_value); #if defined (READLINE) else if (hist_verify == 0) --- 407,411 ---- { if (expanded < 0) ! internal_error ("%s", history_value); #if defined (READLINE) else if (hist_verify == 0) *************** *** 462,468 **** /* Don't use the value of history_control to affect the second ! and subsequent lines of a multi-line command when ! command_oriented_history is enabled. */ if (command_oriented_history && current_command_line_count > 1) { bash_add_history (line); --- 469,479 ---- /* Don't use the value of history_control to affect the second ! and subsequent lines of a multi-line command (old code did ! this only when command_oriented_history is enabled). */ ! #if 0 if (command_oriented_history && current_command_line_count > 1) + #else + if (current_command_line_count > 1) + #endif { bash_add_history (line); *************** *** 694,698 **** npat = histignore.ignores[i].val; ! match = fnmatch (npat, line, 0) != FNM_NOMATCH; if (histignore.ignores[i].flags & HIGN_EXPAND) --- 705,709 ---- npat = histignore.ignores[i].val; ! match = fnmatch (npat, line, FNMATCH_EXTFLAG) != FNM_NOMATCH; if (histignore.ignores[i].flags & HIGN_EXPAND) diff -Nrc2 bash-2.01.1/bashline.c bash-2.02/bashline.c *** bash-2.01.1/bashline.c Fri Aug 29 13:54:04 1997 --- bash-2.02/bashline.c Tue Feb 17 12:09:43 1998 *************** *** 37,40 **** --- 37,41 ---- #include "bashline.h" #include "execute_cmd.h" + #include "findcmd.h" #include "pathexp.h" #include "builtins/common.h" *************** *** 56,65 **** static void shell_expand_line (); static void display_shell_version (), operate_and_get_next (); ! static void history_expand_line (), bash_ignore_filenames (); #ifdef ALIAS ! static void alias_expand_line (); #endif - static void history_and_alias_expand_line (); - static void cleanup_expansion_error (), set_up_new_line (); /* Helper functions for Readline. */ --- 57,73 ---- static void shell_expand_line (); static void display_shell_version (), operate_and_get_next (); ! static void bash_ignore_filenames (); ! static void cleanup_expansion_error (), set_up_new_line (); ! ! #if defined (BANG_HISTORY) ! static int history_expand_line (); ! static int tcsh_magic_space (); ! #endif /* BANG_HISTORY */ #ifdef ALIAS ! static int alias_expand_line (); ! #endif ! #if defined (BANG_HISTORY) && defined (ALIAS) ! static int history_and_alias_expand_line (); #endif /* Helper functions for Readline. */ *************** *** 197,203 **** --- 205,215 ---- /* Bind up our special shell functions. */ + #ifdef BANG_HISTORY rl_add_defun ("history-expand-line", (Function *)history_expand_line, -1); rl_bind_key_in_map ('^', (Function *)history_expand_line, emacs_meta_keymap); + rl_add_defun ("magic-space", (Function *)tcsh_magic_space, -1); + #endif + #ifdef ALIAS rl_add_defun ("alias-expand-line", (Function *)alias_expand_line, -1); *************** *** 1031,1035 **** if (*text == '`') text++; ! else if (*text == '$' && text[1] == '(') text += 2; start_len = text - orig_start; --- 1043,1047 ---- if (*text == '`') text++; ! else if (*text == '$' && text[1] == '(') /* ) */ text += 2; start_len = text - orig_start; *************** *** 1174,1178 **** } ! /* History and alias expand the line. */ static char * history_expand_line_internal (line) --- 1186,1195 ---- } ! /* Functions to perform history and alias expansions on the current line. */ ! ! #if defined (BANG_HISTORY) ! /* Perform history expansion on the current line. If no history expansion ! is done, pre_process_line() returns what it was passed, so we need to ! allocate a new line here. */ static char * history_expand_line_internal (line) *************** *** 1184,1203 **** return (new_line == line) ? savestring (line) : new_line; } - - #if defined (ALIAS) - /* Expand aliases in the current readline line. */ - static void - alias_expand_line (ignore) - int ignore; - { - char *new_line; - - new_line = alias_expand (rl_line_buffer); - - if (new_line) - set_up_new_line (new_line); - else - cleanup_expansion_error (); - } #endif --- 1201,1204 ---- *************** *** 1260,1265 **** } /* History expand the line. */ ! static void history_expand_line (ignore) int ignore; --- 1261,1290 ---- } + #if defined (ALIAS) + /* Expand aliases in the current readline line. */ + static int + alias_expand_line (ignore) + int ignore; + { + char *new_line; + + new_line = alias_expand (rl_line_buffer); + + if (new_line) + { + set_up_new_line (new_line); + return (0); + } + else + { + cleanup_expansion_error (); + return (1); + } + } + #endif + + #if defined (BANG_HISTORY) /* History expand the line. */ ! static int history_expand_line (ignore) int ignore; *************** *** 1270,1280 **** if (new_line) ! set_up_new_line (new_line); else ! cleanup_expansion_error (); } /* History and alias expand the line. */ ! static void history_and_alias_expand_line (ignore) int ignore; --- 1295,1327 ---- if (new_line) ! { ! set_up_new_line (new_line); ! return (0); ! } else ! { ! cleanup_expansion_error (); ! return (1); ! } ! } ! ! /* Expand history substitutions in the current line and then insert a ! space wherever set_up_new_line decided to put rl_point. */ ! static int ! tcsh_magic_space (ignore) ! int ignore; ! { ! if (history_expand_line (ignore) == 0) ! { ! rl_insert (1, ' '); ! return (0); ! } ! else ! return (1); } + #endif /* History and alias expand the line. */ ! static int history_and_alias_expand_line (ignore) int ignore; *************** *** 1298,1308 **** if (new_line) ! set_up_new_line (new_line); else ! cleanup_expansion_error (); } /* History and alias expand the line, then perform the shell word ! expansions by calling expand_string. */ static void shell_expand_line (ignore) --- 1345,1363 ---- if (new_line) ! { ! set_up_new_line (new_line); ! return (0); ! } else ! { ! cleanup_expansion_error (); ! return (1); ! } } /* History and alias expand the line, then perform the shell word ! expansions by calling expand_string. This can't use set_up_new_line() ! because we want the variable expansions as a separate undo'able ! set of operations. */ static void shell_expand_line (ignore) *************** *** 1370,1373 **** --- 1425,1432 ---- } + /* Define NO_FORCE_FIGNORE if you want to match filenames that would + otherwise be ignored if they are the only possible matches. */ + /* #define NO_FORCE_FIGNORE */ + /* If FIGNORE is set, then don't match files with the given suffixes when completing filenames. If only one of the possibilities has an acceptable *************** *** 1394,1397 **** --- 1453,1460 ---- char **newnames; int idx, nidx; + #ifdef NO_FORCE_FIGNORE + char **oldnames; + int oidx; + #endif /* If there is only one completion, see if it is acceptable. If it is *************** *** 1401,1404 **** --- 1464,1468 ---- if (names[1] == (char *)0) { + #ifndef NO_FORCE_FIGNORE if ((*name_func) (names[0]) == 0) { *************** *** 1406,1409 **** --- 1470,1474 ---- names[0] = (char *)NULL; } + #endif return; } *************** *** 1414,1417 **** --- 1479,1486 ---- ; newnames = (char **)xmalloc ((nidx + 1) * (sizeof (char *))); + #ifdef NO_FORCE_FIGNORE + oldnames = (char **)xmalloc ((nidx - 1) * (sizeof (char *))); + oidx = 0; + #endif newnames[0] = names[0]; *************** *** 1421,1425 **** --- 1490,1498 ---- newnames[nidx++] = names[idx]; else + #ifndef NO_FORCE_FIGNORE free (names[idx]); + #else + oldnames[oidx++] = names[idx]; + #endif } *************** *** 1429,1437 **** --- 1502,1520 ---- if (nidx == 1) { + #ifndef NO_FORCE_FIGNORE free (names[0]); names[0] = (char *)NULL; + #else + free (oldnames); + #endif free (newnames); return; } + + #ifdef NO_FORCE_FIGNORE + while (oidx) + free (oldnames[--oidx]); + free (oldnames); + #endif /* If only one is acceptable, copy it to names[0] and return. */ diff -Nrc2 bash-2.01.1/bracecomp.c bash-2.02/bracecomp.c *** bash-2.01.1/bracecomp.c Mon Aug 18 12:32:52 1997 --- bash-2.02/bracecomp.c Tue Jul 22 13:39:03 1997 *************** *** 29,32 **** --- 29,35 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/braces.c bash-2.02/braces.c *** bash-2.01.1/braces.c Wed Feb 19 11:12:08 1997 --- bash-2.02/braces.c Fri Jul 18 16:44:42 1997 *************** *** 26,29 **** --- 26,32 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/builtins/Makefile.in bash-2.02/builtins/Makefile.in *** bash-2.01.1/builtins/Makefile.in Mon Sep 22 16:22:27 1997 --- bash-2.02/builtins/Makefile.in Wed Oct 15 11:28:57 1997 *************** *** 4,7 **** --- 4,8 ---- RANLIB = @RANLIB@ CC = @CC@ + CC_FOR_BUILD = @CC_FOR_BUILD@ AR = @AR@ RM = rm -f *************** *** 12,17 **** topdir = @top_srcdir@ includedir = @includedir@ ! PROFILE_FLAGS = CFLAGS = @CFLAGS@ LOCAL_CFLAGS = @LOCAL_CFLAGS@ --- 13,19 ---- topdir = @top_srcdir@ includedir = @includedir@ + BUILD_DIR = @BUILD_DIR@ ! PROFILE_FLAGS = @PROFILE_FLAGS@ CFLAGS = @CFLAGS@ LOCAL_CFLAGS = @LOCAL_CFLAGS@ *************** *** 19,22 **** --- 21,26 ---- DEFS = @DEFS@ LOCAL_DEFS = @LOCAL_DEFS@ + LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS) + LOCAL_LDFLAGS = @LOCAL_LDFLAGS@ LIBS = @LIBS@ *************** *** 63,67 **** $(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \ $(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \ ! $(srcdir)/reserved.def $(srcdir)/pushd.def $(srcdir)/shopt.def STATIC_SOURCE = common.c evalstring.c evalfile.c getopt.c bashgetopt.c \ --- 67,72 ---- $(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \ $(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \ ! $(srcdir)/reserved.def $(srcdir)/pushd.def $(srcdir)/shopt.def \ ! $(srcdir)/printf.def STATIC_SOURCE = common.c evalstring.c evalfile.c getopt.c bashgetopt.c \ *************** *** 75,79 **** pushd.o read.o return.o set.o setattr.o shift.o source.o \ suspend.o test.o times.o trap.o type.o ulimit.o umask.o \ ! wait.o getopts.o shopt.o getopt.o bashgetopt.o CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h --- 80,84 ---- pushd.o read.o return.o set.o setattr.o shift.o source.o \ suspend.o test.o times.o trap.o type.o ulimit.o umask.o \ ! wait.o getopts.o shopt.o printf.o getopt.o bashgetopt.o CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h *************** *** 81,85 **** all: $(MKBUILTINS) libbuiltins.a ! libbuiltins.a: $(MKBUILTINS) $(OFILES) $(RM) $@ $(AR) cr $@ $(OFILES) --- 86,90 ---- all: $(MKBUILTINS) libbuiltins.a ! libbuiltins.a: $(MKBUILTINS) $(OFILES) builtins.o $(RM) $@ $(AR) cr $@ $(OFILES) *************** *** 87,105 **** builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC) ! $(RM) builtext.h builtins.c ./$(MKBUILTINS) -externfile builtext.h -structfile builtins.c \ ! -noproduction $(DIRECTDEFINE) $(DEFSRC) ! mkbuiltins: $(srcdir)/mkbuiltins.c ../config.h ! $(CC) $(CCFLAGS) -o $(MKBUILTINS) $(srcdir)/mkbuiltins.c $(LIBS) # rules for deficient makes, like SunOS common.o: common.c bashgetopt.o: bashgetopt.c getopt.o: getopt.c ! evalstring.o: evalstring.c ! evalfile.o: evalfile.c - ulimit.o: ulimit.def ulimit.o: pipesize.h --- 92,127 ---- builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC) ! @-if test -f builtins.c; then mv -f builtins.c old-builtins.c; fi ! @-if test -f builtext.h; then mv -f builtext.h old-builtext.h; fi ./$(MKBUILTINS) -externfile builtext.h -structfile builtins.c \ ! -noproduction $(DIRECTDEFINE) $(DEFSRC) ! @-if cmp -s old-builtext.h builtext.h; then \ ! mv old-builtext.h builtext.h; \ ! else \ ! $(RM) old-builtext.h; \ ! fi ! @-if cmp -s old-builtins.c builtins.c; then \ ! mv old-builtins.c builtins.c; \ ! else \ ! $(RM) old-builtins.c; \ ! fi ! mkbuiltins.o: ../config.h ! mkbuiltins.o: mkbuiltins.c ! $(RM) $@ ! $(CC_FOR_BUILD) -c $(CCFLAGS) $< ! ! mkbuiltins: mkbuiltins.o ! $(CC_FOR_BUILD) $(LDFLAGS) -o $(MKBUILTINS) mkbuiltins.o $(LIBS) # rules for deficient makes, like SunOS + mkbuiltins.o: mkbuiltins.c + builtins.o: builtins.c common.o: common.c bashgetopt.o: bashgetopt.c getopt.o: getopt.c ! evalstring.o: evalstring.c ! evalfile.o: evalfile.c ulimit.o: pipesize.h *************** *** 108,112 **** psize.aux: psize.c ! $(CC) $(CCFLAGS) -o $@ $(srcdir)/psize.c documentation: builtins.texi --- 130,134 ---- psize.aux: psize.c ! $(CC_FOR_BUILD) $(CCFLAGS) -o $@ $(srcdir)/psize.c documentation: builtins.texi *************** *** 147,150 **** --- 169,173 ---- kill.o: kill.def let.o: let.def + printf.o: printf.def pushd.o: pushd.def read.o: read.def *************** *** 160,163 **** --- 183,187 ---- trap.o: trap.def type.o: type.def + ulimit.o: ulimit.def umask.o: umask.def wait.o: wait.def *************** *** 275,278 **** --- 299,303 ---- exec.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h exec.o: $(srcdir)/common.h $(topdir)/execute_cmd.h $(topdir)/maxpath.h + exec.o: $(topdir)/findcmd.h exit.o: $(topdir)/bashtypes.h exit.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h *************** *** 303,307 **** getopts.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h hash.o: $(topdir)/builtins.h $(topdir)/command.h $(topdir)/quit.h ! hash.o: $(topdir)/execute_cmd.h $(topdir)/hashlib.h hash.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h hash.o: $(topdir)/error.h $(topdir)/general.h --- 328,332 ---- getopts.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h hash.o: $(topdir)/builtins.h $(topdir)/command.h $(topdir)/quit.h ! hash.o: $(topdir)/findcmd.h $(topdir)/hashlib.h hash.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h hash.o: $(topdir)/error.h $(topdir)/general.h *************** *** 340,343 **** --- 365,374 ---- let.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h let.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h + printf.o: ../config.h $(topdir)/memalloc.h $(topdir)/bashjmp.h + printf.o: $(topdir)/command.h $(topdir)/error.h $(topdir)/general.h + printf.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h + printf.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/sig.h + printf.o: $(topdir)/pathnames.h $(topdir)/shell.h $(topdir)/unwind_prot.h + printf.o: $(topdir)/variables.h $(topdir)/stdc.h $(srcdir)/bashgetopt.h pushd.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h pushd.o: $(topdir)/error.h $(topdir)/general.h *************** *** 373,377 **** shift.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h source.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h ! source.o: $(topdir)/error.h $(topdir)/general.h source.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h source.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h --- 404,408 ---- shift.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h source.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h ! source.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/findcmd.h source.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h source.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h *************** *** 387,390 **** --- 418,422 ---- test.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h test.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h + test.o: $(topdir)/test.h times.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h times.o: $(topdir)/error.h $(topdir)/general.h *************** *** 397,401 **** trap.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h trap.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h ! trap.o: $(topdir)/execute_cmd.h type.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h type.o: $(topdir)/error.h $(topdir)/general.h --- 429,433 ---- trap.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h trap.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h ! trap.o: $(topdir)/findcmd.h type.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h type.o: $(topdir)/error.h $(topdir)/general.h diff -Nrc2 bash-2.01.1/builtins/alias.def bash-2.02/builtins/alias.def *** bash-2.01.1/builtins/alias.def Wed Feb 5 11:41:59 1997 --- bash-2.02/builtins/alias.def Mon Nov 17 12:17:09 1997 *************** *** 38,41 **** --- 38,44 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 81,90 **** { if (aliases == 0) ! return (EXECUTION_FAILURE); alias_list = all_aliases (); if (alias_list == 0) ! return (EXECUTION_FAILURE); for (offset = 0; alias_list[offset]; offset++) --- 84,93 ---- { if (aliases == 0) ! return (EXECUTION_SUCCESS); alias_list = all_aliases (); if (alias_list == 0) ! return (EXECUTION_SUCCESS); for (offset = 0; alias_list[offset]; offset++) *************** *** 119,124 **** else { ! if (interactive) ! builtin_error ("`%s' not found", name); any_failed++; } --- 122,126 ---- else { ! builtin_error ("`%s' not found", name); any_failed++; } *************** *** 180,186 **** else { ! if (interactive) ! builtin_error ("`%s': not an alias", list->word->word); ! aflag++; } --- 182,186 ---- else { ! builtin_error ("`%s': not an alias", list->word->word); aflag++; } diff -Nrc2 bash-2.01.1/builtins/bashgetopt.c bash-2.02/builtins/bashgetopt.c *** bash-2.01.1/builtins/bashgetopt.c Fri Sep 13 11:29:30 1996 --- bash-2.02/builtins/bashgetopt.c Fri Nov 14 13:30:26 1997 *************** *** 162,165 **** --- 162,166 ---- } + #ifdef INCLUDE_UNUSED void report_bad_option () *************** *** 172,173 **** --- 173,175 ---- bad_option (s); } + #endif diff -Nrc2 bash-2.01.1/builtins/bind.def bash-2.02/builtins/bind.def *** bash-2.01.1/builtins/bind.def Thu Sep 12 14:23:00 1996 --- bash-2.02/builtins/bind.def Thu Sep 4 13:38:57 1997 *************** *** 27,31 **** $DEPENDS_ON READLINE $FUNCTION bind_builtin ! $SHORT_DOC bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-r keyseq] [keyseq:readline-function] Bind a key sequence to a Readline function, or to a macro. The syntax is equivalent to that found in ~/.inputrc, but must be --- 27,31 ---- $DEPENDS_ON READLINE $FUNCTION bind_builtin ! $SHORT_DOC bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [keyseq:readline-function] Bind a key sequence to a Readline function, or to a macro. The syntax is equivalent to that found in ~/.inputrc, but must be *************** *** 43,46 **** --- 43,47 ---- -f filename Read key bindings from FILENAME. -q function-name Query about which keys invoke the named function. + -u function-name Unbind all keys which are bound to the named function. -V List variable names and values -v List variable names and values in a form that can *************** *** 54,57 **** --- 55,61 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 72,75 **** --- 76,80 ---- static int query_bindings (); + static int unbind_command (); extern int no_line_editing; *************** *** 77,91 **** #define BIND_RETURN(x) do { return_code = x; goto bind_exit; } while (0) ! #define LFLAG 0x01 ! #define PFLAG 0x02 ! #define FFLAG 0x04 ! #define VFLAG 0x08 ! #define QFLAG 0x10 ! #define MFLAG 0x20 ! #define RFLAG 0x40 ! #define PPFLAG 0x80 ! #define VVFLAG 0x100 ! #define SFLAG 0x200 ! #define SSFLAG 0x400 int --- 82,97 ---- #define BIND_RETURN(x) do { return_code = x; goto bind_exit; } while (0) ! #define LFLAG 0x0001 ! #define PFLAG 0x0002 ! #define FFLAG 0x0004 ! #define VFLAG 0x0008 ! #define QFLAG 0x0010 ! #define MFLAG 0x0020 ! #define RFLAG 0x0040 ! #define PPFLAG 0x0080 ! #define VVFLAG 0x0100 ! #define SFLAG 0x0200 ! #define SSFLAG 0x0400 ! #define UFLAG 0x0800 int *************** *** 97,101 **** Keymap kmap, saved_keymap; int flags, opt; ! char *initfile, *map_name, *fun_name, *remove_seq; if (no_line_editing) --- 103,107 ---- Keymap kmap, saved_keymap; int flags, opt; ! char *initfile, *map_name, *fun_name, *unbind_name, *remove_seq; if (no_line_editing) *************** *** 104,108 **** kmap = saved_keymap = (Keymap) NULL; flags = 0; ! initfile = map_name = fun_name = remove_seq = (char *)NULL; return_code = EXECUTION_SUCCESS; --- 110,114 ---- kmap = saved_keymap = (Keymap) NULL; flags = 0; ! initfile = map_name = fun_name = unbind_name = remove_seq = (char *)NULL; return_code = EXECUTION_SUCCESS; *************** *** 117,121 **** reset_internal_getopt (); ! while ((opt = internal_getopt (list, "lvpVPsSf:q:m:r:")) != EOF) { switch (opt) --- 123,127 ---- reset_internal_getopt (); ! while ((opt = internal_getopt (list, "lvpVPsSf:q:u:m:r:")) != EOF) { switch (opt) *************** *** 142,145 **** --- 148,155 ---- fun_name = list_optarg; break; + case 'u': + flags |= UFLAG; + unbind_name = list_optarg; + break; case 'r': flags |= RFLAG; *************** *** 221,224 **** --- 231,237 ---- return_code = query_bindings (fun_name); + if ((flags & UFLAG) && unbind_name) + return_code = unbind_command (unbind_name); + if ((flags & RFLAG) && remove_seq) { *************** *** 254,258 **** function = rl_named_function (name); ! if (!function) { builtin_error ("unknown function name `%s'", name); --- 267,271 ---- function = rl_named_function (name); ! if (function == 0) { builtin_error ("unknown function name `%s'", name); *************** *** 274,277 **** --- 287,307 ---- printf ("...\n"); free_array (keyseqs); + return EXECUTION_SUCCESS; + } + + static int + unbind_command (name) + char *name; + { + Function *function; + + function = rl_named_function (name); + if (function == 0) + { + builtin_error ("unknown function name `%s'", name); + return EXECUTION_FAILURE; + } + + rl_unbind_function_in_map (function, rl_get_keymap ()); return EXECUTION_SUCCESS; } diff -Nrc2 bash-2.01.1/builtins/break.def bash-2.02/builtins/break.def *** bash-2.01.1/builtins/break.def Mon Mar 3 12:46:46 1997 --- bash-2.02/builtins/break.def Fri Jul 18 16:53:51 1997 *************** *** 31,35 **** #if defined (HAVE_UNISTD_H) ! #include #endif --- 31,38 ---- #if defined (HAVE_UNISTD_H) ! # ifdef _MINIX ! # include ! # endif ! # include #endif diff -Nrc2 bash-2.01.1/builtins/builtin.def bash-2.02/builtins/builtin.def *** bash-2.01.1/builtins/builtin.def Mon Mar 27 14:38:32 1995 --- bash-2.02/builtins/builtin.def Fri Jul 18 16:53:59 1997 *************** *** 32,35 **** --- 32,38 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/builtins/cd.def bash-2.02/builtins/cd.def *** bash-2.01.1/builtins/cd.def Fri Apr 11 12:55:47 1997 --- bash-2.02/builtins/cd.def Tue Mar 17 13:50:51 1998 *************** *** 24,27 **** --- 24,30 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 30,34 **** --- 33,39 ---- #include "../posixdir.h" #include "../posixstat.h" + #ifndef _MINIX #include + #endif #include *************** *** 67,75 **** $SHORT_DOC cd [-PL] [dir] Change the current directory to DIR. The variable $HOME is the ! default DIR. The variable $CDPATH defines the search path for the directory containing DIR. Alternative directory names in CDPATH are separated by a colon (:). A null directory name is the same as the current directory, i.e. `.'. If DIR begins with a slash (/), ! then $CDPATH is not used. If the directory is not found, and the shell option `cdable_vars' is set, then try the word as a variable name. If that variable has a value, then cd to the value of that --- 72,80 ---- $SHORT_DOC cd [-PL] [dir] Change the current directory to DIR. The variable $HOME is the ! default DIR. The variable CDPATH defines the search path for the directory containing DIR. Alternative directory names in CDPATH are separated by a colon (:). A null directory name is the same as the current directory, i.e. `.'. If DIR begins with a slash (/), ! then CDPATH is not used. If the directory is not found, and the shell option `cdable_vars' is set, then try the word as a variable name. If that variable has a value, then cd to the value of that *************** *** 147,153 **** if (old_anm == 0 && array_needs_making && exported_p (tvar)) { ! pwdvar = xmalloc (strlen (dirname) + 5); /* 5 = "PWD" + '=' + '\0' */ strcpy (pwdvar, "PWD="); ! strcpy (pwdvar + 4, dirname); add_or_supercede_exported_var (pwdvar, 0); array_needs_making = 0; --- 152,159 ---- if (old_anm == 0 && array_needs_making && exported_p (tvar)) { ! pwdvar = xmalloc (STRLEN (dirname) + 5); /* 5 = "PWD" + '=' + '\0' */ strcpy (pwdvar, "PWD="); ! if (dirname) ! strcpy (pwdvar + 4, dirname); add_or_supercede_exported_var (pwdvar, 0); array_needs_making = 0; *************** *** 227,230 **** --- 233,238 ---- return (EXECUTION_FAILURE); } + if (interactive) + printf ("%s\n", dirname); } else *************** *** 238,241 **** --- 246,251 ---- while ((path = extract_colon_unit (cdpath, &path_index))) { + /* OPT is 1 if the path element is non-empty */ + opt = path[0] != '\0'; temp = mkpath (path, dirname, 1); free (path); *************** *** 249,262 **** if (change_to_directory (temp, no_symlinks)) { ! if (temp[0] != '.' || temp[1] != '/') ! printf ("%s\n", temp); free (temp); /* Posix.2 says that after using CDPATH, the resultant value of $PWD will not contain symlinks. */ ! return (bindpwd (posixly_correct)); } else free (temp); } } --- 259,285 ---- if (change_to_directory (temp, no_symlinks)) { ! /* POSIX.2 says that if a nonempty directory from CDPATH ! is used to find the directory to change to, the new ! directory name is echoed to stdout, whether or not ! the shell is interactive. */ ! if (opt) ! printf ("%s\n", the_current_working_directory); free (temp); /* Posix.2 says that after using CDPATH, the resultant value of $PWD will not contain symlinks. */ ! return (bindpwd (posixly_correct || no_symlinks)); } else free (temp); + } + + /* POSIX.2 says that if `.' does not appear in $CDPATH, we don't + try the current directory, so we just punt now with an error + message if POSIXLY_CORRECT is non-zero. */ + if (posixly_correct) + { + builtin_error ("%s: %s", dirname, strerror (ENOENT)); + return (EXECUTION_FAILURE); } } diff -Nrc2 bash-2.01.1/builtins/command.def bash-2.02/builtins/command.def *** bash-2.01.1/builtins/command.def Fri Feb 28 12:59:26 1997 --- bash-2.02/builtins/command.def Fri Feb 27 12:01:35 1998 *************** *** 36,39 **** --- 36,42 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 180,188 **** len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0); ! p = xmalloc ((int)len + 2); ! *p = '\0'; ! confstr (_CS_PATH, p, len); ! return (p); ! #else /* !_CSPATH || !HAVE_CONFSTR */ # if defined (CS_PATH) return (savestring (CS_PATH)); --- 183,196 ---- len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0); ! if (len > 0) ! { ! p = xmalloc ((int)len + 2); ! *p = '\0'; ! confstr (_CS_PATH, p, len); ! return (p); ! } ! else ! return (savestring (STANDARD_UTILS_PATH)); ! #else /* !_CS_PATH || !HAVE_CONFSTR */ # if defined (CS_PATH) return (savestring (CS_PATH)); diff -Nrc2 bash-2.01.1/builtins/common.c bash-2.02/builtins/common.c *** bash-2.01.1/builtins/common.c Tue Apr 1 12:24:44 1997 --- bash-2.02/builtins/common.c Wed Feb 4 14:56:31 1998 *************** *** 20,23 **** --- 20,26 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 28,31 **** --- 31,36 ---- #include + #include + #if defined (PREFER_STDARG) # include *************** *** 55,58 **** --- 60,67 ---- #endif + #if !defined (errno) + extern int errno; + #endif /* !errno */ + extern int no_symbolic_links, interactive, interactive_shell; extern int indirection_level, startup_state, subshell_environment; *************** *** 400,408 **** if (directory == 0) { ! fprintf (stderr, "%s: could not get current directory: %s\n", (for_whom && *for_whom) ? for_whom : get_name_for_error (), the_current_working_directory[0] ? the_current_working_directory ! : bash_getcwd_errstr); free (the_current_working_directory); --- 409,418 ---- if (directory == 0) { ! fprintf (stderr, "%s: could not get current directory: %s: %s\n", (for_whom && *for_whom) ? for_whom : get_name_for_error (), the_current_working_directory[0] ? the_current_working_directory ! : bash_getcwd_errstr, ! strerror (errno)); free (the_current_working_directory); *************** *** 692,697 **** --- 702,712 ---- initialize_shell_builtins () { + #ifdef _MINIX + qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin), + (int (*)(const void *, const void *))shell_builtin_compare); + #else qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin), shell_builtin_compare); + #endif } *************** *** 792,799 **** *r++ = c; break; - case '#': /* comment char */ #if 0 case '~': /* tilde expansion */ #endif if (s == string) *r++ = '\\'; --- 807,818 ---- *r++ = c; break; #if 0 case '~': /* tilde expansion */ + if (s == string || s[-1] == '=' || s[-1] == ':') + *r++ = '\\'; + *r++ = c; + break; #endif + case '#': /* comment char */ if (s == string) *r++ = '\\'; *************** *** 828,831 **** --- 847,853 ---- case '$': case '`': /* expansion chars */ return (1); + case '~': /* tilde expansion */ + if (s == string || s[-1] == '=' || s[-1] == ':') + return (1); case '#': if (s == string) /* comment char */ diff -Nrc2 bash-2.01.1/builtins/common.h bash-2.02/builtins/common.h *** bash-2.01.1/builtins/common.h Wed May 14 12:56:35 1997 --- bash-2.02/builtins/common.h Fri Oct 3 16:53:05 1997 *************** *** 31,105 **** #define SEVAL_NOHIST 0x04 extern void builtin_error __P((const char *, ...)); ! extern void builtin_usage (); ! extern void bad_option (); ! extern char **make_builtin_argv (); ! ! extern int get_numeric_arg (); ! extern void remember_args (); ! extern void no_args (); ! extern int no_options (); ! ! extern int read_octal (); ! ! extern void push_context (), pop_context (); ! extern void push_dollar_vars (), pop_dollar_vars (); ! extern void dispose_saved_dollar_vars (); ! extern int dollar_vars_changed (); ! extern void set_dollar_vars_unchanged (), set_dollar_vars_changed (); /* Keeps track of the current working directory. */ extern char *the_current_working_directory; ! extern char *get_working_directory (); ! extern void set_working_directory (); #if defined (JOB_CONTROL) ! extern int get_job_spec (); #endif ! ! extern int display_signal_list (); /* It's OK to declare a function as returning a Function * without providing a definition of what a `Function' is. */ ! extern struct builtin *builtin_address_internal (); ! extern Function *find_shell_builtin (); ! extern Function *builtin_address (); ! extern Function *find_special_builtin (); ! ! extern void initialize_shell_builtins (); ! ! extern char *single_quote (); ! extern char *double_quote (); ! extern char *backslash_quote (); ! extern int contains_shell_metas (); /* Functions from set.def */ ! extern void initialize_shell_options (); ! extern void list_minus_o_opts (); ! extern int set_minus_o_option (); ! extern int minus_o_option_value (); ! extern void reset_shell_options (); /* Functions from shopt.def */ ! extern void reset_shopt_options (); /* Functions from type.def */ ! extern int describe_command (); /* Functions from setattr.def */ ! extern int set_or_show_attributes (); ! extern int show_var_attributes (); ! extern int show_name_attributes (); ! extern void set_var_attribute (); /* Functions from pushd.def */ ! extern char *get_dirstack_element (); ! extern void set_dirstack_element (); ! extern WORD_LIST *get_directory_stack (); /* Functions from evalstring.c */ ! extern int parse_and_execute (); ! extern void parse_and_execute_cleanup (); /* Functions from evalfile.c */ --- 31,107 ---- #define SEVAL_NOHIST 0x04 + /* Functions from common.c */ extern void builtin_error __P((const char *, ...)); ! extern void builtin_usage __P((void)); ! extern void no_args __P((WORD_LIST *)); ! extern void bad_option __P((char *)); ! extern int no_options __P((WORD_LIST *)); ! ! extern char **make_builtin_argv __P((WORD_LIST *, int *)); ! extern void remember_args __P((WORD_LIST *, int)); ! ! extern void push_context __P((void)); ! extern void pop_context __P((void)); ! extern void push_dollar_vars __P((void)); ! extern void pop_dollar_vars __P((void)); ! extern void dispose_saved_dollar_vars __P((void)); ! extern int dollar_vars_changed __P((void)); ! extern void set_dollar_vars_unchanged __P((void)); ! extern void set_dollar_vars_changed __P((void)); ! extern int get_numeric_arg __P((WORD_LIST *, int)); ! extern int read_octal __P((char *)); /* Keeps track of the current working directory. */ extern char *the_current_working_directory; ! extern char *get_working_directory __P((char *)); ! extern void set_working_directory __P((char *)); #if defined (JOB_CONTROL) ! extern int get_job_spec __P((WORD_LIST *)); #endif ! extern int display_signal_list __P((WORD_LIST *, int)); /* It's OK to declare a function as returning a Function * without providing a definition of what a `Function' is. */ ! extern struct builtin *builtin_address_internal __P((char *, int)); ! extern Function *find_shell_builtin __P((char *)); ! extern Function *builtin_address __P((char *)); ! extern Function *find_special_builtin __P((char *)); ! extern void initialize_shell_builtins __P((void)); ! ! extern char *single_quote __P((char *)); ! extern char *double_quote __P((char *)); ! extern char *backslash_quote __P((char *)); ! extern int contains_shell_metas __P((char *)); /* Functions from set.def */ ! extern void initialize_shell_options __P((int)); ! extern void list_minus_o_opts __P((int, int)); ! extern int set_minus_o_option __P((int, char *)); ! extern int minus_o_option_value __P((char *)); ! extern void reset_shell_options __P((void)); /* Functions from shopt.def */ ! extern void reset_shopt_options __P((void)); /* Functions from type.def */ ! extern int describe_command __P((char *, int, int)); /* Functions from setattr.def */ ! extern int set_or_show_attributes __P((WORD_LIST *, int, int)); ! extern int show_var_attributes __P((SHELL_VAR *, int, int)); ! extern int show_name_attributes __P((char *, int)); ! extern void set_var_attribute __P((char *, int, int)); /* Functions from pushd.def */ ! extern char *get_dirstack_from_string __P((char *)); ! extern char *get_dirstack_element __P((int, int)); ! extern void set_dirstack_element __P((int, int, char *)); ! extern WORD_LIST *get_directory_stack __P((void)); /* Functions from evalstring.c */ ! extern int parse_and_execute __P((char *, char *, int)); ! extern void parse_and_execute_cleanup __P((void)); /* Functions from evalfile.c */ diff -Nrc2 bash-2.01.1/builtins/declare.def bash-2.02/builtins/declare.def *** bash-2.01.1/builtins/declare.def Tue Jul 1 14:05:10 1997 --- bash-2.02/builtins/declare.def Thu Oct 16 09:53:20 1997 *************** *** 58,61 **** --- 58,64 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 377,380 **** --- 380,395 ---- FREE (var->value); var->value = t; + } + + /* If we found this variable in the temporary environment, as with + `var=value declare -x var', make sure it is treated identically + to `var=value export var'. Do the same for `declare -r' and + `readonly'. Preserve the attributes, except for att_tempvar. */ + if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var)) + { + SHELL_VAR *tv; + tv = bind_variable (var->name, var->value ? var->value : ""); + tv->attributes = var->attributes & ~att_tempvar; + dispose_variable (var); } } diff -Nrc2 bash-2.01.1/builtins/enable.def bash-2.02/builtins/enable.def *** bash-2.01.1/builtins/enable.def Fri Feb 7 14:05:00 1997 --- bash-2.02/builtins/enable.def Fri Jul 18 16:55:00 1997 *************** *** 43,46 **** --- 43,49 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/builtins/eval.def bash-2.02/builtins/eval.def *** bash-2.01.1/builtins/eval.def Wed May 14 13:15:34 1997 --- bash-2.02/builtins/eval.def Fri Jul 18 16:55:08 1997 *************** *** 30,34 **** #include #if defined (HAVE_UNISTD_H) ! #include #endif --- 30,37 ---- #include #if defined (HAVE_UNISTD_H) ! # ifdef _MINIX ! # include ! # endif ! # include #endif diff -Nrc2 bash-2.01.1/builtins/evalfile.c bash-2.02/builtins/evalfile.c *** bash-2.01.1/builtins/evalfile.c Wed May 14 13:41:47 1997 --- bash-2.02/builtins/evalfile.c Mon Oct 13 14:47:49 1997 *************** *** 76,79 **** --- 76,80 ---- char *string; struct stat finfo; + size_t file_size; VFunction *errfunc; *************** *** 109,114 **** } ! string = xmalloc (1 + (int)finfo.st_size); ! result = read (fd, string, finfo.st_size); string[result] = '\0'; --- 110,122 ---- } ! file_size = (size_t)finfo.st_size; ! /* Check for overflow with large files. */ ! if (file_size != finfo.st_size || file_size + 1 < file_size) ! { ! (*errfunc) ("%s: file is too large", filename); ! return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1); ! } ! string = xmalloc (1 + file_size); ! result = read (fd, string, file_size); string[result] = '\0'; *************** *** 117,121 **** errno = return_val; ! if (result != (int)finfo.st_size) { free (string); --- 125,129 ---- errno = return_val; ! if (result < 0) /* XXX was != file_size, not < 0 */ { free (string); *************** *** 123,126 **** --- 131,140 ---- } + if (result == 0) + { + free (string); + return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1); + } + if (check_binary_file ((unsigned char *)string, (result > 80) ? 80 : result)) { diff -Nrc2 bash-2.01.1/builtins/evalstring.c bash-2.02/builtins/evalstring.c *** bash-2.01.1/builtins/evalstring.c Mon Sep 22 12:54:29 1997 --- bash-2.02/builtins/evalstring.c Mon Sep 22 12:39:24 1997 *************** *** 20,23 **** --- 20,26 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 26,29 **** --- 29,35 ---- #include + #include + + #include "../filecntl.h" #include "../bashansi.h" *************** *** 34,37 **** --- 40,44 ---- #include "../input.h" #include "../execute_cmd.h" + #include "../redir.h" #if defined (HISTORY) *************** *** 41,44 **** --- 48,55 ---- #include "common.h" + #if !defined (errno) + extern int errno; + #endif + extern void run_trap_cleanup (); *************** *** 48,55 **** --- 59,69 ---- extern int last_command_exit_value; extern int running_trap; + extern int posixly_correct; extern COMMAND *global_command; int parse_and_execute_level = 0; + static int cat_file (); + /* How to force parse_and_execute () to clean up after itself. */ void *************** *** 203,207 **** #endif /* ONESHOT */ ! last_result = execute_command_internal (command, 0, NO_PIPE, NO_PIPE, bitmap); --- 217,237 ---- #endif /* ONESHOT */ ! /* See if this is a candidate for $( type == cm_simple && !command->redirects && ! (command->flags & CMD_TIME_PIPELINE) == 0 && ! command->value.Simple->words == 0 && ! command->value.Simple->redirects && ! command->value.Simple->redirects->next == 0 && ! command->value.Simple->redirects->instruction == r_input_direction) ! { ! int r; ! r = cat_file (command->value.Simple->redirects); ! last_result = (r < 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS; ! } ! else ! last_result = execute_command_internal (command, 0, NO_PIPE, NO_PIPE, bitmap); *************** *** 238,240 **** --- 268,361 ---- return (last_result); + } + + /* Write NB bytes from BUF to file descriptor FD, retrying the write if + it is interrupted. We retry three times if we get a zero-length + write. Any other signal causes this function to return prematurely. */ + static int + zwrite (fd, buf, nb) + int fd; + unsigned char *buf; + int nb; + { + int n, i, nt; + + for (n = nb, nt = 0;;) + { + i = write (fd, buf, n); + if (i > 0) + { + n -= i; + if (n <= 0) + return nb; + } + else if (i == 0) + { + if (++nt > 3) + return (nb - n); + } + else if (errno != EINTR) + return -1; + } + } + + /* Handle a $( < file ) command substitution. This expands the filename, + returning errors as appropriate, then just cats the file to the standard + output. */ + static int + cat_file (r) + REDIRECT *r; + { + char lbuf[128], *fn; + int nr, fd, rval; + + if (r->instruction != r_input_direction) + return -1; + + /* Get the filename. */ + if (posixly_correct && !interactive_shell) + disallow_filename_globbing++; + fn = redirection_expand (r->redirectee.filename); + if (posixly_correct && !interactive_shell) + disallow_filename_globbing--; + + if (fn == 0) + { + redirection_error (r, AMBIGUOUS_REDIRECT); + return -1; + } + + fd = open(fn, O_RDONLY); + if (fd < 0) + { + file_error (fn); + free (fn); + return -1; + } + + rval = 0; + while (1) + { + /* Retry the reads on EINTR. Any other error causes a break from the + loop. */ + while ((nr = read (fd, lbuf, sizeof(lbuf))) < 0 && errno == EINTR) + ; + if (nr == 0) + break; + else if (nr < 0) + { + rval = -1; + break; + } + if (zwrite (1, lbuf, nr) < 0) + { + rval = -1; + break; + } + } + + free (fn); + close (fd); + + return (0); } diff -Nrc2 bash-2.01.1/builtins/exec.def bash-2.02/builtins/exec.def *** bash-2.01.1/builtins/exec.def Mon Apr 14 16:40:00 1997 --- bash-2.02/builtins/exec.def Thu Jul 10 11:49:51 1997 *************** *** 50,53 **** --- 50,54 ---- #include "../shell.h" #include "../execute_cmd.h" + #include "../findcmd.h" #if defined (JOB_CONTROL) # include "../jobs.h" diff -Nrc2 bash-2.01.1/builtins/exit.def bash-2.02/builtins/exit.def *** bash-2.01.1/builtins/exit.def Thu Mar 6 10:51:44 1997 --- bash-2.02/builtins/exit.def Wed Nov 12 13:24:31 1997 *************** *** 76,80 **** WORD_LIST *list; { ! if (login_shell == 0 && interactive) { builtin_error ("not login shell: use `exit'"); --- 76,80 ---- WORD_LIST *list; { ! if (login_shell == 0 /* && interactive */) { builtin_error ("not login shell: use `exit'"); diff -Nrc2 bash-2.01.1/builtins/fc.def bash-2.02/builtins/fc.def *** bash-2.01.1/builtins/fc.def Wed May 14 14:24:09 1997 --- bash-2.02/builtins/fc.def Thu Jul 17 09:42:44 1997 *************** *** 50,57 **** #if defined (HISTORY) ! #include #include "../bashtypes.h" #include "../posixstat.h" ! #include #if defined (HAVE_UNISTD_H) --- 50,61 ---- #if defined (HISTORY) ! #ifndef _MINIX ! # include ! #endif #include "../bashtypes.h" #include "../posixstat.h" ! #ifndef _MINIX ! # include ! #endif #if defined (HAVE_UNISTD_H) diff -Nrc2 bash-2.01.1/builtins/getopt.c bash-2.02/builtins/getopt.c *** bash-2.01.1/builtins/getopt.c Thu Mar 6 15:54:53 1997 --- bash-2.02/builtins/getopt.c Fri Jul 18 16:56:06 1997 *************** *** 21,24 **** --- 21,27 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/builtins/getopts.def bash-2.02/builtins/getopts.def *** bash-2.01.1/builtins/getopts.def Fri Feb 28 15:54:28 1997 --- bash-2.02/builtins/getopts.def Fri Jul 18 16:56:17 1997 *************** *** 62,65 **** --- 62,68 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/builtins/hash.def bash-2.02/builtins/hash.def *** bash-2.01.1/builtins/hash.def Thu May 29 09:51:24 1997 --- bash-2.02/builtins/hash.def Thu Jan 29 14:51:26 1998 *************** *** 36,39 **** --- 36,41 ---- #include + #include "../bashtypes.h" + #if defined (HAVE_UNISTD_H) # include *************** *** 44,49 **** #include "../shell.h" #include "../builtins.h" - #include "../execute_cmd.h" #include "../flags.h" #include "../hashcmd.h" #include "common.h" --- 46,51 ---- #include "../shell.h" #include "../builtins.h" #include "../flags.h" + #include "../findcmd.h" #include "../hashcmd.h" #include "common.h" *************** *** 64,68 **** { int expunge_hash_table, opt; ! char *word, *pathname; if (hashing_enabled == 0) --- 66,70 ---- { int expunge_hash_table, opt; ! char *w, *pathname; if (hashing_enabled == 0) *************** *** 108,117 **** { /* Add or rehash the specified commands. */ ! word = list->word->word; if (pathname) ! remember_filename (word, pathname, 0, 0); ! else if (absolute_program (word)) continue; ! else if (add_hashed_command (word, 0)) opt = EXECUTION_FAILURE; } --- 110,119 ---- { /* Add or rehash the specified commands. */ ! w = list->word->word; if (pathname) ! remember_filename (w, pathname, 0, 0); ! else if (absolute_program (w)) continue; ! else if (add_hashed_command (w, 0)) opt = EXECUTION_FAILURE; } *************** *** 122,127 **** static int ! add_hashed_command (word, quiet) ! char *word; int quiet; { --- 124,129 ---- static int ! add_hashed_command (w, quiet) ! char *w; int quiet; { *************** *** 130,142 **** rv = 0; ! if (find_function (word) == 0 && find_shell_builtin (word) == 0) { ! full_path = find_user_command (word); if (full_path && executable_file (full_path)) ! remember_filename (word, full_path, dot_found_in_search, 0); else { if (quiet == 0) ! builtin_error ("%s: not found", word); rv++; } --- 132,144 ---- rv = 0; ! if (find_function (w) == 0 && find_shell_builtin (w) == 0) { ! full_path = find_user_command (w); if (full_path && executable_file (full_path)) ! remember_filename (w, full_path, dot_found_in_search, 0); else { if (quiet == 0) ! builtin_error ("%s: not found", w); rv++; } diff -Nrc2 bash-2.01.1/builtins/help.def bash-2.02/builtins/help.def *** bash-2.01.1/builtins/help.def Wed Feb 5 12:18:38 1997 --- bash-2.02/builtins/help.def Tue Aug 5 12:10:52 1997 *************** *** 37,40 **** --- 37,43 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 42,45 **** --- 45,49 ---- #include "../shell.h" #include "../builtins.h" + #include "../pathexp.h" #include "bashgetopt.h" *************** *** 101,105 **** QUIT; if ((strncmp (pattern, name, plen) == 0) || ! (fnmatch (pattern, name, 0) != FNM_NOMATCH)) { printf ("%s: %s\n", name, shell_builtins[i].short_doc); --- 105,109 ---- QUIT; if ((strncmp (pattern, name, plen) == 0) || ! (fnmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH)) { printf ("%s: %s\n", name, shell_builtins[i].short_doc); diff -Nrc2 bash-2.01.1/builtins/history.def bash-2.02/builtins/history.def *** bash-2.01.1/builtins/history.def Mon Mar 3 12:47:07 1997 --- bash-2.02/builtins/history.def Thu Jul 17 09:43:07 1997 *************** *** 47,51 **** #if defined (HISTORY) #include "../bashtypes.h" ! #include #include "../posixstat.h" #include "../filecntl.h" --- 47,53 ---- #if defined (HISTORY) #include "../bashtypes.h" ! #ifndef _MINIX ! # include ! #endif #include "../posixstat.h" #include "../filecntl.h" diff -Nrc2 bash-2.01.1/builtins/jobs.def bash-2.02/builtins/jobs.def *** bash-2.01.1/builtins/jobs.def Thu May 8 15:10:02 1997 --- bash-2.02/builtins/jobs.def Mon Oct 13 11:39:48 1997 *************** *** 206,214 **** $FUNCTION disown_builtin $DEPENDS_ON JOB_CONTROL ! $SHORT_DOC disown [-h] [jobspec ...] By default, removes each JOBSPEC argument from the table of active jobs. If the -h option is given, the job is not removed from the table, but is marked so that SIGHUP is not sent to the job if the shell receives a ! SIGHUP. $END --- 206,215 ---- $FUNCTION disown_builtin $DEPENDS_ON JOB_CONTROL ! $SHORT_DOC disown [-h] [-ar] [jobspec ...] By default, removes each JOBSPEC argument from the table of active jobs. If the -h option is given, the job is not removed from the table, but is marked so that SIGHUP is not sent to the job if the shell receives a ! SIGHUP. The -a option, when JOBSPEC is not supplied, means to remove all ! jobs from the job table; the -r option means to remove only running jobs. $END *************** *** 218,233 **** WORD_LIST *list; { ! int opt, job, retval, nohup_only; sigset_t set, oset; ! nohup_only = 0; reset_internal_getopt (); ! while ((opt = internal_getopt (list, "h")) != -1) { switch (opt) { case 'h': nohup_only = 1; break; default: builtin_usage (); --- 219,240 ---- WORD_LIST *list; { ! int opt, job, retval, nohup_only, running_jobs, all_jobs; sigset_t set, oset; ! nohup_only = running_jobs = all_jobs = 0; reset_internal_getopt (); ! while ((opt = internal_getopt (list, "ahr")) != -1) { switch (opt) { + case 'a': + all_jobs = 1; + break; case 'h': nohup_only = 1; break; + case 'r': + running_jobs = 1; + break; default: builtin_usage (); *************** *** 238,252 **** retval = EXECUTION_SUCCESS; ! #if 0 ! /* For the future `disown -a' */ ! if (list == 0) { if (nohup_only) ! nohup_all_jobs (); else ! delete_all_jobs (); return (EXECUTION_SUCCESS); } - #endif do --- 245,257 ---- retval = EXECUTION_SUCCESS; ! /* `disown -a' or `disown -r' */ ! if (list == 0 && (all_jobs || running_jobs)) { if (nohup_only) ! nohup_all_jobs (running_jobs); else ! delete_all_jobs (running_jobs); return (EXECUTION_SUCCESS); } do *************** *** 257,261 **** : get_job_spec (list); ! if (job == NO_JOB || jobs == 0 || jobs[job] == 0) { builtin_error ("%s: no such job", list ? list->word->word : "current"); --- 262,266 ---- : get_job_spec (list); ! if (job == NO_JOB || jobs == 0 || job < 0 || job >= job_slots || jobs[job] == 0) { builtin_error ("%s: no such job", list ? list->word->word : "current"); *************** *** 265,269 **** nohup_job (job); else ! delete_job (job); UNBLOCK_CHILD (oset); --- 270,274 ---- nohup_job (job); else ! delete_job (job, 1); UNBLOCK_CHILD (oset); diff -Nrc2 bash-2.01.1/builtins/kill.def bash-2.02/builtins/kill.def *** bash-2.01.1/builtins/kill.def Mon Feb 24 16:08:33 1997 --- bash-2.02/builtins/kill.def Tue Mar 17 13:24:37 1998 *************** *** 40,43 **** --- 40,46 ---- #include #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 78,82 **** if (list == 0) ! return (EXECUTION_SUCCESS); any_succeeded = listing = saw_signal = 0; --- 81,88 ---- if (list == 0) ! { ! builtin_usage (); ! return (EXECUTION_FAILURE); ! } any_succeeded = listing = saw_signal = 0; *************** *** 146,149 **** --- 152,161 ---- } + if (list == 0) + { + builtin_usage (); + return (EXECUTION_FAILURE); + } + while (list) { *************** *** 153,157 **** word++; ! if (all_digits (word)) { /* Use the entire argument in case of minus sign presence. */ --- 165,169 ---- word++; ! if (*word && all_digits (word)) { /* Use the entire argument in case of minus sign presence. */ *************** *** 163,172 **** any_succeeded++; } ! else if (*list->word->word != '%') { builtin_error ("%s: no such pid", list->word->word); CONTINUE_OR_FAIL; } ! else if (interactive || job_control) /* Posix.2 says you can kill without job control active (4.32.4) */ { /* Must be a job spec. Check it out. */ --- 175,184 ---- any_succeeded++; } ! else if (*list->word->word && *list->word->word != '%') { builtin_error ("%s: no such pid", list->word->word); CONTINUE_OR_FAIL; } ! else if (*word && (interactive || job_control)) /* Posix.2 says you can kill without job control active (4.32.4) */ { /* Must be a job spec. Check it out. */ *************** *** 209,213 **** else { ! builtin_error ("`%s' is not a pid or valid job spec", list->word->word); CONTINUE_OR_FAIL; } --- 221,225 ---- else { ! builtin_error ("`%s': not a pid or valid job spec", list->word->word); CONTINUE_OR_FAIL; } diff -Nrc2 bash-2.01.1/builtins/let.def bash-2.02/builtins/let.def *** bash-2.01.1/builtins/let.def Tue Apr 15 14:30:59 1997 --- bash-2.02/builtins/let.def Fri Jul 18 16:57:40 1997 *************** *** 64,67 **** --- 64,70 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/builtins/mkbuiltins.c bash-2.02/builtins/mkbuiltins.c *** bash-2.01.1/builtins/mkbuiltins.c Mon Feb 17 14:57:12 1997 --- bash-2.02/builtins/mkbuiltins.c Mon Oct 13 14:00:49 1997 *************** *** 23,38 **** #if defined (HAVE_UNISTD_H) # include #endif #include "../bashtypes.h" #include #include "../posixstat.h" #include "../filecntl.h" - #if defined (HAVE_UNISTD_H) - # include - #endif /* HAVE_UNISTD_H */ - #include "../bashansi.h" #include --- 23,40 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif + #ifndef _MINIX #include "../bashtypes.h" #include + #endif + #include "../posixstat.h" #include "../filecntl.h" #include "../bashansi.h" #include *************** *** 438,443 **** DEF_FILE *defs; struct stat finfo; char *buffer, *line; ! int fd; if (stat (filename, &finfo) == -1) --- 440,446 ---- DEF_FILE *defs; struct stat finfo; + size_t file_size; char *buffer, *line; ! int fd, nr; if (stat (filename, &finfo) == -1) *************** *** 449,459 **** file_error (filename); ! buffer = xmalloc (1 + (int)finfo.st_size); ! if (read (fd, buffer, finfo.st_size) != finfo.st_size) file_error (filename); close (fd); /* Create and fill in the initial structure describing this file. */ defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE)); --- 452,469 ---- file_error (filename); ! file_size = (size_t)finfo.st_size; ! buffer = xmalloc (1 + file_size); ! if ((nr = read (fd, buffer, file_size)) < 0) file_error (filename); close (fd); + if (nr == 0) + { + fprintf (stderr, "mkbuiltins: %s: skipping zero-length file\n", filename); + return; + } + /* Create and fill in the initial structure describing this file. */ defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE)); *************** *** 467,475 **** /* Build the array of lines. */ i = 0; ! while (i < finfo.st_size) { array_add (&buffer[i], defs->lines); ! while (buffer[i] != '\n' && i < finfo.st_size) i++; buffer[i++] = '\0'; --- 477,485 ---- /* Build the array of lines. */ i = 0; ! while (i < file_size) { array_add (&buffer[i], defs->lines); ! while (buffer[i] != '\n' && i < file_size) i++; buffer[i++] = '\0'; *************** *** 677,681 **** { must_be_building (directive, defs); ! return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]); } --- 687,694 ---- { must_be_building (directive, defs); ! if (defs->builtins) ! return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]); ! else ! return ((BUILTIN_DESC *)NULL); } *************** *** 757,760 **** --- 770,778 ---- builtin = current_builtin (self, defs); + if (builtin == 0) + { + line_error (defs, "syntax error: no current builtin for $FUNCTION directive"); + exit (1); + } if (builtin->function) line_error (defs, "%s already has a function (%s)", diff -Nrc2 bash-2.01.1/builtins/printf.def bash-2.02/builtins/printf.def *** bash-2.01.1/builtins/printf.def Wed Dec 31 19:00:00 1969 --- bash-2.02/builtins/printf.def Thu Jan 29 15:06:57 1998 *************** *** 0 **** --- 1,693 ---- + This file is printf.def, from which is created printf.c. + It implements the builtin "printf" in Bash. + + Copyright (C) 1997 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + + $PRODUCES printf.c + + $BUILTIN printf + $FUNCTION printf_builtin + $SHORT_DOC printf format [arguments] + printf formats and prints ARGUMENTS under control of the FORMAT. 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 + argument. In addition to the standard printf(1) formats, %b means to + expand backslash escape sequences in the corresponding argument, and %q + means to quote the argument in a way that can be reused as shell input. + $END + + #include + + #include "../bashtypes.h" + + #include + #if defined (HAVE_LIMITS_H) + # include + #else + /* Assume 32-bit ints and longs. */ + # define LONG_MAX 2147483647L + # define LONG_MIN (-2147483647L-1) + # define INT_MAX 2147483647 + # define INT_MIN (-2147483647-1) + #endif + + #include + #include + + #include "../bashansi.h" + #include "../shell.h" + #include "../stdc.h" + #include "bashgetopt.h" + + #if !defined (errno) + extern int errno; + #endif + + #define PF(f, func) \ + do { \ + if (fieldwidth && precision) \ + (void)printf(f, fieldwidth, precision, func); \ + else if (fieldwidth && precision == 0) \ + (void)printf(f, fieldwidth, func); \ + else if (precision) \ + (void)printf(f, precision, func); \ + else \ + (void)printf(f, func); \ + } while (0) + + #define PRETURN(value) \ + do { free (format); fflush (stdout); return (value); } while (0) + + #define SKIP1 "#-+ 0" + #define SKIP2 "*0123456789" + + static void printstr __P((char *, char *, int, int, int)); + static char *bexpand __P((char *, int, int *, int *)); + static char *mklong __P((char *, int)); + static int getchr __P((void)); + static char *getstr __P((void)); + static int getint __P((void)); + static int getlong __P((long *)); + static int getulong __P((unsigned long *)); + static double getdouble __P((void)); + static int asciicode __P((void)); + + static WORD_LIST *garglist; + static int retval; + + extern char *backslash_quote (); + + int + printf_builtin (list) + WORD_LIST *list; + { + int ch, end, fieldwidth, precision, foundmod; + char convch, nextch, *format, *fmt, *start; + + retval = EXECUTION_SUCCESS; + reset_internal_getopt (); + while ((ch = internal_getopt (list, "")) != -1) + { + switch (ch) + { + case '?': + default: + builtin_usage(); + return (EX_USAGE); + } + } + list = loptend; + + if (list == 0) + { + builtin_usage (); + return (EX_USAGE); + } + + if (list->word->word == 0 || list->word->word[0] == '\0') + return (EXECUTION_SUCCESS); + + format = ansicstr (list->word->word, strlen (list->word->word), (int *)NULL, (int *)NULL); + + garglist = list->next; + + /* Basic algorithm is to scan the format string for conversion + specifications -- once one is found, find out if the field + width or precision is a '*'; if it is, gather up value. Note, + format strings are reused as necessary to use up the provided + arguments, arguments of zero/null string are provided to use + up the format string. */ + + do + { + /* find next format specification */ + for (fmt = format; *fmt; fmt++) + { + precision = fieldwidth = foundmod = 0; + + if (*fmt != '%') + { + putchar (*fmt); + continue; + } + + /* ASSERT(*fmt == '%') */ + start = fmt++; + + if (*fmt == '%') /* %% prints a % */ + { + putchar ('%'); + continue; + } + + /* found format specification, skip to field width */ + for (; *fmt && strchr(SKIP1, *fmt); ++fmt) + ; + fieldwidth = (*fmt == '*') ? getint () : 0; + + /* skip to possible '.', get following precision */ + for (; *fmt && strchr(SKIP2, *fmt); ++fmt) + ; + if (*fmt == '.') + { + ++fmt; + precision = (*fmt == '*') ? getint () : 0; + } + + /* skip to conversion char */ + for (; *fmt && strchr(SKIP2, *fmt); ++fmt) + ; + if (*fmt == 0) + { + builtin_error ("`%s': missing format character", start); + PRETURN (EXECUTION_FAILURE); + } + + /* skip possible format modifiers */ + if (*fmt == 'l' || *fmt == 'L' || *fmt == 'h') + { + fmt++; + foundmod = 1; + } + + convch = *fmt; + nextch = fmt[1]; + fmt[1] = '\0'; + switch(convch) + { + case 'c': + { + char p; + + p = getchr (); + PF(start, p); + break; + } + + case 's': + { + char *p; + + p = getstr (); + PF(start, p); + break; + } + + case 'b': /* expand escapes in argument */ + { + char *p, *xp; + int rlen; + + p = getstr (); + ch = rlen = 0; + xp = bexpand (p, strlen (p), &ch, &rlen); + + if (xp) + { + /* Have to use printstr because of possible NUL bytes + in XP -- printf does not handle that well. */ + printstr (start, xp, rlen, fieldwidth, precision); + free (xp); + } + + if (ch) + PRETURN (retval); + break; + } + + case 'q': /* print with shell quoting */ + { + char *p, *xp; + + p = getstr (); + xp = backslash_quote (p); + if (xp) + { + /* Use printstr to get fieldwidth and precision right. */ + printstr (start, xp, strlen (xp), fieldwidth, precision); + free (xp); + } + break; + } + + case 'd': + case 'i': + { + long p; + char *f; + + if (foundmod == 0 && ((f = mklong (start, convch)) == NULL)) + PRETURN (EXECUTION_FAILURE); + else + f = start; + if (getlong (&p)) + PRETURN (EXECUTION_FAILURE); + PF(f, p); + break; + } + + case 'o': + case 'u': + case 'x': + case 'X': + { + unsigned long p; + char *f; + + if (foundmod == 0 && ((f = mklong (start, convch)) == NULL)) + PRETURN (EXECUTION_FAILURE); + else + f = start; + if (getulong (&p)) + PRETURN (EXECUTION_FAILURE); + PF (f, p); + break; + } + + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + { + double p; + + p = getdouble (); + PF(start, p); + break; + } + + /* We output unrecognized format characters, but we print a + warning message and return a failure exit status. */ + default: + builtin_error ("`%c': illegal format character", convch); + PRETURN (EXECUTION_FAILURE); + } + + fmt[1] = nextch; + } + } + while (garglist); + + PRETURN (retval); + } + + /* We duplicate a lot of what printf(3) does here. */ + static void + printstr (fmt, string, len, fieldwidth, precision) + char *fmt; /* format */ + char *string; /* expanded string argument */ + int len; /* length of expanded string */ + int fieldwidth; /* argument for width of `*' */ + int precision; /* argument for precision of `*' */ + { + #if 0 + char *s; + #endif + int padlen, nc, ljust, i; + int fw, pr; /* fieldwidth and precision */ + + if (string == 0 || *string == '\0') + return; + + #if 0 + s = fmt; + #endif + if (*fmt == '%') + fmt++; + + ljust = fw = pr = 0; + + /* skip flags */ + while (*fmt == '#' || *fmt == '-' || *fmt == '+' || *fmt == ' ' || *fmt == '0') + { + if (*fmt == '-') + ljust = 1; + fmt++; + } + + /* get fieldwidth, if present */ + if (*fmt == '*') + { + fmt++; + fw = fieldwidth; + } + else if (isdigit (*fmt)) + { + fw = *fmt++ - '0'; + while (isdigit (*fmt)) + fw = (fw * 10) + (*fmt++ - '0'); + } + + /* get precision, if present */ + if (*fmt == '.') + { + fmt++; + if (*fmt == '*') + { + fmt++; + pr = precision; + } + else if (isdigit (*fmt)) + { + pr = *fmt++ - '0'; + while (isdigit (*fmt)) + pr = (pr * 10) + (*fmt++ - '0'); + } + } + + #if 0 + /* If we remove this, get rid of `s'. */ + if (*fmt != 'b' && *fmt != 'q') + { + internal_error ("format parsing problem: %s", s); + fw = pr = 0; + } + #endif + + /* chars from string to print */ + nc = (pr > 0 && pr <= len) ? pr : len; + + padlen = fw - nc; + if (padlen < 0) + padlen = 0; + if (ljust) + padlen = -padlen; + + /* leading pad characters */ + for (; padlen > 0; padlen--) + putchar (' '); + + /* output NC characters from STRING */ + for (i = 0; i < nc; i++) + putchar (string[i]); + + /* output any necessary trailing padding */ + for (; padlen < 0; padlen++) + putchar (' '); + } + + /* Convert STRING by expanding the escape sequences specified by the + POSIX standard for printf's `%b' format string. If SAWC is non-null, + recognize `\c' and use that as a string terminator. If we see \c, set + *SAWC to 1 before returning. LEN is the length of STRING. */ + + #ifdef isoctal + #undef isoctal + #endif + + #define isoctal(c) ((c) >= '0' && (c) <= '7') + + #define OCTVALUE(c) ((c) - '0') + + #ifndef isxdigit + # define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) + #endif + + #define HEXVALUE(c) \ + ((c) >= 'a' && (c) <= 'f' ? (c)-'a'+10 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0') + + static char * + bexpand (string, len, sawc, lenp) + char *string; + int len, *sawc, *lenp; + { + int c, temp; + char *ret, *r, *s; + + if (string == 0 || *string == '\0') + { + if (sawc) + *sawc = 0; + if (lenp) + *lenp = 0; + return ((char *)NULL); + } + + ret = xmalloc (len + 1); + for (r = ret, s = string; s && *s; ) + { + c = *s++; + if (c != '\\' || *s == '\0') + { + *r++ = c; + continue; + } + + switch (c = *s++) + { + #if defined (__STDC__) + case 'a': c = '\a'; break; + #else + case 'a': c = '\007'; break; + #endif + + case 'b': c = '\b'; break; + + case 'e': c = '\033'; break; /* ESC -- non-ANSI */ + + case 'f': c = '\f'; break; + + case 'n': c = '\n'; break; + + case 'r': c = '\r'; break; + + case 't': c = '\t'; break; + + case 'v': c = '\v'; break; + + /* %b octal constants are `\0' followed by one, two, or three + octal digits... */ + case '0': + for (temp = 3, c = 0; isoctal (*s) && temp--; s++) + c = (c * 8) + OCTVALUE (*s); + break; + + /* but, as an extension, the other echo-like octal escape + sequences are supported as well. */ + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + for (temp = 2, c -= '0'; isoctal (*s) && temp--; s++) + c = (c * 8) + OCTVALUE (*s); + break; + + /* And, as another extension, we allow \xNNN, where each N is a + hex digit. */ + case 'x': + for (temp = 3, c = 0; isxdigit (*s) && temp--; s++) + c = (c * 16) + HEXVALUE (*s); + if (temp == 3) + { + builtin_error ("missing hex digit for \\x"); + *r++ = '\\'; + c = 'x'; + } + break; + + case '\\': + #if 0 + case '\'': /* XXX */ + case '"': /* XXX */ + #endif + break; + + case 'c': + if (sawc) + *sawc = 1; + *r = '\0'; + if (lenp) + *lenp = r - ret; + return ret; + + /* other backslash escapes are passed through unaltered */ + default: *r++ = '\\'; break; + } + + *r++ = c; + } + + *r = '\0'; + if (lenp) + *lenp = r - ret; + return ret; + } + + static char * + mklong (str, ch) + char *str; + int ch; + { + static char copy[64]; + int len; + + len = strlen (str) + 2; + FASTCOPY (str, copy, len - 3); + copy[len - 3] = 'l'; + copy[len - 2] = ch; + copy[len - 1] = '\0'; + return (copy); + } + + static int + getchr () + { + int ret; + + if (garglist == 0) + return ('\0'); + + ret = (int)garglist->word->word[0]; + garglist = garglist->next; + return ret; + } + + static char * + getstr () + { + char *ret; + + if (garglist == 0) + return (""); + + ret = garglist->word->word; + garglist = garglist->next; + return ret; + } + + static int + getint () + { + long ret; + + if (getlong (&ret)) + return (0); + + if (ret > INT_MAX) + { + builtin_error ("%s: %s", garglist->word->word, strerror(ERANGE)); + return (0); + } + + return ((int)ret); + } + + static int + getlong (lp) + long *lp; + { + long ret; + + if (garglist == 0) + { + *lp = 0L; + return (0); + } + + if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"') + { + *lp = (long)asciicode (); + return (0); + } + + errno = 0; + /* legal_number does not currently detect overflow, but it should. + Someday it will. */ + if (legal_number (garglist->word->word, &ret) == 0) + { + builtin_error ("%s: illegal number", garglist->word->word); + return (1); + } + else if (errno == ERANGE) + { + builtin_error ("%s: %s", garglist->word->word, strerror(ERANGE)); + return (1); + } + + *lp = ret; + garglist = garglist->next; + return (0); + } + + static int + getulong (ulp) + unsigned long *ulp; + { + unsigned long ret; + char *ep; + + if (garglist == 0) + { + *ulp = (unsigned long)0; + return (0); + } + + if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"') + { + *ulp = (unsigned long)asciicode (); + return (0); + } + + errno = 0; + ret = strtoul (garglist->word->word, &ep, 0); + + if (*ep) + { + builtin_error ("%s: illegal number", garglist->word->word); + return (1); + } + else if (errno == ERANGE) + { + builtin_error ("%s: %s", garglist->word->word, strerror(ERANGE)); + return (1); + } + + *ulp = ret; + garglist = garglist->next; + return (0); + } + + static double + getdouble () + { + double ret; + + if (garglist == 0) + return ((double)0); + + if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"') + return ((double)asciicode ()); + + /* This should use strtod if it is available. */ + ret = atof (garglist->word->word); + garglist = garglist->next; + return (ret); + } + + /* NO check is needed for garglist here. */ + static int + asciicode () + { + register int ch; + + ch = garglist->word->word[1]; + garglist = garglist->next; + return (ch); + } diff -Nrc2 bash-2.01.1/builtins/psize.c bash-2.02/builtins/psize.c *** bash-2.01.1/builtins/psize.c Mon Feb 17 14:35:30 1997 --- bash-2.02/builtins/psize.c Fri Jul 18 16:58:53 1997 *************** *** 25,33 **** --- 25,38 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif #include + #ifndef _MINIX #include "../bashtypes.h" + #endif #include #include diff -Nrc2 bash-2.01.1/builtins/psize.sh bash-2.02/builtins/psize.sh *** bash-2.01.1/builtins/psize.sh Thu May 12 11:13:50 1994 --- bash-2.02/builtins/psize.sh Tue Mar 17 12:27:11 1998 *************** *** 4,7 **** --- 4,13 ---- # pipesize.h so ulimit.c can use it. + TMPDIR=/tmp + TMPNAME=pipsize.$$ + TMPFILE=$TMPDIR/$TMPNAME + + trap 'rm -f $TMPFILE' 0 1 2 3 6 15 + echo "/*" echo " * pipesize.h" *************** *** 12,24 **** echo "" ! ./psize.aux 2>/tmp/pipesize | sleep 3 ! if [ -s /tmp/pipesize ]; then ! echo "#define PIPESIZE `cat /tmp/pipesize`" else echo "#define PIPESIZE 512" fi - - rm -f /tmp/pipesize exit 0 --- 18,36 ---- echo "" ! # ! # Try to avoid tempfile races. We can't really check for the file's ! # existance before we run psize.aux, because `test -e' is not portable, ! # `test -h' (test for symlinks) is not portable, and `test -f' only ! # checks for regular files ! # ! rm -f $TMPFILE ! ./psize.aux 2>$TMPFILE | sleep 3 ! ! if [ -s $TMPFILE ]; then ! echo "#define PIPESIZE `cat $TMPFILE`" else echo "#define PIPESIZE 512" fi exit 0 diff -Nrc2 bash-2.01.1/builtins/pushd.def bash-2.02/builtins/pushd.def *** bash-2.01.1/builtins/pushd.def Tue Apr 15 11:28:10 1997 --- bash-2.02/builtins/pushd.def Fri Nov 14 12:32:52 1997 *************** *** 96,102 **** #if defined (PUSHD_AND_POPD) #include ! #include #if defined (HAVE_UNISTD_H) # include #endif --- 96,107 ---- #if defined (PUSHD_AND_POPD) #include ! #ifndef _MINIX ! # include ! #endif #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 548,551 **** --- 553,584 ---- } + /* Used by the tilde expansion code. */ + char * + get_dirstack_from_string (string) + char *string; + { + int ind, sign, index_flag; + long i; + + sign = 1; + if (*string == '-' || *string == '+') + { + sign = (*string == '-') ? -1 : 1; + string++; + } + if (legal_number (string, &i) == 0) + return ((char *)NULL); + + index_flag = 0; + ind = get_dirstack_index (i, sign, &index_flag); + if (index_flag && (ind < 0 || ind > directory_list_offset)) + return ((char *)NULL); + if (index_flag == 0 || (index_flag == 1 && ind == 0)) + return (get_string_value ("PWD")); + else + return (pushd_directory_list[ind]); + } + + #ifdef INCLUDE_UNUSED char * get_dirstack_element (ind, sign) *************** *** 558,561 **** --- 591,595 ---- : pushd_directory_list[i]; } + #endif void diff -Nrc2 bash-2.01.1/builtins/read.def bash-2.02/builtins/read.def *** bash-2.01.1/builtins/read.def Wed Sep 10 17:04:47 1997 --- bash-2.02/builtins/read.def Mon Nov 17 14:31:28 1997 *************** *** 44,47 **** --- 44,50 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 396,399 **** --- 399,403 ---- if (valid_array_reference (name) == 0) { + #if 0 if (legal_identifier (name) == 0) { *************** *** 401,404 **** --- 405,409 ---- return ((SHELL_VAR *)NULL); } + #endif return (bind_variable (name, value)); } diff -Nrc2 bash-2.01.1/builtins/return.def bash-2.02/builtins/return.def *** bash-2.01.1/builtins/return.def Mon Mar 3 12:47:20 1997 --- bash-2.02/builtins/return.def Fri Jul 18 16:59:43 1997 *************** *** 33,36 **** --- 33,39 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/builtins/set.def bash-2.02/builtins/set.def *** bash-2.01.1/builtins/set.def Fri Apr 25 10:57:03 1997 --- bash-2.02/builtins/set.def Thu Dec 4 09:28:24 1997 *************** *** 25,28 **** --- 25,31 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 230,258 **** #define MINUS_O_FORMAT "%-15s\t%s\n" ! void ! list_minus_o_opts (mode) ! int mode; { ! register int i; ! int *on_or_off, value; ! ! for (value = i = 0; o_options[i].name; i++) ! { ! on_or_off = find_flag (o_options[i].letter); ! if (on_or_off == FLAG_UNKNOWN) ! on_or_off = &value; ! if (mode == -1 || mode == *on_or_off) ! printf (MINUS_O_FORMAT, o_options[i].name, *on_or_off ? on : off); ! } ! for (i = 0; binary_o_options[i].name; i++) ! { ! value = GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name); ! if (mode == -1 || mode == value) ! printf (MINUS_O_FORMAT, binary_o_options[i].name, value ? on : off); ! } } ! static void ! minus_o_option_commands () { register int i; --- 233,250 ---- #define MINUS_O_FORMAT "%-15s\t%s\n" ! static void ! print_minus_o_option (name, value, pflag) ! char *name; ! int value, pflag; { ! if (pflag == 0) ! printf (MINUS_O_FORMAT, name, value ? on : off); ! else ! printf ("set %co %s\n", value ? '-' : '+', name); } ! void ! list_minus_o_opts (mode, reusable) ! int mode, reusable; { register int i; *************** *** 264,273 **** if (on_or_off == FLAG_UNKNOWN) on_or_off = &value; ! printf ("set %co %s\n", *on_or_off ? '-' : '+', o_options[i].name); } for (i = 0; binary_o_options[i].name; i++) { value = GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name); ! printf ("set %co %s\n", value ? '-' : '+', binary_o_options[i].name); } } --- 256,267 ---- if (on_or_off == FLAG_UNKNOWN) on_or_off = &value; ! if (mode == -1 || mode == *on_or_off) ! print_minus_o_option (o_options[i].name, *on_or_off, reusable); } for (i = 0; binary_o_options[i].name; i++) { value = GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name); ! if (mode == -1 || mode == value) ! print_minus_o_option (binary_o_options[i].name, value, reusable); } } *************** *** 422,426 **** { char *value; ! int vsize, i, vptr, *ip; SHELL_VAR *v; --- 416,420 ---- { char *value; ! int vsize, i, vptr, *ip, exported; SHELL_VAR *v; *************** *** 459,466 **** v = find_variable ("SHELLOPTS"); if (v) ! v->attributes &= ~att_readonly; v = bind_variable ("SHELLOPTS", value); v->attributes |= att_readonly; free (value); --- 453,475 ---- v = find_variable ("SHELLOPTS"); + + /* Turn off the read-only attribute so we can bind the new value, and + note whether or not the variable was exported. */ if (v) ! { ! v->attributes &= ~att_readonly; ! exported = exported_p (v); ! } ! else ! exported = 0; ! v = bind_variable ("SHELLOPTS", value); + + /* Turn the read-only attribute back on, and turn off the export attribute + if it was set implicitly by mark_modified_vars and SHELLOPTS was not + exported before we bound the new value. */ v->attributes |= att_readonly; + if (mark_modified_vars && exported == 0 && exported_p (v)) + v->attributes &= ~att_exported; free (value); *************** *** 483,500 **** void ! initialize_shell_options () { char *temp; SHELL_VAR *var; ! var = find_variable ("SHELLOPTS"); ! /* set up any shell options we may have inherited. */ ! if (var && imported_p (var)) { ! temp = (array_p (var)) ? (char *)NULL : savestring (value_cell (var)); ! if (temp) { ! parse_shellopts (temp); ! free (temp); } } --- 492,513 ---- void ! initialize_shell_options (no_shellopts) ! int no_shellopts; { char *temp; SHELL_VAR *var; ! if (no_shellopts == 0) { ! var = find_variable ("SHELLOPTS"); ! /* set up any shell options we may have inherited. */ ! if (var && imported_p (var)) { ! temp = (array_p (var)) ? (char *)NULL : savestring (value_cell (var)); ! if (temp) ! { ! parse_shellopts (temp); ! free (temp); ! } } } *************** *** 608,615 **** if (opt == 0) { ! if (on_or_off == '-') ! list_minus_o_opts (-1); ! else ! minus_o_option_commands (); continue; } --- 621,625 ---- if (opt == 0) { ! list_minus_o_opts (-1, (on_or_off == '+')); continue; } *************** *** 620,627 **** *option_name == '-' || *option_name == '+') { ! if (on_or_off == '-') ! list_minus_o_opts (-1); ! else ! minus_o_option_commands (); continue; } --- 630,634 ---- *option_name == '-' || *option_name == '+') { ! list_minus_o_opts (-1, (on_or_off == '+')); continue; } *************** *** 731,735 **** #endif ! if (legal_identifier (name) == 0) { builtin_error ("`%s': not a valid identifier", name); --- 738,745 ---- #endif ! /* Bash allows functions with names which are not valid identifiers ! to be created when not in posix mode, so check only when in posix ! mode when unsetting a function. */ ! if (((unset_function && posixly_correct) || !unset_function) && legal_identifier (name) == 0) { builtin_error ("`%s': not a valid identifier", name); diff -Nrc2 bash-2.01.1/builtins/setattr.def bash-2.02/builtins/setattr.def *** bash-2.01.1/builtins/setattr.def Mon Aug 18 12:01:47 1997 --- bash-2.02/builtins/setattr.def Wed Oct 15 12:12:19 1997 *************** *** 25,28 **** --- 25,31 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 340,343 **** --- 343,347 ---- { SHELL_VAR *var; + int ret; var = find_tempenv_variable (name); *************** *** 348,351 **** --- 352,357 ---- { show_var_attributes (var, READONLY_OR_EXPORT, nodefs); + if (tempvar_p (var)) + dispose_variable (var); return (0); } diff -Nrc2 bash-2.01.1/builtins/shift.def bash-2.02/builtins/shift.def *** bash-2.01.1/builtins/shift.def Mon Mar 3 12:47:26 1997 --- bash-2.02/builtins/shift.def Fri Jul 18 17:00:19 1997 *************** *** 25,28 **** --- 25,31 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/builtins/shopt.def bash-2.02/builtins/shopt.def *** bash-2.01.1/builtins/shopt.def Thu Apr 17 10:13:23 1997 --- bash-2.02/builtins/shopt.def Fri Sep 19 11:30:38 1997 *************** *** 39,42 **** --- 39,45 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 60,63 **** --- 63,72 ---- extern int cdspelling, expand_aliases; extern int check_window_size; + extern int glob_ignore_case; + extern int hup_on_exit; + + #if defined (EXTENDED_GLOB) + extern int extended_glob; + #endif #if defined (HISTORY) *************** *** 90,93 **** --- 99,105 ---- { "execfail", &no_exit_on_failed_exec, (Function *)NULL }, { "expand_aliases", &expand_aliases, (Function *)NULL }, + #if defined (EXTENDED_GLOB) + { "extglob", &extended_glob, (Function *)NULL }, + #endif #if defined (READLINE) { "histreedit", &history_reediting, (Function *)NULL }, *************** *** 100,103 **** --- 112,116 ---- { "hostcomplete", &perform_hostname_completion, (Function *)enable_hostname_completion }, #endif + { "huponexit", &hup_on_exit, (Function *)NULL }, { "interactive_comments", &interactive_comments, set_interactive_comments }, #if defined (HISTORY) *************** *** 105,108 **** --- 118,122 ---- #endif { "mailwarn", &mail_warning, (Function *)NULL }, + { "nocaseglob", &glob_ignore_case, (Function *)NULL }, { "nullglob", &allow_null_glob_expansion, (Function *)NULL }, { "promptvars", &promptvars, (Function *)NULL }, *************** *** 167,181 **** rval = EXECUTION_SUCCESS; if ((flags & OFLAG) && ((flags & (SFLAG|UFLAG)) == 0)) /* shopt -o */ ! rval = list_shopt_o_options (list, flags & QFLAG); else if (list && (flags & OFLAG)) /* shopt -so args */ rval = set_shopt_o_options ((flags & SFLAG) ? FLAG_ON : FLAG_OFF, list, flags & QFLAG); else if (flags & OFLAG) /* shopt -so */ ! rval = list_some_o_options ((flags & SFLAG) ? FLAG_ON : FLAG_OFF, flags & QFLAG); else if (list && (flags & (SFLAG|UFLAG))) /* shopt -su args */ rval = toggle_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, list, flags & QFLAG); else if ((flags & (SFLAG|UFLAG)) == 0) /* shopt [args] */ ! rval = list_shopts (list, flags & QFLAG); else /* shopt -su */ ! rval = list_some_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, flags & QFLAG); return (rval); } --- 181,195 ---- rval = EXECUTION_SUCCESS; if ((flags & OFLAG) && ((flags & (SFLAG|UFLAG)) == 0)) /* shopt -o */ ! rval = list_shopt_o_options (list, flags); else if (list && (flags & OFLAG)) /* shopt -so args */ rval = set_shopt_o_options ((flags & SFLAG) ? FLAG_ON : FLAG_OFF, list, flags & QFLAG); else if (flags & OFLAG) /* shopt -so */ ! rval = list_some_o_options ((flags & SFLAG) ? 1 : 0, flags); else if (list && (flags & (SFLAG|UFLAG))) /* shopt -su args */ rval = toggle_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, list, flags & QFLAG); else if ((flags & (SFLAG|UFLAG)) == 0) /* shopt [args] */ ! rval = list_shopts (list, flags); else /* shopt -su */ ! rval = list_some_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, flags); return (rval); } *************** *** 193,196 **** --- 207,214 ---- source_uses_path = promptvars = 1; + #if defined (EXTENDED_GLOB) + extended_glob = 0; + #endif + #if defined (HISTORY) literal_history = force_append_history = 0; *************** *** 245,254 **** } /* List the values of all or any of the `shopt' options. Returns 0 if all were listed or all variables queried were on; 1 otherwise. */ static int ! list_shopts (list, quiet) WORD_LIST *list; ! int quiet; { WORD_LIST *l; --- 263,283 ---- } + static int + print_shopt (name, val, flags) + char *name; + int val, flags; + { + if (flags & PFLAG) + printf ("shopt %s %s\n", val ? "-s" : "-u", name); + else + printf (OPTFMT, name, val ? on : off); + } + /* List the values of all or any of the `shopt' options. Returns 0 if all were listed or all variables queried were on; 1 otherwise. */ static int ! list_shopts (list, flags) WORD_LIST *list; ! int flags; { WORD_LIST *l; *************** *** 260,265 **** { val = *shopt_vars[i].value; ! if (quiet == 0) ! printf (OPTFMT, shopt_vars[i].name, val ? on : off); } return (EXECUTION_SUCCESS); --- 289,294 ---- { val = *shopt_vars[i].value; ! if ((flags & QFLAG) == 0) ! print_shopt (shopt_vars[i].name, val, flags); } return (EXECUTION_SUCCESS); *************** *** 278,283 **** if (val == 0) rval = EXECUTION_FAILURE; ! if (quiet == 0) ! printf (OPTFMT, l->word->word, val ? on : off); } return (rval); --- 307,312 ---- if (val == 0) rval = EXECUTION_FAILURE; ! if ((flags & QFLAG) == 0) ! print_shopt (l->word->word, val, flags); } return (rval); *************** *** 285,290 **** static int ! list_some_shopts (mode, quiet) ! int mode, quiet; { int val, i; --- 314,319 ---- static int ! list_some_shopts (mode, flags) ! int mode, flags; { int val, i; *************** *** 293,298 **** { val = *shopt_vars[i].value; ! if (quiet == 0 && mode == val) ! printf (OPTFMT, shopt_vars[i].name, val ? on : off); } return (EXECUTION_SUCCESS); --- 322,327 ---- { val = *shopt_vars[i].value; ! if (((flags & QFLAG) == 0) && mode == val) ! print_shopt (shopt_vars[i].name, val, flags); } return (EXECUTION_SUCCESS); *************** *** 300,306 **** static int ! list_shopt_o_options (list, quiet) WORD_LIST *list; ! int quiet; { WORD_LIST *l; --- 329,335 ---- static int ! list_shopt_o_options (list, flags) WORD_LIST *list; ! int flags; { WORD_LIST *l; *************** *** 309,314 **** if (list == 0) { ! if (quiet == 0) ! list_minus_o_opts (-1); return (EXECUTION_SUCCESS); } --- 338,343 ---- if (list == 0) { ! if ((flags & QFLAG) == 0) ! list_minus_o_opts (-1, (flags & PFLAG)); return (EXECUTION_SUCCESS); } *************** *** 325,330 **** if (val == 0) rval = EXECUTION_FAILURE; ! if (quiet == 0) ! printf (OPTFMT, l->word->word, val ? "on" : "off"); } return (rval); --- 354,364 ---- if (val == 0) rval = EXECUTION_FAILURE; ! if ((flags & QFLAG) == 0) ! { ! if (flags & PFLAG) ! printf ("set %co %s\n", val ? '-' : '+', l->word->word); ! else ! printf (OPTFMT, l->word->word, val ? on : off); ! } } return (rval); *************** *** 332,340 **** static int ! list_some_o_options (mode, quiet) ! int mode, quiet; { ! if (quiet == 0) ! list_minus_o_opts (mode); return (EXECUTION_SUCCESS); } --- 366,374 ---- static int ! list_some_o_options (mode, flags) ! int mode, flags; { ! if ((flags & QFLAG) == 0) ! list_minus_o_opts (mode, (flags & PFLAG)); return (EXECUTION_SUCCESS); } diff -Nrc2 bash-2.01.1/builtins/source.def bash-2.02/builtins/source.def *** bash-2.01.1/builtins/source.def Fri Aug 9 14:09:19 1996 --- bash-2.02/builtins/source.def Thu Jul 17 09:44:41 1997 *************** *** 42,46 **** #include "../posixstat.h" #include "../filecntl.h" ! #include #include --- 42,48 ---- #include "../posixstat.h" #include "../filecntl.h" ! #ifndef _MINIX ! # include ! #endif #include *************** *** 52,56 **** #include "../shell.h" ! #include "../execute_cmd.h" #include "common.h" --- 54,58 ---- #include "../shell.h" ! #include "../findcmd.h" #include "common.h" diff -Nrc2 bash-2.01.1/builtins/suspend.def bash-2.02/builtins/suspend.def *** bash-2.01.1/builtins/suspend.def Wed Feb 5 11:49:32 1997 --- bash-2.02/builtins/suspend.def Fri Jul 18 17:00:49 1997 *************** *** 35,38 **** --- 35,41 ---- #if defined (JOB_CONTROL) #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/builtins/test.def bash-2.02/builtins/test.def *** bash-2.01.1/builtins/test.def Thu Aug 8 12:16:27 1996 --- bash-2.02/builtins/test.def Thu Sep 11 09:28:37 1997 *************** *** 51,57 **** -O FILE True if the file is effectively owned by you. -G FILE True if the file is effectively owned by your group. ! FILE1 -nt FILE2 True if file1 is newer than (according to ! modification date) file2. FILE1 -ot FILE2 True if file1 is older than file2. --- 51,58 ---- -O FILE True if the file is effectively owned by you. -G FILE True if the file is effectively owned by your group. + -N FILE True if the file has been modified since it was last read. ! FILE1 -nt FILE2 True if file1 is newer than file2 (according to ! modification date). FILE1 -ot FILE2 True if file1 is older than file2. *************** *** 71,80 **** True if the strings are not equal. STRING1 < STRING2 ! True if STRING1 sorts before STRING2 lexicographically STRING1 > STRING2 ! True if STRING1 sorts after STRING2 lexicographically Other operators: ! EXPR True if expr is false. EXPR1 -a EXPR2 True if both expr1 AND expr2 are true. --- 72,82 ---- True if the strings are not equal. STRING1 < STRING2 ! True if STRING1 sorts before STRING2 lexicographically. STRING1 > STRING2 ! True if STRING1 sorts after STRING2 lexicographically. Other operators: + -o OPTION True if the shell option OPTION is enabled. ! EXPR True if expr is false. EXPR1 -a EXPR2 True if both expr1 AND expr2 are true. *************** *** 100,103 **** --- 102,108 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 106,109 **** --- 111,115 ---- #include "../shell.h" + #include "../test.h" #include "common.h" diff -Nrc2 bash-2.01.1/builtins/times.def bash-2.02/builtins/times.def *** bash-2.01.1/builtins/times.def Wed Jul 24 13:06:55 1996 --- bash-2.02/builtins/times.def Mon Oct 6 12:55:22 1997 *************** *** 32,35 **** --- 32,38 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 54,58 **** #endif /* HAVE_SYS_TIMES_H */ ! #if defined (HAVE_SYS_RESOURCE_H) # include #endif --- 57,61 ---- #endif /* HAVE_SYS_TIMES_H */ ! #if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE) # include #endif diff -Nrc2 bash-2.01.1/builtins/trap.def bash-2.02/builtins/trap.def *** bash-2.01.1/builtins/trap.def Mon Aug 18 12:07:20 1997 --- bash-2.02/builtins/trap.def Mon Aug 18 12:06:35 1997 *************** *** 43,46 **** --- 43,49 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/builtins/type.def bash-2.02/builtins/type.def *** bash-2.01.1/builtins/type.def Tue Jun 3 11:21:51 1997 --- bash-2.02/builtins/type.def Thu Jul 10 11:55:57 1997 *************** *** 28,45 **** command name. ! If the -t option is used, returns a single word which is one of `alias', `keyword', `function', `builtin', `file' or `', if NAME is an alias, shell reserved word, shell function, shell builtin, disk file, or unfound, respectively. ! If the -p flag is used, either returns the name of the disk file ! that would be executed, or nothing if -t would not return `file'. ! ! If the -a flag is used, displays all of the places that contain an ! executable named `file'. This includes aliases and functions, if and ! only if the -p flag is not also used. ! ! Type accepts -all, -path, and -type in place of -a, -p, and -t, ! respectively. $END --- 28,43 ---- command name. ! If the -t option is used, `type' outputs a single word which is one of `alias', `keyword', `function', `builtin', `file' or `', if NAME is an alias, shell reserved word, shell function, shell builtin, disk file, or unfound, respectively. ! If the -p flag is used, `type' either returns the name of the disk ! file that would be executed, or nothing if `type -t NAME' would not ! return `file'. ! ! If the -a flag is used, `type' displays all of the places that contain ! an executable named `file'. This includes aliases and functions, if ! and only if the -p flag is not also used. $END *************** *** 57,61 **** #include "../shell.h" ! #include "../execute_cmd.h" #include "../hashcmd.h" --- 55,59 ---- #include "../shell.h" ! #include "../findcmd.h" #include "../hashcmd.h" diff -Nrc2 bash-2.01.1/builtins/ulimit.def bash-2.02/builtins/ulimit.def *** bash-2.01.1/builtins/ulimit.def Tue Apr 22 16:37:55 1997 --- bash-2.02/builtins/ulimit.def Thu Oct 9 13:19:19 1997 *************** *** 24,28 **** $BUILTIN ulimit $FUNCTION ulimit_builtin ! $DEPENDS_ON !MINIX $SHORT_DOC ulimit [-SHacdflmnpstuv] [limit] Ulimit provides control over the resources available to processes --- 24,28 ---- $BUILTIN ulimit $FUNCTION ulimit_builtin ! $DEPENDS_ON !_MINIX $SHORT_DOC ulimit [-SHacdflmnpstuv] [limit] Ulimit provides control over the resources available to processes *************** *** 53,60 **** $END #include #include "../bashtypes.h" ! #include #if defined (HAVE_UNISTD_H) --- 53,64 ---- $END + #if !defined (_MINIX) + #include #include "../bashtypes.h" ! #ifndef _MINIX ! # include ! #endif #if defined (HAVE_UNISTD_H) *************** *** 102,106 **** #if !defined (RLIMTYPE) # define RLIMTYPE long ! # define string_to_rlimtype string_to_long # define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "") #endif --- 106,110 ---- #if !defined (RLIMTYPE) # define RLIMTYPE long ! # define string_to_rlimtype(s) strtol(s, (char **)NULL, 10) # define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "") #endif *************** *** 598,603 **** puts ("unlimited"); else if (curlim == RLIM_INVALID) ! printf ("cannot get limit: %s\n", strerror (errno)); else print_rlimtype ((curlim / limits[limind].block_factor), 1); } --- 602,608 ---- puts ("unlimited"); else if (curlim == RLIM_INVALID) ! builtin_error ("cannot get limit: %s\n", strerror (errno)); else print_rlimtype ((curlim / limits[limind].block_factor), 1); } + #endif /* !_MINIX */ diff -Nrc2 bash-2.01.1/builtins/umask.def bash-2.02/builtins/umask.def *** bash-2.01.1/builtins/umask.def Fri Feb 28 13:54:59 1997 --- bash-2.02/builtins/umask.def Thu Jul 17 09:45:26 1997 *************** *** 24,33 **** $BUILTIN umask $FUNCTION umask_builtin ! $SHORT_DOC umask [-S] [mode] The user file-creation mask is set to MODE. If MODE is omitted, or if `-S' is supplied, the current value of the mask is printed. The `-S' option makes the output symbolic; otherwise an octal number is output. ! If MODE begins with a digit, it is interpreted as an octal number, ! otherwise it is a symbolic mode string like that accepted by chmod(1). $END --- 24,35 ---- $BUILTIN umask $FUNCTION umask_builtin ! $SHORT_DOC umask [-p] [-S] [mode] The user file-creation mask is set to MODE. If MODE is omitted, or if `-S' is supplied, the current value of the mask is printed. The `-S' option makes the output symbolic; otherwise an octal number is output. ! If `-p' is supplied, and MODE is omitted, the output is in a form ! that may be used as input. If MODE begins with a digit, it is ! interpreted as an octal number, otherwise it is a symbolic mode string ! like that accepted by chmod(1). $END *************** *** 36,40 **** #include "../bashtypes.h" #include "../filecntl.h" ! #include #if defined (HAVE_UNISTD_H) --- 38,44 ---- #include "../bashtypes.h" #include "../filecntl.h" ! #ifndef _MINIX ! # include ! #endif #if defined (HAVE_UNISTD_H) *************** *** 64,73 **** WORD_LIST *list; { ! int print_symbolically, opt, umask_value; mode_t umask_arg; ! print_symbolically = 0; reset_internal_getopt (); ! while ((opt = internal_getopt (list, "S")) != -1) { switch (opt) --- 68,77 ---- WORD_LIST *list; { ! int print_symbolically, opt, umask_value, pflag; mode_t umask_arg; ! print_symbolically = pflag = 0; reset_internal_getopt (); ! while ((opt = internal_getopt (list, "Sp")) != -1) { switch (opt) *************** *** 76,79 **** --- 80,86 ---- print_symbolically++; break; + case 'p': + pflag++; + break; default: builtin_usage (); *************** *** 117,120 **** --- 124,129 ---- umask (umask_arg); + if (pflag) + printf ("umask%s ", (print_symbolically ? " -S" : "")); if (print_symbolically) print_symbolic_umask (umask_arg); diff -Nrc2 bash-2.01.1/builtins/wait.def bash-2.02/builtins/wait.def *** bash-2.01.1/builtins/wait.def Thu Feb 20 15:20:00 1997 --- bash-2.02/builtins/wait.def Wed Jul 23 15:14:10 1997 *************** *** 137,140 **** --- 137,146 ---- status = wait_for_job (job); } + else if (job_control == 0 && *w == '%') + { + /* can't use jobspecs as arguments if job control is not active. */ + builtin_error ("job control not enabled"); + status = EXECUTION_FAILURE; + } #endif /* JOB_CONTROL */ else diff -Nrc2 bash-2.01.1/builtins.h bash-2.02/builtins.h *** bash-2.01.1/builtins.h Thu Apr 18 13:23:10 1996 --- bash-2.02/builtins.h Fri Jul 18 16:46:36 1997 *************** *** 22,25 **** --- 22,28 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/command.h bash-2.02/command.h *** bash-2.01.1/command.h Tue Mar 18 15:39:24 1997 --- bash-2.02/command.h Fri Nov 21 13:04:39 1997 *************** *** 55,59 **** /* Command Types: */ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, ! cm_connection, cm_function_def, cm_until, cm_group }; /* Possible values for the `flags' field of a WORD_DESC. */ --- 55,60 ---- /* Command Types: */ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, ! cm_connection, cm_function_def, cm_until, cm_group, ! cm_arith, cm_cond }; /* Possible values for the `flags' field of a WORD_DESC. */ *************** *** 144,147 **** --- 145,154 ---- struct select_com *Select; #endif + #if defined (DPAREN_ARITHMETIC) + struct arith_com *Arith; + #endif + #if defined (COND_COMMAND) + struct cond_com *Cond; + #endif } value; } COMMAND; *************** *** 208,211 **** --- 215,246 ---- } WHILE_COM; + #if defined (DPAREN_ARITHMETIC) + /* The arithmetic evaluation command, ((...)). Just a set of flags and + a WORD_LIST, of which the first element is the only one used, for the + time being. */ + typedef struct arith_com { + int flags; + WORD_LIST *exp; + int line; + } ARITH_COM; + #endif /* DPAREN_ARITHMETIC */ + + /* The conditional command, [[...]]. This is a binary tree -- we slippped + a recursive-descent parser into the YACC grammar to parse it. */ + #define COND_AND 1 + #define COND_OR 2 + #define COND_UNARY 3 + #define COND_BINARY 4 + #define COND_TERM 5 + #define COND_EXPR 6 + + typedef struct cond_com { + int flags; + int line; + int type; + WORD_DESC *op; + struct cond_com *left, *right; + } COND_COM; + /* The "simple" command. Just a collection of words and redirects. */ typedef struct simple_com { *************** *** 219,223 **** /* The "function definition" command. */ typedef struct function_def { ! int ignore; /* See description of CMD flags. */ WORD_DESC *name; /* The name of the function. */ COMMAND *command; /* The parsed execution tree. */ --- 254,258 ---- /* The "function definition" command. */ typedef struct function_def { ! int flags; /* See description of CMD flags. */ WORD_DESC *name; /* The name of the function. */ COMMAND *command; /* The parsed execution tree. */ diff -Nrc2 bash-2.01.1/config.h.in bash-2.02/config.h.in *** bash-2.01.1/config.h.in Tue Jul 29 10:54:26 1997 --- bash-2.02/config.h.in Thu Oct 9 11:43:00 1997 *************** *** 111,114 **** --- 111,122 ---- #undef DPAREN_ARITHMETIC + /* Define EXTENDED_GLOB if you want the ksh-style [*+@?!](patlist) extended + pattern matching. */ + #undef EXTENDED_GLOB + + /* Define COND_COMMAND if you want the ksh-style [[...]] conditional + command. */ + #undef COND_COMMAND + /* Define AFS if you are using Transarc's AFS. */ #undef AFS *************** *** 171,174 **** --- 179,191 ---- #undef _MINIX + /* The number of bytes in a int. */ + #undef SIZEOF_INT + + /* The number of bytes in a long. */ + #undef SIZEOF_LONG + + /* The number of bytes in a pointer to char. */ + #undef SIZEOF_CHAR_P + /* Define to `long' if doesn't define. */ #undef off_t *************** *** 183,186 **** --- 200,224 ---- #undef pid_t + /* Define to `int' if doesn't define. */ + #undef int32_t + + /* Define to `unsigned int' if doesn't define. */ + #undef u_int32_t + + /* Define to `int' if doesn't define. */ + #undef ptrdiff_t + + /* Define to `unsigned' if doesn't define. */ + #undef size_t + + /* Define to `int' if doesn't define. */ + #undef uid_t + + /* Define to `long' if doesn't define. */ + #undef clock_t + + /* Define to `long' if doesn't define. */ + #undef time_t + /* Define if the system does not provide POSIX.1 features except with this defined. */ *************** *** 198,204 **** #undef SETVBUF_REVERSED - /* Define to `unsigned' if doesn't define. */ - #undef size_t - /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be --- 236,239 ---- *************** *** 213,217 **** #undef STDC_HEADERS ! /* Define if `sys_siglist' is declared by . */ #undef SYS_SIGLIST_DECLARED --- 248,252 ---- #undef STDC_HEADERS ! /* Define if `sys_siglist' is declared by or . */ #undef SYS_SIGLIST_DECLARED *************** *** 219,231 **** #undef UNDER_SYS_SIGLIST_DECLARED - /* Define to `int' if doesn't define. */ - #undef uid_t - - /* Define to `long' if doesn't define. */ - #undef clock_t - - /* Define to `long' if doesn't define. */ - #undef time_t - #undef DUP2_BROKEN --- 254,257 ---- *************** *** 308,311 **** --- 334,339 ---- #undef STRUCT_WINSIZE_IN_SYS_IOCTL + #undef STRUCT_WINSIZE_IN_TERMIOS + #undef SPEED_T_IN_SYS_TYPES *************** *** 396,399 **** --- 424,436 ---- #undef HAVE_STRERROR + /* Define if you have the strtod function. */ + #undef HAVE_STRTOD + + /* Define if you have the strtol function. */ + #undef HAVE_STRTOL + + /* Define if you have the strtoul function. */ + #undef HAVE_STRTOUL + /* Define if you have the tcgetattr function. */ #undef HAVE_TCGETATTR *************** *** 496,499 **** --- 533,539 ---- /* Define if you have the header file. */ #undef HAVE_LIBINTL_H + + /* Define if you have the header file. */ + #undef HAVE_STDDEF_H #undef HAVE_LIBDL diff -Nrc2 bash-2.01.1/configure bash-2.02/configure *** bash-2.01.1/configure Mon Sep 22 12:58:33 1997 --- bash-2.02/configure Thu Apr 16 10:42:52 1998 *************** *** 1,5 **** #! /bin/sh ! # From configure.in for Bash 2.01, version 1.28, from autoconf version 2.12 --- 1,15 ---- #! /bin/sh ! # From configure.in for Bash 2.02, version 2.19, from autoconf version 2.12 ! ! ! ! ! ! ! ! ! ! *************** *** 113,116 **** --- 123,128 ---- --enable-command-timing enable the time reserved word and command timing" ac_help="$ac_help + --enable-cond-command enable the conditional command" + ac_help="$ac_help --enable-directory-stack enable builtins pushd/popd/dirs" ac_help="$ac_help *************** *** 119,122 **** --- 131,136 ---- --enable-dparen-arithmetic include ((...)) command" ac_help="$ac_help + --enable-extended-glob include ksh-style extended pattern matching" + ac_help="$ac_help --enable-help-builtin include the help builtin" ac_help="$ac_help *************** *** 136,139 **** --- 150,157 ---- ac_help="$ac_help --enable-usg-echo-default make the echo builtin expand escape sequences by default" + ac_help="$ac_help + --enable-profiling allow profiling with gprof" + ac_help="$ac_help + --enable-static-link link bash statically, for use as a root shell" # Initialize some variables set by options. *************** *** 674,678 **** echo $ac_n "checking host system type""... $ac_c" 1>&6 ! echo "configure:677: checking host system type" >&5 host_alias=$host --- 692,696 ---- echo $ac_n "checking host system type""... $ac_c" 1>&6 ! echo "configure:695: checking host system type" >&5 host_alias=$host *************** *** 704,708 **** case "${host_cpu}-${host_os}" in alpha-*) opt_gnu_malloc=no ;; # alpha running osf/1 or linux ! *cray*-*) opt_gnu_malloc=no ;; # Crays *-osf1*) opt_gnu_malloc=no ;; # other osf/1 machines sparc-svr4*) opt_gnu_malloc=no ;; # sparc SVR4, SVR4.2 --- 722,726 ---- case "${host_cpu}-${host_os}" in alpha-*) opt_gnu_malloc=no ;; # alpha running osf/1 or linux ! *Ccray*-*) opt_gnu_malloc=no ;; # Crays *-osf1*) opt_gnu_malloc=no ;; # other osf/1 machines sparc-svr4*) opt_gnu_malloc=no ;; # sparc SVR4, SVR4.2 *************** *** 710,714 **** sgi-irix6*) opt_gnu_malloc=no ;; # needs 8-byte alignment sparc-linux*) opt_gnu_malloc=no ;; # sparc running linux; requires ELF ! *-freebsd*) opt_gnu_malloc=no ;; # they claim it's better *-aix*) opt_gnu_malloc=no ;; # AIX machines *-nextstep*) opt_gnu_malloc=no ;; # NeXT machines running NeXTstep --- 728,732 ---- sgi-irix6*) opt_gnu_malloc=no ;; # needs 8-byte alignment sparc-linux*) opt_gnu_malloc=no ;; # sparc running linux; requires ELF ! #*-freebsd*) opt_gnu_malloc=no ;; # they claim it's better *-aix*) opt_gnu_malloc=no ;; # AIX machines *-nextstep*) opt_gnu_malloc=no ;; # NeXT machines running NeXTstep *************** *** 716,720 **** *-qnx*) opt_gnu_malloc=no ;; # QNX 4.2 *-machten4) opt_gnu_malloc=no ;; # MachTen 4.x ! *-bsdi2.1|*-bsdi3.0) opt_gnu_malloc=no ; : ${CC:=shlicc2} ;; # for loadable builtins esac --- 734,739 ---- *-qnx*) opt_gnu_malloc=no ;; # QNX 4.2 *-machten4) opt_gnu_malloc=no ;; # MachTen 4.x ! *-bsdi2.1|*-bsdi3.?) opt_gnu_malloc=no ; : ${CC:=shlicc2} ;; # for loadable builtins ! *-cygwin32*) opt_gnu_malloc=no ;; # Cygnus's CYGWIN32 environment esac *************** *** 803,810 **** --- 822,834 ---- opt_array_variables=yes opt_dparen_arith=yes + opt_extended_glob=yes opt_brace_expansion=yes opt_disabled_builtins=no opt_command_timing=yes opt_usg_echo=no + opt_cond_command=yes + + opt_static_link=no + opt_profiling=no # Check whether --enable-minimal-config or --disable-minimal-config was given. *************** *** 821,824 **** --- 845,849 ---- opt_select=no opt_help=no opt_array_variables=no opt_dparen_arith=no opt_brace_expansion=no opt_disabled_builtins=no opt_command_timing=no + opt_extended_glob=no opt_cond_command=no fi *************** *** 853,856 **** --- 878,887 ---- fi + # Check whether --enable-cond-command or --disable-cond-command was given. + if test "${enable_cond_command+set}" = set; then + enableval="$enable_cond_command" + opt_cond_command=$enableval + fi + # Check whether --enable-directory-stack or --disable-directory-stack was given. if test "${enable_directory_stack+set}" = set; then *************** *** 871,874 **** --- 902,911 ---- fi + # Check whether --enable-extended-glob or --disable-extended-glob was given. + if test "${enable_extended_glob+set}" = set; then + enableval="$enable_extended_glob" + opt_extended_glob=$enableval + fi + # Check whether --enable-help-builtin or --disable-help-builtin was given. if test "${enable_help_builtin+set}" = set; then *************** *** 926,929 **** --- 963,979 ---- + # Check whether --enable-profiling or --disable-profiling was given. + if test "${enable_profiling+set}" = set; then + enableval="$enable_profiling" + opt_profiling=$enableval + fi + + # Check whether --enable-static-link or --disable-static-link was given. + if test "${enable_static_link+set}" = set; then + enableval="$enable_static_link" + opt_static_link=$enableval + fi + + if test $opt_alias = yes; then *************** *** 1035,1038 **** --- 1085,1100 ---- fi + if test $opt_extended_glob = yes ; then + cat >> confdefs.h <<\EOF + #define EXTENDED_GLOB 1 + EOF + + fi + if test $opt_cond_command = yes ; then + cat >> confdefs.h <<\EOF + #define COND_COMMAND 1 + EOF + + fi if test "$opt_minimal_config" = yes; then *************** *** 1051,1063 **** ! BASHVERS=2.01 ! BASHPATCH=1 ! echo "Beginning configuration for bash-$BASHVERS" # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1062: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 1113,1125 ---- ! BASHVERS=2.02 ! BASHPATCH=0 ! echo "Beginning configuration for bash-$BASHVERS for ${host_cpu}-${host_vendor}-${host_os}" # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1124: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 1088,1092 **** set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1091: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 1150,1154 ---- set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1153: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 1136,1140 **** echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 ! echo "configure:1139: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c --- 1198,1202 ---- echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 ! echo "configure:1201: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c *************** *** 1146,1154 **** cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. --- 1208,1216 ---- cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. *************** *** 1170,1179 **** fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 ! echo "configure:1173: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 ! echo "configure:1178: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 1232,1241 ---- fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 ! echo "configure:1235: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 ! echo "configure:1240: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 1184,1188 **** #endif EOF ! if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1187: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else --- 1246,1250 ---- #endif EOF ! if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1249: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else *************** *** 1199,1203 **** CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 ! echo "configure:1202: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 1261,1265 ---- CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 ! echo "configure:1264: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 1226,1231 **** fi echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 ! echo "configure:1230: checking for POSIXized ISC" >&5 if test -d /etc/conf/kconfig.d && grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 --- 1288,1325 ---- fi + echo $ac_n "checking whether large file support needs explicit enabling""... $ac_c" 1>&6 + echo "configure:1292: checking whether large file support needs explicit enabling" >&5 + ac_getconfs='' + ac_result=yes + ac_set='' + ac_shellvars='CPPFLAGS LDFLAGS LIBS' + for ac_shellvar in $ac_shellvars; do + case $ac_shellvar in + CPPFLAGS) ac_lfsvar=LFS_CFLAGS ac_lfs64var=LFS64_CFLAGS ;; + *) ac_lfsvar=LFS_$ac_shellvar ac_lfs64var=LFS64_$ac_shellvar ;; + esac + eval test '"${'$ac_shellvar'+set}"' = set && ac_set=$ac_shellvar + (getconf $ac_lfsvar) >/dev/null 2>&1 || { ac_result=no; break; } + ac_getconf=`getconf $ac_lfsvar` + ac_getconf64=`getconf $ac_lfs64var` + ac_getconfs=$ac_getconfs$ac_getconf\ $ac_getconf64 + eval ac_test_$ac_shellvar="\$ac_getconf\ \$ac_getconf64" + done + case "$ac_result$ac_getconfs" in + yes) ac_result=no ;; + esac + case "$ac_result$ac_set" in + yes?*) ac_result="yes, but $ac_set is already set, so use its settings" + esac + echo "$ac_t""$ac_result" 1>&6 + case $ac_result in + yes) + for ac_shellvar in $ac_shellvars; do + eval $ac_shellvar=\$ac_test_$ac_shellvar + done ;; + esac + echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 ! echo "configure:1324: checking for POSIXized ISC" >&5 if test -d /etc/conf/kconfig.d && grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 *************** *** 1248,1252 **** echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 ! echo "configure:1251: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then --- 1342,1346 ---- echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 ! echo "configure:1345: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then *************** *** 1263,1267 **** # not just through cpp. cat > conftest.$ac_ext < --- 1357,1361 ---- # not just through cpp. cat > conftest.$ac_ext < *************** *** 1269,1273 **** EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:1272: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then --- 1363,1367 ---- EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:1366: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then *************** *** 1280,1284 **** CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < --- 1374,1378 ---- CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < *************** *** 1286,1290 **** EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:1289: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then --- 1380,1384 ---- EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:1383: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then *************** *** 1310,1324 **** ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6 ! echo "configure:1313: checking for minix/config.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:1323: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then --- 1404,1418 ---- ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6 ! echo "configure:1407: checking for minix/config.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:1417: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then *************** *** 1358,1365 **** --- 1452,1504 ---- + + if test "x$cross_compiling" = "xyes"; then + case "${host}" in + *-cygwin32*) + cross_cache=${srcdir}/cross-build/cygwin32.cache + if test -r "${cross_cache}"; then + echo "loading cross-build cache file ${cross_cache}" + . ${cross_cache} + fi + unset cross_cache + ;; + *) echo "configure: cross-compiling for a non-cygwin32 target is not supported" >&2 + ;; + esac + fi + + if test -z "$CC_FOR_BUILD"; then + if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' + else + CC_FOR_BUILD=gcc + fi + fi + + + if test "x$cross_compiling" = "xno"; then + SIGNAMES_H=lsignames.h + else + SIGNAMES_H='$(srcdir)/cross-build/win32sig.h' + fi + + + test -z "$CFLAGS" && CFLAGS=-g auto_cflags=1 test -n "$GCC" && test -n "$auto_cflags" && CFLAGS="$CFLAGS -O2" + if test "$opt_profiling" = "yes"; then + PROFILE_FLAGS=-pg + opt_static_link=yes + fi + + if test "$opt_static_link" = yes; then + # if we're using gcc, add `-static' to LDFLAGS + if test -n "$GCC" || test "$ac_cv_prog_gcc" = "yes"; then + LDFLAGS="$LDFLAGS -static" + fi + fi + *************** *** 1368,1372 **** if test $ac_cv_prog_gcc = yes; then echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6 ! echo "configure:1371: checking whether ${CC-cc} needs -traditional" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 1507,1511 ---- if test $ac_cv_prog_gcc = yes; then echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6 ! echo "configure:1510: checking whether ${CC-cc} needs -traditional" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 1374,1378 **** ac_pattern="Autoconf.*'x'" cat > conftest.$ac_ext < --- 1513,1517 ---- ac_pattern="Autoconf.*'x'" cat > conftest.$ac_ext < *************** *** 1392,1396 **** if test $ac_cv_prog_gcc_traditional = no; then cat > conftest.$ac_ext < --- 1531,1535 ---- if test $ac_cv_prog_gcc_traditional = no; then cat > conftest.$ac_ext < *************** *** 1425,1429 **** # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 ! echo "configure:1428: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then --- 1564,1568 ---- # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 ! echo "configure:1567: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then *************** *** 1477,1481 **** set dummy ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1480: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 1616,1620 ---- set dummy ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1619: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 1505,1509 **** set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1508: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 1644,1648 ---- set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1647: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 1536,1540 **** set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1539: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 1675,1679 ---- set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1678: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 1566,1570 **** echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 ! echo "configure:1569: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then --- 1705,1709 ---- echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 ! echo "configure:1708: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then *************** *** 1596,1605 **** # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 ! echo "configure:1599: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 1735,1744 ---- # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 ! echo "configure:1738: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 1608,1612 **** ; return 0; } EOF ! if { (eval echo configure:1611: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_header_alloca_h=yes --- 1747,1751 ---- ; return 0; } EOF ! if { (eval echo configure:1750: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_header_alloca_h=yes *************** *** 1629,1638 **** echo $ac_n "checking for alloca""... $ac_c" 1>&6 ! echo "configure:1632: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:1771: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_func_alloca_works=yes --- 1796,1800 ---- ; return 0; } EOF ! if { (eval echo configure:1799: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_func_alloca_works=yes *************** *** 1689,1698 **** echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 ! echo "configure:1692: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:1831: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:1722: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:1861: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" --- 1886,1890 ---- ; return 0; } EOF ! if { (eval echo configure:1889: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" *************** *** 1774,1778 **** echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 ! echo "configure:1777: checking stack direction for C alloca" >&5 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 1913,1917 ---- echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 ! echo "configure:1916: checking stack direction for C alloca" >&5 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 1782,1786 **** else cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_c_stack_direction=1 --- 1940,1944 ---- } EOF ! if { (eval echo configure:1943: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_c_stack_direction=1 *************** *** 1823,1827 **** echo $ac_n "checking whether getpgrp takes no argument""... $ac_c" 1>&6 ! echo "configure:1826: checking whether getpgrp takes no argument" >&5 if eval "test \"`echo '$''{'ac_cv_func_getpgrp_void'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 1962,1966 ---- echo $ac_n "checking whether getpgrp takes no argument""... $ac_c" 1>&6 ! echo "configure:1965: checking whether getpgrp takes no argument" >&5 if eval "test \"`echo '$''{'ac_cv_func_getpgrp_void'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 1831,1835 **** else cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_func_getpgrp_void=yes --- 2025,2029 ---- EOF ! if { (eval echo configure:2028: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_func_getpgrp_void=yes *************** *** 1910,1914 **** echo $ac_n "checking whether setvbuf arguments are reversed""... $ac_c" 1>&6 ! echo "configure:1913: checking whether setvbuf arguments are reversed" >&5 if eval "test \"`echo '$''{'ac_cv_func_setvbuf_reversed'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 2049,2053 ---- echo $ac_n "checking whether setvbuf arguments are reversed""... $ac_c" 1>&6 ! echo "configure:2052: checking whether setvbuf arguments are reversed" >&5 if eval "test \"`echo '$''{'ac_cv_func_setvbuf_reversed'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 1918,1922 **** else cat > conftest.$ac_ext < --- 2057,2061 ---- else cat > conftest.$ac_ext < *************** *** 1932,1936 **** } EOF ! if { (eval echo configure:1935: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_func_setvbuf_reversed=yes --- 2071,2075 ---- } EOF ! if { (eval echo configure:2074: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_func_setvbuf_reversed=yes *************** *** 1956,1965 **** echo $ac_n "checking for vprintf""... $ac_c" 1>&6 ! echo "configure:1959: checking for vprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:2098: checking for vprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_vprintf=yes" --- 2123,2127 ---- ; return 0; } EOF ! if { (eval echo configure:2126: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_vprintf=yes" *************** *** 2008,2017 **** if test "$ac_cv_func_vprintf" != yes; then echo $ac_n "checking for _doprnt""... $ac_c" 1>&6 ! echo "configure:2011: checking for _doprnt" >&5 if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:2150: checking for _doprnt" >&5 if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func__doprnt=yes" --- 2175,2179 ---- ; return 0; } EOF ! if { (eval echo configure:2178: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func__doprnt=yes" *************** *** 2061,2065 **** echo $ac_n "checking for wait3 that fills in rusage""... $ac_c" 1>&6 ! echo "configure:2064: checking for wait3 that fills in rusage" >&5 if eval "test \"`echo '$''{'ac_cv_func_wait3_rusage'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 2200,2204 ---- echo $ac_n "checking for wait3 that fills in rusage""... $ac_c" 1>&6 ! echo "configure:2203: checking for wait3 that fills in rusage" >&5 if eval "test \"`echo '$''{'ac_cv_func_wait3_rusage'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 2069,2073 **** else cat > conftest.$ac_ext < --- 2208,2212 ---- else cat > conftest.$ac_ext < *************** *** 2100,2104 **** } EOF ! if { (eval echo configure:2103: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_func_wait3_rusage=yes --- 2239,2243 ---- } EOF ! if { (eval echo configure:2242: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_func_wait3_rusage=yes *************** *** 2123,2127 **** echo $ac_n "checking for working strcoll""... $ac_c" 1>&6 ! echo "configure:2126: checking for working strcoll" >&5 if eval "test \"`echo '$''{'ac_cv_func_strcoll_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 2262,2266 ---- echo $ac_n "checking for working strcoll""... $ac_c" 1>&6 ! echo "configure:2265: checking for working strcoll" >&5 if eval "test \"`echo '$''{'ac_cv_func_strcoll_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 2131,2135 **** else cat > conftest.$ac_ext < --- 2270,2274 ---- else cat > conftest.$ac_ext < *************** *** 2141,2145 **** } EOF ! if { (eval echo configure:2144: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_func_strcoll_works=yes --- 2280,2284 ---- } EOF ! if { (eval echo configure:2283: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_func_strcoll_works=yes *************** *** 2166,2172 **** if test "$ac_cv_func_vprintf" = no; then echo $ac_n "checking for declaration of vprintf in stdio.h""... $ac_c" 1>&6 ! echo "configure:2169: checking for declaration of vprintf in stdio.h" >&5 cat > conftest.$ac_ext < --- 2305,2311 ---- if test "$ac_cv_func_vprintf" = no; then echo $ac_n "checking for declaration of vprintf in stdio.h""... $ac_c" 1>&6 ! echo "configure:2308: checking for declaration of vprintf in stdio.h" >&5 cat > conftest.$ac_ext < *************** *** 2189,2198 **** echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 ! echo "configure:2192: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 2328,2337 ---- echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 ! echo "configure:2331: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 2211,2215 **** ; return 0; } EOF ! if { (eval echo configure:2214: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void --- 2350,2354 ---- ; return 0; } EOF ! if { (eval echo configure:2353: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void *************** *** 2231,2240 **** echo $ac_n "checking for __setostype""... $ac_c" 1>&6 ! echo "configure:2234: checking for __setostype" >&5 if eval "test \"`echo '$''{'ac_cv_func___setostype'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:2373: checking for __setostype" >&5 if eval "test \"`echo '$''{'ac_cv_func___setostype'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func___setostype=yes" --- 2398,2402 ---- ; return 0; } EOF ! if { (eval echo configure:2401: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func___setostype=yes" *************** *** 2282,2291 **** echo $ac_n "checking for wait3""... $ac_c" 1>&6 ! echo "configure:2285: checking for wait3" >&5 if eval "test \"`echo '$''{'ac_cv_func_wait3'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:2424: checking for wait3" >&5 if eval "test \"`echo '$''{'ac_cv_func_wait3'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_wait3=yes" --- 2449,2453 ---- ; return 0; } EOF ! if { (eval echo configure:2452: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_wait3=yes" *************** *** 2334,2343 **** echo $ac_n "checking for mkfifo""... $ac_c" 1>&6 ! echo "configure:2337: checking for mkfifo" >&5 if eval "test \"`echo '$''{'ac_cv_func_mkfifo'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:2476: checking for mkfifo" >&5 if eval "test \"`echo '$''{'ac_cv_func_mkfifo'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_mkfifo=yes" --- 2501,2505 ---- ; return 0; } EOF ! if { (eval echo configure:2504: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_mkfifo=yes" *************** *** 2394,2403 **** do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 ! echo "configure:2397: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:2536: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" --- 2561,2565 ---- ; return 0; } EOF ! if { (eval echo configure:2564: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" *************** *** 2448,2461 **** for ac_func in bcopy bzero confstr getcwd strcasecmp setenv putenv \ ! setlinebuf setlocale strchr strerror tcgetattr uname \ ! sysconf ulimit times tzset siginterrupt memmove do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 ! echo "configure:2455: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:2595: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" --- 2620,2624 ---- ; return 0; } EOF ! if { (eval echo configure:2623: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" *************** *** 2509,2523 **** ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 ! echo "configure:2512: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:2522: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then --- 2649,2663 ---- ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 ! echo "configure:2652: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:2662: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then *************** *** 2548,2557 **** do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 ! echo "configure:2551: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:2691: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" --- 2716,2720 ---- ; return 0; } EOF ! if { (eval echo configure:2719: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" *************** *** 2603,2607 **** if test "$ac_cv_func_bindtextdomain" = "no"; then echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6 ! echo "configure:2606: checking for bindtextdomain in -lintl" >&5 ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then --- 2743,2747 ---- if test "$ac_cv_func_bindtextdomain" = "no"; then echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6 ! echo "configure:2746: checking for bindtextdomain in -lintl" >&5 ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then *************** *** 2611,2615 **** LIBS="-lintl $LIBS" cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" --- 2762,2766 ---- ; return 0; } EOF ! if { (eval echo configure:2765: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" *************** *** 2653,2662 **** do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 ! echo "configure:2656: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:2796: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" --- 2821,2825 ---- ; return 0; } EOF ! if { (eval echo configure:2824: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" *************** *** 2708,2713 **** fi echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 ! echo "configure:2712: checking for dlopen in -ldl" >&5 ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then --- 2848,2854 ---- fi + if test "$opt_static_link" != yes; then echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 ! echo "configure:2853: checking for dlopen in -ldl" >&5 ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then *************** *** 2717,2721 **** LIBS="-ldl $LIBS" cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" --- 2869,2873 ---- ; return 0; } EOF ! if { (eval echo configure:2872: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" *************** *** 2758,2767 **** do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 ! echo "configure:2761: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:2902: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" --- 2927,2931 ---- ; return 0; } EOF ! if { (eval echo configure:2930: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" *************** *** 2810,2821 **** done echo $ac_n "checking for sys_siglist declaration in signal.h or unistd.h""... $ac_c" 1>&6 ! echo "configure:2815: checking for sys_siglist declaration in signal.h or unistd.h" >&5 if eval "test \"`echo '$''{'ac_cv_decl_sys_siglist'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 2951,2963 ---- done + fi echo $ac_n "checking for sys_siglist declaration in signal.h or unistd.h""... $ac_c" 1>&6 ! echo "configure:2957: checking for sys_siglist declaration in signal.h or unistd.h" >&5 if eval "test \"`echo '$''{'ac_cv_decl_sys_siglist'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 2829,2833 **** ; return 0; } EOF ! if { (eval echo configure:2832: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_decl_sys_siglist=yes --- 2971,2975 ---- ; return 0; } EOF ! if { (eval echo configure:2974: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_decl_sys_siglist=yes *************** *** 2855,2864 **** ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 ! echo "configure:2858: checking for $ac_hdr that defines DIR" >&5 if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 2997,3006 ---- ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 ! echo "configure:3000: checking for $ac_hdr that defines DIR" >&5 if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 2868,2872 **** ; return 0; } EOF ! if { (eval echo configure:2871: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=yes" --- 3010,3014 ---- ; return 0; } EOF ! if { (eval echo configure:3013: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=yes" *************** *** 2893,2897 **** if test $ac_header_dirent = dirent.h; then echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 ! echo "configure:2896: checking for opendir in -ldir" >&5 ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then --- 3035,3039 ---- if test $ac_header_dirent = dirent.h; then echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 ! echo "configure:3038: checking for opendir in -ldir" >&5 ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then *************** *** 2901,2905 **** LIBS="-ldir $LIBS" cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" --- 3054,3058 ---- ; return 0; } EOF ! if { (eval echo configure:3057: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" *************** *** 2934,2938 **** else echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 ! echo "configure:2937: checking for opendir in -lx" >&5 ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then --- 3076,3080 ---- else echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 ! echo "configure:3079: checking for opendir in -lx" >&5 ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then *************** *** 2942,2946 **** LIBS="-lx $LIBS" cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" --- 3095,3099 ---- ; return 0; } EOF ! if { (eval echo configure:3098: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" *************** *** 2976,2985 **** echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 ! echo "configure:2979: checking whether time.h and sys/time.h may both be included" >&5 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 3118,3127 ---- echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 ! echo "configure:3121: checking whether time.h and sys/time.h may both be included" >&5 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 2990,2994 **** ; return 0; } EOF ! if { (eval echo configure:2993: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes --- 3132,3136 ---- ; return 0; } EOF ! if { (eval echo configure:3135: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes *************** *** 3012,3030 **** for ac_hdr in unistd.h stdlib.h stdarg.h varargs.h limits.h string.h \ ! memory.h locale.h termcap.h termio.h termios.h dlfcn.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 ! echo "configure:3019: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:3029: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then --- 3154,3173 ---- for ac_hdr in unistd.h stdlib.h stdarg.h varargs.h limits.h string.h \ ! memory.h locale.h termcap.h termio.h termios.h dlfcn.h \ ! stddef.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 ! echo "configure:3162: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:3172: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then *************** *** 3058,3072 **** ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 ! echo "configure:3061: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:3071: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then --- 3201,3215 ---- ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 ! echo "configure:3204: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:3214: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then *************** *** 3101,3105 **** else echo $ac_n "checking for socket library""... $ac_c" 1>&6 ! echo "configure:3104: checking for socket library" >&5 _bash_needmsg=yes fi --- 3244,3248 ---- else echo $ac_n "checking for socket library""... $ac_c" 1>&6 ! echo "configure:3247: checking for socket library" >&5 _bash_needmsg=yes fi *************** *** 3108,3112 **** else echo $ac_n "checking for getpeername in -lsocket""... $ac_c" 1>&6 ! echo "configure:3111: checking for getpeername in -lsocket" >&5 ac_lib_var=`echo socket'_'getpeername | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then --- 3251,3255 ---- else echo $ac_n "checking for getpeername in -lsocket""... $ac_c" 1>&6 ! echo "configure:3254: checking for getpeername in -lsocket" >&5 ac_lib_var=`echo socket'_'getpeername | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then *************** *** 3116,3120 **** LIBS="-lsocket -lnsl $LIBS" cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" --- 3270,3274 ---- ; return 0; } EOF ! if { (eval echo configure:3273: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" *************** *** 3160,3164 **** else echo $ac_n "checking for libnsl""... $ac_c" 1>&6 ! echo "configure:3163: checking for libnsl" >&5 _bash_needmsg=yes fi --- 3303,3307 ---- else echo $ac_n "checking for libnsl""... $ac_c" 1>&6 ! echo "configure:3306: checking for libnsl" >&5 _bash_needmsg=yes fi *************** *** 3167,3171 **** else echo $ac_n "checking for t_open in -lnsl""... $ac_c" 1>&6 ! echo "configure:3170: checking for t_open in -lnsl" >&5 ac_lib_var=`echo nsl'_'t_open | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then --- 3310,3314 ---- else echo $ac_n "checking for t_open in -lnsl""... $ac_c" 1>&6 ! echo "configure:3313: checking for t_open in -lnsl" >&5 ac_lib_var=`echo nsl'_'t_open | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then *************** *** 3175,3179 **** LIBS="-lnsl $LIBS" cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" --- 3329,3333 ---- ; return 0; } EOF ! if { (eval echo configure:3332: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" *************** *** 3231,3240 **** echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 ! echo "configure:3234: checking for uid_t in sys/types.h" >&5 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 3374,3383 ---- echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 ! echo "configure:3377: checking for uid_t in sys/types.h" >&5 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 3265,3269 **** echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6 ! echo "configure:3268: checking type of array argument to getgroups" >&5 if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 3408,3412 ---- echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6 ! echo "configure:3411: checking type of array argument to getgroups" >&5 if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 3273,3277 **** else cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_type_getgroups=gid_t --- 3441,3445 ---- EOF ! if { (eval echo configure:3444: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_type_getgroups=gid_t *************** *** 3312,3316 **** if test $ac_cv_type_getgroups = cross; then cat > conftest.$ac_ext < --- 3455,3459 ---- if test $ac_cv_type_getgroups = cross; then cat > conftest.$ac_ext < *************** *** 3336,3345 **** echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 ! echo "configure:3339: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 3479,3488 ---- echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 ! echo "configure:3482: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 3349,3353 **** EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:3352: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then --- 3492,3496 ---- EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:3495: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then *************** *** 3366,3370 **** # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < --- 3509,3513 ---- # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < *************** *** 3384,3388 **** # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < --- 3527,3531 ---- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < *************** *** 3405,3409 **** else cat > conftest.$ac_ext < --- 3548,3552 ---- else cat > conftest.$ac_ext < *************** *** 3416,3420 **** EOF ! if { (eval echo configure:3419: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then : --- 3559,3563 ---- EOF ! if { (eval echo configure:3562: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then : *************** *** 3440,3449 **** echo $ac_n "checking for off_t""... $ac_c" 1>&6 ! echo "configure:3443: checking for off_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 3583,3592 ---- echo $ac_n "checking for off_t""... $ac_c" 1>&6 ! echo "configure:3586: checking for off_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 3473,3482 **** echo $ac_n "checking for mode_t""... $ac_c" 1>&6 ! echo "configure:3476: checking for mode_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 3616,3625 ---- echo $ac_n "checking for mode_t""... $ac_c" 1>&6 ! echo "configure:3619: checking for mode_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 3506,3515 **** echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 ! echo "configure:3509: checking for uid_t in sys/types.h" >&5 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 3649,3658 ---- echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 ! echo "configure:3652: checking for uid_t in sys/types.h" >&5 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 3540,3549 **** echo $ac_n "checking for pid_t""... $ac_c" 1>&6 ! echo "configure:3543: checking for pid_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 3683,3692 ---- echo $ac_n "checking for pid_t""... $ac_c" 1>&6 ! echo "configure:3686: checking for pid_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 3573,3582 **** echo $ac_n "checking for size_t""... $ac_c" 1>&6 ! echo "configure:3576: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 3716,3725 ---- echo $ac_n "checking for size_t""... $ac_c" 1>&6 ! echo "configure:3719: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 3606,3615 **** echo $ac_n "checking for time_t""... $ac_c" 1>&6 ! echo "configure:3609: checking for time_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_time_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 3749,3758 ---- echo $ac_n "checking for time_t""... $ac_c" 1>&6 ! echo "configure:3752: checking for time_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_time_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 3640,3649 **** echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 ! echo "configure:3643: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 3783,3792 ---- echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 ! echo "configure:3786: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 3662,3666 **** ; return 0; } EOF ! if { (eval echo configure:3665: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void --- 3805,3809 ---- ; return 0; } EOF ! if { (eval echo configure:3808: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void *************** *** 3681,3691 **** echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 ! echo "configure:3685: checking whether stat file-mode macros are broken" >&5 if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 3824,4251 ---- + echo $ac_n "checking size of int""... $ac_c" 1>&6 + echo "configure:3828: checking size of int" >&5 + if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } + else + cat > conftest.$ac_ext < + main() + { + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(int)); + exit(0); + } + EOF + if { (eval echo configure:3847: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null + then + ac_cv_sizeof_int=`cat conftestval` + else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_int=0 + fi + rm -fr conftest* + fi + + fi + echo "$ac_t""$ac_cv_sizeof_int" 1>&6 + cat >> confdefs.h <&6 + echo "configure:3867: checking size of long" >&5 + if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } + else + cat > conftest.$ac_ext < + main() + { + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(long)); + exit(0); + } + EOF + if { (eval echo configure:3886: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null + then + ac_cv_sizeof_long=`cat conftestval` + else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_long=0 + fi + rm -fr conftest* + fi + + fi + echo "$ac_t""$ac_cv_sizeof_long" 1>&6 + cat >> confdefs.h <&6 + echo "configure:3906: checking size of char *" >&5 + if eval "test \"`echo '$''{'ac_cv_sizeof_char_p'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } + else + cat > conftest.$ac_ext < + main() + { + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(char *)); + exit(0); + } + EOF + if { (eval echo configure:3925: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null + then + ac_cv_sizeof_char_p=`cat conftestval` + else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_char_p=0 + fi + rm -fr conftest* + fi + + fi + echo "$ac_t""$ac_cv_sizeof_char_p" 1>&6 + cat >> confdefs.h <&6 + echo "configure:3946: checking for int32_t" >&5 + if eval "test \"`echo '$''{'ac_cv_type_int32_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + cat > conftest.$ac_ext < + #if STDC_HEADERS + #include + #include + #endif + EOF + if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "int32_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_int32_t=yes + else + rm -rf conftest* + ac_cv_type_int32_t=no + fi + rm -f conftest* + + fi + echo "$ac_t""$ac_cv_type_int32_t" 1>&6 + if test $ac_cv_type_int32_t = no; then + cat >> confdefs.h <<\EOF + #define int32_t + EOF + + fi + + if test "$ac_cv_type_int32_t" = "no"; then + + if test "X$bash_cv_type_int32_t" = "X"; then + _bash_needmsg=yes + else + echo $ac_n "checking which builtin C type is 32 bits wide""... $ac_c" 1>&6 + echo "configure:3984: checking which builtin C type is 32 bits wide" >&5 + _bash_needmsg= + fi + if eval "test \"`echo '$''{'bash_cv_type_int32_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + if test "$cross_compiling" = yes; then + { echo "configure: error: cannot check type sizes if cross-compiling -- defaulting to int" 1>&2; exit 1; } + bash_cv_type_int32_t=int + + else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null + then + bash_cv_type_int32_t=int + else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + bash_cv_type_int32_t=long + fi + rm -fr conftest* + fi + + fi + + if test "X$_bash_needmsg" = "Xyes"; then + echo $ac_n "checking which builtin C type is 32 bits wide""... $ac_c" 1>&6 + echo "configure:4028: checking which builtin C type is 32 bits wide" >&5 + fi + echo "$ac_t""$bash_cv_type_int32_t" 1>&6; + if test "$bash_cv_type_int32_t" = "int"; then + cat >> confdefs.h <<\EOF + #define int32_t int + EOF + + else + cat >> confdefs.h <<\EOF + #define int32_t long + EOF + + fi + + fi + echo $ac_n "checking for u_int32_t""... $ac_c" 1>&6 + echo "configure:4045: checking for u_int32_t" >&5 + if eval "test \"`echo '$''{'ac_cv_type_u_int32_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + cat > conftest.$ac_ext < + #if STDC_HEADERS + #include + #include + #endif + EOF + if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "u_int32_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_u_int32_t=yes + else + rm -rf conftest* + ac_cv_type_u_int32_t=no + fi + rm -f conftest* + + fi + echo "$ac_t""$ac_cv_type_u_int32_t" 1>&6 + if test $ac_cv_type_u_int32_t = no; then + cat >> confdefs.h <<\EOF + #define u_int32_t + EOF + + fi + + if test "$ac_cv_type_u_int32_t" = "no"; then + + if test "X$bash_cv_type_u_int32_t" = "X"; then + _bash_needmsg=yes + else + echo $ac_n "checking which unsigned builtin C type is 32 bits wide""... $ac_c" 1>&6 + echo "configure:4083: checking which unsigned builtin C type is 32 bits wide" >&5 + _bash_needmsg= + fi + if eval "test \"`echo '$''{'bash_cv_type_u_int32_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + if test "$cross_compiling" = yes; then + { echo "configure: error: cannot check type sizes if cross-compiling -- defaulting to int" 1>&2; exit 1; } + bash_cv_type_u_int32_t=int + + else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null + then + bash_cv_type_u_int32_t=int + else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + bash_cv_type_u_int32_t=long + fi + rm -fr conftest* + fi + + fi + + if test "X$_bash_needmsg" = "Xyes"; then + echo $ac_n "checking which unsigned builtin C type is 32 bits wide""... $ac_c" 1>&6 + echo "configure:4127: checking which unsigned builtin C type is 32 bits wide" >&5 + fi + echo "$ac_t""$bash_cv_type_u_int32_t" 1>&6; + if test "$bash_cv_type_u_int32_t" = "int"; then + cat >> confdefs.h <<\EOF + #define u_int32_t unsigned int + EOF + + else + cat >> confdefs.h <<\EOF + #define u_int32_t unsigned long + EOF + + fi + + fi + + echo $ac_n "checking for ptrdiff_t""... $ac_c" 1>&6 + echo "configure:4145: checking for ptrdiff_t" >&5 + if eval "test \"`echo '$''{'ac_cv_type_ptrdiff_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + cat > conftest.$ac_ext < + #if STDC_HEADERS + #include + #include + #endif + EOF + if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "ptrdiff_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_ptrdiff_t=yes + else + rm -rf conftest* + ac_cv_type_ptrdiff_t=no + fi + rm -f conftest* + + fi + echo "$ac_t""$ac_cv_type_ptrdiff_t" 1>&6 + if test $ac_cv_type_ptrdiff_t = no; then + cat >> confdefs.h <<\EOF + #define ptrdiff_t + EOF + + fi + + if test "$ac_cv_type_ptrdiff_t" = "no"; then + + if test "X$bash_cv_type_ptrdiff_t" = "X"; then + _bash_needmsg=yes + else + echo $ac_n "checking which builtin C type is correct for ptrdiff_t""... $ac_c" 1>&6 + echo "configure:4183: checking which builtin C type is correct for ptrdiff_t" >&5 + _bash_needmsg= + fi + if eval "test \"`echo '$''{'bash_cv_type_ptrdiff_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + if test "$cross_compiling" = yes; then + { echo "configure: error: cannot check type sizes if cross-compiling -- defaulting to int" 1>&2; exit 1; } + bash_cv_type_ptrdiff_t=int + + else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null + then + bash_cv_type_ptrdiff_t=int + else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + bash_cv_type_ptrdiff_t=long + fi + rm -fr conftest* + fi + + fi + + if test "X$_bash_needmsg" = "Xyes"; then + echo $ac_n "checking which builtin C type is correct for ptrdiff_t""... $ac_c" 1>&6 + echo "configure:4227: checking which builtin C type is correct for ptrdiff_t" >&5 + fi + echo "$ac_t""$bash_cv_type_ptrdiff_t" 1>&6; + if test "$bash_cv_type_ptrdiff_t" = "int"; then + cat >> confdefs.h <<\EOF + #define ptrdiff_t int + EOF + + else + cat >> confdefs.h <<\EOF + #define ptrdiff_t long + EOF + + fi + + fi + echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 ! echo "configure:4245: checking whether stat file-mode macros are broken" >&5 if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 3738,3742 **** cat > conftest.$ac_ext < --- 4298,4302 ---- cat > conftest.$ac_ext < *************** *** 3751,3755 **** if test -z "$bash_cv_struct_timeval"; then cat > conftest.$ac_ext < --- 4311,4315 ---- if test -z "$bash_cv_struct_timeval"; then cat > conftest.$ac_ext < *************** *** 3774,3778 **** echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 ! echo "configure:3777: checking whether byte ordering is bigendian" >&5 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 4334,4338 ---- echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 ! echo "configure:4337: checking whether byte ordering is bigendian" >&5 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 3781,3785 **** # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < --- 4341,4345 ---- # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < *************** *** 3792,3800 **** ; return 0; } EOF ! if { (eval echo configure:3795: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < --- 4352,4360 ---- ; return 0; } EOF ! if { (eval echo configure:4355: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < *************** *** 3807,3811 **** ; return 0; } EOF ! if { (eval echo configure:3810: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes --- 4367,4371 ---- ; return 0; } EOF ! if { (eval echo configure:4370: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes *************** *** 3827,3831 **** else cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_c_bigendian=no --- 4400,4404 ---- } EOF ! if { (eval echo configure:4403: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_c_bigendian=no *************** *** 3867,3871 **** ac_msg="whether #! works in shell scripts" echo $ac_n "checking $ac_msg""... $ac_c" 1>&6 ! echo "configure:3870: checking $ac_msg" >&5 if eval "test \"`echo '$''{'ac_cv_sys_interpreter'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 4427,4431 ---- ac_msg="whether #! works in shell scripts" echo $ac_n "checking $ac_msg""... $ac_c" 1>&6 ! echo "configure:4430: checking $ac_msg" >&5 if eval "test \"`echo '$''{'ac_cv_sys_interpreter'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 3893,3897 **** fi echo $ac_n "checking for restartable system calls""... $ac_c" 1>&6 ! echo "configure:3896: checking for restartable system calls" >&5 if eval "test \"`echo '$''{'ac_cv_sys_restartable_syscalls'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 4453,4457 ---- fi echo $ac_n "checking for restartable system calls""... $ac_c" 1>&6 ! echo "configure:4456: checking for restartable system calls" >&5 if eval "test \"`echo '$''{'ac_cv_sys_restartable_syscalls'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 3901,3905 **** else cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_sys_restartable_syscalls=yes --- 4479,4483 ---- EOF ! if { (eval echo configure:4482: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_sys_restartable_syscalls=yes *************** *** 3944,3953 **** if test "$ac_cv_func_lstat" = "no"; then echo $ac_n "checking for lstat""... $ac_c" 1>&6 ! echo "configure:3947: checking for lstat" >&5 if eval "test \"`echo '$''{'bash_cv_func_lstat'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:4507: checking for lstat" >&5 if eval "test \"`echo '$''{'bash_cv_func_lstat'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* bash_cv_func_lstat=yes --- 4516,4523 ---- int main() { ! lstat(".",(struct stat *)0); ; return 0; } EOF ! if { (eval echo configure:4522: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* bash_cv_func_lstat=yes *************** *** 3982,3994 **** echo $ac_n "checking if dup2 fails to clear the close-on-exec flag""... $ac_c" 1>&6 ! echo "configure:3985: checking if dup2 fails to clear the close-on-exec flag" >&5 if eval "test \"`echo '$''{'bash_cv_dup2_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check dup2 if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:4545: checking if dup2 fails to clear the close-on-exec flag" >&5 if eval "test \"`echo '$''{'bash_cv_dup2_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check dup2 if cross compiling -- defaulting to no" 1>&2; exit 1; } ! bash_cv_dup2_broken=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_dup2_broken=yes --- 4571,4575 ---- EOF ! if { (eval echo configure:4574: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_dup2_broken=yes *************** *** 4035,4047 **** echo $ac_n "checking whether pgrps need synchronization""... $ac_c" 1>&6 ! echo "configure:4038: checking whether pgrps need synchronization" >&5 if eval "test \"`echo '$''{'bash_cv_pgrp_pipe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check pgrp synchronization if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:4599: checking whether pgrps need synchronization" >&5 if eval "test \"`echo '$''{'bash_cv_pgrp_pipe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check pgrp synchronization if cross compiling -- defaulting to no" 1>&2; exit 1; } ! bash_cv_pgrp_pipe=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_pgrp_pipe=no --- 4657,4661 ---- EOF ! if { (eval echo configure:4660: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_pgrp_pipe=no *************** *** 4120,4124 **** echo $ac_n "checking for type of signal functions""... $ac_c" 1>&6 ! echo "configure:4123: checking for type of signal functions" >&5 if eval "test \"`echo '$''{'bash_cv_signal_vintage'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 4682,4686 ---- echo $ac_n "checking for type of signal functions""... $ac_c" 1>&6 ! echo "configure:4685: checking for type of signal functions" >&5 if eval "test \"`echo '$''{'bash_cv_signal_vintage'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 4126,4130 **** cat > conftest.$ac_ext < --- 4688,4692 ---- cat > conftest.$ac_ext < *************** *** 4139,4143 **** ; return 0; } EOF ! if { (eval echo configure:4142: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* bash_cv_signal_vintage=posix --- 4701,4705 ---- ; return 0; } EOF ! if { (eval echo configure:4704: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* bash_cv_signal_vintage=posix *************** *** 4148,4152 **** cat > conftest.$ac_ext < --- 4710,4714 ---- cat > conftest.$ac_ext < *************** *** 4158,4162 **** ; return 0; } EOF ! if { (eval echo configure:4161: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* bash_cv_signal_vintage=4.2bsd --- 4720,4724 ---- ; return 0; } EOF ! if { (eval echo configure:4723: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* bash_cv_signal_vintage=4.2bsd *************** *** 4167,4171 **** cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* bash_cv_signal_vintage=svr3 --- 4742,4746 ---- ; return 0; } EOF ! if { (eval echo configure:4745: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* bash_cv_signal_vintage=svr3 *************** *** 4219,4229 **** echo $ac_n "checking for sys_errlist and sys_nerr""... $ac_c" 1>&6 ! echo "configure:4223: checking for sys_errlist and sys_nerr" >&5 if eval "test \"`echo '$''{'bash_cv_sys_errlist'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 4781,4861 ---- + if test "$ac_cv_sys_restartable_syscalls" = "no"; then + + echo $ac_n "checking for restartable system calls with posix sigaction""... $ac_c" 1>&6 + echo "configure:4787: checking for restartable system calls with posix sigaction" >&5 + if eval "test \"`echo '$''{'bash_cv_sys_restartable_syscalls'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + if test "$cross_compiling" = yes; then + { echo "configure: error: cannot check restartable syscalls if cross compiling" 1>&2; exit 1; } + else + cat > conftest.$ac_ext < + #include + static int caught = 0; + void ucatch (isig) int isig; { caught = 1; } + main () + { + #if !defined (_POSIX_VERSION) || !defined (HAVE_POSIX_SIGNALS) + exit (1); + #else + struct sigaction act, oact; + int i, status; + + act.sa_handler = ucatch; + /* Might want to add SA_RESTART here, but bash's set_signal_handler + does not. */ + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + sigemptyset(&oact.sa_mask); + i = fork (); + /* A possible race condition here, but in practice it never happens. */ + if (i == 0) { sleep (3); kill (getppid (), SIGINT); sleep (3); exit (0); } + sigaction(SIGINT, &act, &oact); + status = wait(&i); + if (status == -1) wait(&i); + exit (status == -1); + #endif + } + + EOF + if { (eval echo configure:4829: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null + then + bash_cv_sys_restartable_syscalls=yes + else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + bash_cv_sys_restartable_syscalls=no + fi + rm -fr conftest* + fi + + + fi + + echo "$ac_t""$bash_cv_sys_restartable_syscalls" 1>&6 + if test $bash_cv_sys_restartable_syscalls = yes; then + cat >> confdefs.h <<\EOF + #define HAVE_RESTARTABLE_SYSCALLS 1 + EOF + + fi + + fi + echo $ac_n "checking for sys_errlist and sys_nerr""... $ac_c" 1>&6 ! echo "configure:4855: checking for sys_errlist and sys_nerr" >&5 if eval "test \"`echo '$''{'bash_cv_sys_errlist'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 4234,4238 **** ; return 0; } EOF ! if { (eval echo configure:4237: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* bash_cv_sys_errlist=yes --- 4866,4870 ---- ; return 0; } EOF ! if { (eval echo configure:4869: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* bash_cv_sys_errlist=yes *************** *** 4255,4267 **** echo $ac_n "checking for sys_siglist in system C library""... $ac_c" 1>&6 ! echo "configure:4258: checking for sys_siglist in system C library" >&5 if eval "test \"`echo '$''{'bash_cv_sys_siglist'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check for sys_siglist if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:4890: checking for sys_siglist in system C library" >&5 if eval "test \"`echo '$''{'bash_cv_sys_siglist'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check for sys_siglist if cross compiling -- defaulting to no" 1>&2; exit 1; } ! bash_cv_sys_siglist=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_sys_siglist=yes --- 4913,4917 ---- } EOF ! if { (eval echo configure:4916: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_sys_siglist=yes *************** *** 4293,4296 **** --- 4926,4930 ---- fi + echo "$ac_t""$bash_cv_sys_siglist" 1>&6 if test $bash_cv_sys_siglist = yes; then *************** *** 4302,4311 **** echo $ac_n "checking for _sys_siglist in signal.h or unistd.h""... $ac_c" 1>&6 ! echo "configure:4305: checking for _sys_siglist in signal.h or unistd.h" >&5 if eval "test \"`echo '$''{'bash_cv_decl_under_sys_siglist'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:4939: checking for _sys_siglist in signal.h or unistd.h" >&5 if eval "test \"`echo '$''{'bash_cv_decl_under_sys_siglist'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_decl_under_sys_siglist=yes --- 4953,4957 ---- ; return 0; } EOF ! if { (eval echo configure:4956: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_decl_under_sys_siglist=yes *************** *** 4340,4352 **** echo $ac_n "checking for _sys_siglist in system C library""... $ac_c" 1>&6 ! echo "configure:4343: checking for _sys_siglist in system C library" >&5 if eval "test \"`echo '$''{'bash_cv_under_sys_siglist'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check for _sys_siglist if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:4977: checking for _sys_siglist in system C library" >&5 if eval "test \"`echo '$''{'bash_cv_under_sys_siglist'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check for _sys_siglist if cross compiling -- defaulting to no" 1>&2; exit 1; } ! bash_cv_under_sys_siglist=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_under_sys_siglist=yes --- 5000,5004 ---- } EOF ! if { (eval echo configure:5003: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_under_sys_siglist=yes *************** *** 4378,4381 **** --- 5013,5017 ---- fi + echo "$ac_t""$bash_cv_under_sys_siglist" 1>&6 if test $bash_cv_under_sys_siglist = yes; then *************** *** 4388,4397 **** echo $ac_n "checking whether signal handlers are of type void""... $ac_c" 1>&6 ! echo "configure:4391: checking whether signal handlers are of type void" >&5 if eval "test \"`echo '$''{'bash_cv_void_sighandler'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 5024,5033 ---- echo $ac_n "checking whether signal handlers are of type void""... $ac_c" 1>&6 ! echo "configure:5027: checking whether signal handlers are of type void" >&5 if eval "test \"`echo '$''{'bash_cv_void_sighandler'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 4408,4412 **** ; return 0; } EOF ! if { (eval echo configure:4411: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_void_sighandler=yes --- 5044,5048 ---- ; return 0; } EOF ! if { (eval echo configure:5047: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_void_sighandler=yes *************** *** 4428,4437 **** echo $ac_n "checking for clock_t""... $ac_c" 1>&6 ! echo "configure:4431: checking for clock_t" >&5 if eval "test \"`echo '$''{'bash_cv_type_clock_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 5064,5073 ---- echo $ac_n "checking for clock_t""... $ac_c" 1>&6 ! echo "configure:5067: checking for clock_t" >&5 if eval "test \"`echo '$''{'bash_cv_type_clock_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 4464,4473 **** echo $ac_n "checking for sigset_t""... $ac_c" 1>&6 ! echo "configure:4467: checking for sigset_t" >&5 if eval "test \"`echo '$''{'bash_cv_type_sigset_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 5100,5109 ---- echo $ac_n "checking for sigset_t""... $ac_c" 1>&6 ! echo "configure:5103: checking for sigset_t" >&5 if eval "test \"`echo '$''{'bash_cv_type_sigset_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 4500,4509 **** echo $ac_n "checking for quad_t""... $ac_c" 1>&6 ! echo "configure:4503: checking for quad_t" >&5 if eval "test \"`echo '$''{'bash_cv_type_quad_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 5136,5145 ---- echo $ac_n "checking for quad_t""... $ac_c" 1>&6 ! echo "configure:5139: checking for quad_t" >&5 if eval "test \"`echo '$''{'bash_cv_type_quad_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 4541,4557 **** echo $ac_n "checking for size and type of struct rlimit fields""... $ac_c" 1>&6 ! echo "configure:4544: checking for size and type of struct rlimit fields" >&5 if eval "test \"`echo '$''{'bash_cv_type_rlimit'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { rlim_t xxx; ; return 0; } EOF ! if { (eval echo configure:4556: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_type_rlimit=rlim_t --- 5177,5194 ---- echo $ac_n "checking for size and type of struct rlimit fields""... $ac_c" 1>&6 ! echo "configure:5180: checking for size and type of struct rlimit fields" >&5 if eval "test \"`echo '$''{'bash_cv_type_rlimit'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < + #include int main() { rlim_t xxx; ; return 0; } EOF ! if { (eval echo configure:5193: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_type_rlimit=rlim_t *************** *** 4562,4569 **** if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check quad_t if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&2; exit 1; } ! bash_cv_type_rlimit=long else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_type_rlimit=quad_t --- 5219,5223 ---- } EOF ! if { (eval echo configure:5222: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_type_rlimit=quad_t *************** *** 4613,4622 **** echo $ac_n "checking for a c_line member of struct termios""... $ac_c" 1>&6 ! echo "configure:4616: checking for a c_line member of struct termios" >&5 if eval "test \"`echo '$''{'bash_cv_termios_ldisc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 5251,5260 ---- echo $ac_n "checking for a c_line member of struct termios""... $ac_c" 1>&6 ! echo "configure:5254: checking for a c_line member of struct termios" >&5 if eval "test \"`echo '$''{'bash_cv_termios_ldisc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 4626,4630 **** ; return 0; } EOF ! if { (eval echo configure:4629: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_termios_ldisc=yes --- 5264,5268 ---- ; return 0; } EOF ! if { (eval echo configure:5267: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_termios_ldisc=yes *************** *** 4646,4655 **** echo $ac_n "checking for a c_line member of struct termio""... $ac_c" 1>&6 ! echo "configure:4649: checking for a c_line member of struct termio" >&5 if eval "test \"`echo '$''{'bash_cv_termio_ldisc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 5284,5293 ---- echo $ac_n "checking for a c_line member of struct termio""... $ac_c" 1>&6 ! echo "configure:5287: checking for a c_line member of struct termio" >&5 if eval "test \"`echo '$''{'bash_cv_termio_ldisc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 4659,4663 **** ; return 0; } EOF ! if { (eval echo configure:4662: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_termio_ldisc=yes --- 5297,5301 ---- ; return 0; } EOF ! if { (eval echo configure:5300: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_termio_ldisc=yes *************** *** 4680,4689 **** echo $ac_n "checking if struct dirent has a d_ino member""... $ac_c" 1>&6 ! echo "configure:4683: checking if struct dirent has a d_ino member" >&5 if eval "test \"`echo '$''{'bash_cv_dirent_has_dino'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:5321: checking if struct dirent has a d_ino member" >&5 if eval "test \"`echo '$''{'bash_cv_dirent_has_dino'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_dirent_has_dino=yes --- 5352,5356 ---- ; return 0; } EOF ! if { (eval echo configure:5355: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_dirent_has_dino=yes *************** *** 4736,4745 **** echo $ac_n "checking if struct dirent has a d_fileno member""... $ac_c" 1>&6 ! echo "configure:4739: checking if struct dirent has a d_fileno member" >&5 if eval "test \"`echo '$''{'bash_cv_dirent_has_d_fileno'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:5377: checking if struct dirent has a d_fileno member" >&5 if eval "test \"`echo '$''{'bash_cv_dirent_has_d_fileno'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_dirent_has_d_fileno=yes --- 5408,5412 ---- ; return 0; } EOF ! if { (eval echo configure:5411: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_dirent_has_d_fileno=yes *************** *** 4790,4800 **** fi ! echo $ac_n "checking for struct winsize in sys/ioctl.h""... $ac_c" 1>&6 ! echo "configure:4794: checking for struct winsize in sys/ioctl.h" >&5 ! if eval "test \"`echo '$''{'bash_cv_struct_winsize_in_ioctl'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 5428,5438 ---- fi ! echo $ac_n "checking for struct winsize in sys/ioctl.h and termios.h""... $ac_c" 1>&6 ! echo "configure:5432: checking for struct winsize in sys/ioctl.h and termios.h" >&5 ! if eval "test \"`echo '$''{'bash_cv_struct_winsize_header'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 4804,4835 **** ; return 0; } EOF ! if { (eval echo configure:4807: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ! bash_cv_struct_winsize_in_ioctl=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ! bash_cv_struct_winsize_in_ioctl=no fi rm -f conftest* fi ! echo "$ac_t""$bash_cv_struct_winsize_in_ioctl" 1>&6 ! if test $bash_cv_struct_winsize_in_ioctl = yes; then ! cat >> confdefs.h <<\EOF #define STRUCT_WINSIZE_IN_SYS_IOCTL 1 EOF fi ! echo $ac_n "checking for the existance of strsignal""... $ac_c" 1>&6 ! echo "configure:4829: checking for the existance of strsignal" >&5 if eval "test \"`echo '$''{'bash_cv_have_strsignal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 5442,5500 ---- ; return 0; } EOF ! if { (eval echo configure:5445: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then ! rm -rf conftest* ! bash_cv_struct_winsize_header=ioctl_h ! else ! echo "configure: failed program was:" >&5 ! cat conftest.$ac_ext >&5 ! rm -rf conftest* ! cat > conftest.$ac_ext < ! #include ! int main() { ! struct winsize x; ! ; return 0; } ! EOF ! if { (eval echo configure:5461: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ! bash_cv_struct_winsize_header=termios_h else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ! bash_cv_struct_winsize_header=other ! fi ! rm -f conftest* ! fi rm -f conftest* fi ! if test $bash_cv_struct_winsize_header = ioctl_h; then ! echo "$ac_t""sys/ioctl.h" 1>&6 ! cat >> confdefs.h <<\EOF #define STRUCT_WINSIZE_IN_SYS_IOCTL 1 EOF + elif test $bash_cv_struct_winsize_header = termios_h; then + echo "$ac_t""termios.h" 1>&6 + cat >> confdefs.h <<\EOF + #define STRUCT_WINSIZE_IN_TERMIOS 1 + EOF + + else + echo "$ac_t""not found" 1>&6 fi ! echo $ac_n "checking for the existence of strsignal""... $ac_c" 1>&6 ! echo "configure:5494: checking for the existence of strsignal" >&5 if eval "test \"`echo '$''{'bash_cv_have_strsignal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 4839,4843 **** ; return 0; } EOF ! if { (eval echo configure:4842: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* bash_cv_have_strsignal=yes --- 5504,5508 ---- ; return 0; } EOF ! if { (eval echo configure:5507: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* bash_cv_have_strsignal=yes *************** *** 4860,4872 **** echo $ac_n "checking if opendir() opens non-directories""... $ac_c" 1>&6 ! echo "configure:4863: checking if opendir() opens non-directories" >&5 if eval "test \"`echo '$''{'bash_cv_opendir_not_robust'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check opendir if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:5528: checking if opendir() opens non-directories" >&5 if eval "test \"`echo '$''{'bash_cv_opendir_not_robust'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check opendir if cross compiling -- defaulting to no" 1>&2; exit 1; } ! bash_cv_opendir_not_robust=no ! else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_opendir_not_robust=yes --- 5571,5575 ---- } EOF ! if { (eval echo configure:5574: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_opendir_not_robust=yes *************** *** 4927,4939 **** echo $ac_n "checking for declaration of printf in ""... $ac_c" 1>&6 ! echo "configure:4930: checking for declaration of printf in " >&5 if eval "test \"`echo '$''{'bash_cv_printf_declared'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check printf declaration if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <""... $ac_c" 1>&6 ! echo "configure:5597: checking for declaration of printf in " >&5 if eval "test \"`echo '$''{'bash_cv_printf_declared'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check printf declaration if cross compiling -- defaulting to yes" 1>&2; exit 1; } ! bash_cv_printf_declared=yes ! else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_printf_declared=yes --- 5621,5625 ---- EOF ! if { (eval echo configure:5624: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_printf_declared=yes *************** *** 4975,4987 **** echo $ac_n "checking whether ulimit can substitute for getdtablesize""... $ac_c" 1>&6 ! echo "configure:4978: checking whether ulimit can substitute for getdtablesize" >&5 if eval "test \"`echo '$''{'bash_cv_ulimit_maxfds'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check ulimit if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:5647: checking whether ulimit can substitute for getdtablesize" >&5 if eval "test \"`echo '$''{'bash_cv_ulimit_maxfds'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check ulimit if cross compiling -- defaulting to no" 1>&2; exit 1; } ! bash_cv_ulimit_maxfds=no ! else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_ulimit_maxfds=yes --- 5664,5668 ---- EOF ! if { (eval echo configure:5667: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_ulimit_maxfds=yes *************** *** 5016,5028 **** echo $ac_n "checking to see if getenv can be redefined""... $ac_c" 1>&6 ! echo "configure:5019: checking to see if getenv can be redefined" >&5 if eval "test \"`echo '$''{'bash_cv_getenv_redef'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check getenv redefinition if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:5690: checking to see if getenv can be redefined" >&5 if eval "test \"`echo '$''{'bash_cv_getenv_redef'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check getenv redefinition if cross compiling -- defaulting to yes" 1>&2; exit 1; } ! bash_cv_getenv_redef=yes ! else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_getenv_redef=yes --- 5732,5736 ---- EOF ! if { (eval echo configure:5735: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_getenv_redef=yes *************** *** 5082,5094 **** echo $ac_n "checking if getcwd() calls popen()""... $ac_c" 1>&6 ! echo "configure:5085: checking if getcwd() calls popen()" >&5 if eval "test \"`echo '$''{'bash_cv_getcwd_calls_popen'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check whether getcwd calls popen if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:5758: checking if getcwd() calls popen()" >&5 if eval "test \"`echo '$''{'bash_cv_getcwd_calls_popen'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check whether getcwd calls popen if cross compiling -- defaulting to no" 1>&2; exit 1; } ! bash_cv_getcwd_calls_popen=no ! else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_getcwd_calls_popen=no --- 5820,5824 ---- EOF ! if { (eval echo configure:5823: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_getcwd_calls_popen=no *************** *** 5168,5177 **** echo $ac_n "checking for declaration of sbrk in ""... $ac_c" 1>&6 ! echo "configure:5171: checking for declaration of sbrk in " >&5 if eval "test \"`echo '$''{'bash_cv_sbrk_declared'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 5843,5852 ---- echo $ac_n "checking for declaration of sbrk in ""... $ac_c" 1>&6 ! echo "configure:5846: checking for declaration of sbrk in " >&5 if eval "test \"`echo '$''{'bash_cv_sbrk_declared'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 5199,5211 **** echo $ac_n "checking for presence of POSIX-style sigsetjmp/siglongjmp""... $ac_c" 1>&6 ! echo "configure:5202: checking for presence of POSIX-style sigsetjmp/siglongjmp" >&5 if eval "test \"`echo '$''{'bash_cv_func_sigsetjmp'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check for sigsetjmp/siglongjmp if cross-compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:5877: checking for presence of POSIX-style sigsetjmp/siglongjmp" >&5 if eval "test \"`echo '$''{'bash_cv_func_sigsetjmp'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check for sigsetjmp/siglongjmp if cross-compiling -- defaulting to missing" 1>&2; exit 1; } ! bash_cv_func_sigsetjmp=missing ! else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_func_sigsetjmp=present --- 5925,5929 ---- } EOF ! if { (eval echo configure:5928: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_func_sigsetjmp=present *************** *** 5260,5264 **** fi - fi --- 5937,5940 ---- *************** *** 5273,5285 **** echo $ac_n "checking whether or not strcoll and strcmp differ""... $ac_c" 1>&6 ! echo "configure:5276: checking whether or not strcoll and strcmp differ" >&5 if eval "test \"`echo '$''{'bash_cv_func_strcoll_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check strcoll if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:5952: checking whether or not strcoll and strcmp differ" >&5 if eval "test \"`echo '$''{'bash_cv_func_strcoll_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check strcoll if cross compiling -- defaulting to no" 1>&2; exit 1; } ! bash_cv_func_strcoll_broken=no ! else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_func_strcoll_broken=yes --- 5998,6002 ---- EOF ! if { (eval echo configure:6001: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_func_strcoll_broken=yes *************** *** 5332,5336 **** fi - fi --- 6010,6013 ---- *************** *** 5347,5359 **** echo $ac_n "checking if signal handlers must be reinstalled when invoked""... $ac_c" 1>&6 ! echo "configure:5350: checking if signal handlers must be reinstalled when invoked" >&5 if eval "test \"`echo '$''{'bash_cv_must_reinstall_sighandlers'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check signal handling if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:6027: checking if signal handlers must be reinstalled when invoked" >&5 if eval "test \"`echo '$''{'bash_cv_must_reinstall_sighandlers'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check signal handling if cross compiling -- defaulting to no" 1>&2; exit 1; } ! bash_cv_must_reinstall_sighandlers=no ! else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_must_reinstall_sighandlers=no --- 6081,6085 ---- EOF ! if { (eval echo configure:6084: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_must_reinstall_sighandlers=no *************** *** 5426,5438 **** echo $ac_n "checking for presence of necessary job control definitions""... $ac_c" 1>&6 ! echo "configure:5429: checking for presence of necessary job control definitions" >&5 if eval "test \"`echo '$''{'bash_cv_job_control_missing'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check job control if cross-compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:6108: checking for presence of necessary job control definitions" >&5 if eval "test \"`echo '$''{'bash_cv_job_control_missing'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check job control if cross-compiling -- defaulting to missing" 1>&2; exit 1; } ! bash_cv_job_control_missing=missing ! else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_job_control_missing=present --- 6162,6166 ---- } EOF ! if { (eval echo configure:6165: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_job_control_missing=present *************** *** 5493,5497 **** fi - fi --- 6174,6177 ---- *************** *** 5505,5517 **** echo $ac_n "checking for presence of named pipes""... $ac_c" 1>&6 ! echo "configure:5508: checking for presence of named pipes" >&5 if eval "test \"`echo '$''{'bash_cv_sys_named_pipes'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check for named pipes if cross-compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&6 ! echo "configure:6188: checking for presence of named pipes" >&5 if eval "test \"`echo '$''{'bash_cv_sys_named_pipes'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ! { echo "configure: error: cannot check for named pipes if cross-compiling -- defaulting to missing" 1>&2; exit 1; } ! bash_cv_sys_named_pipes=missing ! else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_sys_named_pipes=present --- 6229,6233 ---- } EOF ! if { (eval echo configure:6232: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then bash_cv_sys_named_pipes=present *************** *** 5559,5563 **** fi - fi --- 6241,6244 ---- *************** *** 5572,5581 **** echo $ac_n "checking for TIOCGWINSZ in sys/ioctl.h""... $ac_c" 1>&6 ! echo "configure:5575: checking for TIOCGWINSZ in sys/ioctl.h" >&5 if eval "test \"`echo '$''{'bash_cv_tiocgwinsz_in_ioctl'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 6253,6262 ---- echo $ac_n "checking for TIOCGWINSZ in sys/ioctl.h""... $ac_c" 1>&6 ! echo "configure:6256: checking for TIOCGWINSZ in sys/ioctl.h" >&5 if eval "test \"`echo '$''{'bash_cv_tiocgwinsz_in_ioctl'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 5585,5589 **** ; return 0; } EOF ! if { (eval echo configure:5588: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_tiocgwinsz_in_ioctl=yes --- 6266,6270 ---- ; return 0; } EOF ! if { (eval echo configure:6269: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_tiocgwinsz_in_ioctl=yes *************** *** 5606,5615 **** echo $ac_n "checking for TIOCSTAT in sys/ioctl.h""... $ac_c" 1>&6 ! echo "configure:5609: checking for TIOCSTAT in sys/ioctl.h" >&5 if eval "test \"`echo '$''{'bash_cv_tiocstat_in_ioctl'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 6287,6296 ---- echo $ac_n "checking for TIOCSTAT in sys/ioctl.h""... $ac_c" 1>&6 ! echo "configure:6290: checking for TIOCSTAT in sys/ioctl.h" >&5 if eval "test \"`echo '$''{'bash_cv_tiocstat_in_ioctl'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 5619,5623 **** ; return 0; } EOF ! if { (eval echo configure:5622: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_tiocstat_in_ioctl=yes --- 6300,6304 ---- ; return 0; } EOF ! if { (eval echo configure:6303: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_tiocstat_in_ioctl=yes *************** *** 5640,5649 **** echo $ac_n "checking for FIONREAD in sys/ioctl.h""... $ac_c" 1>&6 ! echo "configure:5643: checking for FIONREAD in sys/ioctl.h" >&5 if eval "test \"`echo '$''{'bash_cv_fionread_in_ioctl'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 6321,6330 ---- echo $ac_n "checking for FIONREAD in sys/ioctl.h""... $ac_c" 1>&6 ! echo "configure:6324: checking for FIONREAD in sys/ioctl.h" >&5 if eval "test \"`echo '$''{'bash_cv_fionread_in_ioctl'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 5653,5657 **** ; return 0; } EOF ! if { (eval echo configure:5656: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_fionread_in_ioctl=yes --- 6334,6338 ---- ; return 0; } EOF ! if { (eval echo configure:6337: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_fionread_in_ioctl=yes *************** *** 5675,5684 **** echo $ac_n "checking for speed_t in sys/types.h""... $ac_c" 1>&6 ! echo "configure:5678: checking for speed_t in sys/types.h" >&5 if eval "test \"`echo '$''{'bash_cv_speed_t_in_sys_types'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 6356,6365 ---- echo $ac_n "checking for speed_t in sys/types.h""... $ac_c" 1>&6 ! echo "configure:6359: checking for speed_t in sys/types.h" >&5 if eval "test \"`echo '$''{'bash_cv_speed_t_in_sys_types'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 5687,5691 **** ; return 0; } EOF ! if { (eval echo configure:5690: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_speed_t_in_sys_types=yes --- 6368,6372 ---- ; return 0; } EOF ! if { (eval echo configure:6371: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_speed_t_in_sys_types=yes *************** *** 5708,5717 **** echo $ac_n "checking whether programs are able to redeclare getpw functions""... $ac_c" 1>&6 ! echo "configure:5711: checking whether programs are able to redeclare getpw functions" >&5 if eval "test \"`echo '$''{'bash_cv_can_redecl_getpw'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < --- 6389,6398 ---- echo $ac_n "checking whether programs are able to redeclare getpw functions""... $ac_c" 1>&6 ! echo "configure:6392: checking whether programs are able to redeclare getpw functions" >&5 if eval "test \"`echo '$''{'bash_cv_can_redecl_getpw'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 5724,5728 **** ; return 0; } EOF ! if { (eval echo configure:5727: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_can_redecl_getpw=yes --- 6405,6409 ---- ; return 0; } EOF ! if { (eval echo configure:6408: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_can_redecl_getpw=yes *************** *** 5747,5756 **** case "$host_os" in hpux*) echo $ac_n "checking whether $host_os needs _KERNEL for RLIMIT defines""... $ac_c" 1>&6 ! echo "configure:5750: checking whether $host_os needs _KERNEL for RLIMIT defines" >&5 if eval "test \"`echo '$''{'bash_cv_kernel_rlimit'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:6431: checking whether $host_os needs _KERNEL for RLIMIT defines" >&5 if eval "test \"`echo '$''{'bash_cv_kernel_rlimit'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_kernel_rlimit=no --- 6446,6450 ---- ; return 0; } EOF ! if { (eval echo configure:6449: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_kernel_rlimit=no *************** *** 5773,5792 **** rm -rf conftest* cat > conftest.$ac_ext < ! #define _KERNEL ! #include ! #undef _KERNEL ! int main() { int f; f = RLIMIT_DATA; ! ; return 0; } EOF ! if { (eval echo configure:5791: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_kernel_rlimit=yes --- 6454,6473 ---- rm -rf conftest* cat > conftest.$ac_ext < ! #define _KERNEL ! #include ! #undef _KERNEL ! int main() { int f; f = RLIMIT_DATA; ! ; return 0; } EOF ! if { (eval echo configure:6472: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bash_cv_kernel_rlimit=yes *************** *** 5822,5826 **** else echo $ac_n "checking which library has the termcap functions""... $ac_c" 1>&6 ! echo "configure:5825: checking which library has the termcap functions" >&5 _bash_needmsg= fi --- 6503,6507 ---- else echo $ac_n "checking which library has the termcap functions""... $ac_c" 1>&6 ! echo "configure:6506: checking which library has the termcap functions" >&5 _bash_needmsg= fi *************** *** 5829,5833 **** else echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6 ! echo "configure:5832: checking for tgetent in -ltermcap" >&5 ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then --- 6510,6514 ---- else echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6 ! echo "configure:6513: checking for tgetent in -ltermcap" >&5 ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then *************** *** 5837,5841 **** LIBS="-ltermcap $LIBS" cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" --- 6529,6533 ---- ; return 0; } EOF ! if { (eval echo configure:6532: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" *************** *** 5867,5871 **** echo "$ac_t""no" 1>&6 echo $ac_n "checking for tgetent in -lcurses""... $ac_c" 1>&6 ! echo "configure:5870: checking for tgetent in -lcurses" >&5 ac_lib_var=`echo curses'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then --- 6548,6552 ---- echo "$ac_t""no" 1>&6 echo $ac_n "checking for tgetent in -lcurses""... $ac_c" 1>&6 ! echo "configure:6551: checking for tgetent in -lcurses" >&5 ac_lib_var=`echo curses'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then *************** *** 5875,5879 **** LIBS="-lcurses $LIBS" cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" --- 6567,6571 ---- ; return 0; } EOF ! if { (eval echo configure:6570: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" *************** *** 5905,5909 **** echo "$ac_t""no" 1>&6 echo $ac_n "checking for tgetent in -lncurses""... $ac_c" 1>&6 ! echo "configure:5908: checking for tgetent in -lncurses" >&5 ac_lib_var=`echo ncurses'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then --- 6586,6590 ---- echo "$ac_t""no" 1>&6 echo $ac_n "checking for tgetent in -lncurses""... $ac_c" 1>&6 ! echo "configure:6589: checking for tgetent in -lncurses" >&5 ac_lib_var=`echo ncurses'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then *************** *** 5913,5917 **** LIBS="-lncurses $LIBS" cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" --- 6605,6609 ---- ; return 0; } EOF ! if { (eval echo configure:6608: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" *************** *** 5953,5960 **** if test "X$_bash_needmsg" = "Xyes"; then echo $ac_n "checking which library has the termcap functions""... $ac_c" 1>&6 ! echo "configure:5956: checking which library has the termcap functions" >&5 fi echo "$ac_t""using $bash_cv_termcap_lib" 1>&6 ! if test $bash_cv_termcap_lib = gnutermcap; then LDFLAGS="$LDFLAGS -L./lib/termcap" TERMCAP_LIB="./lib/termcap/libtermcap.a" --- 6634,6641 ---- if test "X$_bash_needmsg" = "Xyes"; then echo $ac_n "checking which library has the termcap functions""... $ac_c" 1>&6 ! echo "configure:6637: checking which library has the termcap functions" >&5 fi echo "$ac_t""using $bash_cv_termcap_lib" 1>&6 ! if test $bash_cv_termcap_lib = gnutermcap && test -z "$prefer_curses"; then LDFLAGS="$LDFLAGS -L./lib/termcap" TERMCAP_LIB="./lib/termcap/libtermcap.a" *************** *** 5976,5980 **** echo $ac_n "checking whether /dev/fd is available""... $ac_c" 1>&6 ! echo "configure:5979: checking whether /dev/fd is available" >&5 if eval "test \"`echo '$''{'bash_cv_dev_fd'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 6657,6661 ---- echo $ac_n "checking whether /dev/fd is available""... $ac_c" 1>&6 ! echo "configure:6660: checking whether /dev/fd is available" >&5 if eval "test \"`echo '$''{'bash_cv_dev_fd'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 6012,6016 **** echo $ac_n "checking for default mail directory""... $ac_c" 1>&6 ! echo "configure:6015: checking for default mail directory" >&5 if eval "test \"`echo '$''{'bash_cv_mail_dir'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 6693,6697 ---- echo $ac_n "checking for default mail directory""... $ac_c" 1>&6 ! echo "configure:6696: checking for default mail directory" >&5 if eval "test \"`echo '$''{'bash_cv_mail_dir'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** *** 6104,6107 **** --- 6785,6789 ---- *qnx*) LOCAL_CFLAGS="-Dqnx -F -3s" LOCAL_LDFLAGS="-3s -lunix -lncurses" ;; powerux) LOCAL_LIBS="-lgen" ;; + cygwin32*) LOCAL_LIBS="-luser32" ;; esac *************** *** 6123,6132 **** case "$srcdir" in .) ;; ! *) for d in doc tests support lib ; do # dirs test -d $d || mkdir $d done ! for ld in readline glob tilde malloc termcap; do # libdirs test -d lib/$ld || mkdir lib/$ld done ;; esac --- 6805,6815 ---- case "$srcdir" in .) ;; ! *) for d in doc tests support lib examples; do # dirs test -d $d || mkdir $d done ! for ld in readline glob tilde malloc sh termcap; do # libdirs test -d lib/$ld || mkdir lib/$ld done + test -d examples/loadables || mkdir examples/loadables # loadable builtins ;; esac *************** *** 6151,6154 **** --- 6834,6839 ---- + + #AC_SUBST(ALLOCA_SOURCE) #AC_SUBST(ALLOCA_OBJECT) *************** *** 6256,6261 **** trap 'rm -fr `echo "Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile \ ! lib/malloc/Makefile lib/termcap/Makefile lib/tilde/Makefile \ ! doc/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF --- 7051,7057 ---- CONFIG_FILES=\${CONFIG_FILES-"Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile \ ! lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile \ ! lib/tilde/Makefile doc/Makefile support/Makefile \ ! examples/loadables/Makefile"} EOF cat >> $CONFIG_STATUS <<\EOF diff -Nrc2 bash-2.01.1/configure.in bash-2.02/configure.in *** bash-2.01.1/configure.in Tue Jul 29 10:55:31 1997 --- bash-2.02/configure.in Wed Mar 4 10:22:48 1998 *************** *** 1,4 **** dnl ! dnl Configure script for bash-2.01 dnl dnl report bugs to chet@po.cwru.edu --- 1,4 ---- dnl ! dnl Configure script for bash-2.02 dnl dnl report bugs to chet@po.cwru.edu *************** *** 7,11 **** dnl checks for version info ! AC_REVISION([for Bash 2.01, version 1.28, from autoconf version] AC_ACVERSION)dnl AC_INIT(shell.h) --- 7,11 ---- dnl checks for version info ! AC_REVISION([for Bash 2.02, version 2.19, from autoconf version] AC_ACVERSION)dnl AC_INIT(shell.h) *************** *** 35,39 **** case "${host_cpu}-${host_os}" in alpha-*) opt_gnu_malloc=no ;; # alpha running osf/1 or linux ! *cray*-*) opt_gnu_malloc=no ;; # Crays *-osf1*) opt_gnu_malloc=no ;; # other osf/1 machines sparc-svr4*) opt_gnu_malloc=no ;; # sparc SVR4, SVR4.2 --- 35,39 ---- case "${host_cpu}-${host_os}" in alpha-*) opt_gnu_malloc=no ;; # alpha running osf/1 or linux ! *[Cc]ray*-*) opt_gnu_malloc=no ;; # Crays *-osf1*) opt_gnu_malloc=no ;; # other osf/1 machines sparc-svr4*) opt_gnu_malloc=no ;; # sparc SVR4, SVR4.2 *************** *** 41,45 **** sgi-irix6*) opt_gnu_malloc=no ;; # needs 8-byte alignment sparc-linux*) opt_gnu_malloc=no ;; # sparc running linux; requires ELF ! *-freebsd*) opt_gnu_malloc=no ;; # they claim it's better *-aix*) opt_gnu_malloc=no ;; # AIX machines *-nextstep*) opt_gnu_malloc=no ;; # NeXT machines running NeXTstep --- 41,45 ---- sgi-irix6*) opt_gnu_malloc=no ;; # needs 8-byte alignment sparc-linux*) opt_gnu_malloc=no ;; # sparc running linux; requires ELF ! #*-freebsd*) opt_gnu_malloc=no ;; # they claim it's better *-aix*) opt_gnu_malloc=no ;; # AIX machines *-nextstep*) opt_gnu_malloc=no ;; # NeXT machines running NeXTstep *************** *** 47,51 **** *-qnx*) opt_gnu_malloc=no ;; # QNX 4.2 *-machten4) opt_gnu_malloc=no ;; # MachTen 4.x ! *-bsdi2.1|*-bsdi3.0) opt_gnu_malloc=no ; : ${CC:=shlicc2} ;; # for loadable builtins esac --- 47,52 ---- *-qnx*) opt_gnu_malloc=no ;; # QNX 4.2 *-machten4) opt_gnu_malloc=no ;; # MachTen 4.x ! *-bsdi2.1|*-bsdi3.?) opt_gnu_malloc=no ; : ${CC:=shlicc2} ;; # for loadable builtins ! *-cygwin32*) opt_gnu_malloc=no ;; # Cygnus's CYGWIN32 environment esac *************** *** 105,112 **** --- 106,119 ---- opt_array_variables=yes opt_dparen_arith=yes + opt_extended_glob=yes opt_brace_expansion=yes opt_disabled_builtins=no opt_command_timing=yes opt_usg_echo=no + opt_cond_command=yes + + dnl options that affect how bash is compiled and linked + opt_static_link=no + opt_profiling=no dnl argument parsing for optional features *************** *** 121,124 **** --- 128,132 ---- opt_select=no opt_help=no opt_array_variables=no opt_dparen_arith=no opt_brace_expansion=no opt_disabled_builtins=no opt_command_timing=no + opt_extended_glob=no opt_cond_command=no fi *************** *** 128,134 **** --- 136,144 ---- AC_ARG_ENABLE(brace-expansion, --enable-brace-expansion include brace expansion, opt_brace_expansion=$enableval) AC_ARG_ENABLE(command-timing, --enable-command-timing enable the time reserved word and command timing, opt_command_timing=$enableval) + AC_ARG_ENABLE(cond-command, --enable-cond-command enable the conditional command, opt_cond_command=$enableval) AC_ARG_ENABLE(directory-stack, --enable-directory-stack enable builtins pushd/popd/dirs, opt_dirstack=$enableval) AC_ARG_ENABLE(disabled-builtins, --enable-disabled-builtins allow disabled builtins to still be invoked, opt_disabled_builtins=$enableval) AC_ARG_ENABLE(dparen-arithmetic, [--enable-dparen-arithmetic include ((...)) command], opt_dparen_arith=$enableval) + AC_ARG_ENABLE(extended-glob, --enable-extended-glob include ksh-style extended pattern matching, opt_extended_glob=$enableval) AC_ARG_ENABLE(help-builtin, --enable-help-builtin include the help builtin, opt_help=$enableval) AC_ARG_ENABLE(history, --enable-history turn on command history, opt_history=$enableval) *************** *** 141,144 **** --- 151,158 ---- AC_ARG_ENABLE(usg-echo-default, --enable-usg-echo-default make the echo builtin expand escape sequences by default, opt_usg_echo=$enableval) + dnl options that alter how bash is compiled and linked + AC_ARG_ENABLE(profiling, --enable-profiling allow profiling with gprof, opt_profiling=$enableval) + AC_ARG_ENABLE(static-link, --enable-static-link [link bash statically, for use as a root shell], opt_static_link=$enableval) + dnl opt_job_control is handled later, after BASH_JOB_CONTROL_MISSING runs *************** *** 203,206 **** --- 217,226 ---- AC_DEFINE(DEFAULT_ECHO_TO_USG) fi + if test $opt_extended_glob = yes ; then + AC_DEFINE(EXTENDED_GLOB) + fi + if test $opt_cond_command = yes ; then + AC_DEFINE(COND_COMMAND) + fi if test "$opt_minimal_config" = yes; then *************** *** 227,237 **** esyscmd(cat _patchlevel)dnl ! echo "Beginning configuration for bash-$BASHVERS" dnl compilation checks AC_PROG_CC AC_ISC_POSIX AC_MINIX dnl We want these before the checks, so the checks can modify their values. test -z "$CFLAGS" && CFLAGS=-g auto_cflags=1 --- 247,298 ---- esyscmd(cat _patchlevel)dnl ! echo "Beginning configuration for bash-$BASHVERS for ${host_cpu}-${host_vendor}-${host_os}" dnl compilation checks + dnl AC_PROG_CC sets $cross_compiling to `yes' if cross-compiling for a + dnl different environment AC_PROG_CC + BASH_LARGE_FILE_SUPPORT AC_ISC_POSIX AC_MINIX + dnl BEGIN changes for CYGNUS cross-building for cygwin32 + + dnl load up the cross-building cache file -- add more cases and cache + dnl files as necessary + if test "x$cross_compiling" = "xyes"; then + case "${host}" in + *-cygwin32*) + cross_cache=${srcdir}/cross-build/cygwin32.cache + if test -r "${cross_cache}"; then + echo "loading cross-build cache file ${cross_cache}" + . ${cross_cache} + fi + unset cross_cache + ;; + *) echo "configure: cross-compiling for a non-cygwin32 target is not supported" >&2 + ;; + esac + fi + + if test -z "$CC_FOR_BUILD"; then + if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' + else + CC_FOR_BUILD=gcc + fi + fi + AC_SUBST(CC_FOR_BUILD) + + dnl Set SIGNAMES_H based on whether or not we're cross-compiling + if test "x$cross_compiling" = "xno"; then + SIGNAMES_H=lsignames.h + else + SIGNAMES_H='$(srcdir)/cross-build/win32sig.h' + fi + AC_SUBST(SIGNAMES_H) + + dnl END changes for CYGNUS cross-building for cygwin32 + dnl We want these before the checks, so the checks can modify their values. test -z "$CFLAGS" && CFLAGS=-g auto_cflags=1 *************** *** 240,243 **** --- 301,318 ---- test -n "$GCC" && test -n "$auto_cflags" && CFLAGS="$CFLAGS -O2" + dnl handle options that alter how bash is compiled and linked + dnl these must come after the test for cc/gcc + if test "$opt_profiling" = "yes"; then + PROFILE_FLAGS=-pg + opt_static_link=yes + fi + + if test "$opt_static_link" = yes; then + # if we're using gcc, add `-static' to LDFLAGS + if test -n "$GCC" || test "$ac_cv_prog_gcc" = "yes"; then + LDFLAGS="$LDFLAGS -static" + fi + fi + AC_SUBST(CFLAGS) AC_SUBST(CPPFLAGS) *************** *** 288,293 **** dnl checks for c library functions AC_CHECK_FUNCS(bcopy bzero confstr getcwd strcasecmp setenv putenv \ ! setlinebuf setlocale strchr strerror tcgetattr uname \ ! sysconf ulimit times tzset siginterrupt memmove) dnl checks for locale functions --- 363,369 ---- dnl checks for c library functions AC_CHECK_FUNCS(bcopy bzero confstr getcwd strcasecmp setenv putenv \ ! setlinebuf setlocale strchr strerror strtod strtol \ ! strtoul tcgetattr uname sysconf ulimit times tzset \ ! siginterrupt memmove) dnl checks for locale functions *************** *** 305,310 **** --- 381,388 ---- dnl checks for the dynamic loading library functions in libc and libdl + if test "$opt_static_link" != yes; then AC_CHECK_LIB(dl, dlopen) AC_CHECK_FUNCS(dlopen dlclose dlsym) + fi dnl this defines SYS_SIGLIST_DECLARED *************** *** 316,320 **** AC_CHECK_HEADERS(unistd.h stdlib.h stdarg.h varargs.h limits.h string.h \ ! memory.h locale.h termcap.h termio.h termios.h dlfcn.h) AC_CHECK_HEADERS(sys/ptem.h sys/pte.h sys/stream.h sys/select.h sys/file.h \ sys/resource.h sys/param.h sys/socket.h \ --- 394,399 ---- AC_CHECK_HEADERS(unistd.h stdlib.h stdarg.h varargs.h limits.h string.h \ ! memory.h locale.h termcap.h termio.h termios.h dlfcn.h \ ! stddef.h) AC_CHECK_HEADERS(sys/ptem.h sys/pte.h sys/stream.h sys/select.h sys/file.h \ sys/resource.h sys/param.h sys/socket.h \ *************** *** 340,343 **** --- 419,440 ---- AC_TYPE_SIGNAL + AC_CHECK_SIZEOF(int) + AC_CHECK_SIZEOF(long) + AC_CHECK_SIZEOF(char *) + + AC_CHECK_TYPE(int32_t) + if test "$ac_cv_type_int32_t" = "no"; then + BASH_TYPE_INT32_T + fi + AC_CHECK_TYPE(u_int32_t) + if test "$ac_cv_type_u_int32_t" = "no"; then + BASH_TYPE_U_INT32_T + fi + + AC_CHECK_TYPE(ptrdiff_t) + if test "$ac_cv_type_ptrdiff_t" = "no"; then + BASH_TYPE_PTRDIFF_T + fi + dnl structures AC_HEADER_STAT *************** *** 371,374 **** --- 468,475 ---- BASH_SIGNAL_CHECK + if test "$ac_cv_sys_restartable_syscalls" = "no"; then + BASH_SYS_RESTARTABLE_SYSCALLS + fi + dnl checking for the presence of certain library symbols BASH_SYS_ERRLIST *************** *** 472,475 **** --- 573,577 ---- *qnx*) LOCAL_CFLAGS="-Dqnx -F -3s" LOCAL_LDFLAGS="-3s -lunix -lncurses" ;; powerux) LOCAL_LIBS="-lgen" ;; + cygwin32*) LOCAL_LIBS="-luser32" ;; esac *************** *** 491,500 **** case "$srcdir" in .) ;; ! *) for d in doc tests support lib ; do # dirs test -d $d || mkdir $d done ! for ld in readline glob tilde malloc termcap; do # libdirs test -d lib/$ld || mkdir lib/$ld done ;; esac --- 593,603 ---- case "$srcdir" in .) ;; ! *) for d in doc tests support lib examples; do # dirs test -d $d || mkdir $d done ! for ld in readline glob tilde malloc sh termcap; do # libdirs test -d lib/$ld || mkdir lib/$ld done + test -d examples/loadables || mkdir examples/loadables # loadable builtins ;; esac *************** *** 502,505 **** --- 605,610 ---- BUILD_DIR=`pwd` + AC_SUBST(PROFILE_FLAGS) + AC_SUBST(incdir) AC_SUBST(BUILD_DIR) *************** *** 523,528 **** AC_OUTPUT([Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile \ ! lib/malloc/Makefile lib/termcap/Makefile lib/tilde/Makefile \ ! doc/Makefile], [ # Makefile uses this timestamp file to record whether config.h is up to date. --- 628,634 ---- AC_OUTPUT([Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile \ ! lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile \ ! lib/tilde/Makefile doc/Makefile support/Makefile \ ! examples/loadables/Makefile], [ # Makefile uses this timestamp file to record whether config.h is up to date. diff -Nrc2 bash-2.01.1/copy_cmd.c bash-2.02/copy_cmd.c *** bash-2.01.1/copy_cmd.c Mon Feb 17 14:24:15 1997 --- bash-2.02/copy_cmd.c Thu Jan 29 14:49:11 1998 *************** *** 23,27 **** #include "config.h" ! #include #if defined (HAVE_UNISTD_H) --- 23,27 ---- #include "config.h" ! #include "bashtypes.h" #if defined (HAVE_UNISTD_H) *************** *** 29,43 **** #endif #include "shell.h" WORD_DESC * ! copy_word (word) ! WORD_DESC *word; { WORD_DESC *new_word; new_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC)); ! FASTCOPY ((char *)word, (char *)new_word, sizeof (WORD_DESC)); ! new_word->word = savestring (word->word); return (new_word); } --- 29,45 ---- #endif + #include + #include "shell.h" WORD_DESC * ! copy_word (w) ! WORD_DESC *w; { WORD_DESC *new_word; new_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC)); ! FASTCOPY ((char *)w, (char *)new_word, sizeof (WORD_DESC)); ! new_word->word = savestring (w->word); return (new_word); } *************** *** 202,211 **** } static SIMPLE_COM * copy_simple_command (com) SIMPLE_COM *com; { ! SIMPLE_COM *new_simple = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM)); new_simple->flags = com->flags; new_simple->words = copy_word_list (com->words); --- 204,248 ---- } + #if defined (DPAREN_ARITHMETIC) + static ARITH_COM * + copy_arith_command (com) + ARITH_COM *com; + { + ARITH_COM *new_arith; + + new_arith = (ARITH_COM *)xmalloc (sizeof (ARITH_COM)); + new_arith->flags = com->flags; + new_arith->exp = copy_word_list (com->exp); + new_arith->line = com->line; + + return (new_arith); + } + #endif + + #if defined (COND_COMMAND) + static COND_COM * + copy_cond_command (com) + COND_COM *com; + { + COND_COM *new_cond; + + new_cond = (COND_COM *)xmalloc (sizeof (COND_COM)); + new_cond->flags = com->flags; + new_cond->line = com->line; + new_cond->op = copy_word (com->op); + new_cond->left = com->left ? copy_cond_command (com->left) : (COND_COM *)NULL; + new_cond->right = com->right ? copy_cond_command (com->right) : (COND_COM *)NULL; + + return (new_cond); + } + #endif + static SIMPLE_COM * copy_simple_command (com) SIMPLE_COM *com; { ! SIMPLE_COM *new_simple; + new_simple = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM)); new_simple->flags = com->flags; new_simple->words = copy_word_list (com->words); *************** *** 276,279 **** --- 313,328 ---- new_command->value.If = copy_if_command (command->value.If); break; + + #if defined (DPAREN_ARITHMETIC) + case cm_arith: + new_command->value.Arith = copy_arith_command (command->value.Arith); + break; + #endif + + #if defined (COND_COMMAND) + case cm_cond: + new_command->value.Cond = copy_cond_command (command->value.Cond); + break; + #endif case cm_simple: diff -Nrc2 bash-2.01.1/cross-build/cygwin32.cache bash-2.02/cross-build/cygwin32.cache *** bash-2.01.1/cross-build/cygwin32.cache Wed Dec 31 19:00:00 1969 --- bash-2.02/cross-build/cygwin32.cache Fri Jan 30 12:44:53 1998 *************** *** 0 **** --- 1,39 ---- + # 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'} + + 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'} + + # end of cross-build/cygwin32.cache diff -Nrc2 bash-2.01.1/cross-build/win32sig.h bash-2.02/cross-build/win32sig.h *** bash-2.01.1/cross-build/win32sig.h Wed Dec 31 19:00:00 1969 --- bash-2.02/cross-build/win32sig.h Tue Oct 14 12:25:43 1997 *************** *** 0 **** --- 1,254 ---- + /* This file is used when cross-compiling for the CYGWIN32 environment on + a Unix machine. */ + #include + #include + + #ifndef __GNUC__ + # error cross compiling requires gcc + #endif + + /* A translation list so we can be polite to our users. Use gcc + labelled initializers to set up the array. Note that some entries + might wind up being NULL. */ + + char *signal_names[NSIG + 2] = { + [0] "EXIT", + + #ifdef SIGLOST + [SIGLOST] "SIGLOST", + #endif + + #ifdef SIGMSG + [SIGMSG] "SIGMSG", + #endif + + #ifdef SIGDANGER + [SIGDANGER] "SIGDANGER", + #endif + + #ifdef SIGMIGRATE + [SIGMIGRATE] "SIGMIGRATE", + #endif + + #ifdef SIGPRE + [SIGPRE] "SIGPRE", + #endif + + #ifdef SIGVIRT + [SIGVIRT] "SIGVIRT", + #endif + + #ifdef SIGALRM1 + [SIGALRM1] "SIGALRM1", + #endif + + #ifdef SIGWAITING + [SIGWAITING] "SIGWAITING", + #endif + + #ifdef SIGGRANT + [SIGGRANT] "SIGGRANT", + #endif + + #ifdef SIGKAP + [SIGKAP] "SIGKAP", + #endif + + #ifdef SIGRETRACT + [SIGRETRACT] "SIGRETRACT", + #endif + + #ifdef SIGSOUND + [SIGSOUND] "SIGSOUND", + #endif + + #ifdef SIGSAK + [SIGSAK] "SIGSAK", + #endif + + #ifdef SIGLWP + [SIGLWP] "SIGLWP", + #endif + + #ifdef SIGFREEZE + [SIGFREEZE] "SIGFREEZE", + #endif + + #ifdef SIGTHAW + [SIGTHAW] "SIGTHAW", + #endif + + #ifdef SIGCANCEL + [SIGCANCEL] "SIGCANCEL", + #endif + + #ifdef SIGDIL + [SIGDIL] "SIGDIL", + #endif + + #ifdef SIGCLD + #ifndef SIGCHLD + [SIGCLD] "SIGCLD", + #else + #if SIGCHLD != SIGCLD + [SIGCLD] "SIGCLD", + #endif + #endif + #endif + + #ifdef SIGPWR + [SIGPWR] "SIGPWR", + #endif + + #ifdef SIGPOLL + #ifndef SIGIO + [SIGPOLL] "SIGPOLL", + #else + #if SIGIO != SIGPOLL + [SIGPOLL] "SIGPOLL", + #endif + #endif + #endif + + #ifdef SIGWINDOW + [SIGWINDOW] "SIGWINDOW", + #endif + + #ifdef SIGHUP + [SIGHUP] "SIGHUP", + #endif + + #ifdef SIGINT + [SIGINT] "SIGINT", + #endif + + #ifdef SIGQUIT + [SIGQUIT] "SIGQUIT", + #endif + + #ifdef SIGILL + [SIGILL] "SIGILL", + #endif + + #ifdef SIGTRAP + [SIGTRAP] "SIGTRAP", + #endif + + #ifdef SIGIOT + #ifndef SIGABRT + [SIGIOT] "SIGIOT", + #else + #if SIGABRT != SIGIOT + [SIGIOT] "SIGIOT", + #endif + #endif + #endif + + #ifdef SIGABRT + [SIGABRT] "SIGABRT", + #endif + + #ifdef SIGEMT + [SIGEMT] "SIGEMT", + #endif + + #ifdef SIGFPE + [SIGFPE] "SIGFPE", + #endif + + #ifdef SIGKILL + [SIGKILL] "SIGKILL", + #endif + + #ifdef SIGBUS + [SIGBUS] "SIGBUS", + #endif + + #ifdef SIGSEGV + [SIGSEGV] "SIGSEGV", + #endif + + #ifdef SIGSYS + [SIGSYS] "SIGSYS", + #endif + + #ifdef SIGPIPE + [SIGPIPE] "SIGPIPE", + #endif + + #ifdef SIGALRM + [SIGALRM] "SIGALRM", + #endif + + #ifdef SIGTERM + [SIGTERM] "SIGTERM", + #endif + + #ifdef SIGURG + [SIGURG] "SIGURG", + #endif + + #ifdef SIGSTOP + [SIGSTOP] "SIGSTOP", + #endif + + #ifdef SIGTSTP + [SIGTSTP] "SIGTSTP", + #endif + + #ifdef SIGCONT + [SIGCONT] "SIGCONT", + #endif + + #ifdef SIGCHLD + [SIGCHLD] "SIGCHLD", + #endif + + #ifdef SIGTTIN + [SIGTTIN] "SIGTTIN", + #endif + + #ifdef SIGTTOU + [SIGTTOU] "SIGTTOU", + #endif + + #ifdef SIGIO + [SIGIO] "SIGIO", + #endif + + #ifdef SIGXCPU + [SIGXCPU] "SIGXCPU", + #endif + + #ifdef SIGXFSZ + [SIGXFSZ] "SIGXFSZ", + #endif + + #ifdef SIGVTALRM + [SIGVTALRM] "SIGVTALRM", + #endif + + #ifdef SIGPROF + [SIGPROF] "SIGPROF", + #endif + + #ifdef SIGWINCH + [SIGWINCH] "SIGWINCH", + #endif + + #ifdef SIGINFO + [SIGINFO] "SIGINFO", + #endif + + #ifdef SIGUSR1 + [SIGUSR1] "SIGUSR1", + #endif + + #ifdef SIGUSR2 + [SIGUSR2] "SIGUSR2", + #endif + + [NSIG] "DEBUG", + + [NSIG + 1] (char *)0x0 + }; diff -Nrc2 bash-2.01.1/dispose_cmd.c bash-2.02/dispose_cmd.c *** bash-2.01.1/dispose_cmd.c Tue Feb 25 12:17:14 1997 --- bash-2.02/dispose_cmd.c Thu Jan 29 14:52:25 1998 *************** *** 21,24 **** --- 21,26 ---- #include "config.h" + #include "bashtypes.h" + #if defined (HAVE_UNISTD_H) # include *************** *** 133,136 **** --- 135,161 ---- } + #if defined (DPAREN_ARITHMETIC) + case cm_arith: + { + register ARITH_COM *c; + + c = command->value.Arith; + dispose_words (c->exp); + free (c); + break; + } + #endif /* DPAREN_ARITHMETIC */ + + #if defined (COND_COMMAND) + case cm_cond: + { + register COND_COM *c; + + c = command->value.Cond; + dispose_cond_node (c); + break; + } + #endif /* COND_COMMAND */ + case cm_function_def: { *************** *** 151,161 **** } /* How to free a WORD_DESC. */ void ! dispose_word (word) ! WORD_DESC *word; { ! FREE (word->word); ! free (word); } --- 176,205 ---- } + #if defined (COND_COMMAND) + /* How to free a node in a conditional command. */ + void + dispose_cond_node (cond) + COND_COM *cond; + { + if (cond) + { + if (cond->left) + dispose_cond_node (cond->left); + if (cond->right) + dispose_cond_node (cond->right); + if (cond->op) + dispose_word (cond->op); + free (cond); + } + } + #endif /* COND_COMMAND */ + /* How to free a WORD_DESC. */ void ! dispose_word (w) ! WORD_DESC *w; { ! FREE (w->word); ! free (w); } diff -Nrc2 bash-2.01.1/dispose_cmd.h bash-2.02/dispose_cmd.h *** bash-2.01.1/dispose_cmd.h Sun Dec 19 15:08:01 1993 --- bash-2.02/dispose_cmd.h Fri Sep 12 13:14:51 1997 *************** *** 30,32 **** --- 30,36 ---- extern void dispose_redirects __P((REDIRECT *)); + #if defined (COND_COMMAND) + extern void dispose_cond_node __P((COND_COM *)); + #endif + #endif /* !_DISPOSE_CMD_H_ */ diff -Nrc2 bash-2.01.1/doc/FAQ bash-2.02/doc/FAQ *** bash-2.01.1/doc/FAQ Thu Jun 5 10:59:13 1997 --- bash-2.02/doc/FAQ Thu Apr 16 13:31:25 1998 *************** *** 1,3 **** ! This is the Bash FAQ, version 2.5, for Bash version 2.01. This document contains a set of frequently-asked questions concerning --- 1,3 ---- ! This is the Bash FAQ, version 2.11, for Bash version 2.02. This document contains a set of frequently-asked questions concerning *************** *** 14,18 **** This document is available for anonymous FTP with the URL ! ftp://slc2.ins.cwru.edu/pub/bash/FAQ ---------- --- 14,18 ---- This document is available for anonymous FTP with the URL ! ftp://ftp.cwru.edu/pub/bash/FAQ ---------- *************** *** 35,40 **** Section B: The latest version ! 11) What's new in version 2.01? ! 12) Are there any user-visible incompatibilities between bash-2.01 and bash-1.14.7? --- 35,40 ---- Section B: The latest version ! 11) What's new in version 2.02? ! 12) Are there any user-visible incompatibilities between bash-2.02 and bash-1.14.7? *************** *** 121,125 **** 2) What's the latest version? ! The latest version is 2.01, first made available on June 6, 1997. 3) Where can I get it? --- 121,125 ---- 2) What's the latest version? ! The latest version is 2.02, first made available on Monday, 20 April, 1998. 3) Where can I get it? *************** *** 127,141 **** Bash is the GNU project's shell, and so is available from the master GNU archive site, prep.ai.mit.edu, and its mirrors. The ! latest version is also available for FTP from slc2.ins.cwru.edu, ! the maintainer's machine. The following URLs tell how to get ! version 2.01: ! ftp://prep.ai.mit.edu/pub/gnu/bash-2.01.tar.gz ! ftp://slc2.ins.cwru.edu/pub/dist/bash-2.01.tar.gz Formatted versions of the documentation are available with the URLs: ! ftp://prep.ai.mit.edu/pub/gnu/bash-doc-2.01.tar.gz ! ftp://slc2.ins.cwru.edu/pub/dist/bash-doc-2.01.tar.gz 4) On what machines will bash run? --- 127,140 ---- Bash is the GNU project's shell, and so is available from the master GNU archive site, prep.ai.mit.edu, and its mirrors. The ! latest version is also available for FTP from ftp.cwru.edu. ! The following URLs tell how to get version 2.02: ! ftp://prep.ai.mit.edu/pub/gnu/bash-2.02.tar.gz ! ftp://ftp.cwru.edu/pub/bash/bash-2.02.tar.gz Formatted versions of the documentation are available with the URLs: ! ftp://prep.ai.mit.edu/pub/gnu/bash-doc-2.02.tar.gz ! ftp://ftp.cwru.edu/pub/bash/bash-doc-2.02.tar.gz 4) On what machines will bash run? *************** *** 163,168 **** http://www.cygnus.com/misc/gnu-win32 ! Cygnus has ported bash-1.14.7. Maybe someday they (or I) will port ! bash-2.01 (or later) to the GNU-Win32 environment. D. J. Delorie has ported bash-1.14.7 to run under MS-DOS, as part of --- 162,181 ---- http://www.cygnus.com/misc/gnu-win32 ! Cygnus has ported bash-1.14.7, and their port is part of the current ! gnu-win32 release. Cygnus has also done a port of bash-2.01 to the ! GNU-Win32 environment, and it should be available as part of their next ! release. ! ! Bash-2.02 should require no local Cygnus changes to build and run under ! GNU-WIN32. ! ! 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 ! ! Softway Systems has ported bash-2.01.1 to their OpenNT system, a ! Unix subsystem for NT that replaces the Microsoft POSIX subsystem. ! Check out http://www.opennt.com for more information. D. J. Delorie has ported bash-1.14.7 to run under MS-DOS, as part of *************** *** 180,188 **** ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh1147s.zip ! A port of bash-1.12 is available for OS/2 from ! ftp://hobbes.nmsu.edu/os2/unix/bash_112.zip ! I haven't looked at it. 6) How can I build bash with gcc? --- 193,203 ---- ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh1147s.zip ! 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. 6) How can I build bash with gcc? *************** *** 194,202 **** Some machines let you use `chsh' to change your login shell. Other ! systems use `passwd -s'. 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 --- 209,217 ---- 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 *************** *** 299,305 **** Section B: The latest version ! 11) What's new in version 2.01? ! Bash-2.01 contains only a few new features. new `GROUPS' builtin array variable containing the user's group list --- 314,342 ---- Section B: The latest version ! 11) What's new in version 2.02? ! Bash-2.02 has a number of new features. Here's a short list: ! ! 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 $( $@ + .1.html: + $(RM) $@ + -${MAN2HTML} $< | ${HTMLPOST} > $@ + .ms.ps: $(RM) $@ *************** *** 72,75 **** --- 78,85 ---- -${NROFF} -man $< > $@ + .3.html: + $(RM) $@ + -${MAN2HTML} $< > $@ + all: ps info dvi text html nodvi: ps info text html *************** *** 79,83 **** info: bashref.info text: bash.0 bashbug.0 builtins.0 readline.0 ! html: bashref.html bashref.dvi: $(srcdir)/bashref.texi $(HSUSER) $(RLUSER) --- 89,93 ---- info: bashref.info text: bash.0 bashbug.0 builtins.0 readline.0 ! html: bashref.html bash.html bashref.dvi: $(srcdir)/bashref.texi $(HSUSER) $(RLUSER) *************** *** 103,106 **** --- 113,117 ---- bash.txt: bash.1 bash.ps: bash.1 + bash.html: bash.1 $(MAN2HTML) bashbug.ps: bashbug.1 builtins.ps: builtins.1 bash.1 *************** *** 111,114 **** --- 122,128 ---- readline.ps: readline.3 article.ps: article.ms + + $(MAN2HTML): ${topdir}/support/man2html.c + -( cd ${BUILD_DIR}/support ; ${MAKE} ${MFLAGS} man2html) faq: faq.news faq.news2 faq.mail faq.version diff -Nrc2 bash-2.01.1/doc/bash.1 bash-2.02/doc/bash.1 *** bash-2.01.1/doc/bash.1 Mon May 19 12:56:34 1997 --- bash-2.02/doc/bash.1 Wed Apr 1 12:25:56 1998 *************** *** 7,15 **** .\" chet@ins.CWRU.Edu .\" ! .\" Last Change: Mon May 19 12:45:24 EDT 1997 .\" .\" bash_builtins, strip all but Built-Ins section .if \n(zZ=1 .ig zZ ! .TH BASH 1 "1997 May 19" GNU .\" .\" There's some problem with having a `@' --- 7,15 ---- .\" chet@ins.CWRU.Edu .\" ! .\" Last Change: Wed Apr 1 12:16:09 EST 1998 .\" .\" bash_builtins, strip all but Built-Ins section .if \n(zZ=1 .ig zZ ! .TH BASH 1 "1998 Apr 1" GNU .\" .\" There's some problem with having a `@' *************** *** 62,71 **** .PP .B Bash ! is ultimately intended to be a conformant implementation of the IEEE POSIX Shell and Tools specification (IEEE Working Group 1003\.2). .SH OPTIONS In addition to the single-character shell options documented in the description of the \fBset\fR builtin command, \fBbash\fR ! interprets the following flags when it is invoked: .PP .PD 0 --- 62,71 ---- .PP .B Bash ! is intended to be a conformant implementation of the IEEE POSIX Shell and Tools specification (IEEE Working Group 1003\.2). .SH OPTIONS In addition to the single-character shell options documented in the description of the \fBset\fR builtin command, \fBbash\fR ! interprets the following options when it is invoked: .PP .PD 0 *************** *** 74,78 **** If the .B \-c ! flag is present, then commands are read from .IR string . If there are arguments after the --- 74,78 ---- If the .B \-c ! option is present, then commands are read from .IR string . If there are arguments after the *************** *** 84,88 **** If the .B \-r ! flag is present, the shell becomes .I restricted (see --- 84,88 ---- If the .B \-r ! option is present, the shell becomes .I restricted (see *************** *** 94,98 **** If the .B \-i ! flag is present, the shell is .IR interactive . .TP --- 94,98 ---- If the .B \-i ! option is present, the shell is .IR interactive . .TP *************** *** 100,104 **** If the .B \-s ! flag 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 --- 100,104 ---- 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 *************** *** 131,134 **** --- 131,138 ---- .PD 0 .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. *************** *** 310,315 **** as closely as possible, while conforming to the POSIX standard as well. ! When invoked as a login shell, it first attempts to read and execute ! commands from .I /etc/profile and --- 314,319 ---- as closely as possible, while conforming to the POSIX standard as well. ! When invoked as an interactive login shell, it first attempts to ! read and execute commands from .I /etc/profile and *************** *** 350,360 **** .B \-\-posix command line option, it follows the POSIX standard for startup files. ! In this mode, the .SM .B ENV ! variable is expanded and commands are read and executed from the file whose name is the expanded value. No other startup files are read. - This is done by interactive shells only. .PP .B Bash --- 354,363 ---- .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 *************** *** 428,433 **** .PP .B ! .if n ! case do done elif else esac fi for function if in select then until while { } time ! .if t ! case do done elif else esac fi for function if in select then until while { } time .if t .RE .RE --- 431,436 ---- .PP .B ! .if n ! case do done elif else esac fi for function if in select then until while { } time [[ ]] ! .if t ! case do done elif else esac fi for function if in select then until while { } time [[ ]] .if t .RE .RE *************** *** 583,586 **** --- 586,650 ---- \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. + .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. + The return value is 0 if the string matches or does not match + the pattern, respectively, and 1 otherwise. + Any part of the pattern may be quoted to force it to be matched as a + string. + .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 + .if t \fIexpression1\fP \fB\(bv\(bv\fP \fIexpression2\fP + .if n \fIexpression1\fP \fB||\fP \fIexpression2\fP + True if either + .I expression1 + or + .I expression2 + is true. + .PD + .RE + .LP + The \fB&&\fP and + .if t \fB\(bv\(bv\fP + .if n \fB||\fP + operators do not execute \fIexpression2\fP if the value of + \fIexpression1\fP is sufficient to determine the return value of + the entire conditional expression. + .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 *************** *** 592,595 **** --- 656,662 ---- .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 \fBselect\fP \fIname\fP [ \fBin\fP \fIword\fP; ] \fBdo\fP \fIlist\fP ; \fBdone\fP *************** *** 695,699 **** be ignored. An interactive shell without the .B interactive_comments - .B shopt option enabled does not allow comments. The .B interactive_comments --- 762,765 ---- *************** *** 718,723 **** It preserves the literal value of the next character that follows, with the exception of . If a \fB\e\fP pair ! appears, and the backslash is not quoted, the \fB\e\fP ! is treated as a line continuation (that is, it is effectively ignored). .PP Enclosing characters in single quotes preserves the literal value --- 784,790 ---- It preserves the literal value of the next character that follows, with the exception of . If a \fB\e\fP pair ! appears, and the backslash is not itself quoted, the \fB\e\fP ! 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 *************** *** 792,796 **** .TP .B \e\fInnn\fP ! the character whose ASCII code is \fInnn\fP (octal) .PD .RE --- 859,868 ---- .TP .B \e\fInnn\fP ! the character whose ASCII code is the octal value \fInnn\fP ! (one to three digits) ! .TP ! .B \ex\fInnn\fP ! the character whose ASCII code is the hexadecimal value \fInnn\fP ! (one to three digits) .PD .RE *************** *** 845,849 **** .B EXPANSION below). If the variable has its ! .B \-i attribute set (see .B declare --- 917,921 ---- .B EXPANSION below). If the variable has its ! .B integer attribute set (see .B declare *************** *** 853,858 **** then .I value ! is subject to arithmetic expansion even if the $((...)) syntax does ! not appear (see .B "Arithmetic Expansion" below). --- 925,930 ---- then .I value ! is subject to arithmetic expansion even if the $((...)) expansion is ! not used (see .B "Arithmetic Expansion" below). *************** *** 895,900 **** .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 --- 967,972 ---- .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 *************** *** 912,921 **** .B @ Expands to the positional parameters, starting from one. When the ! expansion occurs within double quotes, each parameter expands as a ! separate word. That is, `` ! .BR $@ '' ! is equivalent to ! ``\fB$1\fP'' ``\fB$2\fP'' ... ! When there are no positional parameters, ``\fB$@\fP'' and .B $@ expand to nothing (i.e., they are removed). --- 984,991 ---- .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" ... ! When there are no positional parameters, "\fB$@\fP" and .B $@ expand to nothing (i.e., they are removed). *************** *** 935,939 **** (such as the .B \-i ! flag). .TP .B $ --- 1005,1009 ---- (such as the .B \-i ! option). .TP .B $ *************** *** 981,985 **** .TP .B PPID ! The process ID of the shell's parent. .TP .B PWD --- 1051,1055 ---- .TP .B PPID ! The process ID of the shell's parent. This variable is readonly. .TP .B PWD *************** *** 1000,1011 **** .B UID Expands to the user ID of the current user, initialized at shell startup. .TP .B EUID Expands to the effective user ID of the current user, initialized at ! shell startup. .TP .B GROUPS An array variable containing the list of groups of which the current ! user is a member. .TP .B BASH --- 1070,1082 ---- .B UID Expands to the user ID of the current user, initialized at shell startup. + This variable is readonly. .TP .B EUID Expands to the effective user ID of the current user, initialized at ! shell startup. This variable is readonly. .TP .B GROUPS An array variable containing the list of groups of which the current ! user is a member. This variable is readonly. .TP .B BASH *************** *** 1018,1023 **** .TP .B BASH_VERSINFO ! An array variable whose members hold version information for this ! instance of .BR bash . The values assigned to the array members are as follows: --- 1089,1094 ---- .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: *************** *** 1220,1233 **** The home directory of the current user; the default argument for the \fBcd\fP builtin command. .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 ! ``.:~:/usr''. .TP .B BASH_ENV --- 1291,1305 ---- 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 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 ``.:~:/usr''. .TP .B BASH_ENV *************** *** 1235,1239 **** its value is interpreted as a filename containing commands to initialize the shell, as in ! .IR .bashrc . The value of .SM --- 1307,1311 ---- its value is interpreted as a filename containing commands to initialize the shell, as in ! .IR ~/.bashrc . The value of .SM *************** *** 1263,1268 **** .B MAILPATH A colon-separated list of file names to be checked for mail. ! The message to be printed may be specified by separating the file name from ! the message with a `?'. $_ stands for the name of the current mailfile. Example: .RS --- 1335,1342 ---- .B MAILPATH A colon-separated list of file names to be checked for mail. ! The message to be printed when mail arrives in a particular file ! may be specified by separating the file name 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 *************** *** 1398,1402 **** .B LC_COLLATE This variable determines the collation order used when sorting the ! results of pathname expansion. .TP .B LC_MESSAGES --- 1472,1483 ---- .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 *************** *** 1488,1491 **** --- 1569,1575 ---- This variable's function is superseded by .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 + .BR HISTCONTROL . .TP .B HISTIGNORE *************** *** 1500,1503 **** --- 1584,1590 ---- 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 + .BR HISTIGNORE . .TP .B histchars *************** *** 1508,1512 **** below). The first character is the .IR "history expansion character" , ! that is, the character which signals the start of a history expansion, normally `\fB!\fP'. The second character is the --- 1595,1599 ---- below). The first character is the .IR "history expansion character" , ! the character which signals the start of a history expansion, normally `\fB!\fP'. The second character is the *************** *** 1516,1520 **** The default is `\fB^\fP'. The optional third character is the character ! which signifies 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 --- 1603,1607 ---- 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 *************** *** 1624,1628 **** The .B unset ! builtin is used to destroy arrays. \fBunset\fP \fIname\fP[\fIsubscript\fP] destroys the array element at index \fIsubscript\fP. \fBunset\fP \fIname\fP, where \fIname\fP is an array, or --- 1711,1715 ---- The .B unset ! builtin is used to destroy arrays. \fBunset\fP \fBname\fP[\fIsubscript\fP] destroys the array element at index \fIsubscript\fP. \fBunset\fP \fIname\fP, where \fIname\fP is an array, or *************** *** 1673,1677 **** 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 --- 1760,1764 ---- 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 *************** *** 1688,1694 **** followed by a series of comma-separated strings between a pair of braces, followed by an optional ! .IR postamble . The preamble is prefixed to each string contained ! within the braces, and the postamble is then appended to each resulting string, expanding left to right. .PP --- 1775,1781 ---- followed by a series of comma-separated strings 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 *************** *** 1754,1762 **** .SS Tilde Expansion .PP ! If a word begins with a tilde character (`\fB~\fP'), all of the characters ! preceding the first slash (or all characters, if there is no slash) ! are treated as a possible \fIlogin name\fP. If this \fIlogin name\fP ! is the null string, the tilde is replaced with the value of the ! parameter .SM .BR HOME . --- 1841,1852 ---- .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 . *************** *** 1764,1790 **** .SM .B HOME ! is unset, the home directory of ! the user executing the shell is substituted instead. .PP ! If a `+' follows the tilde, the value of .SM .B PWD ! replaces the tilde and `+'. If ! a `\-' follows, the value of .SM ! .B OLDPWD ! is substituted. ! If the value following the tilde is a valid \fIlogin name\fP, ! the tilde and \fIlogin name\fP are replaced with the home directory ! associated with that name. If the name is invalid, or the tilde ! expansion fails, the word is unchanged. .PP ! Each variable assignment is checked for unquoted ! tildes immediately following a .B : or .BR = . ! In these cases, tilde substitution is also performed. Consequently, one ! may use file names with tildes in assignments to .SM .BR PATH , --- 1854,1889 ---- .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 .BR = . ! In these cases, tilde expansion is also performed. ! Consequently, one may use file names with tildes in assignments to .SM .BR PATH , *************** *** 1804,1807 **** --- 1903,1911 ---- 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 paramter + expansion. + .PP .PD 0 .TP *************** *** 1881,1885 **** \fBSubstring Expansion.\fP Expands to up to \fIlength\fP characters of \fIparameter\fP, ! starting at \fIoffset\fP. If \fIlength\fP is omitted, expands to the substring of \fIparameter\fP, starting at the character specified by \fIoffset\fP. --- 1985,1989 ---- \fBSubstring Expansion.\fP Expands to up to \fIlength\fP characters of \fIparameter\fP, ! starting at the characters specified by \fIoffset\fP. If \fIlength\fP is omitted, expands to the substring of \fIparameter\fP, starting at the character specified by \fIoffset\fP. *************** *** 1897,1902 **** the result is the \fIlength\fP members of the array beginning with ${\fIparameter\fP[\fIoffset\fP]}. ! Substring indexing is zero-based unless the positional parameters are ! used, in which case the indexing starts at 1. .TP ${\fB#\fP\fIparameter\fP} --- 2001,2006 ---- the result is the \fIlength\fP members of the array beginning with ${\fIparameter\fP[\fIoffset\fP]}. ! Substring indexing is zero-based unless the positional parameters ! are used, in which case the indexing starts at 1. .TP ${\fB#\fP\fIparameter\fP} *************** *** 1908,1912 **** or .BR @ , ! the length substituted is the number of positional parameters. If .I parameter --- 2012,2016 ---- or .BR @ , ! the value substituted is the number of positional parameters. If .I parameter *************** *** 1915,1919 **** or .BR @ , ! the length substituted is the number of elements in the array. .TP .PD 0 --- 2019,2023 ---- or .BR @ , ! the value substituted is the number of elements in the array. .TP .PD 0 *************** *** 1928,1932 **** the value of .IR parameter , ! then the expansion is the value of .I parameter with the shortest matching pattern (the ``\fB#\fP'' case) or the --- 2032,2036 ---- 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 *************** *** 1956,1962 **** The \fIword\fP is expanded to produce a pattern just as in pathname expansion. ! If the pattern matches a trailing portion of the value of .IR parameter , ! then the expansion is the value of .I parameter with the shortest matching pattern (the ``\fB%\fP'' case) or the --- 2060,2066 ---- 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 *************** *** 2015,2019 **** .SS Command Substitution .PP ! \fICommand substitution\fP allows the output of a command to replace the command name. There are two forms: .PP --- 2119,2123 ---- .SS Command Substitution .PP ! \fICommand substitution\fP allows the output of a command to replace the command name. There are two forms: .PP *************** *** 2031,2034 **** --- 2135,2142 ---- 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, *************** *** 2038,2045 **** or .BR \e . 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 old form, escape the inner backquotes with backslashes. .PP --- 2146,2155 ---- 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 *************** *** 2087,2091 **** argument should be read to obtain the output of \fIlist\fP. .PP ! On systems that support it, \fIprocess substitution\fP is performed simultaneously with parameter and variable expansion, command substitution, --- 2197,2201 ---- argument should be read to obtain the output of \fIlist\fP. .PP ! When available, \fIprocess substitution\fP is performed simultaneously with parameter and variable expansion, command substitution, *************** *** 2170,2173 **** --- 2280,2284 ---- .BR * , .BR ? , + .BR ( , and .BR [ . *************** *** 2181,2186 **** .B nullglob is disabled, the word is left unchanged. ! If the option is set, and no matches are found, the word is removed. When a pattern is used for pathname expansion, the character --- 2292,2303 ---- .B nullglob is disabled, the word is left unchanged. ! If the ! .B nullglob ! option is set, and no matches are found, the word is removed. + 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 *************** *** 2190,2194 **** .B dotglob is set. ! The slash character must always be matched explicitly. In other cases, the .B ``.'' --- 2307,2312 ---- .B dotglob is set. ! When matching a pathname, the slash character must always be ! matched explicitly. In other cases, the .B ``.'' *************** *** 2200,2204 **** .B SHELL BUILTIN COMMANDS for a description of the ! .B nullglob and .B dotglob --- 2318,2323 ---- .B SHELL BUILTIN COMMANDS for a description of the ! .BR nocaseglob , ! .BR nullglob , and .B dotglob *************** *** 2246,2249 **** --- 2365,2375 ---- 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. The special pattern characters must be quoted if + they are to be matched literally. + .PP The special pattern characters have the following meanings: .PP *************** *** 2276,2279 **** --- 2402,2470 ---- 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.2 standard: + .PP + .RS + .B + .if n alnum alpha ascii blank cntrl digit graph lower print punct space upper xdigit + .if t alnum alpha ascii blank cntrl digit graph lower print punct space upper xdigit + .br + A character class matches any character belonging to that class. + .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 + .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 exactly 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 *************** *** 2282,2286 **** characters .BR \e , ! .BR ` , and \^\f3"\fP\^ that did not result from one of the above expansions are removed. --- 2473,2477 ---- characters .BR \e , ! .BR ' , and \^\f3"\fP\^ that did not result from one of the above expansions are removed. *************** *** 2308,2316 **** 1). .PP ! The word that follows the redirection operator in the following ! descriptions is subjected to brace expansion, tilde expansion, ! parameter expansion, command substitution, arithmetic expansion, ! quote removal, and pathname expansion. If it expands to more ! than one word, .B bash reports an error. --- 2499,2507 ---- 1). .PP ! 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, and pathname expansion. ! If it expands to more than one word, .B bash reports an error. *************** *** 2336,2339 **** --- 2527,2532 ---- before the standard output was redirected to .IR dirlist . + .PP + A failure to open or create a file causes the redirection to fail. .SS Redirecting Input .PP *************** *** 2373,2388 **** .BR > , and the ! .B \-C option to the .B set builtin has been enabled, the redirection will fail if the filename ! whose name results from the expansion of \fIword\fP exists. If the redirection operator is .BR >| , ! then the value of the ! .B \-C option to the .B set ! builtin command is not tested, and the redirection is attempted even if the file named by \fIword\fP exists. .SS Appending Redirected Output --- 2566,2584 ---- .BR > , and the ! .B noclobber option to the .B set builtin has been enabled, the redirection will fail if the filename ! 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 *************** *** 2461,2465 **** is the result of quote removal on .IR word , ! and the lines in the here-document are not expanded. Otherwise, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion. In the latter --- 2657,2662 ---- 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. In the latter *************** *** 2495,2499 **** expands to one or more digits, the file descriptor denoted by .I n ! is made to be a copy of that file descriptor. If .I word evaluates to --- 2692,2700 ---- 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 *************** *** 2514,2517 **** --- 2715,2721 ---- .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. As a special case, if \fIn\fP is omitted, and \fIword\fP does not expand to one or more digits, the standard output and standard *************** *** 2533,2536 **** --- 2737,2742 ---- is not specified. If the file does not exist, it is created. .SH ALIASES + 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 .I aliases *************** *** 2597,2601 **** on that line are not affected by the new alias. This behavior is also an issue when functions are executed. ! Aliases are expanded when the function definition is read, not when the function is executed, because a function definition is itself a compound command. As a consequence, aliases --- 2803,2807 ---- 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 compound command. As a consequence, aliases *************** *** 2606,2610 **** in compound commands. .PP ! Note that for almost every purpose, aliases are superseded by shell functions. .SH FUNCTIONS --- 2812,2816 ---- in compound commands. .PP ! For almost every purpose, aliases are superseded by shell functions. .SH FUNCTIONS *************** *** 2645,2649 **** positional parameters and the special parameter .B # ! are restored to the values they had prior to function execution. .PP --- 2851,2855 ---- positional parameters and the special parameter .B # ! are restored to the values they had prior to the function's execution. .PP *************** *** 2670,2673 **** --- 2876,3131 ---- Functions may be recursive. 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 builtin command and + \fBArithmetic Expansion\fP). + Evaluation is done in long integers with no check for overflow, + though division by 0 is trapped and flagged as an error. + 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 \- + + 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 evaluation + .TP + .B = *= /= %= += \-= <<= >>= &= ^= |= + assignment + .PD + .PP + Shell variables are allowed as operands; parameter expansion is + performed before the expression is evaluated. + The value of a parameter is coerced to a long integer within + an expression. A shell variable need not have its integer 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 \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. + 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 interchangably 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 + /dev/fd/\fIn\fP, then file descriptor \fIn\fP is checked. + .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 \-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 \-O \fIfile\fP + True if \fIfile\fP exists and is owned by the effective user id. + .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 \-S \fIfile\fP + True if \fIfile\fP exists and is a socket. + .TP + .B \-N \fIfile\fP + True if \fIfile\fP exists and has been modified since it was last read. + .TP + \fIfile1\fP \-\fBnt\fP \fIfile2\fP + True if \fIfile1\fP is newer (according to + modification date) than \fIfile2\fP. + .TP + \fIfile1\fP \-\fBot\fP \fIfile2\fP + True if \fIfile1\fP is older than \fIfile2\fP. + .TP + \fIfile1\fP \fB\-ef\fP \fIfile2\fP + True if \fIfile1\fP and \fIfile2\fP have the same device and + inode numbers. + .TP + .B \-o \fIoptname\fP + True if 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 \-z \fIstring\fP + True if the length of \fIstring\fP is zero. + .TP + .B \-n \fIstring\fP + .TP + \fIstring\fP + True if the length of + .I string + is non-zero. + .TP + \fIstring1\fP \fB==\fP \fIstring2\fP + True if the strings are equal. \fB=\fP may be used in place of + \fB==\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 + in the current locale. + .TP + \fIstring1\fP \fB>\fP \fIstring2\fP + True if \fIstring1\fP sorts after \fIstring2\fP lexicographically + in the current locale. + .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 *************** *** 2704,2711 **** is performed only if the command is not found in the hash table. If the search is unsuccessful, the shell prints an error ! message and returns a non-zero exit status. .PP If the search is successful, or if the command name contains ! one or more slashes, the shell executes the named program. Argument 0 is set to the name given, and the remaining arguments to the command are set to the arguments given, if any. --- 3162,3170 ---- is performed only if the command is not found in the hash table. If the search is unsuccessful, 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. *************** *** 2735,2738 **** --- 3194,3259 ---- 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: + .sp 1 + .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 \fB$PPID\fP + .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. + .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 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 the 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 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. .SH ENVIRONMENT When a program is invoked it is given an array of strings *************** *** 2778,2782 **** If the .B \-k ! flag is set (see the .B set builtin command below), then --- 3299,3303 ---- If the .B \-k ! option is set (see the .B set builtin command below), then *************** *** 2792,2796 **** command in its environment. .SH "EXIT STATUS" ! For the purposes of the shell, 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. --- 3313,3317 ---- command in its environment. .SH "EXIT STATUS" ! 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. *************** *** 2802,2805 **** --- 3323,3329 ---- 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 *************** *** 2812,2816 **** command below. .SH SIGNALS ! When \fBbash\fP is interactive, it ignores .SM .B SIGTERM --- 3336,3340 ---- command below. .SH SIGNALS ! When \fBbash\fP is interactive, in the absence of any traps, it ignores .SM .B SIGTERM *************** *** 2834,2841 **** .BR SIGTSTP . .PP ! Synchronous jobs started by \fBbash\fP have signals set to the ! values inherited by the shell from its parent. When job control ! is not in effect, background jobs (jobs started with ! .BR & ) ignore .SM --- 3358,3364 ---- .BR SIGTSTP . .PP ! Synchronous jobs started 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 *************** *** 2843,2847 **** and .SM ! .BR SIGQUIT . Commands run as a result of command substitution ignore the keyboard-generated job control signals --- 3366,3371 ---- and .SM ! .B SIGQUIT ! as well. Commands run as a result of command substitution ignore the keyboard-generated job control signals *************** *** 2860,2865 **** .SM .B SIGHUP ! to all jobs, running or stopped. To prevent the shell from ! sending the signal to a particular job, remove it from the jobs table with the .B disown --- 3384,3396 ---- .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 *************** *** 2867,2875 **** .SM .B "SHELL BUILTIN COMMANDS" ! below) or use ! .B "disown \-h" ! to mark it to not receive .SM ! .BR SIGHUP . .SH "JOB CONTROL" .I Job control --- 3398,3425 ---- .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 ! When \fBbash\fP receives a signal for which a trap has been set while ! waiting for a command to complete, 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 *************** *** 2945,2949 **** be returned to .BR bash . ! You may then manipulate the state of this job, using the .B bg command to continue it in the background, the --- 3495,3499 ---- 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 *************** *** 2984,2988 **** .IR "current job" , which is the last job stopped while it was in ! the foreground. The .I "previous job" --- 3534,3538 ---- .IR "current job" , which is the last job stopped while it was in ! the foreground or started in the background. The .I "previous job" *************** *** 3017,3021 **** .B set builtin command ! is set, .B bash reports such changes immediately. --- 3567,3571 ---- .B set builtin command ! is enabled, .B bash reports such changes immediately. *************** *** 3063,3066 **** --- 3613,3619 ---- newline .TP + .B \er + carriage return + .TP .B \es the name of the shell, the basename of *************** *** 3246,3250 **** .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 --- 3799,3803 ---- .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 *************** *** 3252,3256 **** as a symbolic key name, possibly with \fIMeta\-\fP or \fIControl\-\fP prefixes, or as a key sequence. ! 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: --- 3805,3809 ---- as a symbolic key name, possibly with \fIMeta\-\fP or \fIControl\-\fP prefixes, or as a key sequence. ! 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: *************** *** 3278,3282 **** into the line). .PP ! In the second form, \fB"keyseq"\fP:\fIfunction\-name\fP or \fImacro\fP, .B keyseq differs from --- 3831,3835 ---- into the line). .PP ! In the second form, \fB"keyseq"\fP:\^\fIfunction\-name\fP or \fImacro\fP, .B keyseq differs from *************** *** 3306,3311 **** is bound to insert the text .BR "Function Key 1" . ! The full set of escape sequences is .RS .TP .B \eC\- --- 3859,3865 ---- is bound to insert the text .BR "Function Key 1" . ! The full set of GNU Emacs style escape sequences is .RS + .PD 0 .TP .B \eC\- *************** *** 3327,3335 **** literal ' .RE .PP ! When entering the text of a macro, single or double quotes should ! be used to indicate a macro definition. Unquoted text ! is assumed to be a function name. Backslash ! will quote any character in the macro text, including " and '. .PP .B Bash --- 3881,3931 ---- literal ' .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 character whose ASCII code is the octal value \fInnn\fP ! (one to three digits) ! .TP ! .B \ex\fInnn\fP ! the character whose ASCII code is the hexadecimal value \fInnn\fP ! (one to three 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 '. .PP .B Bash *************** *** 3382,3385 **** --- 3978,3985 ---- 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\-query\-items (100) This determines when the user is queried about viewing *************** *** 3434,3438 **** .TP .B keymap (emacs) ! Set the current readline keymap. The set of legal keymap names is \fIemacs, emacs\-standard, emacs\-meta, emacs\-ctlx, vi, vi\-command\fP, and --- 4034,4038 ---- .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 *************** *** 3458,3461 **** --- 4058,4065 ---- sequence. .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 show\-all\-if\-ambiguous (Off) This alters the default behavior of the completion functions. If *************** *** 3475,3479 **** compilation features of the C preprocessor which allows key bindings and variable settings to be performed as the result ! of tests. There are three parser directives used. .IP \fB$if\fP The --- 4079,4083 ---- 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 *************** *** 3496,3500 **** terminal's function keys. The word on the right side of the .B = ! is tested against the full name of the terminal and the portion of the terminal name before the first \fB\-\fP. This allows .I sun --- 4100,4104 ---- 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 *************** *** 3512,3515 **** --- 4116,4120 ---- a specific program. For instance, the following command adds a key sequence that quotes the current or previous word in Bash: + .sp 1 .RS .nf *************** *** 3522,3530 **** .RE .IP \fB$endif\fP ! This command, as you saw 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. .SS Searching .PP --- 4127,4145 ---- .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 *************** *** 3562,3566 **** 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 part of the contents of the current line. .SS "Readline Command Names" .PP --- 4177,4181 ---- 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 *************** *** 3668,3674 **** the previous history entry). With an argument, behave exactly like \fByank\-nth\-arg\fP. .TP .B shell\-expand\-line (M\-C\-e) ! Expand the line the way the shell does when it reads it. This performs alias and history expansion as well as all of the shell word expansions. See --- 4283,4291 ---- the previous history entry). With an argument, behave exactly like \fByank\-nth\-arg\fP. + Successive calls to \fByank\-last\-arg\fP move back through the history + list, inserting the last argument of each line in turn. .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 *************** *** 3684,3687 **** --- 4301,4311 ---- 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. *************** *** 3709,3714 **** Delete the character under the cursor. If point is at the beginning of the line, there are no characters in the line, and ! the last character typed was not ! .BR C\-d , then return .SM --- 4333,4337 ---- Delete the character under the cursor. If point is at the beginning of the line, there are no characters in the line, and ! the last character typed was not bound to \fBdelete\-char\fP, then return .SM *************** *** 3720,3724 **** .TP .B quoted\-insert (C\-q, C\-v) ! Add the next character that you type to the line verbatim. This is how to insert characters like \fBC\-q\fP, for example. .TP --- 4343,4347 ---- .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 *************** *** 3740,3752 **** .B upcase\-word (M\-u) Uppercase the current (or following) word. With a negative argument, ! do the previous word, but do not move point. .TP .B downcase\-word (M\-l) Lowercase the current (or following) word. With a negative argument, ! do the previous word, but do not move point. .TP .B capitalize\-word (M\-c) Capitalize the current (or following) word. With a negative argument, ! do the previous word, but do not move point. .PD .SS Killing and Yanking --- 4363,4375 ---- .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. .PD .SS Killing and Yanking *************** *** 3762,3766 **** .B unix\-line\-discard (C\-u) Kill backward from point to the beginning of the line. ! .\" There is no real difference between this and backward-kill-line .TP .B kill\-whole\-line --- 4385,4390 ---- .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 *************** *** 3793,3799 **** --- 4417,4425 ---- .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) *************** *** 3849,3852 **** --- 4475,4491 ---- \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 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 complete\-filename (M\-/) Attempt filename completion on the text before point. *************** *** 3884,3888 **** it as a command name. Command completion attempts to match the text against aliases, reserved words, shell ! functions, builtins, and finally executable filenames, in that order. .TP --- 4523,4527 ---- 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 *************** *** 3946,3950 **** .TP .B revert\-line (M\-r) ! Undo all changes made to this line. This is like typing the .B undo command enough times to return the line to its initial state. --- 4585,4589 ---- .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. *************** *** 4133,4146 **** is read, before the shell breaks it into words. It takes place in two parts. ! The first is to determine which line from the previous history to use during substitution. The second is to select portions of that line for inclusion into the current one. ! The line selected from the previous 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 as one word. History expansions are introduced by the appearance of the history expansion character, which is \^\fB!\fP\^ by default. --- 4772,4785 ---- 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. *************** *** 4241,4245 **** .B : separates the event specification from the word designator. ! It can be omitted if the word designator begins with a .BR ^ , .BR $ , --- 4880,4884 ---- .B : separates the event specification from the word designator. ! It may be omitted if the word designator begins with a .BR ^ , .BR $ , *************** *** 4360,4439 **** if it is the last character of the event line. .PD - .SH "ARITHMETIC EVALUATION" - The shell allows arithmetic expressions to be evaluated, under - certain circumstances (see the \fBlet\fP builtin command and - \fBArithmetic Expansion\fP). - Evaluation - is done in long integers with no check for overflow, though division - by 0 is trapped and flagged as an error. 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 \- + - unary minus and plus - .TP - .B ! ~ - logical and bitwise negation - .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 evaluation - .TP - .B = *= /= %= += \-= <<= >>= &= ^= |= - assignment - .PD - .PP - Shell variables are allowed as operands; parameter expansion is - performed before the expression is evaluated. - The value of a parameter is coerced to a long integer within - an expression. A shell variable need not have its integer 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 \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. - 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 interchangably 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 "SHELL BUILTIN COMMANDS" .\" start of bash_builtins --- 4999,5002 ---- *************** *** 4495,4499 **** the script (0 if no commands are executed), and false if .I filename ! is not found. .TP \fBalias\fP [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] --- 5058,5062 ---- 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] ...] *************** *** 4512,4516 **** .TP \fBbg\fP [\fIjobspec\fP] ! Place \fIjobspec\fP in the background, as if it had been started with .BR & . If \fIjobspec\fP is not present, the shell's notion of the --- 5075,5080 ---- .TP \fBbg\fP [\fIjobspec\fP] ! Resume the suspended job \fIjobspec\fP in the background, as if it ! had been started with .BR & . If \fIjobspec\fP is not present, the shell's notion of the *************** *** 4523,4527 **** .TP .PD 0 ! \fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSV\fP] [\fB\-q\fP \fIname\fP] [\fB\-r\fP \fIkeyseq\fP] .TP \fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fB\-f\fP \fIfilename\fP --- 5087,5093 ---- .TP .PD 0 ! \fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSV\fP] ! .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 *************** *** 4585,4588 **** --- 5151,5157 ---- 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. *************** *** 4614,4622 **** .IR arguments , and return its exit status. ! This is useful when you wish to define a function whose name is the same as a shell builtin, ! but need the functionality of the ! builtin within the function itself. The \fBcd\fP builtin is ! commonly redefined this way. The return status is false if .I shell\-builtin is not a shell builtin command. --- 5183,5191 ---- .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. *************** *** 4690,4694 **** used to invoke .I command ! to be printed; the .B \-V option produces a more verbose description. --- 5259,5263 ---- used to invoke .I command ! to be displayed; the .B \-V option produces a more verbose description. *************** *** 4771,4775 **** .B \-r Make \fIname\fPs readonly. These names cannot then be assigned values ! by subsequent assignment statements. .TP .B \-x --- 5340,5344 ---- .B \-r Make \fIname\fPs readonly. These names cannot then be assigned values ! by subsequent assignment statements or unset. .TP .B \-x *************** *** 4783,4787 **** \fIname\fP local, as with the .B local ! command. The return value is 0 unless an illegal option is encountered, an attempt is made to define a function using "\-f foo=bar", an attempt is made to assign a value to a readonly variable, --- 5352,5356 ---- \fIname\fP local, as with the .B local ! command. The return value is 0 unless an invalid option is encountered, an attempt is made to define a function using "\-f foo=bar", an attempt is made to assign a value to a readonly variable, *************** *** 4789,4793 **** using the compound assignment syntax (see .B Arrays ! above), one of the \fInames\fP is not a legal 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, --- 5358,5362 ---- 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, *************** *** 4835,4848 **** .PP The return value is 0 unless an ! illegal option is supplied or \fIn\fP indexes beyond the end of the directory stack. .RE .TP ! \fBdisown\fP [\fB\-h\fP] [\fIjobspec\fP ...] Without options, each .I jobspec is removed from the table of active jobs. ! If the \fB\-h\fP option is given, the job is not removed from the table, ! but is marked so that .SM .B SIGHUP --- 5404,5418 ---- .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, each .I jobspec is removed from the table of active jobs. ! 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 *************** *** 4852,4857 **** If no .I jobspec ! is present, the \fIcurrent job\fP is used. The return value is ! 0 unless a .I jobspec does not specify a valid job. --- 5422,5440 ---- If no .I jobspec ! is present, and neither the ! .B \-a ! nor the ! .B \-r ! option is supplied, the \fIcurrent job\fP is used. ! 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. *************** *** 4905,4917 **** backslash .TP ! .B \ennn ! the character whose ASCII code is \fInnn\fP (octal) .PD .RE .TP \fBenable\fP [\fB\-adnps\fP] [\fB\-f\fP \fIfilename\fP] [\fIname\fP ...] ! Enable and disable builtin shell commands. This allows ! the execution of a disk command which has the same name as a shell ! builtin without specifying a full file name. If \fB\-n\fP is used, each \fIname\fP is disabled; otherwise, --- 5488,5506 ---- backslash .TP ! .B \e\fInnn\fP ! the character whose ASCII code is the octal value \fInnn\fP ! (one to three digits) ! .TP ! .B \ex\fInnn\fP ! the character whose ASCII code is the hexadecimal value \fInnn\fP ! (one to three digits) .PD .RE .TP \fBenable\fP [\fB\-adnps\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 with 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, *************** *** 4959,4963 **** returns 0. .TP ! \fBexec\fP [\fB\-cl\fP] [\fB\-a\fP \fIname\fP] [\fIcommand\fP] [\fIarguments\fP] If .I command --- 5548,5552 ---- returns 0. .TP ! \fBexec\fP [\fB\-cl\fP] [\fB\-a\fP \fIname\fP] [\fIcommand\fP [\fIarguments\fP]] If .I command *************** *** 4991,4995 **** .I command is not specified, any redirections take effect in the current shell, ! and the return status is 0. .TP \fBexit\fP [\fIn\fP] --- 5580,5585 ---- .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] *************** *** 5029,5035 **** named variables. .B export ! returns an exit status of 0 unless an illegal option is encountered, ! one of the \fInames\fP is not a legal shell variable name, or .B \-f is supplied with a --- 5619,5625 ---- named variables. .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 *************** *** 5068,5078 **** The .B \-n ! flag suppresses the command numbers when listing. The .B \-r ! flag reverses the order of the commands. If the .B \-l ! flag is given, the commands are listed on standard output. Otherwise, the editor given by --- 5658,5668 ---- 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 *************** *** 5113,5117 **** re-executes the last command. .sp 1 ! If the first form is used, the return value is 0 unless an illegal option is encountered or .I first --- 5703,5707 ---- 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 *************** *** 5131,5137 **** .TP \fBfg\fP [\fIjobspec\fP] ! Place .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. --- 5721,5728 ---- .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. *************** *** 5179,5182 **** --- 5770,5785 ---- is to be used. .sp 1 + When the end of options is encountered, \fBgetopts\fP exits with a + return value greater than zero. + \fBOPTIND\fP is set to the index of the first non-option argument, + and \fBname\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 *************** *** 5185,5199 **** .I silent error reporting is used. In normal operation diagnostic messages ! are printed when illegal options or missing option arguments are encountered. If the variable .SM .B OPTERR ! is set to 0, no error message will be displayed, even if the first character of .I optstring is not a colon. .sp 1 ! If an illegal option is seen, .B getopts places ? into --- 5788,5802 ---- .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 *************** *** 5228,5237 **** .sp 1 .B getopts - normally parses the positional parameters, but if more arguments are - given in - .IR args , - .B getopts - parses those instead. - .B getopts returns true if an option, specified or unspecified, is found. It returns false if the end of options is encountered or an --- 5831,5834 ---- *************** *** 5257,5261 **** The return status is true unless a .I name ! is not found or an illegal option is supplied. .TP \fBhelp\fP [\fIpattern\fP] --- 5854,5858 ---- The return status is true unless a .I name ! is not found or an invalid option is supplied. .TP \fBhelp\fP [\fIpattern\fP] *************** *** 5331,5335 **** .PD .PP ! The return value is 0 unless an illegal option is encountered or an error occurs while reading or writing the history file. .RE --- 5928,5932 ---- .PD .PP ! The return value is 0 unless an invalid option is encountered or an error occurs while reading or writing the history file. .RE *************** *** 5367,5372 **** .I jobspec is given, output is restricted to information about that job. ! The return status is 0 unless an illegal option is encountered ! or an illegal .I jobspec is supplied. --- 5964,5969 ---- .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. *************** *** 5392,5396 **** \fBkill\fP [\fB\-s\fP \fIsigspec\fP | \fB\-n\fP \fIsignum\fP | \fB\-\fP\fIsigspec\fP] [\fIpid\fP | \fIjobspec\fP] ... .TP ! \fBkill\fP \fB\-l\fP [\fIsignum\fP | \fIsigspec\fP] .PD Send the signal named by --- 5989,5993 ---- \fBkill\fP [\fB\-s\fP \fIsigspec\fP | \fB\-n\fP \fIsignum\fP | \fB\-\fP\fIsigspec\fP] [\fIpid\fP | \fIjobspec\fP] ... .TP ! \fBkill\fP \fB\-l\fP [\fIsigspec\fP | \fIexit_status\fP] .PD Send the signal named by *************** *** 5420,5435 **** .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 specified signals are listed, and ! the return status is 0. The arguments to .B \-l ! may be either signal names or signal numbers; if signal names ! are given, the corresponding signal number is displayed. .B kill returns true if at least one signal was successfully sent, or false ! if an error occurs or an illegal option is encountered. .TP \fBlet\fP \fIarg\fP [\fIarg\fP ...] --- 6017,6035 ---- .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 ...] *************** *** 5446,5452 **** .TP \fBlocal\fP [\fIname\fP[=\fIvalue\fP] ...] ! For each argument, create a local variable named ! .IR name , ! and assign it .IR value . When --- 6046,6052 ---- .TP \fBlocal\fP [\fIname\fP[=\fIvalue\fP] ...] ! For each argument, a local variable named ! .I name ! is created, and assigned .IR value . When *************** *** 5462,5466 **** when not within a function. The return status is 0 unless .B local ! is used outside a function, or an illegal .I name is supplied. --- 6062,6066 ---- when not within a function. The return status is 0 unless .B local ! is used outside a function, or an invalid .I name is supplied. *************** *** 5503,5511 **** is performed as well, and the return status is 0. .B popd ! returns false if an illegal option is encountered, the directory stack is empty, a non-existent directory stack entry is specified, or the directory change fails. .RE .TP .PD 0 \fBpushd\fP [\fB\-n\fP] [\fIdir\fP] --- 6103,6129 ---- 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 \fIformat\fP [\fIarguments\fP] + Write the formatted \fIarguments\fP to the standard output under the + control of the \fIformat\fP. + 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) formats, %b causes + \fBprintf\fP to expand backslash escape sequences in the corresponding + \fIargument\fP, and %q causes \fBprintf\fP to output the corresponding + \fIargument\fP in a format that can be reused as shell input. + .sp 1 + 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. + .TP .PD 0 \fBpushd\fP [\fB\-n\fP] [\fIdir\fP] *************** *** 5575,5579 **** option is used, symbolic links are followed. The return status is 0 unless an error occurs while ! reading the name of the current directory. .TP \fBread\fP [\fB\-er\fP] [\fB\-a\fP \fIaname\fP] [\fB\-p\fP \fIprompt\fP] [\fIname\fP ...] --- 6193,6198 ---- option is used, symbolic links are followed. 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\-er\fP] [\fB\-a\fP \fIaname\fP] [\fB\-p\fP \fIprompt\fP] [\fIname\fP ...] *************** *** 5583,5593 **** the second word to the second .IR name , ! and so on, with leftover words assigned to the last .IR name . ! Only the characters in .SM .B IFS ! are recognized as word delimiters. Options, if supplied, have the ! following meanings: .RS .PD 0 --- 6202,6215 ---- 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 standard input than names, ! the remaining names are assigned empty values. ! The characters in .SM .B IFS ! are used to split the line into words. ! Options, if supplied, have the following meanings: .RS .PD 0 *************** *** 5609,5612 **** --- 6231,6235 ---- .I aname is unset before any new values are assigned. + Other \fIname\fP arguments are ignored. .TP .B \-e *************** *** 5647,5654 **** .B \-p option is supplied, a list of all readonly names is printed. ! The return status is 0 unless an illegal option is encountered, one of the .I names ! is not a legal shell variable name, or .B \-f is supplied with a --- 6270,6280 ---- .B \-p option is supplied, a list of all readonly names is printed. ! The ! .B \-p ! option causes output to be displayed in a format thatmay be reused as input. ! 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 *************** *** 5675,5679 **** \fBset\fP [\fB\-\-abefhkmnptuvxBCHP\fP] [\fB\-o\fP \fIoption\fP] [\fIarg\fP ...] Without options, the name and value of each shell variable are displayed ! in a format that can be re-used as input. When options are specified, they set or unset shell attributes. Any arguments remaining after the options are processed are treated --- 6301,6306 ---- \fBset\fP [\fB\-\-abefhkmnptuvxBCHP\fP] [\fB\-o\fP \fIoption\fP] [\fIarg\fP ...] Without options, the name and value of each shell variable are displayed ! in a format that can be reused as input. ! The output is sorted according to the current locale. When options are specified, they set or unset shell attributes. Any arguments remaining after the options are processed are treated *************** *** 5721,5725 **** .B \-h Remember the location of commands as they are looked up for execution. ! This is on by default. .TP 8 .B \-k --- 6348,6352 ---- .B \-h Remember the location of commands as they are looked up for execution. ! This is enabled by default. .TP 8 .B \-k *************** *** 5729,5733 **** .TP 8 .B \-m ! Monitor mode. Job control is enabled. This flag is on by default for interactive shells on systems that support it (see --- 6356,6360 ---- .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 *************** *** 5861,5868 **** mode. In this mode, the .B $ENV ! file is not processed, and shell functions ! are not inherited from the environment. This is enabled automatically ! on startup if the effective user (group) id is not equal to the real ! user (group) id. Turning this option off causes the effective user and group ids to be set to the real user and group ids. .TP 8 --- 6488,6497 ---- mode. In this mode, the .B $ENV ! file is not processed, shell functions are not inherited from the ! environment, and the variable ! The \fBSHELLOPTS\fP variable, if it appears in the environment, is ignored. ! This is enabled automatically on startup if the effective user (group) ! id is not equal to the real user (group) id. ! Turning this option off causes the effective user and group ids to be set to the real user and group ids. .TP 8 *************** *** 5908,5912 **** Enable .B ! ! style history substitution. This flag is on by default when the shell is interactive. .TP 8 --- 6537,6541 ---- Enable .B ! ! style history substitution. This option is on by default when the shell is interactive. .TP 8 *************** *** 5922,5926 **** .TP 8 .B \-\- ! If no arguments follow this flag, then the positional parameters are unset. Otherwise, the positional parameters are set to the \fIarg\fPs, even if some of them begin with a --- 6551,6555 ---- .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 *************** *** 5938,5951 **** .PD .PP ! The flags are off by default ! unless otherwise noted. ! Using + rather than \- causes these flags ! to be turned off. The ! flags can also be specified as options to an ! invocation of the shell. The current ! set of flags may be found in .BR $\- . ! The return status is always true ! unless an illegal option is encountered. .RE .TP --- 6567,6577 ---- .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 *************** *** 5978,5983 **** .B \-p option, a list of all settable options is displayed, with ! an indication of whether or not each is set. Other options have ! the following meanings: .RS .PD 0 --- 6604,6611 ---- .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 *************** *** 6016,6020 **** 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 legal shell option. .PP --- 6644,6648 ---- 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 *************** *** 6082,6085 **** --- 6710,6717 ---- This option is enabled by default for interactive shells. .TP 8 + .B extglob + If set, the extended pattern matching features described above under + \fBPathname Expansion\fP are enabled. + .TP 8 .B histappend If set, the history list is appended to the file named by the value *************** *** 6104,6109 **** If set, and .B readline ! is being used, bash will attempt to perform hostname completion when a ! word beginning with \fB@\fP is being completed (see .B Completing under --- 6736,6741 ---- 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 *************** *** 6113,6116 **** --- 6745,6754 ---- 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 *************** *** 6133,6136 **** --- 6771,6782 ---- \fImailfile\fP has been read'' is displayed. .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 nullglob If set, *************** *** 6161,6165 **** .B PATH to find the directory containing the file supplied as an argument. ! This is enabled by default. .RE .TP --- 6807,6811 ---- .B PATH to find the directory containing the file supplied as an argument. ! This option is enabled by default. .RE .TP *************** *** 6183,6295 **** the evaluation of the conditional expression .IR expr . ! 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. Each ! operator and operand must be a separate argument. If \fIfile\fP ! is of the form /dev/fd/\fIn\fP, then file descriptor \fIn\fP is ! checked. Expressions are composed of the following primaries: .RS .PD 0 .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 \-k \fIfile\fP - True if \fIfile\fP has its ``sticky'' bit set. - .TP - .B \-L \fIfile\fP - True if \fIfile\fP exists and is a symbolic link. - .TP - .B \-p \fIfile\fP - True if \fIfile\fP exists and is a named pipe. - .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 \-S \fIfile\fP - True if \fIfile\fP exists and is a socket. - .TP - .B \-t \fIfd\fP - True if - .I fd - is opened on 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 \-O \fIfile\fP - True if \fIfile\fP exists and is owned by the effective user id. - .TP - .B \-G \fIfile\fP - True if \fIfile\fP exists and is owned by the effective group id. - .TP - \fIfile1\fP \-\fBnt\fP \fIfile2\fP - True if \fIfile1\fP is newer (according to - modification date) than \fIfile2\fP. - .TP - \fIfile1\fP \-\fBot\fP \fIfile2\fP - True if \fIfile1\fP is older than \fIfile2\fP. - .TP - \fIfile1\fP \fB\-ef\fP \fIfile2\fP - True if \fIfile1\fP and \fIfile2\fP have the same device and - inode numbers. - .TP - .B \-o \fIoptname\fP - True if shell option - .I optname - is enabled. - See the list of options under the description of the - .B \-o - option to the - .B set - builtin above. - .TP - .B \-z \fIstring\fP - True if the length of \fIstring\fP is zero. - .TP - .B \-n \fIstring\fP - .TP - \fIstring\fP - True if the length of - .I string - is non-zero. - .TP - \fIstring1\fP \fB=\fP \fIstring2\fP - True if the strings are equal. \fB==\fP may be used in place of - \fB=\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 .B ! \fIexpr\fP True if --- 6829,6843 ---- 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" . ! .if t .sp 0.5 ! .if n .sp 1 ! Expressions may be combined using the following operators, listed ! in decreasing order of precedence. .RS .PD 0 .TP .B ! \fIexpr\fP True if *************** *** 6297,6304 **** is false. .TP \fIexpr1\fP \-\fBa\fP \fIexpr2\fP True if both .I expr1 ! AND .I expr2 are true. --- 6845,6856 ---- 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. *************** *** 6307,6334 **** True if either .I expr1 ! OR .I expr2 is true. .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 .RE .TP .B times --- 6859,6917 ---- 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 ! 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. ! 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. ! The \fB\-a\fP and \fB\-o\fP operators are considered binary operators ! in this case. ! .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. .RE + .PD .TP .B times *************** *** 6402,6406 **** returns true. .TP ! \fBtype\fP [\fB\-all\fP] [\fB\-type\fP | \fB\-path\fP] \fIname\fP [\fIname\fP ...] With no options, indicate how each --- 6985,6989 ---- returns true. .TP ! \fBtype\fP [\fB\-atp\fP] \fIname\fP [\fIname\fP ...] With no options, indicate how each *************** *** 6408,6413 **** would be interpreted if used as a command name. If the ! .B \-type ! flag is used, .B type prints a string which is one of --- 6991,6996 ---- 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 *************** *** 6427,6432 **** is returned. If the ! .B \-path ! flag is used, .B type either returns the name of the disk file --- 7010,7015 ---- is returned. If the ! .B \-p ! option is used, .B type either returns the name of the disk file *************** *** 6434,6443 **** .I name were specified as a command name, ! or nothing if ! .B \-type would not return .IR file . If a command is hashed, ! .B \-path prints the hashed value, not necessarily the file that appears first in --- 7017,7025 ---- .I name were specified as a command name, ! or nothing if \f(CWtype -t name\fP would not return .IR file . If a command is hashed, ! .B \-p prints the hashed value, not necessarily the file that appears first in *************** *** 6445,6450 **** .BR PATH . If the ! .B \-all ! flag is used, .B type prints all of the places that contain --- 7027,7032 ---- .BR PATH . If the ! .B \-a ! option is used, .B type prints all of the places that contain *************** *** 6453,6473 **** This includes aliases and functions, if and only if the ! .B \-path ! flag is not also used. The table of hashed commands is not consulted when using ! .BR \-all . ! .B type ! accepts ! .BR \-a , ! .BR \-t , ! and ! .B \-p ! in place of ! .BR \-all , ! .BR \-type , ! and ! .BR \-path , ! respectively. .B type returns true if any of the arguments are found, false if --- 7035,7043 ---- 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 . .B type returns true if any of the arguments are found, false if *************** *** 6551,6560 **** .BR \-u , which are unscaled values. The return status is 0 ! unless an illegal option is encountered, a non-numeric argument other than \fBunlimited\fP is supplied as \fIlimit\fP, or an error occurs while setting a new limit. .RE .TP ! \fBumask\fP [\fB\-S\fP] [\fImode\fP] The user file-creation mask is set to .IR mode . --- 7121,7130 ---- .BR \-u , which are unscaled values. The return status is 0 ! unless an invalid option is encountered, a non-numeric argument other than \fBunlimited\fP is supplied as \fIlimit\fP, 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 . *************** *** 6576,6579 **** --- 7146,7154 ---- 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. *************** *** 6653,6657 **** It behaves identically to .B bash ! with the exception that the following are disallowed: .IP \(bu changing directories with \fBcd\fP --- 7228,7232 ---- It behaves identically to .B bash ! with the exception that the following are disallowed or not performed: .IP \(bu changing directories with \fBcd\fP *************** *** 6673,6676 **** --- 7248,7253 ---- importing function definitions from the shell environment at startup .IP \(bu + parsing the value of \fBSHELLOPTS\fP from the shell environment at startup + .IP \(bu redirecting output using the >, >|, <>, >&, &>, and >> redirection operators .IP \(bu *************** *** 6694,6698 **** .IP \(bu turning off restricted mode with ! .BR "set +r" . .PP These restrictions are enforced after any startup files are read. --- 7271,7275 ---- .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. *************** *** 6762,6766 **** If you have a fix, you are encouraged to mail that as well! Suggestions and `philosophical' bug reports may be mailed ! to \fPbug-bash\fP@\fIprep.ai.MIT.Edu\fP or posted to the Usenet newsgroup .BR gnu.bash.bug . --- 7339,7343 ---- 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 . diff -Nrc2 bash-2.01.1/doc/bashref.info bash-2.02/doc/bashref.info *** bash-2.01.1/doc/bashref.info Mon Jul 21 13:58:25 1997 --- bash-2.02/doc/bashref.info Thu Apr 2 16:53:42 1998 *************** *** 1,8 **** This is Info file bashref.info, produced by Makeinfo version 1.67 from ! the input file /usr/homes/chet/src/bash/bash-2.01.1/doc/bashref.texi. INFO-DIR-SECTION Utilities START-INFO-DIR-ENTRY ! * Bash: (bash). GNU Bourne-Again SHell END-INFO-DIR-ENTRY --- 1,8 ---- This is Info file bashref.info, produced by Makeinfo version 1.67 from ! the input file /usr/homes/chet/src/bash/src/doc/bashref.texi. INFO-DIR-SECTION Utilities START-INFO-DIR-ENTRY ! * Bash: (bash). The GNU Bourne-Again SHell. END-INFO-DIR-ENTRY *************** *** 10,18 **** the Bash shell. ! This is Edition 2.0, last updated 19 May 1997, of `The GNU Bash Reference Manual', ! for `Bash', Version 2.01. ! Copyright (C) 1991, 1993, 1996 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of --- 10,18 ---- the Bash shell. ! This is Edition 2.2, last updated 1 April 1998, of `The GNU Bash Reference Manual', ! for `Bash', Version 2.02. ! Copyright (C) 1991, 1993, 1996, 1997 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of *************** *** 28,32 **** into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved ! by the Foundation.  --- 28,32 ---- into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved ! by the Free Software Foundation.  *************** *** 39,44 **** the Bash shell. ! This is Edition 2.0, last updated 19 May 1997, of `The GNU Bash ! Reference Manual', for `Bash', Version 2.01. Copyright (C) 1991, 1993, 1996 Free Software Foundation, Inc. --- 39,44 ---- the Bash shell. ! This is Edition 2.2, last updated 1 April 1998, of `The GNU Bash ! Reference Manual', for `Bash', Version 2.02. Copyright (C) 1991, 1993, 1996 Free Software Foundation, Inc. *************** *** 67,76 **** Bourne shell. - * Csh Features:: Features originally found in the - Berkeley C-Shell. - - * Korn Shell Features:: Features originally found in the Korn - Shell. - * Bash Features:: Features found only in Bash. --- 67,70 ---- *************** *** 125,131 **** Bash is an `sh'-compatible shell that incorporates useful features ! from the Korn shell `ksh' and the C shell `csh'. It is ultimately ! intended to be a conformant implementation of the IEEE POSIX Shell and ! Tools specification (IEEE Working Group 1003.2). It offers functional improvements over `sh' for both interactive and programming use. --- 119,125 ---- Bash is an `sh'-compatible shell that incorporates useful features ! from the Korn shell `ksh' and the C shell `csh'. It is intended to be ! a conformant implementation of the IEEE POSIX Shell and Tools ! specification (IEEE Working Group 1003.2). It offers functional improvements over `sh' for both interactive and programming use. *************** *** 133,138 **** will be the default shell. Like other GNU software, Bash is quite portable. It currently runs on nearly every version of Unix and a few ! other operating systems - independently-supported ports exist for OS/2 ! and Windows NT.  --- 127,132 ---- will be the default shell. Like other GNU software, Bash is quite portable. It currently runs on nearly every version of Unix and a few ! other operating systems - independently-supported ports exist for ! MS-DOS, OS/2, Windows 95, and Windows NT.  *************** *** 145,162 **** commands. A Unix shell is both a command interpreter, which provides the user interface to the rich set of Unix utilities, and a programming ! language, allowing these utilitites to be combined. The shell reads ! commands either from a terminal or a file. Files containing commands ! can be created, and become commands themselves. These new commands ! have the same status as system commands in directories like `/bin', ! allowing users or groups to establish custom environments. A shell allows execution of Unix commands, both synchronously and ! asynchronously. The "redirection" constructs permit fine-grained ! control of the input and output of those commands, and the shell allows ! control over the contents of their environment. Unix shells also ! provide a small set of built-in commands ("builtins") implementing ! functionality impossible (e.g., `cd', `break', `continue', and `exec'), ! or inconvenient (`history', `getopts', `kill', or `pwd', for example) ! to obtain via separate utilities. Shells may be used interactively or non-interactively: they accept input typed from the keyboard or from a file. All of the shell builtins are described in subsequent sections. --- 139,158 ---- commands. A Unix shell is both a command interpreter, which provides the user interface to the rich set of Unix utilities, and a programming ! language, allowing these utilitites 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 like ! `/bin', allowing users or groups to establish custom environments. A shell allows execution of Unix 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 "redirection" constructs permit fine-grained control of ! the input and output of those commands, and the shell allows control ! over the contents of their environment. Unix shells also provide a ! small set of built-in commands ("builtins") implementing functionality ! impossible (e.g., `cd', `break', `continue', and `exec'), or ! inconvenient (`history', `getopts', `kill', or `pwd', for example) to ! obtain via separate utilities. Shells may be used interactively or non-interactively: they accept input typed from the keyboard or from a file. All of the shell builtins are described in subsequent sections. *************** *** 272,276 **** specification for the `standard' Unix shell. ! This chapter briefly summarizes the shell's "building blocks": commands, control structures, shell functions, shell parameters, shell expansions, redirections, which are a way to direct input and output --- 268,272 ---- specification for the `standard' Unix shell. ! This chapter briefly summarizes the shell's `building blocks': commands, control structures, shell functions, shell parameters, shell expansions, redirections, which are a way to direct input and output *************** *** 280,290 **** * Shell Syntax:: What your input means to the shell. ! * Simple Commands:: The most common type of command. ! * Pipelines:: Connecting the input and output of several ! commands. ! * Lists:: How to execute commands sequentially. ! * Looping Constructs:: Shell commands for iterative action. ! * Conditional Constructs:: Shell commands for conditional execution. ! * Command Grouping:: Ways to group commands. * Shell Functions:: Grouping commands by name. * Shell Parameters:: Special shell variables. --- 276,280 ---- * 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:: Special shell variables. *************** *** 296,300 ****  ! File: bashref.info, Node: Shell Syntax, Next: Simple Commands, Up: Basic Shell Features Shell Syntax --- 286,290 ----  ! File: bashref.info, Node: Shell Syntax, Next: Shell Commands, Up: Basic Shell Features Shell Syntax *************** *** 323,331 **** 2. Breaks the input into words and operators, obeying the quoting ! rules described in *Note Quoting::. Tokens are separated by `metacharacters'. Alias expansion is performed by this step (*note Aliases::.). ! 3. Parses the tokens into simple and compound commands. 4. Performs the various shell expansions (*note Shell Expansions::.), --- 313,322 ---- 2. Breaks the input into words and operators, obeying the quoting ! rules described in *Note Quoting::. These tokens are separated by `metacharacters'. Alias expansion is performed by this step (*note Aliases::.). ! 3. Parses the tokens into simple and compound commands (*note Shell ! Commands::.). 4. Performs the various shell expansions (*note Shell Expansions::.), *************** *** 340,344 **** 7. Optionally waits for the command to complete and collects its exit ! status. --- 331,335 ---- 7. Optionally waits for the command to complete and collects its exit ! status (*note Exit Status::.). *************** *** 366,373 **** recognized as such, and to prevent parameter expansion. ! Each of the shell `metacharacters' (*note Definitions::.) has ! special meaning to the shell and must be quoted if they are to ! represent themselves. There are three quoting mechanisms: the ESCAPE ! CHARACTER, single quotes, and double quotes.  --- 357,364 ---- recognized as such, and to prevent parameter expansion. ! Each of the shell metacharacters (*note Definitions::.) has special ! meaning to the shell and must be quoted if it is to represent itself. ! There are three quoting mechanisms: the ESCAPE CHARACTER, single ! quotes, and double quotes.  *************** *** 380,385 **** preserves the literal value of the next character that follows, with the exception of `newline'. If a `\newline' pair appears, and the ! backslash is not quoted, the `\newline' is treated as a line ! continuation (that is, it is effectively ignored).  --- 371,377 ---- preserves the literal value of the next character that follows, with the exception of `newline'. If a `\newline' pair appears, and the ! backslash itself is not quoted, the `\newline' is treated as a line ! continuation (that is, it is removed from the input stream and ! effectively ignored).  *************** *** 402,409 **** all characters within the quotes, with the exception of `$', ``', and `\'. The characters `$' and ``' retain their special meaning within ! double quotes. The backslash retains its special meaning only when ! followed by one of the following characters: `$', ``', `"', `\', or ! `newline'. A double quote may be quoted within double quotes by ! preceding it with a backslash. The special parameters `*' and `@' have special meaning when in --- 394,404 ---- all characters within the quotes, with the exception of `$', ``', and `\'. The characters `$' and ``' retain their special meaning within ! double quotes (*note Shell Expansions::.). The backslash retains its ! special meaning only when followed by one of the following characters: ! `$', ``', `"', `\', or `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. The special parameters `*' and `@' have special meaning when in *************** *** 449,453 **** `\NNN' ! the character whose `ASCII' code is NNN in octal The result is single-quoted, as if the dollar sign had not been present. --- 444,453 ---- `\NNN' ! the character whose `ASCII' code is the octal value NNN (one to ! three digits) ! ! `\xNNN' ! the character whose `ASCII' code is the hexadecimal value NNN (one ! to three digits) The result is single-quoted, as if the dollar sign had not been present. *************** *** 476,491 **** without the `interactive_comments' option enabled does not allow comments. The `interactive_comments' option is on by default in ! interactive shells.  ! File: bashref.info, Node: Simple Commands, Next: Pipelines, Prev: Shell Syntax, Up: Basic Shell Features Simple Commands ! =============== ! A simple command is the kind of command you'll encounter most often. It's just a sequence of words separated by `blank's, terminated by one ! of the shell control operators (*note Definitions::.). The first word ! generally specifies a command to be executed. The return status (*note Exit Status::.) of a simple command is its --- 476,508 ---- without the `interactive_comments' option enabled does not allow comments. The `interactive_comments' option is on by default in ! interactive shells. *Note Is This Shell Interactive?::, for a ! description of what makes a shell interactive. ! !  ! File: bashref.info, Node: Shell Commands, Next: Shell Functions, Prev: Shell Syntax, Up: Basic Shell Features ! ! Shell Commands ! ============== ! ! * Menu: ! ! * Simple Commands:: The most common type of command. ! * Pipelines:: Connecting the input and output of several ! commands. ! * Lists:: How to execute commands sequentially. ! * Looping Constructs:: Shell commands for iterative action. ! * Conditional Constructs:: Shell commands for conditional execution. ! * Command Grouping:: Ways to group commands.  ! File: bashref.info, Node: Simple Commands, Next: Pipelines, Up: Shell Commands Simple Commands ! --------------- ! A simple command is the kind of command encountered most often. It's just a sequence of words separated by `blank's, terminated by one ! of the shell's control operators (*note Definitions::.). The first ! word generally specifies a command to be executed. The return status (*note Exit Status::.) of a simple command is its *************** *** 494,501 ****  ! File: bashref.info, Node: Pipelines, Next: Lists, Prev: Simple Commands, Up: Basic Shell Features Pipelines ! ========= A `pipeline' is a sequence of simple commands separated by `|'. --- 511,518 ----  ! File: bashref.info, Node: Pipelines, Next: Lists, Prev: Simple Commands, Up: Shell Commands Pipelines ! --------- A `pipeline' is a sequence of simple commands separated by `|'. *************** *** 509,528 **** The reserved word `time' causes timing statistics to be printed for ! the pipeline once it finishes. The `-p' option changes the output ! format to that specified by POSIX. The `TIMEFORMAT' variable may be ! set to a format string that specifies how the timing information should ! be displayed. *Note Bash Variables::, for a description of the ! available formats. ! ! Each command in a pipeline is executed in its own subshell. The exit ! status of a pipeline is the exit status of the last command in the ! pipeline. If the reserved word `!' precedes the pipeline, the exit ! status is the logical NOT of the exit status of the last command.  ! File: bashref.info, Node: Lists, Next: Looping Constructs, Prev: Pipelines, Up: Basic Shell Features Lists of Commands ! ================= A `list' is a sequence of one or more pipelines separated by one of --- 526,553 ---- The reserved word `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 `-p' option changes the output format to that ! specified by POSIX. The `TIMEFORMAT' variable may be set to a format ! string that specifies how the timing information should be displayed. ! *Note Bash Variables::, for a description of the available formats. ! The use of `time' as a reserved word permits the timing of shell ! builtins, shell functions, and pipelines. An external `time' command ! cannot time these easily. ! ! If the pipeline is not executed asynchronously (*note Lists::.), the ! shell waits for all commands in the pipeline to complete. ! ! Each command in a pipeline is executed in its own subshell (*note ! Command Execution Environment::.). The exit status of a pipeline is ! the exit status of the last command in the pipeline. If the reserved ! word `!' precedes the pipeline, the exit status is the logical negation ! of the exit status of the last command.  ! File: bashref.info, Node: Lists, Next: Looping Constructs, Prev: Pipelines, Up: Shell Commands Lists of Commands ! ----------------- A `list' is a sequence of one or more pipelines separated by one of *************** *** 534,542 **** If a command is terminated by the control operator `&', the shell ! executes the command in the BACKGROUND in a subshell. The shell does ! not wait for the command to finish, and the return status is 0 (true). ! Commands separated by a `;' 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. The control operators `&&' and `||' denote AND lists and OR lists, --- 559,571 ---- If a command is terminated by the control operator `&', the shell ! executes the command asynchronously in a subshell. This is known as ! executing the command in the BACKGROUND. The shell does not wait for ! the command to finish, and the return status is 0 (true). The standard ! input for asynchronous commands, in the absence of any explicit ! redirections, is redirected from `/dev/null'. ! ! Commands separated by a `;' 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. The control operators `&&' and `||' denote AND lists and OR lists, *************** *** 550,554 **** COMMAND || COMMAND2 ! COMMAND2 is executed if and only if COMMAND returns a non-zero exit status. --- 579,583 ---- COMMAND || COMMAND2 ! COMMAND2 is executed if, and only if, COMMAND returns a non-zero exit status. *************** *** 557,575 ****  ! File: bashref.info, Node: Looping Constructs, Next: Conditional Constructs, Prev: Lists, Up: Basic Shell Features Looping Constructs ! ================== ! ! Note that wherever you see a `;' in the description of a command's ! syntax, it may be replaced indiscriminately with one or more newlines. Bash supports the following looping constructs. `until' The syntax of the `until' command is: until TEST-COMMANDS; do CONSEQUENT-COMMANDS; done ! Execute CONSEQUENT-COMMANDS as long as the final command in ! TEST-COMMANDS has an exit status which is not zero. `while' --- 586,606 ----  ! File: bashref.info, Node: Looping Constructs, Next: Conditional Constructs, Prev: Lists, Up: Shell Commands Looping Constructs ! ------------------ Bash supports the following looping constructs. + Note that wherever you see a `;' in the description of a command's + syntax, it may be replaced with one or more newlines. + `until' The syntax of the `until' command is: until TEST-COMMANDS; do CONSEQUENT-COMMANDS; done ! Execute CONSEQUENT-COMMANDS as long as TEST-COMMANDS has an exit ! status which is not zero. The return status is the exit status of ! the last command executed in CONSEQUENT-COMMANDS, or zero if none ! was executed. `while' *************** *** 577,582 **** while TEST-COMMANDS; do CONSEQUENT-COMMANDS; done ! Execute CONSEQUENT-COMMANDS as long as the final command in ! TEST-COMMANDS has an exit status of zero. `for' --- 608,615 ---- while TEST-COMMANDS; do CONSEQUENT-COMMANDS; done ! Execute CONSEQUENT-COMMANDS as long as TEST-COMMANDS has an exit ! status of zero. The return status is the exit status of the last ! command executed in CONSEQUENT-COMMANDS, or zero if none was ! executed. `for' *************** *** 584,590 **** for NAME [in WORDS ...]; do COMMANDS; done ! Execute COMMANDS for each member in WORDS, with NAME bound to the ! current member. If `in WORDS' is not present, `in "$@"' is ! assumed. The `break' and `continue' builtins (*note Bourne Shell Builtins::.) --- 617,626 ---- for NAME [in WORDS ...]; do COMMANDS; done ! Expand WORDS, and execute COMMANDS once for each member in the ! resultant list, with NAME bound to the current member. If `in ! WORDS' is not present, `in "$@"' is assumed. The return status is ! the exit status of the last command that executes. If there are ! no items in the expansion of WORDS, no commands are executed, and ! the return status is zero. The `break' and `continue' builtins (*note Bourne Shell Builtins::.) *************** *** 592,599 ****  ! File: bashref.info, Node: Conditional Constructs, Next: Command Grouping, Prev: Looping Constructs, Up: Basic Shell Features Conditional Constructs ! ====================== `if' --- 628,635 ----  ! File: bashref.info, Node: Conditional Constructs, Next: Command Grouping, Prev: Looping Constructs, Up: Shell Commands Conditional Constructs ! ---------------------- `if' *************** *** 607,625 **** fi ! Execute CONSEQUENT-COMMANDS only if the final command in ! TEST-COMMANDS has an exit status of zero. Otherwise, each `elif' ! list is executed in turn, and if its exit status is zero, the ! corresponding MORE-CONSEQUENTS is executed and the command ! completes. If `else ALTERNATE-CONSEQUENTS' is present, and the ! final command in the final `if' or `elif' clause has a non-zero ! exit status, then execute ALTERNATE-CONSEQUENTS. `case' The syntax of the `case' command is: ! `case WORD in [ ( PATTERN [| PATTERN]...) COMMANDS ;;]... esac' ! Selectively execute COMMANDS based upon WORD matching PATTERN. ! The `|' is used to separate multiple patterns. Here is an example using `case' in a script that could be used to --- 643,676 ---- fi ! The TEST-COMMANDS list is executed, and if its return status is ! zero, the CONSEQUENT-COMMANDS list is executed. If TEST-COMMANDS ! returns a non-zero status, each `elif' list is executed in turn, ! and if its exit status is zero, the corresponding MORE-CONSEQUENTS ! is executed and the command completes. If `else ! ALTERNATE-CONSEQUENTS' is present, and the final command in the ! final `if' or `elif' clause has a non-zero exit status, then ! ALTERNATE-CONSEQUENTS is executed. The return status is the exit ! status of the last command executed, or zero if no condition ! tested true. `case' The syntax of the `case' command is: ! `case WORD in [ [(] PATTERN [| PATTERN]...) COMMAND-LIST ;;]... esac' ! `case' will selectively execute the COMMAND-LIST corresponding to ! the first PATTERN that matches WORD. The `|' is used to separate ! multiple patterns, and the `)' operator terminates a pattern list. ! A list of patterns and an associated command-list is known as a ! CLAUSE. Each clause must be terminated with `;;'. The WORD ! undergoes tilde expansion, parameter expansion, command ! substitution, arithmetic expansion, and quote removal before ! matching is attempted. Each PATTERN undergoes tilde expansion, ! parameter expansion, command substitution, and arithmetic ! expansion. ! ! There may be an arbitrary number of `case' clauses, each terminated ! by a `;;'. The first pattern that matches determines the ! command-list that is executed. Here is an example using `case' in a script that could be used to *************** *** 636,657 **** echo " legs." `((...))' (( EXPRESSION )) ! The EXPRESSION is evaluated according to the rules described below ! (*note 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 let "EXPRESSION" ! The `select' construct, which allows users to choose from a list of ! items presented as a menu, is also available. *Note Korn Shell ! Constructs::, for a full description of `select'.  ! File: bashref.info, Node: Command Grouping, Next: Shell Functions, Prev: Conditional Constructs, Up: Basic Shell Features Grouping Commands ! ================= Bash provides two ways to group a list of commands to be executed as --- 687,780 ---- echo " legs." + The return status is zero if no PATTERN is matched. Otherwise, the + return status is the exit status of the COMMAND-LIST executed. + + `select' + The `select' construct allows the easy generation of menus. It + has almost the same syntax as the `for' command: + + select NAME [in WORDS ...]; do COMMANDS; done + + The list of words following `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 `in WORDS' is + omitted, the positional parameters are printed, as if `in "$@"' + had been specifed. The `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 + NAME is set to that word. If the line is empty, the words and + prompt are displayed again. If `EOF' is read, the `select' + command completes. Any other value read causes NAME to be set to + null. The line read is saved in the variable `REPLY'. + + The COMMANDS are executed after each selection until a `break' or + `return' command is executed, at which point the `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. + + select fname in *; + do + echo you picked $fname \($REPLY\) + break; + done + `((...))' (( EXPRESSION )) ! The arithmetic EXPRESSION is evaluated according to the rules ! described below (*note 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 let "EXPRESSION" ! *Note Bash Builtins::, for a full description of the `let' builtin. ! ! `[[...]]' ! [[ EXPRESSION ]] ! ! Return a status of 0 or 1 depending on the evaluation of the ! conditional expression EXPRESSION. Expressions are composed of ! the primaries described below in *Note Bash Conditional ! Expressions::. Word splitting and filename expansion are not ! performed on the words between the `[[' and `]]'; tilde expansion, ! parameter and variable expansion, arithmetic expansion, command ! substitution, process substitution, and quote removal are ! performed. ! ! When the `==' and `!=' operators are used, the string to the right ! of the operator is considered a pattern and matched according to ! the rules described below in *Note Pattern Matching::. The return ! value is 0 if the string matches or does not match the pattern, ! respectively, and 1 otherwise. Any part of the pattern may be ! quoted to force it to be matched as a string. ! ! Expressions may be combined using the following operators, listed ! in decreasing order of precedence: ! ! `( EXPRESSION )' ! Returns the value of EXPRESSION. This may be used to ! override the normal precedence of operators. ! ! `! EXPRESSION' ! True if EXPRESSION is false. ! ! `EXPRESSION1 && EXPRESSION2' ! True if both EXPRESSION1 and EXPRESSION2 are true. ! ! `EXPRESSION1 || EXPRESSION2' ! True if either EXPRESSION1 or EXPRESSION2 is true. ! ! The && and || commands do not execute EXPRESSION2 if the value of ! EXPRESSION1 is sufficient to determine the return value of the ! entire conditional expression.  ! File: bashref.info, Node: Command Grouping, Prev: Conditional Constructs, Up: Shell Commands Grouping Commands ! ----------------- Bash provides two ways to group a list of commands to be executed as *************** *** 664,669 **** Placing a list of commands between parentheses causes a subshell ! to be created, and each of the commands to be executed in that ! subshell. Since the LIST is executed in a subshell, variable assignments do not remain in effect after the subshell completes. --- 787,792 ---- Placing a list of commands between parentheses causes a subshell ! to be created, and each of the commands in LIST to be executed in ! that subshell. Since the LIST is executed in a subshell, variable assignments do not remain in effect after the subshell completes. *************** *** 673,677 **** 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 following LIST is required. In addition to the creation of a subshell, there is a subtle --- 796,800 ---- 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 LIST is required. In addition to the creation of a subshell, there is a subtle *************** *** 686,690 ****  ! File: bashref.info, Node: Shell Functions, Next: Shell Parameters, Prev: Command Grouping, Up: Basic Shell Features Shell Functions --- 809,813 ----  ! File: bashref.info, Node: Shell Functions, Next: Shell Parameters, Prev: Shell Commands, Up: Basic Shell Features Shell Functions *************** *** 700,707 **** This defines a shell function named NAME. The reserved word ! `function' is optional. The BODY of the function is the COMMAND-LIST ! between { and }. This list is executed whenever NAME is specified as ! the name of a command. The exit status of a function is the exit ! status of the last command executed in the body. When a function is executed, the arguments to the function become --- 823,831 ---- This defines a shell function named NAME. The reserved word ! `function' is optional. If the `function' reserved word is supplied, ! the parentheses are optional. The BODY of the function is the ! COMMAND-LIST between { and }. This list is executed whenever NAME is ! specified as the name of a command. The exit status of a function is ! the exit status of the last command executed in the body. When a function is executed, the arguments to the function become *************** *** 715,720 **** the function call. When a function completes, the values of the positional parameters and the special parameter `#' are restored to the ! values they had prior to function execution. If a numeric argument is ! given to `return', that is the function return status. Variables local to the function may be declared with the `local' --- 839,846 ---- the function call. When a function completes, the values of the positional parameters and the special parameter `#' are restored to the ! values they had prior to the function's execution. If a numeric ! argument is given to `return', that is the function's return status; ! otherwise the functions's return status is the exit status of the last ! command executed before the `return'. Variables local to the function may be declared with the `local' *************** *** 750,759 **** VALUEs undergo tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal (detailed ! below). If the variable has its `-i' attribute set (see the description of the `declare' builtin in *Note Bash Builtins::), then ! VALUE is subject to arithmetic expansion even if the `$((...))' syntax ! does not appear (*note Arithmetic Expansion::.). Word splitting is not ! performed, with the exception of `"$@"' as explained below. Filename ! expansion is not performed.  --- 876,885 ---- VALUEs undergo tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal (detailed ! below). If the variable has its `integer' attribute set (see the description of the `declare' builtin in *Note Bash Builtins::), then ! VALUE is subject to arithmetic expansion even if the `$((...))' ! expansion is not used (*note Arithmetic Expansion::.). Word splitting ! is not performed, with the exception of `"$@"' as explained below. ! Filename expansion is not performed.  *************** *** 766,773 **** 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 `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 (*note Shell ! Functions::.). When a positional parameter consisting of more than a single digit --- 892,899 ---- 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 `set' builtin command. Positional parameter `N' may be ! referenced as `${N}'. Positional parameters may not be assigned to ! with assignment statements. The positional parameters are temporarily ! replaced when a shell function is executed (*note Shell Functions::.). When a positional parameter consisting of more than a single digit *************** *** 795,799 **** `@' Expands to the positional parameters, starting from one. When the ! expansion occurs within double quotes, each parameter expands as a separate word. That is, `"$@"' is equivalent to `"$1" "$2" ...'. When there are no positional parameters, `"$@"' and `$@' expand to --- 921,925 ---- `@' Expands to the positional parameters, starting from one. When the ! expansion occurs within double quotes, each parameter expands to a separate word. That is, `"$@"' is equivalent to `"$1" "$2" ...'. When there are no positional parameters, `"$@"' and `$@' expand to *************** *** 814,818 **** `$' Expands to the process ID of the shell. In a `()' subshell, it ! expands to the process ID of the current shell, not the subshell. `!' --- 940,944 ---- `$' Expands to the process ID of the shell. In a `()' subshell, it ! expands to the process ID of the invoking shell, not the subshell. `!' *************** *** 822,830 **** `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, ! `$0' is set to the name of that file. If Bash is started with the ! `-c' option, then `$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. `_' --- 948,957 ---- `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 ! (*note Shell Scripts::.), `$0' is set to the name of that file. ! If Bash is started with the `-c' option (*note Invoking Bash::.), ! then `$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. `_' *************** *** 832,836 **** shell script being executed as passed in the argument list. Subsequently, expands to the last argument to the previous command, ! after expansion. Also set to the full filename of each command executed and placed in the environment exported to that command. When checking mail, this parameter holds the name of the mail file. --- 959,963 ---- shell script being executed as passed in the argument list. Subsequently, expands to the last argument to the previous command, ! after expansion. Also set to the full pathname of each command executed and placed in the environment exported to that command. When checking mail, this parameter holds the name of the mail file. *************** *** 860,865 **** --- 987,995 ---- * 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. *************** *** 870,878 **** words. - Brace expansion, tilde expansion, and arithmetic expansion are - described in other sections. For brace expansion, see *Note Brace - Expansion::; for tilde expansion, see *Note Tilde Expansion::; and for - arithmetic expansion, see *Note Arithmetic Expansion::. - The order of expansions is: brace expansion, tilde expansion, parameter, variable, and arithmetic expansion and command substitution --- 1000,1003 ---- *************** *** 882,886 **** On systems that can support it, there is an additional expansion available: PROCESS SUBSTITUTION. This is performed at the same time as ! parameter, variable, and arithemtic expansion and command substitution. Only brace expansion, word splitting, and filename expansion can --- 1007,1011 ---- On systems that can support it, there is an additional expansion available: PROCESS SUBSTITUTION. This is performed at the same time as ! parameter, variable, and arithmetic expansion and command substitution. Only brace expansion, word splitting, and filename expansion can *************** *** 894,898 ****  ! File: bashref.info, Node: Shell Parameter Expansion, Next: Command Substitution, Up: Shell Expansions Shell Parameter Expansion --- 1019,1122 ----  ! File: bashref.info, Node: Brace Expansion, Next: Tilde Expansion, Up: Shell Expansions ! ! Brace Expansion ! --------------- ! ! Brace expansion is a mechanism by which arbitrary strings may be ! generated. This mechanism is similar to FILENAME EXPANSION (*note ! Filename Expansion::.), but the file names generated need not exist. ! Patterns to be brace expanded take the form of an optional PREAMBLE, ! followed by a series of comma-separated strings between a pair of ! braces, followed by an optional POSTSCRIPT. The preamble is prepended ! 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, ! bash$ echo a{d,c,b}e ! ade ace abe ! ! 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. ! ! A correctly-formed brace expansion must contain unquoted opening and ! closing braces, and at least one unquoted comma. Any incorrectly ! formed brace expansion is left unchanged. ! ! This construct is typically used as shorthand when the common prefix ! of the strings to be generated is longer than in the above example: ! mkdir /usr/local/src/bash/{old,new,dist,bugs} ! or ! chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}} ! !  ! File: bashref.info, Node: Tilde Expansion, Next: Shell Parameter Expansion, Prev: Brace Expansion, Up: Shell Expansions ! ! Tilde Expansion ! --------------- ! ! If a word begins with an unquoted tilde character (`~'), all of the ! characters up to the first unquoted slash (or all characters, if there ! is no unquoted slash) are considered a 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 LOGIN NAME. ! If this login name is the null string, the tilde is replaced with the ! value of the `HOME' shell variable. If `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 `~+', the value of the shell variable `PWD' ! replaces the tilde-prefix. If the tilde-prefix is `~-', the value of ! the shell variable `OLDPWD', if it is set, is substituted. ! ! If the characters following the tilde in the tilde-prefix consist of ! a number N, 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 `dirs' builtin invoked with the characters ! following tilde in the tilde-prefix as an argument (*note The Directory ! Stack::.). If the tilde-prefix, sans the tilde, consists of a number ! without a leading `+' or `-', `+' 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 `:' or `='. In these cases, tilde expansion is ! also performed. Consequently, one may use file names with tildes in ! assignments to `PATH', `MAILPATH', and `CDPATH', and the shell assigns ! the expanded value. ! ! The following table shows how Bash treats unquoted tilde-prefixes: ! ! `~' ! The value of `$HOME' ! ! `~/foo' ! `$HOME/foo' ! ! `~fred/foo' ! The subdirectory `foo' of the home directory of the user `fred' ! ! `~+/foo' ! `$PWD/foo' ! ! `~-/foo' ! `${OLDPWD-'~-'}/foo' ! ! `~N' ! The string that would be displayed by `dirs +N' ! ! `~+N' ! The string that would be displayed by `dirs +N' ! ! `~-N' ! The string that would be displayed by `dirs -N' ! !  ! File: bashref.info, Node: Shell Parameter Expansion, Next: Command Substitution, Prev: Tilde Expansion, Up: Shell Expansions Shell Parameter Expansion *************** *** 905,908 **** --- 1129,1137 ---- following it which could be interpreted as part of the name. + When braces are used, the matching ending brace is the first `}' 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 ${PARAMETER}. The value of PARAMETER is substituted. The braces are required when PARAMETER is a *************** *** 946,954 **** `${PARAMETER:OFFSET}' `${PARAMETER:OFFSET:LENGTH}' ! Expands to up to LENGTH characters of PARAMETER, starting at ! OFFSET. If LENGTH is omitted, expands to the substring of ! PARAMETER, starting at the character specified by OFFSET. LENGTH ! and OFFSET are arithmetic expressions (*note Arithmetic ! Evaluation::.). This is referred to as Substring Expansion. LENGTH must evaluate to a number greater than or equal to zero. --- 1175,1183 ---- `${PARAMETER:OFFSET}' `${PARAMETER:OFFSET:LENGTH}' ! Expands to up to LENGTH characters of PARAMETER, starting at the ! character specified by OFFSET. If LENGTH is omitted, expands to ! the substring of PARAMETER, starting at the character specified by ! OFFSET. LENGTH and OFFSET are arithmetic expressions (*note Shell ! Arithmetic::.). This is referred to as Substring Expansion. LENGTH must evaluate to a number greater than or equal to zero. *************** *** 958,971 **** OFFSET. If PARAMETER is an array name indexed by `@' or `*', the result is the LENGTH members of the array beginning with ! ${PARAMETER[OFFSET]}. Substring indexing is zero-based unless the ! positional parameters are used, in which case the indexing starts ! at 1. `${#PARAMETER}' ! The length in characters of the value of PARAMETER is substituted. ! If PARAMETER is `*' or `@', the length substituted is the number ! of positional parameters. If PARAMETER is an array name ! subscripted by `*' or `@', the length substituted is the number of ! elements in the array. `${PARAMETER#WORD}' --- 1187,1200 ---- OFFSET. If PARAMETER is an array name indexed by `@' or `*', the result is the LENGTH members of the array beginning with ! `${PARAMETER[OFFSET]}'. Substring indexing is zero-based unless ! the positional parameters are used, in which case the indexing ! starts at 1. `${#PARAMETER}' ! The length in characters of the expanded value of PARAMETER is ! substituted. If PARAMETER is `*' or `@', the value substituted is ! the number of positional parameters. If PARAMETER is an array ! name subscripted by `*' or `@', the value substituted is the ! number of elements in the array. `${PARAMETER#WORD}' *************** *** 973,998 **** The WORD is expanded to produce a pattern just as in filename expansion (*note Filename Expansion::.). If the pattern matches ! the beginning of the value of PARAMETER, then the expansion is the ! value of PARAMETER with the shortest matching pattern (the `#' ! case) or the longest matching pattern (the `##' case) deleted. If ! PARAMETER is `@' or `*', the pattern removal operation is applied ! to each positional parameter in turn, and the expansion is the ! resultant list. If PARAMETER is an array variable subscripted with ! `@' or `*', the pattern removal operation is applied to each ! member of the array in turn, and the expansion is the resultant ! list. `${PARAMETER%WORD}' `${PARAMETER%%WORD}' The WORD is expanded to produce a pattern just as in filename ! expansion. If the pattern matches a trailing portion of the value ! of PARAMETER, then the expansion is the value of PARAMETER with ! the shortest matching pattern (the `%' case) or the longest ! matching pattern (the `%%' case) deleted. If PARAMETER is `@' or ! `*', the pattern removal operation is applied to each positional ! parameter in turn, and the expansion is the resultant list. If ! PARAMETER is an array variable subscripted with `@' or `*', the ! pattern removal operation is applied to each member of the array ! in turn, and the expansion is the resultant list. `${PARAMETER/PATTERN/STRING}' --- 1202,1228 ---- The WORD is expanded to produce a pattern just as in filename expansion (*note Filename Expansion::.). If the pattern matches ! the beginning of the expanded value of PARAMETER, then the result ! of the expansion is the expanded value of PARAMETER with the ! shortest matching pattern (the `#' case) or the longest matching ! pattern (the `##' case) deleted. If PARAMETER is `@' or `*', the ! pattern removal operation is applied to each positional parameter ! in turn, and the expansion is the resultant list. If PARAMETER is ! an array variable subscripted with `@' or `*', the pattern removal ! operation is applied to each member of the array in turn, and the ! expansion is the resultant list. `${PARAMETER%WORD}' `${PARAMETER%%WORD}' The WORD is expanded to produce a pattern just as in filename ! expansion. If the pattern matches a trailing portion of the ! expanded value of PARAMETER, then the result of the expansion is ! the value of PARAMETER with the shortest matching pattern (the `%' ! case) or the longest matching pattern (the `%%' case) deleted. If ! PARAMETER is `@' or `*', the pattern removal operation is applied ! to each positional parameter in turn, and the expansion is the ! resultant list. If PARAMETER is an array variable subscripted ! with `@' or `*', the pattern removal operation is applied to each ! member of the array in turn, and the expansion is the resultant ! list. `${PARAMETER/PATTERN/STRING}' *************** *** 1014,1018 ****  ! File: bashref.info, Node: Command Substitution, Next: Process Substitution, Prev: Shell Parameter Expansion, Up: Shell Expansions Command Substitution --- 1244,1248 ----  ! File: bashref.info, Node: Command Substitution, Next: Arithmetic Expansion, Prev: Shell Parameter Expansion, Up: Shell Expansions Command Substitution *************** *** 1028,1040 **** Bash performs the expansion by executing COMMAND and replacing the command substitution with the standard output of the command, with any ! trailing newlines deleted. When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by `$', ``', or `\'. ! When using the `$(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 old ! form, escape the inner backquotes with backslashes. If the substitution appears within double quotes, word splitting and --- 1258,1273 ---- Bash performs the expansion by executing 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 `$(cat ! FILE)' can be replaced by the equivalent but faster `$(< FILE)'. When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by `$', ``', or `\'. ! The first backquote not preceded by a backslash terminates the command ! substitution. When using the `$(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 *************** *** 1042,1046 ****  ! File: bashref.info, Node: Process Substitution, Next: Word Splitting, Prev: Command Substitution, Up: Shell Expansions Process Substitution --- 1275,1302 ----  ! File: bashref.info, Node: Arithmetic Expansion, Next: Process Substitution, Prev: Command Substitution, Up: Shell Expansions ! ! Arithmetic Expansion ! -------------------- ! ! Arithmetic expansion allows the evaluation of an arithmetic ! expression and the substitution of the result. The format for ! arithmetic expansion is: ! ! $(( EXPRESSION )) ! ! 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 expansion, command ! substitution, and quote removal. Arithmetic substitutions may be ! nested. ! ! The evaluation is performed according to the rules listed below ! (*note Shell Arithmetic::.). If the expression is invalid, Bash prints ! a message indicating failure to the standard error and no substitution ! occurs. ! !  ! File: bashref.info, Node: Process Substitution, Next: Word Splitting, Prev: Arithmetic Expansion, Up: Shell Expansions Process Substitution *************** *** 1062,1068 **** should be read to obtain the output of LIST. ! On systems that support it, process substitution is performed ! simultaneously with parameter and variable expansion, command ! substitution, and arithmetic expansion.  --- 1318,1324 ---- should be read to obtain the output of LIST. ! When available, process substitution is performed simultaneously with ! parameter and variable expansion, command substitution, and arithmetic ! expansion.  *************** *** 1102,1125 **** ------------------ After word splitting, unless the `-f' option has been set (*note The ! Set Builtin::.), Bash scans each word for the characters `*', `?', and ! `['. If one of these characters appears, then the word is regarded as ! a PATTERN, and replaced with an alphabetically sorted list of file names matching the pattern. If no matching file names are found, and ! the shell option `nullglob' is disabled, the word is left unchanged. If ! the option is set, and no matches are found, the word is removed. When ! a pattern is used for filename generation, the character `.' at the ! start of a filename or immediately following a slash must be matched ! explicitly, unless the shell option `dotglob' is set. The slash ! character must always be matched explicitly. In other cases, the `.' ! character is not treated specially. See the description of `shopt' in ! *Note Bash Builtins::, for a description of the `nullglob' and ! `dotglob' options. The `GLOBIGNORE' shell variable may be used to restrict the set of ! filenames matching a PATTERN. If `GLOBIGNORE' is set, each matching filename that also matches one of the patterns in `GLOBIGNORE' is removed from the list of matches. The filenames `.' and `..' are ! always ignored, even when `GLOBIGNORE'. is set. However, setting `GLOBIGNORE' has the effect of enabling the `dotglob' shell option, so all other filenames beginning with a `.' will match. To get the old --- 1358,1389 ---- ------------------ + * Menu: + + * Pattern Matching:: How the shell matches patterns. + After word splitting, unless the `-f' option has been set (*note The ! Set Builtin::.), Bash scans each word for the characters `*', `?', `(', ! and `['. If one of these characters appears, then the word is regarded ! as a PATTERN, and replaced with an alphabetically sorted list of file names matching the pattern. If no matching file names are found, and ! the shell option `nullglob' is disabled, the word is left unchanged. ! If the `nullglob' option is set, and no matches are found, the word is ! removed. If the shell option `nocaseglob' is enabled, the match is ! performed without regard to the case of alphabetic characters. ! ! When a pattern is used for filename generation, the character `.' at ! the start of a filename or immediately following a slash must be ! matched explicitly, unless the shell option `dotglob' is set. When ! matching a file name, the slash character must always be matched ! explicitly. In other cases, the `.' character is not treated specially. ! ! See the description of `shopt' in *Note Bash Builtins::, for a ! description of the `nocaseglob', `nullglob', and `dotglob' options. The `GLOBIGNORE' shell variable may be used to restrict the set of ! filenames matching a pattern. If `GLOBIGNORE' is set, each matching filename that also matches one of the patterns in `GLOBIGNORE' is removed from the list of matches. The filenames `.' and `..' are ! always ignored, even when `GLOBIGNORE' is set. However, setting `GLOBIGNORE' has the effect of enabling the `dotglob' shell option, so all other filenames beginning with a `.' will match. To get the old *************** *** 1128,1131 **** --- 1392,1406 ---- `GLOBIGNORE' is unset. +  + File: bashref.info, Node: Pattern Matching, Up: Filename Expansion + + Pattern Matching + ................ + + 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. The special pattern characters must be + quoted if they are to be matched literally. + The special pattern characters have the following meanings: `*' *************** *** 1144,1147 **** --- 1419,1459 ---- including it as the first character in the set. + Within `[' and `]', CHARACTER CLASSES can be specified using the + syntax `[:'CLASS`:]', where CLASS is one of the following classes + defined in the POSIX.2 standard: + alnum alpha ascii blank cntrl digit graph lower + print punct space upper xdigit + + A character class matches any character belonging to that class. + + Within `[' and `]', an EQUIVALENCE CLASS can be specified using + the syntax `[='C`=]', which matches all characters with the same + collation weight (as defined by the current locale) as the + character C. + + Within `[' and `]', the syntax `[.'SYMBOL`.]' matches the + collating symbol SYMBOL. + + If the `extglob' shell option is enabled using the `shopt' builtin, + several extended pattern matching operators are recognized. In the + following description, a PATTERN-LIST is a list of one or more patterns + separated by a `|'. Composite patterns may be formed using one or more + of the following sub-patterns: + + `?(PATTERN-LIST)' + Matches zero or one occurrence of the given patterns. + + `*(PATTERN-LIST)' + Matches zero or more occurrences of the given patterns. + + `+(PATTERN-LIST)' + Matches one or more occurrences of the given patterns. + + `@(PATTERN-LIST)' + Matches exactly one of the given patterns. + + `!(PATTERN-LIST)' + Matches anything except one of the given patterns. +  File: bashref.info, Node: Quote Removal, Prev: Filename Expansion, Up: Shell Expansions *************** *** 1173,1181 **** refers to the standard output (file descriptor 1). ! The word that follows the redirection operator in the following ! descriptions is subjected to brace expansion, tilde expansion, ! parameter expansion, command substitution, arithmetic expansion, quote ! removal, and filename expansion. If it expands to more than one word, ! Bash reports an error. Note that the order of redirections is significant. For example, --- 1485,1493 ---- 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, and filename expansion. If it expands to ! more than one word, Bash reports an error. Note that the order of redirections is significant. For example, *************** *** 1191,1194 **** --- 1503,1508 ---- redirected to DIRLIST. + A failure to open or create a file causes the redirection to fail. + Redirecting Input ----------------- *************** *** 1213,1222 **** [n]>[|]WORD ! If the redirection operator is `>', and the `-C' option to the `set' ! builtin has been enabled, the redirection will fail if the filename ! whose name results from the expansion of WORD exists. If the ! redirection operator is `>|', then the value of the `-C' option to the ! `set' builtin command is not tested, and the redirection is attempted ! even if the file named by WORD exists. Appending Redirected Output --- 1527,1536 ---- [n]>[|]WORD ! If the redirection operator is `>', and the `noclobber' option to ! the `set' builtin has been enabled, the redirection will fail if the ! filename whose name results from the expansion of WORD exists and is a ! regular file. If the redirection operator is `>|', or the redirection ! operator is `>' and the `noclobber' option is not enabled, the ! redirection is attempted even if the file named by WORD exists. Appending Redirected Output *************** *** 1265,1273 **** arithmetic expansion is performed on WORD. If any characters in WORD are quoted, the DELIMITER is the result of quote removal on WORD, and ! the lines in the here-document are not expanded. Otherwise, all lines ! of the here-document are subjected to parameter expansion, command ! substitution, and arithmetic expansion. In the latter case, the pair ! `\newline' is ignored, and `\' must be used to quote the characters ! `\', `$', and ``'. If the redirection operator is `<<-', then all leading tab --- 1579,1587 ---- arithmetic expansion is performed on WORD. If any characters in WORD are quoted, the DELIMITER is the result of quote removal on WORD, and ! the lines in the here-document are not expanded. If WORD is unquoted, ! all lines of the here-document are subjected to parameter expansion, ! command substitution, and arithmetic expansion. In the latter case, ! the pair `\newline' is ignored, and `\' must be used to quote the ! characters `\', `$', and ``'. If the redirection operator is `<<-', then all leading tab *************** *** 1284,1290 **** is used to duplicate input file descriptors. If WORD expands to one or more digits, the file descriptor denoted by `n' is made to be a copy of ! that file descriptor. If WORD evaluates to `-', file descriptor `n' is ! closed. If `n' is not specified, the standard input (file descriptor ! 0) is used. The operator --- 1598,1605 ---- is used to duplicate input file descriptors. If WORD expands to one or more digits, the file descriptor denoted by `n' is made to be a copy of ! that file descriptor. If the digits in WORD do not specify a file ! descriptor open for input, a redirection error occurs. If WORD ! evaluates to `-', file descriptor `n' is closed. If `n' is not ! specified, the standard input (file descriptor 0) is used. The operator *************** *** 1292,1299 **** is used similarly to duplicate output file descriptors. If `n' is not ! specified, the standard output (file descriptor 1) is used. As a ! special case, if `n' is omitted, and WORD does not expand to one or ! more digits, the standard output and standard error are redirected as ! described previously. Opening File Descriptors for Reading and Writing --- 1607,1615 ---- is used similarly to duplicate output file descriptors. If `n' is not ! specified, the standard output (file descriptor 1) is used. If the ! digits in WORD do not specify a file descriptor open for output, a ! redirection error occurs. As a special case, if `n' is omitted, and ! WORD does not expand to one or more digits, the standard output and ! standard error are redirected as described previously. Opening File Descriptors for Reading and Writing *************** *** 1315,1320 **** --- 1631,1643 ---- * 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. *************** *** 1326,1330 ****  ! File: bashref.info, Node: Command Search and Execution, Next: Environment, Up: Executing Commands Command Search and Execution --- 1649,1696 ----  ! File: bashref.info, Node: Simple Command Expansion, Next: Command Search and Execution, Up: Executing Commands ! ! Simple Command Expansion ! ------------------------ ! ! When a simple command is executed, the shell performs the following ! expansions, assignments, and redirections, from left to right. ! ! 1. The words that the parser has marked as variable assignments (those ! preceding the command name) and redirections are saved for later ! processing. ! ! 2. The words that are not variable assignments or redirections are ! expanded (*note 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. ! ! 3. Redirections are performed as described above (*note ! Redirections::.). ! ! 4. The text after the `=' in each variable assignment undergoes tilde ! expansion, parameter expansion, command substitution, arithmetic ! expansion, and quote removal before being assigned to the variable. ! ! 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. ! !  ! File: bashref.info, Node: Command Search and Execution, Next: Command Execution Environment, Prev: Simple Command Expansion, Up: Executing Commands Command Search and Execution *************** *** 1346,1367 **** contains no slashes, Bash searches each element of `$PATH' for a directory containing an executable file by that name. Bash uses a ! hash table to remember the full filenames of executable files (see ! the description of `hash' in *Note Bourne Shell Builtins::) to ! avoid multiple `PATH' searches. A full search of the directories in `$PATH' is performed only if the command is not found in the hash table. If the search is unsuccessful, the shell prints an ! error message and returns a nonzero exit status. 4. If the search is successful, or if the command name contains one ! or more slashes, the shell executes the named program. Argument 0 ! is set to the name given, and the remaining arguments to the ! command are set to the arguments supplied, if any. 5. If this execution fails because the file is not in executable ! format, and the file is not a directory, it is assumed to be SHELL ! SCRIPT (*note Shell Scripts::.).  ! File: bashref.info, Node: Environment, Next: Exit Status, Prev: Command Search and Execution, Up: Executing Commands Environment --- 1712,1804 ---- contains no slashes, Bash searches each element of `$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 `PATH' searches (see the description of `hash' in ! *Note Bourne Shell Builtins::). A full search of the directories in `$PATH' is performed only if the command is not found in the hash table. If the search is unsuccessful, the shell prints an ! error message and returns an exit status of 127. 4. 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. 5. 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 ! SHELL SCRIPT and the shell executes it as described in *Note Shell ! Scripts::. ! ! 6. If the command was not begun asynchronously, the shell waits for ! the command to complete and collects its exit status. ! ! !  ! File: bashref.info, Node: Command Execution Environment, Next: Environment, Prev: Command Search and Execution, Up: Executing Commands ! ! Command Execution Environment ! ----------------------------- ! ! The shell has an EXECUTION ENVIRONMENT, which consists of the ! following: ! ! * open files inherited by the shell at invocation, as modified by ! redirections supplied to the `exec' builtin ! ! * the current working directory as set by `cd', `pushd', or `popd', ! or inherited by the shell at invocation ! ! * the file creation mode mask as set by `umask' or inherited from ! the shell's parent ! ! * current traps set by `trap' ! ! * shell parameters that are set by variable assignment or with `set' ! or inherited from the shell's parent in the environment ! ! * shell functions defined during execution or inherited from the ! shell's parent in the environment ! ! * options enabled at invocation (either by default or with ! command-line arguments) or by `set' ! ! * options enabled by `shopt' ! ! * shell aliases defined with `alias' (*note Aliases::.) ! ! * various process IDs, including those of background jobs (*note ! Lists::.), the value of `$$', and the value of `$PPID' ! ! 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. ! ! * the shell's open files, plus any modifications and additions ! specified by redirections to the command ! ! * the current working directory ! ! * the file creation mode mask ! ! * shell variables marked for export, along with variables exported ! for the command, passed in the environment (*note Environment::.) ! ! * traps caught by the shell are reset to the values inherited from ! the shell's parent, and traps ignored by the shell are ignored ! ! A command invoked in this separate environment cannot affect the ! shell's execution environment. ! ! Command substitution 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.  ! File: bashref.info, Node: Environment, Next: Exit Status, Prev: Command Execution Environment, Up: Executing Commands Environment *************** *** 1381,1386 **** 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 `unset' command, ! plus any additions via the `export' and `declare -x' commands. The environment for any simple command or function may be augmented --- 1818,1824 ---- 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 `unset' and ! `export -n' commands, plus any additions via the `export' and `declare ! -x' commands. The environment for any simple command or function may be augmented *************** *** 1389,1393 **** environment seen by that command. ! If the `-k' flag is set (*note The Set Builtin::., then all parameter assignments are placed in the environment for a command, not just those that precede the command name. --- 1827,1831 ---- environment seen by that command. ! If the `-k' option is set (*note The Set Builtin::.), then all parameter assignments are placed in the environment for a command, not just those that precede the command name. *************** *** 1403,1412 **** ----------- ! For the purposes of the shell, 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 N, Bash uses the value 128+N as the exit status. If a command is not found, the child process created to execute it --- 1841,1850 ---- ----------- ! 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 N, Bash uses the value 128+N as the exit status. If a command is not found, the child process created to execute it *************** *** 1414,1417 **** --- 1852,1858 ---- 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 (*note Conditional Constructs::.) and some of the list constructs (*note *************** *** 1420,1424 **** 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.  --- 1861,1866 ---- 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.  *************** *** 1428,1451 **** ------- ! When Bash is interactive, it ignores `SIGTERM' (so that `kill 0' ! does not kill an interactive shell), and `SIGINT' is caught and handled ! (so that the `wait' builtin is interruptible). When Bash receives a ! `SIGINT', it breaks out of any executing loops. In all cases, Bash ! ignores `SIGQUIT'. If job control is in effect (*note Job Control::.), ! Bash ignores `SIGTTIN', `SIGTTOU', and `SIGTSTP'. ! Synchronous jobs started by Bash have signals set to the values inherited by the shell from its parent. When job control is not in ! effect, background jobs (commands terminated with `&') ignore `SIGINT' ! and `SIGQUIT'. Commands run as a result of command substitution ignore ! the keyboard-generated job control signals `SIGTTIN', `SIGTTOU', and `SIGTSTP'. The shell exits by default upon receipt of a `SIGHUP'. Before ! exiting, it resends the `SIGHUP' to all jobs, running or stopped. To ! prevent the shell from sending the `SIGHUP' signal to a particular job, ! remove it from the jobs table with the `disown' builtin (*note Job ! Control Builtins::.) or use `disown -h' to mark it to not receive ! `SIGHUP'.  --- 1870,1907 ---- ------- ! When Bash is interactive, in the absence of any traps, it ignores ! `SIGTERM' (so that `kill 0' does not kill an interactive shell), and ! `SIGINT' is caught and handled (so that the `wait' builtin is ! interruptible). When Bash receives a `SIGINT', it breaks out of any ! executing loops. In all cases, Bash ignores `SIGQUIT'. If job control ! is in effect (*note Job Control::.), Bash ignores `SIGTTIN', `SIGTTOU', ! and `SIGTSTP'. ! 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 `SIGINT' and `SIGQUIT' as well. ! Commands run as a result of command substitution ignore the ! keyboard-generated job control signals `SIGTTIN', `SIGTTOU', and `SIGTSTP'. The shell exits by default upon receipt of a `SIGHUP'. Before ! exiting, it resends the `SIGHUP' to all jobs, running or stopped. ! Stopped jobs are sent `SIGCONT' to ensure that they receive the ! `SIGHUP'. To prevent the shell from sending the `SIGHUP' signal to a ! particular job, it should be removed from the jobs table with the ! `disown' builtin (*note Job Control Builtins::.) or marked to not ! receive `SIGHUP' using `disown -h'. ! ! If the `huponexit' shell option has been set with `shopt' (*note ! Bash Builtins::.), Bash sends a `SIGHUP' to all jobs when an ! interactive login shell exits. ! ! When Bash receives a signal for which a trap has been set while ! waiting for a command to complete, the trap will not be executed until ! the command completes. When Bash is waiting for an asynchronous ! command via the `wait' builtin, the reception of a signal for which a ! trap has been set will cause the `wait' builtin to return immediately ! with an exit status greater than 128, immediately after which the trap ! is executed.  *************** *** 1476,1480 **** if `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. Most versions of Unix make this a part of the kernel's command --- 1932,1938 ---- if `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 `hash' in ! *Note Bourne Shell Builtins::) are retained by the child. Most versions of Unix make this a part of the kernel's command *************** *** 1490,1494 ****  ! File: bashref.info, Node: Bourne Shell Features, Next: Csh Features, Prev: Basic Shell Features, Up: Top Bourne Shell Style Features --- 1948,1952 ----  ! File: bashref.info, Node: Bourne Shell Features, Next: Bash Features, Prev: Basic Shell Features, Up: Top Bourne Shell Style Features *************** *** 1506,1510 **** This section briefly summarizes things which Bash inherits from the Bourne Shell: builtins, variables, and other features. It also lists ! the significant differences between Bash and the Bourne Shell.  --- 1964,1969 ---- This section briefly summarizes things which Bash inherits from the Bourne Shell: builtins, variables, and other features. It also lists ! the significant differences between Bash and the Bourne Shell. Many of ! the builtins have been extended by POSIX or Bash.  *************** *** 1521,1534 **** : [ARGUMENTS] Do nothing beyond expanding ARGUMENTS and performing redirections. `.' . FILENAME Read and execute commands from the FILENAME argument in the ! current shell context. `break' break [N] Exit from a `for', `while', `until', or `select' loop. If N is ! supplied, the Nth enclosing loop is exited. `cd' --- 1980,2001 ---- : [ARGUMENTS] Do nothing beyond expanding ARGUMENTS and performing redirections. + The return status is zero. `.' . FILENAME Read and execute commands from the FILENAME argument in the ! current shell context. If FILENAME does not contain a slash, the ! `$PATH' variable is used to find FILENAME. The current directory ! is searched if FILENAME is not found in `$PATH'. The return ! status is the exit status of the last command executed, or zero if ! no commands are executed. If FILENAME is not found, or cannot be ! read, the return status is non-zero. `break' break [N] Exit from a `for', `while', `until', or `select' loop. If N is ! supplied, the Nth enclosing loop is exited. N must be greater ! than or equal to 1. The return status is zero unless N is not ! greater than or equal to 1. `cd' *************** *** 1538,1543 **** the shell variable `CDPATH' exists, it is used as a search path. If DIRECTORY begins with a slash, `CDPATH' is not used. The `-P' ! option means to not follow symbolic links; symlinks are followed ! by default or with the `-L' option. `continue' --- 2005,2012 ---- the shell variable `CDPATH' exists, it is used as a search path. If DIRECTORY begins with a slash, `CDPATH' is not used. The `-P' ! option means to not follow symbolic links; symbolic links are ! followed by default or with the `-L' option. If DIRECTORY is `-', ! it is equivalent to `$OLDPWD'. The return status is zero if the ! directory is successfully changed, non-zero otherwise. `continue' *************** *** 1545,1568 **** Resume the next iteration of an enclosing `for', `while', `until', or `select' loop. If N is supplied, the execution of the Nth ! enclosing loop is resumed. `eval' eval [ARGUMENTS] The arguments are concatenated together into a single command, ! which is then read and executed. `exec' ! exec [-cl] [-a NAME] [COMMAND] [ARGUMENTS] ! If COMMAND is supplied, it replaces the shell. If the `-l' option ! is supplied, the shell places a dash in the zeroth arg passed to ! COMMAND. This is what the `login' program does. The `-c' option ! causes COMMAND to be executed with an empty environment. If `-a' ! is supplied, the shell passes NAME as the zeroth argument to ! COMMAND. If no COMMAND is specified, redirections may be used to ! affect the current shell environment. `exit' exit [N] Exit the shell, returning a status of N to the shell's parent. `export' --- 2014,2044 ---- Resume the next iteration of an enclosing `for', `while', `until', or `select' loop. If N is supplied, the execution of the Nth ! enclosing loop is resumed. N must be greater than or equal to 1. ! The return status is zero unless N is not greater than or equal to ! 1. `eval' eval [ARGUMENTS] 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 `eval'. If there are no arguments or only ! empty arguments, the return status is zero. `exec' ! exec [-cl] [-a NAME] [COMMAND [ARGUMENTS]] ! If COMMAND is supplied, it replaces the shell without creating a ! new process. If the `-l' option is supplied, the shell places a ! dash in the zeroth arg passed to COMMAND. This is what the ! `login' program does. The `-c' option causes COMMAND to be ! executed with an empty environment. If `-a' is supplied, the ! shell passes NAME as the zeroth argument to COMMAND. If no ! 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. `exit' exit [N] Exit the shell, returning a status of N to the shell's parent. + Any trap on `EXIT' is executed before the shell terminates. `export' *************** *** 1570,1576 **** Mark each NAME to be passed to child processes in the environment. If the `-f' option is supplied, the NAMEs refer to shell ! functions. The `-n' option means to no longer mark each NAME for ! export. If no NAMES are supplied, or if the `-p' option is given, ! a list of exported names is displayed. `getopts' --- 2046,2057 ---- Mark each NAME to be passed to child processes in the environment. If the `-f' option is supplied, the NAMEs refer to shell ! functions; otherwise the names refer to shell variables. The `-n' ! option means to no longer mark each NAME for export. If no NAMES ! are supplied, or if the `-p' option is given, a list of exported ! names is displayed. The `-p' option displays output in a form ! that may be reused as input. The return status is zero unless an ! invalid option is supplied, one of the names is not a valid shell ! variable name, or `-f' is supplied with a name that is not a shell ! function. `getopts' *************** *** 1590,1601 **** invocation if a new set of parameters is to be used. `getopts' can report errors in two ways. If the first character of OPTSTRING is a colon, SILENT error reporting is used. In normal ! operation diagnostic messages are printed when illegal options or missing option arguments are encountered. If the variable `OPTERR' ! is set to 0, no error message will be displayed, even if the first character of `optstring' is not a colon. ! If an illegal option is seen, `getopts' places `?' into NAME and, if not silent, prints an error message and unsets `OPTARG'. If `getopts' is silent, the option character found is placed in --- 2071,2089 ---- invocation if a new set of parameters is to be used. + When the end of options is encountered, `getopts' exits with a + return value greater than zero. `OPTIND' is set to the index of + the first non-option argument, and `name' is set to `?'. + + `getopts' normally parses the positional parameters, but if more + arguments are given in ARGS, `getopts' parses those instead. + `getopts' can report errors in two ways. If the first character of OPTSTRING is a colon, SILENT error reporting is used. In normal ! operation diagnostic messages are printed when invalid options or missing option arguments are encountered. If the variable `OPTERR' ! is set to 0, no error messages will be displayed, even if the first character of `optstring' is not a colon. ! If an invalid option is seen, `getopts' places `?' into NAME and, if not silent, prints an error message and unsets `OPTARG'. If `getopts' is silent, the option character found is placed in *************** *** 1608,1623 **** character found. - `getopts' normally parses the positional parameters, but if more - arguments are given in ARGS, `getopts' parses those instead. - `hash' hash [-r] [-p FILENAME] [NAME] ! Remember the full filenames of commands specified as arguments, so ! they need not be searched for on subsequent invocations. The ! commands are found by searching through the directories listed in ! `$PATH'. The `-p' option inhibits the path search, and FILENAME ! is used as the location of NAME. The `-r' option causes the shell ! to forget all remembered locations. If no arguments are given, ! information about remembered commands is printed. `pwd' --- 2096,2110 ---- character found. `hash' hash [-r] [-p FILENAME] [NAME] ! Remember the full pathnames of commands specified as NAME ! arguments, so they need not be searched for on subsequent ! invocations. The commands are found by searching through the ! directories listed in `$PATH'. The `-p' option inhibits the path ! search, and FILENAME is used as the location of NAME. The `-r' ! option causes the shell to forget all remembered locations. If no ! arguments are given, information about remembered commands is ! printed. The return status is zero unless a NAME is not found or ! an invalid option is supplied. `pwd' *************** *** 1626,1662 **** supplied, the path printed will not contain symbolic links. If the `-L' option is supplied, the path printed may contain symbolic ! links. `readonly' readonly [-apf] [NAME] ... ! Mark each NAME as unchangable. The values of these names may not ! be changed by subsequent assignment. If the `-f' option is ! supplied, each NAME refers to a shell function. The `-a' option ! means each NAME refers to an array variable. If no NAME arguments ! are given, or if the `-p' option is supplied, a list of all ! readonly names is printed. `return' return [N] ! Cause a shell function to exit with value N. This may also be used ! to terminate execution of a script being executed with the `.' ! builtin. `shift' shift [N] ! Shift positional parameters to the left by N. The positional ! parameters from N+1 ... are renamed to `$1' ... . Parameters ! represented by the numbers `$#' to N+1 are unset. N must be a ! non-negative number less than or equal to `$#'. `test' `[' ! Evaluate a conditional expression (*note Bash Conditional ! Expressions::.). `times' times Print out the user and system times used by the shell and its ! children. `trap' --- 2113,2218 ---- supplied, the path printed will not contain symbolic links. If the `-L' option is supplied, the path 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. `readonly' readonly [-apf] [NAME] ... ! Mark each NAME as readonly. The values of these names may not be ! changed by subsequent assignment. If the `-f' option is supplied, ! each NAME refers to a shell function. The `-a' option means each ! NAME refers to an array variable. If no NAME arguments are given, ! or if the `-p' option is supplied, a list of all readonly names is ! printed. The `-p' option causes output to be displayed in a ! format that may be reused as input. The return status is zero ! unless an invalid option is supplied, one of the NAME arguments is ! not a valid shell variable or function name, or the `-f' option is ! supplied with a name that is not a shell function. `return' return [N] ! Cause a shell function to exit with the return value N. This may ! also be used to terminate execution of a script being executed ! with the `.' builtin, returning either N or the exit status of the ! last command executed within the script as the exit status of the ! script. The return status is false if `return' is used outside a ! function and not during the execution of a script by `.'. `shift' shift [N] ! Shift the positional parameters to the left by N. The positional ! parameters from N+1 ... `$#' are renamed to `$1' ... `$#'-N+1. ! Parameters represented by the numbers `$#' to N+1 are unset. N ! must be a non-negative number less than or equal to `$#'. If N is ! zero or greater than `$#', the positional parameters are not ! changed. The return status is zero unless N is greater than `$#' ! or less than zero, non-zero otherwise. `test' `[' ! Evaluate a conditional expression EXPR. Each operator and operand ! must be a separate argument. Expressions are composed of the ! primaries described below in *Note Bash Conditional Expressions::. ! ! Expressions may be combined using the following operators, listed ! in decreasing order of precedence. ! ! `! EXPR' ! True if EXPR is false. ! ! `( EXPR )' ! Returns the value of EXPR. This may be used to override the ! normal precedence of operators. ! ! `EXPR1 -a EXPR2' ! True if both EXPR1 and EXPR2 are true. ! ! `EXPR1 -o EXPR2' ! True if either EXPR1 or EXPR2 is true. ! ! The `test' and `[' builtins evaluate conditional expressions using ! a set of rules based on the number of arguments. ! ! 0 arguments ! The expression is false. ! ! 1 argument ! The expression is true if and only if the argument is not ! null. ! ! 2 arguments ! If the first argument is `!', the expression is true if and ! only if the second argument is null. If the first argument ! is one of the unary conditional operators (*note 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. ! ! 3 arguments ! If the second argument is one of the binary conditional ! operators (*note Bash Conditional Expressions::.), the result ! of the expression is the result of the binary test using the ! first and third arguments as operands. If the first argument ! is `!', the value is the negation of the two-argument test ! using the second and third arguments. If the first argument ! is exactly `(' and the third argument is exactly `)', the ! result is the one-argument test of the second argument. ! Otherwise, the expression is false. The `-a' and `-o' ! operators are considered binary operators in this case. ! ! 4 arguments ! If the first argument is `!', 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. ! ! 5 or more arguments ! The expression is parsed and evaluated according to precedence ! using the rules listed above. `times' times Print out the user and system times used by the shell and its ! children. The return status is zero. `trap' *************** *** 1670,1679 **** with each SIGSPEC. If no arguments are supplied, or only `-p' is given, `trap' prints the list of commands associated with each ! signal number. Each SIGSPEC is either a signal name such as ! `SIGINT' (with or without the `SIG' prefix) or a signal number. ! If a SIGSPEC is `0' or `EXIT', ARG is executed when the shell ! exits. If a SIGSPEC is `DEBUG', the command ARG is executed after ! every simple command. The `-l' option causes the shell to print a ! list of signal names and their corresponding numbers. Signals ignored upon entry to the shell cannot be trapped or reset. --- 2226,2236 ---- with each SIGSPEC. If no arguments are supplied, or only `-p' is given, `trap' prints the list of commands associated with each ! signal number in a form that may be reused as shell input. Each ! SIGSPEC is either a signal name such as `SIGINT' (with or without ! the `SIG' prefix) or a signal number. If a SIGSPEC is `0' or ! `EXIT', ARG is executed when the shell exits. If a SIGSPEC is ! `DEBUG', the command ARG is executed after every simple command. ! The `-l' option causes the shell to print a list of signal names ! and their corresponding numbers. Signals ignored upon entry to the shell cannot be trapped or reset. *************** *** 1681,1686 **** process when it is created. `umask' ! umask [-S] [MODE] Set the shell process's file creation mask to MODE. If MODE begins with a digit, it is interpreted as an octal number; if not, --- 2238,2246 ---- process when it is created. + The return status is zero unless a SIGSPEC does not specify a + valid signal. + `umask' ! umask [-p] [-S] [MODE] Set the shell process's file creation mask to MODE. If MODE begins with a digit, it is interpreted as an octal number; if not, *************** *** 1688,1692 **** by the `chmod' command. If MODE is omitted, the current value of the mask is printed. If the `-S' option is supplied without a ! MODE argument, the mask is printed in a symbolic format. `unset' --- 2248,2256 ---- by the `chmod' command. If MODE is omitted, the current value of the mask is printed. If the `-S' option is supplied without a ! MODE argument, the mask is printed in a symbolic format. If the ! `-p' option is supplied, and 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 MODE argument is ! supplied, and non-zero otherwise. `unset' *************** *** 1695,1700 **** supplied, or the `-v' option is given, each NAME refers to a shell variable. If the `-f' option is given, the NAMEs refer to shell ! functions, and the function definition is removed. Read-only ! variables and functions may not be unset.  --- 2259,2265 ---- supplied, or the `-v' option is given, each NAME refers to a shell variable. If the `-f' option is given, the NAMEs refer to shell ! functions, and the function definition is removed. Readonly ! variables and functions may not be unset. The return status is ! zero unless a NAME does not exist or is readonly.  *************** *** 1707,1732 **** shell. In some cases, Bash assigns a default value to the variable. ! `IFS' ! A list of characters that separate fields; used when the shell ! splits words as part of expansion. ! ! `PATH' ! A colon-separated list of directories in which the shell looks for ! commands. `HOME' The current user's home directory; the default for the `cd' builtin ! command. ! ! `CDPATH' ! A colon-separated list of directories used as a search path for ! the `cd' command. ! `MAILPATH' ! A colon-separated list of files which the shell periodically checks ! for new mail. You can also specify what message is printed by ! separating the file name from the message with a `?'. When used ! in the text of the message, `$_' stands for the name of the ! current mailfile. `MAIL' --- 2272,2287 ---- shell. In some cases, Bash assigns a default value to the variable. ! `CDPATH' ! A colon-separated list of directories used as a search path for ! the `cd' builtin command. `HOME' The current user's home directory; the default for the `cd' builtin ! command. The value of this variable is also used by tilde ! expansion (*note Tilde Expansion::.). ! `IFS' ! A list of characters that separate fields; used when the shell ! splits words as part of expansion. `MAIL' *************** *** 1735,1738 **** --- 2290,2312 ---- specified file. + `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 file name from the message with a `?'. When used in the text + of the message, `$_' expands to the name of the current mail file. + + `OPTARG' + The value of the last option argument processed by the `getopts' + builtin. + + `OPTIND' + The index of the last option argument processed by the `getopts' + builtin. + + `PATH' + A colon-separated list of directories in which the shell looks for + commands. + `PS1' The primary prompt string. The default value is `\s-\v\$ '. *************** *** 1741,1751 **** The secondary prompt string. The default value is `> '. - `OPTIND' - The index of the last option processed by the `getopts' builtin. - - `OPTARG' - The value of the last option argument processed by the `getopts' - builtin. -  File: bashref.info, Node: Other Bourne Shell Features, Prev: Bourne Shell Variables, Up: Bourne Shell Features --- 2315,2318 ---- *************** *** 1763,1769 **** POSIX 1003.2 standard as the specification of how these features are to be implemented. There are some differences between the traditional ! Bourne shell and the POSIX standard; this section quickly details the ! differences of significance. A number of these differences are ! explained in greater depth in subsequent sections.  --- 2330,2336 ---- POSIX 1003.2 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 subsequent sections.  *************** *** 1773,1972 **** ---------------------------------------------- ! Bash is POSIX-conformant, even where the POSIX specification differs ! from traditional `sh' behavior. ! Bash has multi-character invocation options (*note Invoking Bash::.). ! Bash has command-line editing (*note Command Line Editing::.) and ! the `bind' builtin. ! Bash has command history (*note Bash History Facilities::.) and the ! `history' and `fc' builtins to manipulate it. ! Bash implements `csh'-like history expansion (*note History ! Interaction::.). ! Bash has one-dimensional array variables (*note Arrays::.), and the ! appropriate variable expansions and assignment syntax to use them. ! Some of the Bash builtins take options to act on arrays. Bash provides ! some built-in array variables. ! Bash implements the `!' keyword to negate the return value of a ! pipeline (*note Pipelines::.). Very useful when an `if' statement ! needs to act only if a test fails. ! Bash includes the `select' compound command, which allows the ! generation of simple menus (*note Korn Shell Constructs::.). ! Bash includes brace expansion (*note Brace Expansion::.) and tilde ! expansion (*note Tilde Expansion::.). ! Bash implements command aliases and the `alias' and `unalias' ! builtins (*note Aliases::.). ! Bash provides shell arithmetic and arithmetic expansion (*note Shell ! Arithmetic::.). ! The POSIX and `ksh'-style `$()' form of command substitution is ! implemented (*note Command Substitution::.), and preferred to the ! Bourne shell's ```' (which is also implemented for backwards ! compatibility). ! 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 ! `export' command. ! Bash includes the POSIX and `ksh'-style pattern removal `%', `#', ! `%%' and `##' constructs to remove leading or trailing substrings from ! variable values (*note Shell Parameter Expansion::.). ! The expansion `${#xx}', which returns the length of `$xx', is ! supported (*note Shell Parameter Expansion::.). ! The `$'...'' quoting syntax, which expands ANSI-C backslash-escaped ! characters in the text between the single quotes, is supported (*note ! ANSI-C Quoting::.). ! Bash supports the `$"..."' quoting syntax to do locale-specific ! translation of the characters between the double quotes. The `-D' and ! `--dump-strings' invocation options list the translatable strings found ! in a script (*note Locale Translation::.). ! The expansion `${var:'OFFSET`[:'LENGTH`]}', which expands to the ! substring of `var''s value of length LENGTH, optionally beginning at ! OFFSET, is present (*note Shell Parameter Expansion::.). ! The expansion `${var/[/]'PATTERN`[/'REPLACEMENT`]}', which matches ! PATTERN and replaces it with REPLACEMENT in the value of `var', is ! available (*note Shell Parameter Expansion::.). ! Bash has INDIRECT variable expansion using `${!word}' (*note Shell ! Parameter Expansion::.). ! Bash can expand positional parameters beyond `$9' using `${NUM}'. ! Bash has process substitution (*note Process Substitution::.). ! Bash automatically assigns variables that provide information about ! the current user (`UID', `EUID', and `GROUPS'), the current host ! (`HOSTTYPE', `OSTYPE', `MACHTYPE', and `HOSTNAME'), and the instance of ! Bash that is running (`BASH', `BASH_VERSION', and `BASH_VERSINFO'. ! *Note Bash Variables::, for details. ! The `IFS' variable is used to split only the results of expansion, ! not all words (*note Word Splitting::.). This closes a longstanding ! shell security hole. ! It is possible to have a variable and a function with the same name; ! `sh' does not separate the two name spaces. ! Bash functions are permitted to have local variables using the ! `local' builtin, and thus useful recursive functions may be written. ! Variable assignments preceding commands affect only that command, ! even builtins and functions (*note Environment::.). In `sh', all ! variable assignments preceding commands are global unless the command ! is executed from the file system. ! Bash performs filename expansion on filenames specified as operands ! to output redirection operators. ! Bash contains the `<>' redirection operator, allowing a file to be ! opened for both reading and writing, and the `&>' redirection operator, ! for directing standard output and standard error to the same file ! (*note Redirections::.). ! The `noclobber' option is available to avoid overwriting existing ! files with output redirection (*note The Set Builtin::.). The `>|' ! redirection operator may be used to override `noclobber'. ! Bash interprets special backslash-escaped characters in the prompt ! strings when interactive (*note Printing a Prompt::.). ! Bash allows you to write a function to override a builtin, and ! provides access to that builtin's functionality within the function via ! the `builtin' and `command' builtins (*note Bash Builtins::.). ! The `command' builtin allows selective disabling of functions when ! command lookup is performed (*note Bash Builtins::.). ! Individual builtins may be enabled or disabled using the `enable' ! builtin (*note Bash Builtins::.). ! The Bash `hash' builtin allows a name to be associated with an ! arbitrary filename, even when that filename cannot be found by ! searching the `$PATH', using `hash -p'. ! Shell functions may be exported to children via the environment ! (*note Shell Functions::.). ! Bash includes a `help' builtin for quick reference to shell ! facilities (*note Bash Builtins::.). ! The Bash `read' builtin (*note Bash Builtins::.) will read a line ! ending in `\' with the `-r' option, and will use the `REPLY' variable ! as a default if no arguments are supplied. The Bash `read' builtin ! also accepts a prompt string with the `-p' option and will use Readline ! to obtain the line when given the `-e' option. ! ! Bash includes the `shopt' builtin, for finer control of shell ! optional capabilities (*note Bash Builtins::.). ! Bash has much more optional behavior controllable with the `set' ! builtin (*note The Set Builtin::.). ! The `disown' builtin can remove a job from the internal shell job ! table (*note Job Control Builtins::.). ! The `return' builtin may be used to abort execution of scripts ! executed with the `.' or `source' builtins (*note Bourne Shell ! Builtins::.). ! The `test' builtin (*note Bourne Shell Builtins::.) is slightly ! different, as it implements the POSIX 1003.2 algorithm, which specifies ! the behavior based on the number of arguments. ! The `trap' builtin (*note Bourne Shell Builtins::.) allows a `DEBUG' ! pseudo-signal specification, similar to `EXIT'. Commands specified ! with a `DEBUG' trap are executed after every simple command. The ! `DEBUG' trap is not inherited by shell functions. ! The Bash `export', `readonly', and `declare' builtins can take a ! `-f' option to act on shell functions, a `-p' option to display ! variables with various attributes set in a format that can be used as ! shell input, a `-n' option to remove various variable attributes, and ! `name=value' arguments to set variable attributes and values ! simultaneously. ! The Bash `cd' and `pwd' builtins (*note Bourne Shell Builtins::.) ! each take `-L' and `-P' builtins to switch between logical and physical ! modes. ! The Bash `type' builtin is more extensive and gives more information ! about the names it finds (*note Bash Builtins::.). ! Bash implements a `csh'-like directory stack, and provides the ! `pushd', `popd', and `dirs' builtins to manipulate it (*note C Shell ! Builtins::.). Bash also makes the directory stack visible as the value ! of the `DIRSTACK' shell variable. ! The Bash restricted mode is more useful (*note The Restricted ! Shell::.); the SVR4.2 shell restricted mode is too limited. ! Bash has the `time' reserved word and command timing (*note ! Pipelines::.). The display of the timing statistics may be controlled ! with the `TIMEFORMAT' variable. ! The SVR4.2 shell has two privilege-related builtins (`mldmode' and ! `priv') not present in Bash. ! Bash does not have the `stop' or `newgrp' builtins. ! Bash does not use the `SHACCT' variable or perform shell accounting. ! The SVR4.2 `sh' uses a `TIMEOUT' variable like Bash uses `TMOUT'. ! More features unique to Bash may be found in *Note Bash Features::. Implementation Differences From The SVR4.2 Shell --- 2340,2570 ---- ---------------------------------------------- ! * Bash is POSIX-conformant, even where the POSIX specification ! differs from traditional `sh' behavior. ! * Bash has multi-character invocation options (*note Invoking ! Bash::.). ! * Bash has command-line editing (*note Command Line Editing::.) and ! the `bind' builtin. ! * Bash has command history (*note Bash History Facilities::.) and the ! `history' and `fc' builtins to manipulate it. ! * Bash implements `csh'-like history expansion (*note History ! Interaction::.). ! * Bash has one-dimensional array variables (*note 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. ! * The `$'...'' quoting syntax, which expands ANSI-C ! backslash-escaped characters in the text between the single quotes, ! is supported (*note ANSI-C Quoting::.). ! * Bash supports the `$"..."' quoting syntax to do locale-specific ! translation of the characters between the double quotes. The ! `-D', `--dump-strings', and `--dump-po-strings' invocation options ! list the translatable strings found in a script (*note Locale ! Translation::.). ! * Bash implements the `!' keyword to negate the return value of a ! pipeline (*note Pipelines::.). Very useful when an `if' statement ! needs to act only if a test fails. ! * Bash has the `time' reserved word and command timing (*note ! Pipelines::.). The display of the timing statistics may be ! controlled with the `TIMEFORMAT' variable. ! * Bash includes the `select' compound command, which allows the ! generation of simple menus (*note Conditional Constructs::.). ! * Bash includes the `[[' compound command, which makes conditional ! testing part of the shell grammar (*note Conditional ! Constructs::.). ! * Bash includes brace expansion (*note Brace Expansion::.) and tilde ! expansion (*note Tilde Expansion::.). ! * Bash implements command aliases and the `alias' and `unalias' ! builtins (*note Aliases::.). ! * Bash provides shell arithmetic, the `((' compound command (*note ! Conditional Constructs::.), and arithmetic expansion (*note Shell ! Arithmetic::.). ! * 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 `export' command. ! * Bash includes the POSIX pattern removal `%', `#', `%%' and `##' ! expansions to remove leading or trailing substrings from variable ! values (*note Shell Parameter Expansion::.). ! * The expansion `${#xx}', which returns the length of `${xx}', is ! supported (*note Shell Parameter Expansion::.). ! * The expansion `${var:'OFFSET`[:'LENGTH`]}', which expands to the ! substring of `var''s value of length LENGTH, beginning at OFFSET, ! is present (*note Shell Parameter Expansion::.). ! * The expansion `${var/[/]'PATTERN`[/'REPLACEMENT`]}', which matches ! PATTERN and replaces it with REPLACEMENT in the value of `var', is ! available (*note Shell Parameter Expansion::.). ! * Bash has INDIRECT variable expansion using `${!word}' (*note Shell ! Parameter Expansion::.). ! * Bash can expand positional parameters beyond `$9' using `${NUM}'. ! * The POSIX `$()' form of command substitution is implemented (*note ! Command Substitution::.), and preferred to the Bourne shell's ```' ! (which is also implemented for backwards compatibility). ! * Bash has process substitution (*note Process Substitution::.). ! * Bash automatically assigns variables that provide information ! about the current user (`UID', `EUID', and `GROUPS'), the current ! host (`HOSTTYPE', `OSTYPE', `MACHTYPE', and `HOSTNAME'), and the ! instance of Bash that is running (`BASH', `BASH_VERSION', and ! `BASH_VERSINFO'). *Note Bash Variables::, for details. ! * The `IFS' variable is used to split only the results of expansion, ! not all words (*note Word Splitting::.). This closes a ! longstanding shell security hole. ! * Bash implements the full set of POSIX.2 filename expansion ! operators, including CHARACTER CLASSES, EQUIVALENCE CLASSES, and ! COLLATING SYMBOLS (*note Filename Expansion::.). ! * Bash implements extended pattern matching features when the ! `extglob' shell option is enabled (*note Pattern Matching::.). ! * It is possible to have a variable and a function with the same ! name; `sh' does not separate the two name spaces. ! * Bash functions are permitted to have local variables using the ! `local' builtin, and thus useful recursive functions may be ! written. ! * Variable assignments preceding commands affect only that command, ! even builtins and functions (*note Environment::.). In `sh', all ! variable assignments preceding commands are global unless the ! command is executed from the file system. ! * Bash performs filename expansion on filenames specified as operands ! to input and output redirection operators. ! * Bash contains the `<>' redirection operator, allowing a file to be ! opened for both reading and writing, and the `&>' redirection ! operator, for directing standard output and standard error to the ! same file (*note Redirections::.). ! * The `noclobber' option is available to avoid overwriting existing ! files with output redirection (*note The Set Builtin::.). The ! `>|' redirection operator may be used to override `noclobber'. ! * The Bash `cd' and `pwd' builtins (*note Bourne Shell Builtins::.) ! each take `-L' and `-P' builtins to switch between logical and ! physical modes. ! * 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 `builtin' and `command' builtins (*note Bash ! Builtins::.). ! * The `command' builtin allows selective disabling of functions when ! command lookup is performed (*note Bash Builtins::.). ! * Individual builtins may be enabled or disabled using the `enable' ! builtin (*note Bash Builtins::.). ! * The Bash `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 ! (*note Bourne Shell Builtins::.). ! * Shell functions may be exported to children via the environment ! using `export -f' (*note Shell Functions::.). ! * The Bash `export', `readonly', and `declare' builtins can take a ! `-f' option to act on shell functions, a `-p' option to display ! variables with various attributes set in a format that can be used ! as shell input, a `-n' option to remove various variable ! attributes, and `name=value' arguments to set variable attributes ! and values simultaneously. ! ! * The Bash `hash' builtin allows a name to be associated with an ! arbitrary filename, even when that filename cannot be found by ! searching the `$PATH', using `hash -p' (*note Bourne Shell ! Builtins::.). ! ! * Bash includes a `help' builtin for quick reference to shell ! facilities (*note Bash Builtins::.). ! ! * The `printf' builtin is available to display formatted output ! (*note Bash Builtins::.). ! ! * The Bash `read' builtin (*note Bash Builtins::.) will read a line ! ending in `\' with the `-r' option, and will use the `REPLY' ! variable as a default if no arguments are supplied. The Bash ! `read' builtin also accepts a prompt string with the `-p' option ! and will use Readline to obtain the line when given the `-e' ! option. ! * The `return' builtin may be used to abort execution of scripts ! executed with the `.' or `source' builtins (*note Bourne Shell ! Builtins::.). ! * Bash includes the `shopt' builtin, for finer control of shell ! optional capabilities (*note Bash Builtins::.). ! * Bash has much more optional behavior controllable with the `set' ! builtin (*note The Set Builtin::.). ! * The `test' builtin (*note Bourne Shell Builtins::.) is slightly ! different, as it implements the POSIX algorithm, which specifies ! the behavior based on the number of arguments. ! * The `trap' builtin (*note Bourne Shell Builtins::.) allows a ! `DEBUG' pseudo-signal specification, similar to `EXIT'. Commands ! specified with a `DEBUG' trap are executed after every simple ! command. The `DEBUG' trap is not inherited by shell functions. ! * The Bash `type' builtin is more extensive and gives more ! information about the names it finds (*note Bash Builtins::.). ! * The Bash `umask' builtin permits a `-p' option to cause the output ! to be displayed in the form of a `umask' command that may be ! reused as input (*note Bourne Shell Builtins::.). ! * Bash implements a `csh'-like directory stack, and provides the ! `pushd', `popd', and `dirs' builtins to manipulate it (*note The ! Directory Stack::.). Bash also makes the directory stack visible ! as the value of the `DIRSTACK' shell variable. ! * Bash interprets special backslash-escaped characters in the prompt ! strings when interactive (*note Printing a Prompt::.). ! * The Bash restricted mode is more useful (*note The Restricted ! Shell::.); the SVR4.2 shell restricted mode is too limited. ! * The `disown' builtin can remove a job from the internal shell job ! table (*note Job Control Builtins::.) or suppress the sending of ! `SIGHUP' to a job when the shell exits as the result of a `SIGHUP'. ! * The SVR4.2 shell has two privilege-related builtins (`mldmode' and ! `priv') not present in Bash. ! * Bash does not have the `stop' or `newgrp' builtins. ! ! * Bash does not use the `SHACCT' variable or perform shell ! accounting. ! ! * The SVR4.2 `sh' uses a `TIMEOUT' variable like Bash uses `TMOUT'. ! ! More features unique to Bash may be found in *Note Bash Features::. Implementation Differences From The SVR4.2 Shell *************** *** 1986,1990 **** trapping `SIGSEGV'. If the shell is started from a process with `SIGSEGV' blocked (e.g., by using the `system()' C library ! function call), the shell misbehaves badly. * In a questionable attempt at security, the SVR4.2 shell, when --- 2584,2588 ---- trapping `SIGSEGV'. If the shell is started from a process with `SIGSEGV' blocked (e.g., by using the `system()' C library ! function call), it misbehaves badly. * In a questionable attempt at security, the SVR4.2 shell, when *************** *** 1993,2001 **** commonly 100. This can lead to unexpected results. ! * The SVR4.2 shell does not allow users to trap `SIGALRM' or ! `SIGCHLD'. ! * For some reason, the SVR4.2 shell does not allow the `MAILCHECK' ! variable to be unset. * The SVR4.2 shell treats `^' as the undocumented equivalent of `|'. --- 2591,2599 ---- commonly 100. This can lead to unexpected results. ! * The SVR4.2 shell does not allow users to trap `SIGSEGV', ! `SIGALRM', or `SIGCHLD'. ! * The SVR4.2 shell does not allow the `IFS', `MAILCHECK', `PATH', ! `PS1', or `PS2' variables to be unset. * The SVR4.2 shell treats `^' as the undocumented equivalent of `|'. *************** *** 2014,2486 ****  ! File: bashref.info, Node: Csh Features, Next: Korn Shell Features, Prev: Bourne Shell Features, Up: Top ! ! C-Shell Style Features ! ********************** ! The C-Shell ("`csh'") was created by Bill Joy at The University of ! California at Berkeley. It is generally considered to have better ! features for interactive use than the original Bourne shell. Some of ! the `csh' features present in Bash include job control, history ! expansion, `protected' redirection, and several variables to control ! the interactive behaviour of the shell (e.g., `IGNOREEOF'). ! *Note Using History Interactively::, for details on history ! expansion. ! ! * Menu: ! ! * Brace Expansion:: Expansion of expressions within braces. ! * Tilde Expansion:: Expansion of the ~ character. ! * C Shell Builtins:: Builtin commands adopted from the C Shell. ! * C Shell Variables:: Variables which Bash uses in essentially ! the same way as the C Shell. ! !  ! File: bashref.info, Node: Brace Expansion, Next: Tilde Expansion, Up: Csh Features ! ! Brace Expansion ! =============== ! ! Brace expansion is a mechanism by which arbitrary strings may be ! generated. This mechanism is similar to FILENAME EXPANSION (*note ! Filename Expansion::.), but the file names generated need not exist. ! Patterns to be brace expanded take the form of an optional PREAMBLE, ! followed by a series of comma-separated strings between a pair of ! braces, followed by an optional POSTAMBLE. The preamble is prepended ! to each string contained within the braces, and the postamble 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, ! bash$ echo a{d,c,b}e ! ade ace abe ! ! 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. ! ! A correctly-formed brace expansion must contain unquoted opening and ! closing braces, and at least one unquoted comma. Any incorrectly ! formed brace expansion is left unchanged. ! ! This construct is typically used as shorthand when the common prefix ! of the strings to be generated is longer than in the above example: ! mkdir /usr/local/src/bash/{old,new,dist,bugs} ! or ! chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}} ! !  ! File: bashref.info, Node: Tilde Expansion, Next: C Shell Builtins, Prev: Brace Expansion, Up: Csh Features ! ! Tilde Expansion ! =============== ! ! Bash has tilde (~) expansion, similar, but not identical, to that of ! `csh'. The following table shows what unquoted words beginning with a ! tilde expand to. ! ! `~' ! The current value of `$HOME'. ! ! `~/foo' ! `$HOME/foo' ! ! `~fred/foo' ! The subdirectory `foo' of the home directory of the user `fred'. ! ! `~+/foo' ! `$PWD/foo' ! ! `~-/foo' ! `$OLDPWD/foo' ! ! Bash will also tilde expand words following redirection operators ! and words following `=' in assignment statements. ! !  ! File: bashref.info, Node: C Shell Builtins, Next: C Shell Variables, Prev: Tilde Expansion, Up: Csh Features ! ! C Shell Builtins ! ================ ! ! Bash has several builtin commands whose definition is very similar ! to `csh'. ! ! `pushd' ! pushd [DIR | +N | -N] [-n] ! ! Save the current directory on a list and then `cd' to DIR. With no ! arguments, exchanges the top two directories. ! ! `+N' ! Brings the Nth directory (counting from the left of the list ! printed by `dirs', starting with zero) to the top of the list ! by rotating the stack. ! ! `-N' ! Brings the Nth directory (counting from the right of the list ! printed by `dirs', starting with zero) to the top of the list ! by rotating the stack. ! ! `-n' ! Suppresses the normal change of directory when adding ! directories to the stack, so that only the stack is ! manipulated. ! ! `DIR' ! Makes the current working directory be the top of the stack, ! and then `cd's to DIR. You can see the saved directory list ! with the `dirs' command. ! ! `popd' ! popd [+N | -N] [-n] ! ! Pop the directory stack, and `cd' to the new top directory. When ! no arguments are given, `popd' removes the top directory from the ! stack and performs a `cd' to the new top directory. The elements ! are numbered from 0 starting at the first directory listed with ! `dirs'; i.e., `popd' is equivalent to `popd +0'. ! `+N' ! Removes the Nth directory (counting from the left of the list ! printed by `dirs'), starting with zero. ! ! `-N' ! Removes the Nth directory (counting from the right of the ! list printed by `dirs'), starting with zero. ! ! `-n' ! Suppresses the normal change of directory when removing ! directories from the stack, so that only the stack is ! manipulated. ! ! `dirs' ! dirs [+N | -N] [-clvp] ! Display the list of currently remembered directories. Directories ! find their way onto the list with the `pushd' command; you can get ! back up through the list with the `popd' command. ! `+N' ! Displays the Nth directory (counting from the left of the ! list printed by `dirs' when invoked without options), starting ! with zero. ! ! `-N' ! Displays the Nth directory (counting from the right of the ! list printed by `dirs' when invoked without options), starting ! with zero. ! ! `-c' ! Clears the directory stack by deleting all of the elements. ! ! `-l' ! Produces a longer listing; the default listing format uses a ! tilde to denote the home directory. ! ! `-p' ! Causes `dirs' to print the directory stack with one entry per ! line. ! ! `-v' ! Causes `dirs' to print the directory stack with one entry per ! line, prepending each entry with its index in the stack. ! ! `history' ! history [-c] [N] ! history [-anrw] [FILENAME] ! history -ps ARG ! ! Display the history list with line numbers. Lines prefixed with ! with a `*' have been modified. An argument of N says to list only ! the last N lines. Options, if supplied, have the following ! meanings: ! ! `-w' ! Write out the current history to the history file. ! ! `-r' ! Read the current history file and append its contents to the ! history list. ! ! `-a' ! Append the new history lines (history lines entered since the ! beginning of the current Bash session) to the history file. ! ! `-n' ! Append the history lines not already read from the history ! file to the current history list. These are lines appended ! to the history file since the beginning of the current Bash ! session. ! ! `-c' ! Clear the history list. This may be combined with the other ! options to replace the history list completely. ! ! `-s' ! The ARGs are added to the end of the history list as a single ! entry. ! ! `-p' ! Perform history substitution on the ARGs and display the ! result on the standard output, without storing the results in ! the history list. ! ! When the `-w', `-r', `-a', or `-n' option is used, if FILENAME is ! given, then it is used as the history file. If not, then the ! value of the `HISTFILE' variable is used. ! ! `logout' ! Exit a login shell. ! ! `source' ! A synonym for `.' (*note Bourne Shell Builtins::.). ! !  ! File: bashref.info, Node: C Shell Variables, Prev: C Shell Builtins, Up: Csh Features ! ! C Shell Variables ! ================= ! ! `IGNOREEOF' ! If this variable is set, its value is used the number of ! consecutive `EOF's Bash will read before exiting. By default, ! Bash will exit upon reading a single `EOF'. If `IGNOREEOF' is not ! set to a numeric value, Bash acts as if its value were 10. ! !  ! File: bashref.info, Node: Korn Shell Features, Next: Bash Features, Prev: Csh Features, Up: Top ! ! Korn Shell Style Features ! ************************* ! ! This section describes features primarily inspired by the Korn Shell ! (`ksh'). In some cases, the POSIX 1003.2 standard has adopted these ! commands and variables from the Korn Shell; Bash implements those ! features using the POSIX standard as a guide. ! ! * Menu: ! ! * Korn Shell Constructs:: Shell grammar constructs adopted from the ! Korn Shell ! * Korn Shell Builtins:: Builtin commands adopted from the Korn Shell. ! * Korn Shell Variables:: Variables which Bash uses in essentially ! the same way as the Korn Shell. ! * Aliases:: Substituting one command for another. ! !  ! File: bashref.info, Node: Korn Shell Constructs, Next: Korn Shell Builtins, Up: Korn Shell Features ! ! Korn Shell Constructs ! ===================== ! ! Bash includes the Korn Shell `select' construct. This construct ! allows the easy generation of menus. It has almost the same syntax as ! the `for' command. ! ! The syntax of the `select' command is: ! select NAME [in WORDS ...]; do COMMANDS; done ! ! The list of words following `in' 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 `in WORDS' is omitted, the ! positional parameters are printed. The `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 ! NAME is set to that word. If the line is empty, the words and prompt ! are displayed again. If `EOF' is read, the `select' command completes. ! Any other value read causes NAME to be set to null. The line read is ! saved in the variable `REPLY'. ! ! The COMMANDS are executed after each selection until a `break' or ! `return' command is executed, at which point the `select' command ! completes. ! ! Bash also has adopted command timing from the Korn shell. If the ! `time' reserved word precedes a pipeline, which may consist of a single ! command, timing statistics for the pipeline are displayed when it ! completes. The statistics currently consist of elapsed (wall-clock) ! time and user and system time consumed by the command's execution. ! ! The use of `time' as a reserved word permits the timing of shell ! builtins, shell functions, and pipelines. An external `time' command ! cannot time these easily. ! !  ! File: bashref.info, Node: Korn Shell Builtins, Next: Korn Shell Variables, Prev: Korn Shell Constructs, Up: Korn Shell Features ! ! Korn Shell Builtins ! =================== ! ! This section describes Bash builtin commands taken from `ksh'. ! ! `fc' ! `fc [-e ENAME] [-nlr] [FIRST] [LAST]' ! `fc -s [PAT=REP] [COMMAND]' ! ! Fix Command. In the first form, a range of commands from FIRST to ! LAST is selected from the history list. Both FIRST and LAST may ! be specified as a string (to locate the most recent 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 LAST is not specified it is set to ! FIRST. If FIRST is not specified it is set to the previous ! command for editing and -16 for listing. If the `-l' flag is ! given, the commands are listed on standard output. The `-n' flag ! suppresses the command numbers when listing. The `-r' flag ! reverses the order of the listing. Otherwise, the editor given by ! ENAME is invoked on a file containing those commands. If ENAME is ! not given, the value of the following variable expansion is used: ! `${FCEDIT:-${EDITOR:-vi}}'. This says to use the value of the ! `FCEDIT' variable if set, or the value of the `EDITOR' variable if ! that is set, or `vi' if neither is set. When editing is complete, ! the edited commands are echoed and executed. ! ! In the second form, COMMAND is re-executed after each instance of ! PAT in the selected command is replaced by REP. ! ! A useful alias to use with the `fc' command is `r='fc -s'', so ! that typing `r cc' runs the last command beginning with `cc' and ! typing `r' re-executes the last command (*note Aliases::.). ! ! `let' ! The `let' builtin allows arithmetic to be performed on shell ! variables. For details, refer to *Note Arithmetic Builtins::. ! ! `typeset' ! The `typeset' command is supplied for compatibility with the Korn ! shell; however, it has been deprecated in favor of the `declare' ! command (*note Bash Builtins::.). ! !  ! File: bashref.info, Node: Korn Shell Variables, Next: Aliases, Prev: Korn Shell Builtins, Up: Korn Shell Features ! ! Korn Shell Variables ! ==================== ! ! `REPLY' ! The default variable for the `read' builtin. ! ! `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. ! ! `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. ! ! `PS3' ! The value of this variable is used as the prompt for the `select' ! command. If this variable is not set, the `select' command ! prompts with `#? ' ! ! `PS4' ! This is the prompt printed before the command line is echoed when ! the `-x' option is set (*note The Set Builtin::.). The default is ! `+ '. ! ! `PWD' ! The current working directory as set by the `cd' builtin. ! ! `OLDPWD' ! The previous working directory as set by the `cd' builtin. ! ! `TMOUT' ! If set to a value greater than zero, the value is interpreted as ! the number of seconds to wait for input after issuing the primary ! prompt. Bash terminates after that number of seconds if input does ! not arrive. ! ! `LINENO' ! The line number in the script or shell function currently ! executing. ! ! `FCEDIT' ! The editor used as a default by the `fc' builtin command. ! !  ! File: bashref.info, Node: Aliases, Prev: Korn Shell Variables, Up: Korn Shell Features ! ! Aliases ! ======= ! ! * Menu: ! ! * Alias Builtins:: Builtins commands to maniuplate aliases. ! ! The shell maintains a list of ALIASES that may be set and unset with ! the `alias' and `unalias' builtin commands. ! ! The first word of each 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 alias name and the replacement text may contain any valid shell ! input, including shell metacharacters, with the exception that the ! alias name may not contain <=>. 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 ! `ls' to `"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 space or tab character, then the next command word following the ! alias is also checked for alias expansion. ! ! Aliases are created and listed with the `alias' command, and removed ! with the `unalias' command. ! ! There is no mechanism for using arguments in the replacement text, ! as in `csh'. If arguments are needed, a shell function should be used ! (*note Shell Functions::.). ! ! Aliases are not expanded when the shell is not interactive, unless ! the `expand_aliases' shell option is set using `shopt' (*note Bash ! Builtins::.). ! ! 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 the function definition is read, not when the ! function is executed, because a function definition is itself a ! compound 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 `alias' ! in compound commands. ! ! Note that for almost every purpose, aliases are superseded by shell ! functions. ! !  ! File: bashref.info, Node: Alias Builtins, Up: Aliases ! ! Alias Builtins ! -------------- ! ! `alias' ! alias [`-p'] [NAME[=VALUE] ...] ! ! Without arguments or with the `-p' option, `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 NAME whose VALUE is given. If no VALUE is given, the name ! and value of the alias is printed. ! ! `unalias' ! unalias [-a] [NAME ... ] ! ! Remove each NAME from the list of aliases. If `-a' is supplied, ! all aliases are removed. ! !  ! File: bashref.info, Node: Bash Features, Next: Job Control, Prev: Korn Shell Features, Up: Top ! ! Bash Features ! ************* ! ! This section describes features unique to Bash. * Menu: --- 2612,2621 ----  ! File: bashref.info, Node: Bash Features, Next: Job Control, Prev: Bourne Shell Features, Up: Top ! Bash Features ! ************* ! This section describes features unique to Bash. * Menu: *************** *** 2497,2501 **** * Bash Variables:: List of variables that exist in Bash. * Shell Arithmetic:: Arithmetic on shell variables. ! * Arrays:: Array Variables * Printing a Prompt:: Controlling the PS1 string. * The Restricted Shell:: A more controlled mode of shell execution. --- 2632,2638 ---- * Bash Variables:: List of variables that exist in Bash. * Shell Arithmetic:: Arithmetic on shell variables. ! * Aliases:: Substituting one command for another. ! * Arrays:: Array Variables. ! * The Directory Stack:: History of visited directories. * Printing a Prompt:: Controlling the PS1 string. * The Restricted Shell:: A more controlled mode of shell execution. *************** *** 2518,2521 **** --- 2655,2662 ---- the single-character options in order for them to be recognized. + `--dump-po-strings' + Equivalent to `-D', but the output is in the GNU `gettext' PO + (portable object) file format. + `--dump-strings' Equivalent to `-D'. *************** *** 2527,2532 **** Make this shell act as if it were directly invoked by login. This is equivalent to `exec -l bash' but can be issued from another ! shell, such as `csh'. If you wanted to replace your current login ! shell with a Bash login shell, you would say `exec bash --login'. `--noediting' --- 2668,2673 ---- Make this shell act as if it were directly invoked by login. This is equivalent to `exec -l bash' but can be issued from another ! shell, such as `csh'. `exec bash --login' will replace the ! current shell with a Bash login shell. `--noediting' *************** *** 2565,2570 **** output and exit successfully. ! There are several single-character options you can give which are ! not available with the `set' builtin. `-c STRING' --- 2706,2711 ---- output and exit successfully. ! There are several single-character options that may be supplied at ! invocation which are not available with the `set' builtin. `-c STRING' *************** *** 2577,2584 **** `-r' ! Make the shell restricted. `-s' ! If this flag 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 --- 2718,2725 ---- `-r' ! Make the shell a restricted shell (*note The Restricted Shell::.). `-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 *************** *** 2592,2597 **** commands will be executed. An *interactive* shell is one whose input and output are both ! connected to terminals (as determined by `isatty()'), or one started with the `-i' option. --- 2733,2743 ---- commands will be executed. + `--' + A `--' signals the end of options and disables further option + processing. Any arguments after the `--' are treated as filenames + and arguments. + An *interactive* shell is one whose input and output are both ! connected to terminals (as determined by `isatty(3)'), or one started with the `-i' option. *************** *** 2653,2660 **** conforming to the POSIX standard as well. ! When invoked as a login shell, it first attempts to read and execute ! commands from `/etc/profile' and `~/.profile', in that order. The ! `--noprofile' option may be used to inhibit this behavior. When ! invoked as an interactive shell with the name `sh', `bash' looks for the variable `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 --- 2799,2806 ---- conforming to the POSIX standard as well. ! When invoked as an interactive login shell, it first attempts to read ! and execute commands from `/etc/profile' and `~/.profile', in that ! order. The `--noprofile' option may be used to inhibit this behavior. ! When invoked as an interactive shell with the name `sh', Bash looks for the variable `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 *************** *** 2669,2675 **** When Bash is started in POSIX mode, as with the `--posix' command line option, it follows the POSIX standard for startup files. In this ! mode, the `ENV' variable is expanded and commands are read and executed ! from the file whose name is the expanded value. No other startup files ! are read. This is done by interactive shells only. Bash attempts to determine when it is being run by the remote shell --- 2815,2821 ---- When Bash is started in POSIX mode, as with the `--posix' command line option, it follows the POSIX standard for startup files. In this ! mode, interactive shells expand the `ENV' variable and commands are ! read and executed from the file whose name is the expanded value. No ! other startup files are read. Bash attempts to determine when it is being run by the remote shell *************** *** 2678,2682 **** is readable. It will not do this if invoked as `sh'. The `--norc' option may be used to inhibit this behavior, and the `--rcfile' option ! may be used to force another file to be read, but rshd does not generally invoke the shell with those options or allow them to be specified. --- 2824,2828 ---- is readable. It will not do this if invoked as `sh'. The `--norc' option may be used to inhibit this behavior, and the `--rcfile' option ! may be used to force another file to be read, but `rshd' does not generally invoke the shell with those options or allow them to be specified. *************** *** 2692,2699 **** by `isatty(3)'), or one started with the `-i' option. ! You may wish to determine within a startup script whether Bash is ! running interactively or not. To do this, examine the variable `$PS1'; ! it is unset in non-interactive shells, and set in interactive shells. ! Thus: if [ -z "$PS1" ]; then --- 2838,2844 ---- by `isatty(3)'), or one started with the `-i' option. ! To determine within a startup script whether Bash is running ! interactively or not, examine the variable `$PS1'; it is unset in ! non-interactive shells, and set in interactive shells. Thus: if [ -z "$PS1" ]; then *************** *** 2703,2708 **** fi ! Alternatively, you may test the value of the `-' special parameter. ! It contains `i' when the shell is interactive. For example: case "$-" in --- 2848,2853 ---- fi ! Alternatively, startup scripts may test the value of the `-' special ! parameter. It contains `i' when the shell is interactive. For example: case "$-" in *************** *** 2721,2725 **** `bind' ! bind [-m KEYMAP] [-lpsvPSV] [-q NAME] [-r KEYSEQ] bind [-m KEYMAP] -f FILENAME bind [-m KEYMAP] KEYSEQ:FUNCTION-NAME --- 2866,2871 ---- `bind' ! bind [-m KEYMAP] [-lpsvPSV] ! bind [-m KEYMAP] [-q FUNCTION] [-u FUNCTION] [-r KEYSEQ] bind [-m KEYMAP] -f FILENAME bind [-m KEYMAP] KEYSEQ:FUNCTION-NAME *************** *** 2741,2795 **** `-l' ! List the names of all Readline functions `-p' Display Readline function names and bindings in such a way ! that they can be re-read `-P' ! List current Readline function names and bindings `-v' Display Readline variable names and values in such a way that ! they can be re-read `-V' ! List current Readline variable names and values `-s' Display Readline key sequences bound to macros and the ! strings they output in such a way that they can be re-read `-S' Display Readline key sequences bound to macros and the ! strings they output `-f FILENAME' ! Read key bindings from FILENAME ! `-q' ! Query about which keys invoke the named FUNCTION `-r KEYSEQ' ! Remove any current binding for KEYSEQ `builtin' builtin [SHELL-BUILTIN [ARGS]] ! Run a shell builtin. This is useful when you wish to define a ! shell function with the same name as a shell builtin, but need the ! functionality of the builtin within the function itself. `command' ! command [-pVv] COMMAND [ARGS ...] ! Runs COMMAND with ARG ignoring shell functions. If you have a ! shell function called `ls', and you wish to call the command `ls', ! you can say `command ls'. The `-p' option means to use a default ! value for `$PATH' that is guaranteed to find all of the standard ! utilities. If either the `-V' or `-v' option is supplied, a description of COMMAND is printed. The `-v' option causes a single word indicating the command or file name used to invoke COMMAND to be ! printed; the `-V' option produces a more verbose description. `declare' --- 2887,2955 ---- `-l' ! List the names of all Readline functions. `-p' Display Readline function names and bindings in such a way ! that they can be re-read. `-P' ! List current Readline function names and bindings. `-v' Display Readline variable names and values in such a way that ! they can be re-read. `-V' ! List current Readline variable names and values. `-s' Display Readline key sequences bound to macros and the ! strings they output in such a way that they can be re-read. `-S' Display Readline key sequences bound to macros and the ! strings they output. `-f FILENAME' ! Read key bindings from FILENAME. ! `-q FUNCTION' ! Query about which keys invoke the named FUNCTION. ! ! `-u FUNCTION' ! Unbind all keys bound to the named FUNCTION. `-r KEYSEQ' ! Remove any current binding for KEYSEQ. ! ! The return status is zero unless an invalid option is supplied or ! an error occurs. `builtin' builtin [SHELL-BUILTIN [ARGS]] ! Run a shell builtin, passing it 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 ! SHELL-BUILTIN is not a shell builtin command. `command' ! command [-pVv] COMMAND [ARGUMENTS ...] ! Runs COMMAND with ARGUMENTS ignoring any shell function named ! COMMAND. Only shell builtin commands or commands found by ! searching the `PATH' are executed. If there is a shell function ! named `ls', running `command ls' within the function will execute ! the external command `ls' instead of calling the function ! recursively. The `-p' option means to use a default value for ! `$PATH' that is guaranteed to find all of the standard utilities. ! The return status in this case is 127 if COMMAND cannot be found ! or an error occurred, and the exit status of COMMAND otherwise. If either the `-V' or `-v' option is supplied, a description of COMMAND is printed. The `-v' option causes a single word indicating the command or file name used to invoke COMMAND to be ! displayed; the `-V' option produces a more verbose description. ! In this case, the return status is zero if COMMAND is found, and ! non-zero if not. `declare' *************** *** 2819,2823 **** `-r' Make NAMEs readonly. These names cannot then be assigned ! values by subsequent assignment statements. `-x' --- 2979,2983 ---- `-r' Make NAMEs readonly. These names cannot then be assigned ! values by subsequent assignment statements or unset. `-x' *************** *** 2829,2837 **** `local' command. `echo' ! echo [-neE] [arg ...] ! Output the `arg's, separated by spaces, terminated with a newline. ! The return status is always 0. If `-n' is specified, the ! trailing newline is suppressed. If the `-e' option is given, interpretation of the following backslash-escaped characters is enabled. The `-E' option disables the interpretation of these --- 2989,3007 ---- `local' command. + The return status is zero unless an invalid option is encountered, + an attempt is made to define a function using `-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 (*note Arrays::.), one of the + 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 `-f'. + `echo' ! echo [-neE] [ARG ...] ! Output the ARGs, separated by spaces, terminated with a newline. ! The return status is always 0. If `-n' is specified, the trailing ! newline is suppressed. If the `-e' option is given, interpretation of the following backslash-escaped characters is enabled. The `-E' option disables the interpretation of these *************** *** 2868,2878 **** backslash ! `\nnn' ! the character whose ASCII code is `nnn' (octal) `enable' enable [-n] [-p] [-f FILENAME] [-ads] [NAME ...] ! Enable and disable builtin shell commands. This allows you to use ! a disk command which has the same name as a shell builtin. If `-n' is used, the NAMEs become disabled. Otherwise NAMEs are enabled. For example, to use the `test' binary found via `$PATH' --- 3038,3055 ---- backslash ! `\NNN' ! the character whose `ASCII' code is the octal value NNN (one ! to three digits) ! ! `\xNNN' ! the character whose `ASCII' code is the hexadecimal value NNN ! (one to three digits) `enable' enable [-n] [-p] [-f FILENAME] [-ads] [NAME ...] ! 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 with specifying a full pathname, even though the ! shell normally searches for builtins before disk commands. If `-n' is used, the NAMEs become disabled. Otherwise NAMEs are enabled. For example, to use the `test' binary found via `$PATH' *************** *** 2887,2908 **** The `-f' option means to load the new builtin command NAME from shared object FILENAME, on systems that support dynamic loading. ! The `-d' option will delete a builtin loaded with `-f'. If there ! are no options, a list of the shell builtins is displayed. The ! `-s' option restricts `enable' to the POSIX.2 special builtins. If `-s' is used with `-f', the new builtin becomes a special builtin. `help' help [PATTERN] Display helpful information about builtin commands. If PATTERN is specified, `help' gives detailed help on all commands matching ! PATTERN, otherwise a list of the builtins is printed. `local' local NAME[=VALUE] ! For each argument, create a local variable called NAME, and give ! it VALUE. `local' can only be used within a function; it makes ! the variable NAME have a visible scope restricted to that function ! and its children. `logout' --- 3064,3098 ---- The `-f' option means to load the new builtin command NAME from shared object FILENAME, on systems that support dynamic loading. ! The `-d' option will delete a builtin loaded with `-f'. ! ! If there are no options, a list of the shell builtins is displayed. ! The `-s' option restricts `enable' to the POSIX special builtins. If `-s' is used with `-f', the new builtin becomes a special builtin. + The return status is zero unless a NAME is not a shell builtin or + there is an error loading a new builtin from a shared object. + `help' help [PATTERN] Display helpful information about builtin commands. If PATTERN is specified, `help' gives detailed help on all commands matching ! PATTERN, otherwise a list of the builtins is printed. The return ! status is zero unless no command matches PATTERN. ! ! `let' ! let EXPRESSION [EXPRESSION] ! The `let' builtin allows arithmetic to be performed on shell ! variables. Each EXPRESSION is evaluated according to the rules ! given below in *Note Shell Arithmetic::. If the last EXPRESSION ! evaluates to 0, `let' returns 1; otherwise 0 is returned. `local' local NAME[=VALUE] ! For each argument, a local variable named NAME is created, and ! assigned VALUE. `local' can only be used within a function; it ! makes the variable NAME have a visible scope restricted to that ! function and its children. The return status is zero unless ! `local' is used outside a function or an invalid NAME is supplied. `logout' *************** *** 2910,2923 **** Exit a login shell, returning a status of N to the shell's parent. `read' read [-a ANAME] [-p PROMPT] [-er] [NAME ...] One line is read from the standard input, and the first word is assigned to the first NAME, the second word to the second NAME, ! and so on, with leftover words assigned to the last NAME. Only ! the characters in the value of the `IFS' variable are recognized ! as word delimiters. If no names are supplied, the line read is ! assigned to the variable `REPLY'. The return code is zero, unless ! end-of-file is encountered. Options, if supplied, have the ! following meanings: `-r' --- 3100,3134 ---- Exit a login shell, returning a status of N to the shell's parent. + `printf' + `printf' FORMAT [ARGUMENTS] + Write the formatted ARGUMENTS to the standard output under the + control of the FORMAT. The 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 ARGUMENT. In addition to the standard `printf(1)' + formats, `%b' causes `printf' to expand backslash escape sequences + in the corresponding ARGUMENT, and `%q' causes `printf' to output + the corresponding ARGUMENT in a format that can be reused as shell + input. + + The FORMAT is reused as necessary to consume all of the ARGUMENTS. + If the FORMAT requires more ARGUMENTS than are supplied, the extra + format specifications behave as if a zero value or null string, as + appropriate, had been supplied. + `read' read [-a ANAME] [-p PROMPT] [-er] [NAME ...] One line is read from the standard input, and the first word is assigned to the first NAME, the second word to the second NAME, ! and so on, with leftover words and their intervening separators ! assigned to the last NAME. If there are fewer words read from the ! standard input than names, the remaining names are assigned empty ! values. The characters in the value of the `IFS' variable are ! used to split the line into words. If no names are supplied, the ! line read is assigned to the variable `REPLY'. The return code is ! zero, unless end-of-file is encountered. Options, if supplied, ! have the following meanings: `-r' *************** *** 2927,2937 **** `-p PROMPT' ! Display `prompt', without a trailing newline, before ! attempting to read any input. The prompt is displayed only ! if input is coming from a terminal. `-a ANAME' The words are assigned to sequential indices of the array ! variable ANAME, starting at 0. `-e' --- 3138,3150 ---- `-p PROMPT' ! Display PROMPT, without a trailing newline, before attempting ! to read any input. The prompt is displayed only if input is ! coming from a terminal. `-a ANAME' The words are assigned to sequential indices of the array ! variable ANAME, starting at 0. All elements are removed from ! ANAME before the assignment. Other NAME arguments are ! ignored. `-e' *************** *** 2944,2951 **** With no options, or with the `-p' option, a list of all settable options is displayed, with an indication of whether or not each is ! set. Other options have the following meanings: `-s' ! Enable (set) each OPTNAME `-u' --- 3157,3165 ---- With no options, or with the `-p' option, a list of all settable options is displayed, with an indication of whether or not each is ! set. The `-p' option causes output to be displayed in a form that ! may be reused as input. Other options have the following meanings: `-s' ! Enable (set) each OPTNAME. `-u' *************** *** 2962,2966 **** `-o' option to the `set' builtin (*note The Set Builtin::.). ! If either of `-s' or `-u' is used with no OPTNAME arguments, the display is limited to those options which are set or unset, respectively. --- 3176,3180 ---- `-o' option to the `set' builtin (*note The Set Builtin::.). ! If either `-s' or `-u' is used with no OPTNAME arguments, the display is limited to those options which are set or unset, respectively. *************** *** 2971,2975 **** The return status when listing options is zero if all OPTNAMES are enabled, non-zero otherwise. When setting or unsetting options, ! the return status is zero unless an OPTNAME is not a legal shell option. --- 3185,3189 ---- The return status when listing options is zero if all OPTNAMES are enabled, non-zero otherwise. When setting or unsetting options, ! the return status is zero unless an OPTNAME is not a valid shell option. *************** *** 3012,3015 **** --- 3226,3238 ---- fails. + `expand_aliases' + If set, aliases are expanded as described below< under Aliases + (*note Aliases::.). This option is enabled by default for + interactive shells. + + `extglob' + If set, the extended pattern matching features described above + (*note Pattern Matching::.) are enabled. + `histappend' If set, the history list is appended to the file named by the *************** *** 3029,3036 **** `hostcomplete' If set, and Readline is being used, Bash will attempt to ! perform hostname completion when a word beginning with `@' is being completed (*note Commands For Completion::.). This option is enabled by default. `interactive_comments' Allow a word beginning with `#' to cause that word and all --- 3252,3263 ---- `hostcomplete' If set, and Readline is being used, Bash will attempt to ! perform hostname completion when a word containing a `@' is being completed (*note Commands For Completion::.). This option is enabled by default. + `huponexit' + If set, Bash will send `SIGHUP' to all jobs when an + interactive login shell exits (*note Signals::.). + `interactive_comments' Allow a word beginning with `#' to cause that word and all *************** *** 3048,3051 **** --- 3275,3282 ---- `"The mail in MAILFILE has been read"' is displayed. + `nocaseglob' + If set, Bash matches filenames in a case-insensitive fashion + when performing filename expansion. + `nullglob' If set, Bash allows filename patterns which match no files to *************** *** 3065,3076 **** If set, the `source' builtin uses the value of `PATH' to find the directory containing the file supplied as an argument. ! This is enabled by default. `type' ! type [-all] [-type | -path] [NAME ...] For each NAME, indicate how it would be interpreted if used as a command name. ! If the `-type' flag is used, `type' returns a single word which is one of `alias', `function', `builtin', `file' or `keyword', if NAME is an alias, shell function, shell builtin, disk file, or --- 3296,3316 ---- If set, the `source' builtin uses the value of `PATH' to find the directory containing the file supplied as an argument. ! This option is enabled by default. ! ! The return status when listing options is zero if all OPTNAMES are ! enabled, non-zero otherwise. When setting or unsetting options, ! the return status is zero unless an OPTNAME is not a valid shell ! option. ! ! `source' ! source FILENAME ! A synonym for `.' (*note Bourne Shell Builtins::.). `type' ! type [-atp] [NAME ...] For each NAME, indicate how it would be interpreted if used as a command name. ! If the `-t' option is used, `type' prints a single word which is one of `alias', `function', `builtin', `file' or `keyword', if NAME is an alias, shell function, shell builtin, disk file, or *************** *** 3078,3091 **** nothing is printed, and `type' returns a failure status. ! If the `-path' flag is used, `type' either returns the name of the ! disk file that would be executed, or nothing if `-type' would not return `file'. ! If the `-all' flag is used, returns all of the places that contain ! an executable named FILE. This includes aliases and functions, if ! and only if the `-path' flag is not also used. ! `type' accepts `-a', `-t', and `-p' as equivalent to `-all', ! `-type', and `-path', respectively. `ulimit' --- 3318,3337 ---- nothing is printed, and `type' returns a failure status. ! If the `-p' option is used, `type' either returns the name of the ! disk file that would be executed, or nothing if `-t' would not return `file'. ! If the `-a' option is used, `type' returns all of the places that ! contain an executable named FILE. This includes aliases and ! functions, if and only if the `-p' option is not also used. ! ! The return status is zero if any of the NAMES are found, non-zero ! if none are found. ! `typeset' ! typeset [-afFrxi] [-p] [NAME[=VALUE]] ! The `typeset' command is supplied for compatibility with the Korn ! shell; however, it has been deprecated in favor of the `declare' ! builtin command. `ulimit' *************** *** 3095,3114 **** option is given, it is interpreted as follows: `-S' ! change and report the soft limit associated with a resource. `-H' ! change and report the hard limit associated with a resource. `-a' ! all current limits are reported. `-c' ! the maximum size of core files created. `-d' ! the maximum size of a process's data segment. `-f' ! the maximum size of files created by the shell. `-l' --- 3341,3360 ---- option is given, it is interpreted as follows: `-S' ! Change and report the soft limit associated with a resource. `-H' ! Change and report the hard limit associated with a resource. `-a' ! All current limits are reported. `-c' ! The maximum size of core files created. `-d' ! The maximum size of a process's data segment. `-f' ! The maximum size of files created by the shell. `-l' *************** *** 3116,3138 **** `-m' ! the maximum resident set size. `-n' ! the maximum number of open file descriptors. `-p' ! the pipe buffer size. `-s' ! the maximum stack size. `-t' ! the maximum amount of cpu time in seconds. `-u' ! the maximum number of processes available to a single user. `-v' ! the maximum amount of virtual memory available to the process. If LIMIT is given, it is the new value of the specified resource. --- 3362,3384 ---- `-m' ! The maximum resident set size. `-n' ! The maximum number of open file descriptors. `-p' ! The pipe buffer size. `-s' ! The maximum stack size. `-t' ! The maximum amount of cpu time in seconds. `-u' ! The maximum number of processes available to a single user. `-v' ! The maximum amount of virtual memory available to the process. If LIMIT is given, it is the new value of the specified resource. *************** *** 3145,3148 **** --- 3391,3398 ---- and `-n' and `-u', which are unscaled values. + The return status is zero unless an invalid option is supplied, a + non-numeric argument other than `unlimited' is supplied as a + LIMIT, or an error occurs while setting a new limit. +  File: bashref.info, Node: The Set Builtin, Next: Bash Conditional Expressions, Prev: Bash Builtins, Up: Bash Features *************** *** 3151,3158 **** =============== ! This builtin is so overloaded that it deserves its own section. `set' ! set [-abefhkmnptuvxdBCHP] [-o OPTION] [ARGUMENT ...] `-a' --- 3401,3415 ---- =============== ! This builtin is so complicated that it deserves its own section. `set' ! set [--abefhkmnptuvxBCHP] [-o OPTION] [ARGUMENT ...] ! ! If no options or arguments are supplied, `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. ! ! When options are supplied, they set or unset shell attributes. ! Options, if specified, have the following meanings: `-a' *************** *** 3165,3170 **** `-e' ! Exit immediately if a simple command exits with a non-zero ! status. `-f' --- 3422,3430 ---- `-e' ! Exit immediately if a simple command (*note Simple ! Commands::.) exits with a non-zero status, unless the command ! that fails is part of an `until' or `while' loop, part of an ! `if' statement, part of a `&&' or `||' list, or if the ! command's return status is being inverted using `!'. `-f' *************** *** 3173,3177 **** `-h' Locate and remember (hash) commands as they are looked up for ! execution. `-k' --- 3433,3437 ---- `-h' Locate and remember (hash) commands as they are looked up for ! execution. This option is enabled by default. `-k' *************** *** 3184,3210 **** `-n' ! Read commands but do not execute them. `-o OPTION-NAME' ! Set the flag corresponding to OPTION-NAME: `allexport' ! same as `-a'. `braceexpand' ! same as `-B'. `emacs' ! use an `emacs'-style line editing interface (*note Command Line Editing::.). `errexit' ! same as `-e'. `hashall' ! same as `-h'. `histexpand' ! same as `-H'. `history' --- 3444,3472 ---- `-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. `-o OPTION-NAME' ! Set the option corresponding to OPTION-NAME: `allexport' ! Same as `-a'. `braceexpand' ! Same as `-B'. `emacs' ! Use an `emacs'-style line editing interface (*note Command Line Editing::.). `errexit' ! Same as `-e'. `hashall' ! Same as `-h'. `histexpand' ! Same as `-H'. `history' *************** *** 3214,3271 **** `ignoreeof' ! the shell will not exit upon reading EOF. `keyword' ! same as `-k'. `monitor' ! same as `-m'. `noclobber' ! same as `-C'. `noexec' ! same as `-n'. `noglob' ! same as `-f'. `notify' ! same as `-b'. `nounset' ! same as `-u'. `onecmd' ! same as `-t'. `physical' ! same as `-P'. `posix' ! change the behavior of Bash where the default operation differs from the POSIX 1003.2 standard to match the ! standard. This is intended to make Bash behave as a ! strict superset of that standard. `privileged' ! same as `-p'. `verbose' ! same as `-v'. `vi' ! use a `vi'-style line editing interface. `xtrace' ! same as `-x'. `-p' ! Turn on privileged mode. In this mode, the `$BASH_ENV' file ! is not processed, and shell functions are not inherited from ! the environment. This is enabled automatically on startup if ! the effective user (group) id is not equal to the real user ! (group) id. Turning this option off causes the effective user ! and group ids to be set to the real user and group ids. `-t' --- 3476,3536 ---- `ignoreeof' ! An interactive shell will not exit upon reading EOF. `keyword' ! Same as `-k'. `monitor' ! Same as `-m'. `noclobber' ! Same as `-C'. `noexec' ! Same as `-n'. `noglob' ! Same as `-f'. `notify' ! Same as `-b'. `nounset' ! Same as `-u'. `onecmd' ! Same as `-t'. `physical' ! Same as `-P'. `posix' ! Change the behavior of Bash where the default operation differs from the POSIX 1003.2 standard to match the ! standard (*note Bash POSIX Mode::.). This is intended ! to make Bash behave as a strict superset of that ! standard. `privileged' ! Same as `-p'. `verbose' ! Same as `-v'. `vi' ! Use a `vi'-style line editing interface. `xtrace' ! Same as `-x'. `-p' ! Turn on privileged mode. In this mode, the `$BASH_ENV' and ! `$ENV' files are not processed, shell functions are not ! inherited from the environment, and the `SHELLOPTS' variable, ! if it appears in the environment, is ignored. This is ! enabled automatically on startup if the effective user ! (group) id is not equal to the real user (group) id. Turning ! this option off causes the effective user and group ids to be ! set to the real user and group ids. `-t' *************** *** 3273,3277 **** `-u' ! Treat unset variables as an error when substituting. `-v' --- 3538,3544 ---- `-u' ! Treat unset variables as an error when performing parameter ! expansion. An error message will be written to the standard ! error, and a non-interactive shell will exit. `-v' *************** *** 3279,3283 **** `-x' ! Print commands and their arguments as they are executed. `-B' --- 3546,3551 ---- `-x' ! Print a trace of simple commands and their arguments after ! they are expanded and before they are executed. `-B' *************** *** 3286,3295 **** `-C' ! Disallow output redirection to existing files. `-H' Enable `!' style history substitution (*note History ! Interaction::.). This flag is on by default for interactive ! shells. `-P' --- 3554,3564 ---- `-C' ! Prevent output redirection using `>', `>&', and `<>' from ! overwriting existing files. `-H' Enable `!' style history substitution (*note History ! Interaction::.). This option is on by default for ! interactive shells. `-P' *************** *** 3300,3304 **** which change the current directory. ! For example, if `/usr/sys' is a link to `/usr/local/sys' then: $ cd /usr/sys; echo $PWD /usr/sys --- 3569,3574 ---- which change the current directory. ! For example, if `/usr/sys' is a symbolic link to ! `/usr/local/sys' then: $ cd /usr/sys; echo $PWD /usr/sys *************** *** 3313,3317 **** `--' ! If no arguments follow this flag, then the positional parameters are unset. Otherwise, the positional parameters are set to the ARGUMENTS, even if some of them begin with a --- 3583,3587 ---- `--' ! If no arguments follow this option, then the positional parameters are unset. Otherwise, the positional parameters are set to the ARGUMENTS, even if some of them begin with a *************** *** 3324,3334 **** positional parameters remain unchanged. ! 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 ARGUMENTS are positional parameters and are ! assigned, in order, to `$1', `$2', ... `$N'. If no arguments are ! given, all shell variables are printed.  --- 3594,3607 ---- positional parameters remain unchanged. ! Using `+' rather than `-' 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 `$-'. The remaining N ARGUMENTS are positional parameters and are ! assigned, in order, to `$1', `$2', ... `$N'. The special ! parameter `#' is set to N. ! ! The return status is always zero unless an invalid option is ! supplied.  *************** *** 3338,3349 **** ============================ ! Conditional expressions are used by the `test' and `[' builtins. 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. Each operator and operand must ! be a separate argument. If FILE is of the form `/dev/fd/N', then file ! descriptor N is checked. Expressions are composed of the following ! primaries: `-b FILE' --- 3611,3625 ---- ============================ ! Conditional expressions are used by the `[[' compound command and ! the `test' and `[' 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 any FILE argument to one of ! the primaries is of the form `/dev/fd/N', then file descriptor N is ! checked. ! ! `-a FILE' ! True if FILE exists. `-b FILE' *************** *** 3363,3376 **** `-g FILE' ! True if FILE exists and is set-group-id. `-k FILE' ! True if FILE has its "sticky" bit set. ! ! `-L FILE' ! True if FILE exists and is a symbolic link. `-p FILE' ! True if FILE exists and is a named pipe. `-r FILE' --- 3639,3649 ---- `-g FILE' ! True if FILE exists and its set-group-id bit is set. `-k FILE' ! True if FILE exists and its "sticky" bit is set. `-p FILE' ! True if FILE exists and is a named pipe (FIFO). `-r FILE' *************** *** 3380,3388 **** True if FILE exists and has a size greater than zero. - `-S FILE' - True if FILE exists and is a socket. - `-t FD' ! True if FD is opened on a terminal. `-u FILE' --- 3653,3658 ---- True if FILE exists and has a size greater than zero. `-t FD' ! True if file descriptor FD is open and refers to a terminal. `-u FILE' *************** *** 3401,3404 **** --- 3671,3683 ---- True if FILE exists and is owned by the effective group id. + `-L FILE' + True if FILE exists and is a symbolic link. + + `-S FILE' + True if FILE exists and is a socket. + + `-N FILE' + True if FILE exists and has been modified since it was last read. + `FILE1 -nt FILE2' True if FILE1 is newer (according to modification date) than FILE2. *************** *** 3422,3427 **** True if the length of STRING is non-zero. ! `STRING1 = STRING2' ! True if the strings are equal. `==' may be used in place of `='. `STRING1 != STRING2' --- 3701,3706 ---- True if the length of STRING is non-zero. ! `STRING1 == STRING2' ! True if the strings are equal. `=' may be used in place of `=='. `STRING1 != STRING2' *************** *** 3429,3445 **** `STRING1 < STRING2' ! True if STRING1 sorts before STRING2 lexicographically. `STRING1 > STRING2' ! True if STRING1 sorts after STRING2 lexicographically. ! ! `! EXPR' ! True if EXPR is false. ! ! `EXPR1 -a EXPR2' ! True if both EXPR1 and EXPR2 are true. ! ! `EXPR1 -o EXPR2' ! True if either EXPR1 and EXPR2 is true. `ARG1 OP ARG2' --- 3708,3717 ---- `STRING1 < STRING2' ! True if STRING1 sorts before STRING2 lexicographically in the ! current locale. `STRING1 > STRING2' ! True if STRING1 sorts after STRING2 lexicographically in the ! current locale. `ARG1 OP ARG2' *************** *** 3450,3491 **** positive or negative integers. - The Bash `test' and `[' builtins evaluate conditional expressions - using a set of rules based on the number of arguments. These are the - rules: - - 0 arguments - The expression is false. - - 1 argument - The expression is true if and only if the argument is not null. - - 2 arguments - If the first argument is `!', the expression is true if and only - if the second argument is null. If the first argument is one of - the listed unary operators, the expression is true if the unary - test is true. If the first argument is not a legal unary - operator, the expression is false. - - 3 arguments - If the first argument is `!', the value is the negation of the - two-argument test using the second and third arguments. If the - second argument is one of the binary operators, the result of the - expression is the result of the binary test using the first and - third arguments as operands. If the first argument is exactly `(' - and the third argument is exactly `)', the result is the - one-argument test of the second argument. Otherwise, the - expression is false. The `-a' and `-o' operators are considered - binary operators in this case. - - 4 arguments - If the first argument is `!', 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. `-a' has a higher precedence than `-o'. - - 5 or more arguments - The expression is parsed and evaluated according to precedence, - with `-a' having a higher precedence than `-o'. -  File: bashref.info, Node: Bash Variables, Next: Shell Arithmetic, Prev: Bash Conditional Expressions, Up: Bash Features --- 3722,3725 ---- *************** *** 3497,3500 **** --- 3731,3737 ---- normally treat them specially. + `BASH' + The full pathname used to execute the current instance of Bash. + `BASH_ENV' If this variable is set when Bash is invoked to execute a shell *************** *** 3503,3543 **** Files::. ! `TIMEFORMAT' ! The value of this parameter is used as a format string specifying ! how the timing information for pipelines prefixed with the `time' ! reserved word should be displayed. The `%' 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. ! `%%' ! A literal `%'. ! `%[P][l]R' ! The elapsed time in seconds. ! `%[P][l]U' ! The number of CPU seconds spent in user mode. ! `%[P][l]S' ! The number of CPU seconds spent in system mode. ! `%P' ! The CPU percentage, computed as (%U + %S) / %R. ! The optional 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 P greater than ! 3 are changed to 3. If P is not specified, the value 3 is used. ! The optional `l' specifies a longer format, including minutes, of ! the form MMmSS.FFs. The value of P determines whether or not the ! fraction is included. ! If this variable is not set, bash acts as if it had the value ! `$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS''. ! If the value is null, no timing information is displayed. A ! trailing newline is added when the format string is displayed. `HISTCONTROL' --- 3740,3823 ---- Files::. ! `BASH_VERSION' ! The version number of the current instance of Bash. ! `BASH_VERSINFO' ! A readonly array variable whose members hold version information ! for this instance of Bash. The values assigned to the array ! members are as follows: ! `BASH_VERSINFO[0]' ! The major version number (the RELEASE). ! `BASH_VERSINFO[1]' ! The minor version number (the VERSION). ! `BASH_VERSINFO[2]' ! The patch level. ! `BASH_VERSINFO[3]' ! The build version. ! `BASH_VERSINFO[4]' ! The release status (e.g., BETA1). ! ! `BASH_VERSINFO[5]' ! The value of `MACHTYPE'. ! ! `DIRSTACK' ! An array variable (*note Arrays::.) containing the current ! contents of the directory stack. Directories appear in the stack ! in the order they are displayed by the `dirs' builtin. Assigning ! to members of this array variable may be used to modify ! directories already in the stack, but the `pushd' and `popd' ! builtins must be used to add and remove directories. Assignment ! to this variable will not change the current directory. If ! `DIRSTACK' is unset, it loses its special properties, even if it ! is subsequently reset. ! ! `EUID' ! The numeric effective user id of the current user. This variable ! is readonly. ! ! `FCEDIT' ! The editor used as a default by the `-e' option to the `fc' ! builtin command. ! ! `FIGNORE' ! A colon-separated list of suffixes to ignore when performing ! filename completion. A file name whose suffix matches one of the ! entries in `FIGNORE' is excluded from the list of matched file ! names. A sample value is `.o:~' ! ! `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 ! `GLOBIGNORE', it is removed from the list of matches. ! `GROUPS' ! An array variable containing the list of groups of which the ! current user is a member. This variable is readonly. ! `histchars' ! Up to three characters which control history expansion, quick ! substitution, and tokenization (*note History Interaction::.). ! The first character is the "history-expansion-char", that is, the ! character which signifies the start of a history expansion, ! normally `!'. The second character is the character which ! signifies `quick substitution' when seen as the first character on ! a line, normally `^'. 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 `#'. ! 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. ! ! `HISTCMD' ! The history number, or index in the history list, of the current ! command. If `HISTCMD' is unset, it loses its special properties, ! even if it is subsequently reset. `HISTCONTROL' *************** *** 3547,3551 **** entered line. A value of `ignoreboth' combines the two options. Unset, or set to any other value than those above, means to save ! all lines on the history list. `HISTIGNORE' --- 3827,3833 ---- entered line. A value of `ignoreboth' combines the two options. Unset, or set to any other value than those above, means to save ! all lines on the history list. 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 `HISTCONTROL'. `HISTIGNORE' *************** *** 3558,3562 **** characters, `&' matches the previous history line. `&' may be escaped using a backslash. The backslash is removed before ! attempting a match. `HISTIGNORE' subsumes the function of `HISTCONTROL'. A pattern of --- 3840,3846 ---- characters, `&' matches the previous history line. `&' 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 `HISTIGNORE'. `HISTIGNORE' subsumes the function of `HISTCONTROL'. A pattern of *************** *** 3571,3576 **** `HISTSIZE' ! If set, this is the maximum number of commands to remember in the ! history. `HISTFILESIZE' --- 3855,3860 ---- `HISTSIZE' ! The maximum number of commands to remember on the history list. ! The default value is 500. `HISTFILESIZE' *************** *** 3581,3604 **** size after writing it when an interactive shell exits. - `histchars' - Up to three characters which control history expansion, quick - substitution, and tokenization (*note History Interaction::.). - The first character is the "history-expansion-char", that is, the - character which signifies the start of a history expansion, - normally `!'. The second character is the character which - signifies `quick substitution' when seen as the first character on - a line, normally `^'. The optional third character is the - character which signifies the remainder of the line is a comment, - when found as the first character of a word, usually `#'. 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. - - `HISTCMD' - The history number, or index in the history list, of the current - command. If `HISTCMD' is unset, it loses its special properties, - even if it is subsequently reset. - `HOSTFILE' Contains the name of a file in the same format as `/etc/hosts' that --- 3865,3868 ---- *************** *** 3608,3640 **** the already existing database. ! `MAILCHECK' ! How often (in seconds) that the shell should check for mail in the ! files specified in `MAILPATH'. ! `PROMPT_COMMAND' ! If present, this contains a string which is a command to execute ! before the printing of each primary prompt (`$PS1'). ! `UID' ! The numeric real user id of the current user. ! `EUID' ! The numeric effective user id of the current user. ! `GROUPS' ! An array variable containing the list of groups of which the ! current user is a member. ! `PPID' ! The process id of the shell's parent process. ! `HOSTNAME' ! The name of the current host. ! `HOSTTYPE' ! A string describing the machine Bash is running on. ! `OSTYPE' ! A string describing the operating system Bash is running on. `MACHTYPE' --- 3872,3922 ---- the already existing database. ! `HOSTNAME' ! The name of the current host. ! `HOSTTYPE' ! A string describing the machine Bash is running on. ! `IGNOREEOF' ! Controls the action of the shell on receipt of an `EOF' character ! as the sole input. If set, the value denotes the number of ! consecutive `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 `EOF' signifies the end of input to the shell. This is only ! in effect for interactive shells. ! `INPUTRC' ! The name of the Readline startup file, overriding the default of ! `~/.inputrc'. ! `LANG' ! Used to determine the locale category for any category not ! specifically selected with a variable starting with `LC_'. ! `LC_ALL' ! This variable overrides the value of `LANG' and any other `LC_' ! variable specifying a locale category. ! `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 (*note Filename ! Expansion::.). ! ! `LC_CTYPE' ! This variable determines the interpretation of characters and the ! behavior of character classes within filename expansion and pattern ! matching (*note Filename Expansion::.). ! `LC_MESSAGES' ! This variable determines the locale used to translate double-quoted ! strings preceded by a `$' (*note Locale Translation::.). ! `LINENO' ! The line number in the script or shell function currently ! executing. `MACHTYPE' *************** *** 3642,3676 **** executing, in the standard GNU CPU-COMPANY-SYSTEM format. ! `SHELLOPTS' ! A colon-separated list of enabled shell options. Each word in the ! list is a valid argument for the `-o' option to the `set' builtin ! command (*note The Set Builtin::.). The options appearing in ! `SHELLOPTS' are those reported as `on' by `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. ! `FIGNORE' ! A colon-separated list of suffixes to ignore when performing ! filename completion. A file name whose suffix matches one of the ! entries in `FIGNORE' is excluded from the list of matched file ! names. A sample value is `.o:~' ! `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 ! `GLOBIGNORE', it is removed from the list of matches. ! `DIRSTACK' ! An array variable (*note Arrays::.) containing the current ! contents of the directory stack. Directories appear in the stack ! in the order they are displayed by the `dirs' builtin. Assigning ! to members of this array variable may be used to modify ! directories already in the stack, but the `pushd' and `popd' ! builtins must be used to add and remove directories. Assignment ! to this variable will not change the current directory. If ! `DIRSTACK' is unset, it loses its special properties, even if it ! is subsequently reset. `PIPESTATUS' --- 3924,3940 ---- executing, in the standard GNU CPU-COMPANY-SYSTEM format. ! `MAILCHECK' ! How often (in seconds) that the shell should check for mail in the ! files specified in the `MAILPATH' or `MAIL' variables. ! `OLDPWD' ! The previous working directory as set by the `cd' builtin. ! `OPTERR' ! If set to the value 1, Bash displays error messages generated by ! the `getopts' builtin command. ! `OSTYPE' ! A string describing the operating system Bash is running on. `PIPESTATUS' *************** *** 3679,3714 **** foreground pipeline (which may contain only a single command). ! `INPUTRC' ! The name of the Readline startup file, overriding the default of ! `~/.inputrc'. ! ! `BASH' ! The full filename used to execute the current instance of Bash. ! `BASH_VERSION' ! The version number of the current instance of Bash. ! `BASH_VERSINFO' ! An array variable whose members hold version information for this ! instance of Bash. The values assigned to the array members are as ! follows: ! `BASH_VERSINFO[0]' ! The major version number (the RELEASE). ! `BASH_VERSINFO[1]' ! The minor version number (the VERSION). ! `BASH_VERSINFO[2]' ! The patch level. ! `BASH_VERSINFO[3]' ! The build version. ! `BASH_VERSINFO[4]' ! The release status (e.g., BETA1). ! `BASH_VERSINFO[5]' ! The value of `MACHTYPE'. `SHLVL' --- 3943,3990 ---- foreground pipeline (which may contain only a single command). ! `PPID' ! The process id of the shell's parent process. This variable is ! readonly. ! `PROMPT_COMMAND' ! If present, this contains a string which is a command to execute ! before the printing of each primary prompt (`$PS1'). ! `PS3' ! The value of this variable is used as the prompt for the `select' ! command. If this variable is not set, the `select' command ! prompts with `#? ' ! `PS4' ! This is the prompt printed before the command line is echoed when ! the `-x' option is set (*note The Set Builtin::.). The first ! character of `PS4' is replicated multiple times, as necessary, to ! indicate multiple levels of indirection. The default is `+ '. ! `PWD' ! The current working directory as set by the `cd' builtin. ! `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. ! `REPLY' ! The default variable for the `read' builtin. ! `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. ! `SHELLOPTS' ! A colon-separated list of enabled shell options. Each word in the ! list is a valid argument for the `-o' option to the `set' builtin ! command (*note The Set Builtin::.). The options appearing in ! `SHELLOPTS' are those reported as `on' by `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. `SHLVL' *************** *** 3717,3770 **** nested. ! `OPTERR' ! If set to the value 1, Bash displays error messages generated by ! the `getopts' builtin command. ! `LANG' ! Used to determine the locale category for any category not ! specifically selected with a variable starting with `LC_'. ! `LC_ALL' ! This variable overrides the value of `LANG' and any other `LC_' ! variable specifying a locale category. ! `LC_COLLATE' ! This variable determines the collation order used when sorting the ! results of filename expansion (*note Filename Expansion::.). ! `LC_MESSAGES' ! This variable determines the locale used to translate double-quoted ! strings preceded by a `$' (*note Locale Translation::.). ! `IGNOREEOF' ! Controls the action of the shell on receipt of an `EOF' character ! as the sole input. If set, then the value of it is the number of ! consecutive `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 `EOF' signifies the end of input to the shell. This is only ! in effect for interactive shells. !  ! File: bashref.info, Node: Shell Arithmetic, Next: Arrays, Prev: Bash Variables, Up: Bash Features ! Shell Arithmetic ! ================ ! * Menu: ! * Arithmetic Evaluation:: How shell arithmetic works. ! * Arithmetic Expansion:: How to use arithmetic in shell expansions. ! * Arithmetic Builtins:: Builtin commands that use shell arithmetic. ! Bash includes several mechanisms to evaluate arithmetic expressions ! and display the result or use it as part of a command.  ! File: bashref.info, Node: Arithmetic Evaluation, Next: Arithmetic Expansion, Up: Shell Arithmetic ! Arithmetic Evaluation ! --------------------- The shell allows arithmetic expressions to be evaluated, as one of --- 3993,4049 ---- nested. ! `TIMEFORMAT' ! The value of this parameter is used as a format string specifying ! how the timing information for pipelines prefixed with the `time' ! reserved word should be displayed. The `%' 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. ! `%%' ! A literal `%'. ! `%[P][l]R' ! The elapsed time in seconds. ! `%[P][l]U' ! The number of CPU seconds spent in user mode. ! `%[P][l]S' ! The number of CPU seconds spent in system mode. ! `%P' ! The CPU percentage, computed as (%U + %S) / %R. ! The optional 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 P greater than ! 3 are changed to 3. If P is not specified, the value 3 is used. ! The optional `l' specifies a longer format, including minutes, of ! the form MMmSS.FFs. The value of P determines whether or not the ! fraction is included. ! If this variable is not set, Bash acts as if it had the value ! `$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'' ! If the value is null, no timing information is displayed. A ! trailing newline is added when the format string is displayed. ! `TMOUT' ! If set to a value greater than zero, the value is interpreted as ! the number of seconds to wait for input after issuing the primary ! prompt. Bash terminates after that number of seconds if input does ! not arrive. ! `UID' ! The numeric real user id of the current user. This variable is ! readonly.  ! File: bashref.info, Node: Shell Arithmetic, Next: Aliases, Prev: Bash Variables, Up: Bash Features ! Shell Arithmetic ! ================ The shell allows arithmetic expressions to be evaluated, as one of *************** *** 3782,3785 **** --- 4061,4067 ---- logical and bitwise negation + `**' + exponentiation + `* / %' multiplication, division, remainder *************** *** 3839,3879 ****  ! File: bashref.info, Node: Arithmetic Expansion, Next: Arithmetic Builtins, Prev: Arithmetic Evaluation, Up: Shell Arithmetic ! Arithmetic Expansion ! -------------------- ! Arithmetic expansion allows the evaluation of an arithmetic ! expression and the substitution of the result. The format for ! arithmetic expansion is: ! $(( EXPRESSION )) ! The expression is treated as if it were within double quotes, but a ! double quote inside the braces or parentheses is not treated specially. ! All tokens in the expression undergo parameter expansion, command ! substitution, and quote removal. Arithmetic substitutions may be ! nested. ! The evaluation is performed according to the rules listed above. If ! the expression is invalid, Bash prints a message indicating failure and ! no substitution occurs. !  ! File: bashref.info, Node: Arithmetic Builtins, Prev: Arithmetic Expansion, Up: Shell Arithmetic ! Arithmetic Builtins ! ------------------- ! `let' ! let EXPRESSION [EXPRESSION] ! The `let' builtin allows arithmetic to be performed on shell ! variables. Each EXPRESSION is evaluated according to the rules ! given previously (*note Arithmetic Evaluation::.). If the last ! EXPRESSION evaluates to 0, `let' returns 1; otherwise 0 is ! returned.  ! File: bashref.info, Node: Arrays, Next: Printing a Prompt, Prev: Shell Arithmetic, Up: Bash Features Arrays --- 4121,4201 ----  ! File: bashref.info, Node: Aliases, Next: Arrays, Prev: Shell Arithmetic, Up: Bash Features ! ! Aliases ! ======= ! ! * Menu: ! ! * Alias Builtins:: Builtins commands to maniuplate aliases. ! ! 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 `alias' and `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 alias name and the replacement text may contain any valid ! shell input, including shell metacharacters, with the exception that ! the alias name may not contain `='. 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 `ls' to `"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 space or tab character, then the next command word ! following the alias is also checked for alias expansion. ! ! Aliases are created and listed with the `alias' command, and removed ! with the `unalias' command. ! ! There is no mechanism for using arguments in the replacement text, ! as in `csh'. If arguments are needed, a shell function should be used ! (*note Shell Functions::.). ! ! Aliases are not expanded when the shell is not interactive, unless ! the `expand_aliases' shell option is set using `shopt' (*note Bash ! Builtins::.). ! 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 ! compound 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 `alias' ! in compound commands. ! For almost every purpose, aliases are superseded by shell functions. !  ! File: bashref.info, Node: Alias Builtins, Up: Aliases ! Alias Builtins ! -------------- ! `alias' ! alias [`-p'] [NAME[=VALUE] ...] ! Without arguments or with the `-p' option, `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 NAME whose VALUE is given. If no VALUE is given, the name ! and value of the alias is printed. ! `unalias' ! unalias [-a] [NAME ... ] ! Remove each NAME from the list of aliases. If `-a' is supplied, ! all aliases are removed.  ! File: bashref.info, Node: Arrays, Next: The Directory Stack, Prev: Aliases, Up: Bash Features Arrays *************** *** 3928,3934 **** The `unset' builtin is used to destroy arrays. `unset' ! NAME[SUBSCRIPT] destroys the array element at index SUBSCRIPT. `unset' ! NAME, where NAME is an array, removes the entire array. A subscript of ! `*' or `@' also removes the entire array. The `declare', `local', and `readonly' builtins each accept a `-a' --- 4250,4256 ---- The `unset' builtin is used to destroy arrays. `unset' ! `name[SUBSCRIPT]' destroys the array element at index SUBSCRIPT. ! `unset' NAME, where NAME is an array, removes the entire array. A ! subscript of `*' or `@' also removes the entire array. The `declare', `local', and `readonly' builtins each accept a `-a' *************** *** 3940,3944 ****  ! File: bashref.info, Node: Printing a Prompt, Next: The Restricted Shell, Prev: Arrays, Up: Bash Features Controlling the Prompt --- 4262,4359 ----  ! File: bashref.info, Node: The Directory Stack, Next: Printing a Prompt, Prev: Arrays, Up: Bash Features ! ! The Directory Stack ! =================== ! ! The directory stack is a list of recently-visited directories. The ! `pushd' builtin adds directories to the stack as it changes the current ! directory, and the `popd' builtin removes specified directories from ! the stack and changes the current directory to the directory removed. ! The `dirs' builtin displays the contents of the directory stack. ! ! The contents of the directory stack are also visible as the value of ! the `DIRSTACK' shell variable. ! ! `dirs' ! dirs [+N | -N] [-clvp] ! Display the list of currently remembered directories. Directories ! are added to the list with the `pushd' command; the `popd' command ! removes directories from the list. ! `+N' ! Displays the Nth directory (counting from the left of the ! list printed by `dirs' when invoked without options), starting ! with zero. ! ! `-N' ! Displays the Nth directory (counting from the right of the ! list printed by `dirs' when invoked without options), starting ! with zero. ! ! `-c' ! Clears the directory stack by deleting all of the elements. ! ! `-l' ! Produces a longer listing; the default listing format uses a ! tilde to denote the home directory. ! ! `-p' ! Causes `dirs' to print the directory stack with one entry per ! line. ! ! `-v' ! Causes `dirs' to print the directory stack with one entry per ! line, prefixing each entry with its index in the stack. ! ! `popd' ! popd [+N | -N] [-n] ! ! Remove the top entry from the directory stack, and `cd' to the new ! top directory. When no arguments are given, `popd' removes the ! top directory from the stack and performs a `cd' to the new top ! directory. The elements are numbered from 0 starting at the first ! directory listed with `dirs'; i.e., `popd' is equivalent to `popd ! +0'. ! `+N' ! Removes the Nth directory (counting from the left of the list ! printed by `dirs'), starting with zero. ! ! `-N' ! Removes the Nth directory (counting from the right of the ! list printed by `dirs'), starting with zero. ! ! `-n' ! Suppresses the normal change of directory when removing ! directories from the stack, so that only the stack is ! manipulated. ! ! `pushd' ! pushd [DIR | +N | -N] [-n] ! ! Save the current directory on the top of the directory stack and ! then `cd' to DIR. With no arguments, `pushd' exchanges the top ! two directories. ! ! `+N' ! Brings the Nth directory (counting from the left of the list ! printed by `dirs', starting with zero) to the top of the list ! by rotating the stack. ! ! `-N' ! Brings the Nth directory (counting from the right of the list ! printed by `dirs', starting with zero) to the top of the list ! by rotating the stack. ! ! `-n' ! Suppresses the normal change of directory when adding ! directories to the stack, so that only the stack is ! manipulated. ! ! `DIR' ! Makes the current working directory be the top of the stack, ! and then executes the equivalent of ``cd' DIR'. `cd's to DIR. ! !  ! File: bashref.info, Node: Printing a Prompt, Next: The Restricted Shell, Prev: The Directory Stack, Up: Bash Features Controlling the Prompt *************** *** 3947,3951 **** The value of the variable `PROMPT_COMMAND' is examined just before Bash prints each primary prompt. If it is set and non-null, then the ! value is executed just as if you had typed it on the command line. In addition, the following table describes the special characters --- 4362,4366 ---- The value of the variable `PROMPT_COMMAND' is examined just before Bash prints each primary prompt. If it is set and non-null, 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 *************** *** 3953,4022 **** `\a' ! a bell character. `\d' ! the date, in "Weekday Month Date" format (e.g., "Tue May 26"). `\e' ! an escape character. `\h' ! the hostname, up to the first `.'. `\H' ! the hostname. `\n' ! newline. `\s' ! the name of the shell, the basename of `$0' (the portion following the final slash). `\t' ! the time, in 24-hour HH:MM:SS format. `\T' ! the time, in 12-hour HH:MM:SS format. `\@' ! the time, in 12-hour am/pm format. `\v' ! the version of Bash (e.g., 2.00) `\V' ! the release of Bash, version + patchlevel (e.g., 2.00.0) `\w' ! the current working directory. `\W' ! the basename of `$PWD'. ! ! `\u' ! your username. `\!' ! the history number of this command. `\#' ! the command number of this command. `\$' ! if the effective uid is 0, `#', otherwise `$'. ! `\nnn' ! the character corresponding to the octal number `nnn'. `\\' ! a backslash. `\[' ! begin a sequence of non-printing characters. This could be used to embed a terminal control sequence into the prompt. `\]' ! end a sequence of non-printing characters.  --- 4368,4440 ---- `\a' ! A bell character. `\d' ! The date, in "Weekday Month Date" format (e.g., "Tue May 26"). `\e' ! An escape character. `\h' ! The hostname, up to the first `.'. `\H' ! The hostname. `\n' ! A newline. ! ! `\r' ! A carriage return. `\s' ! The name of the shell, the basename of `$0' (the portion following the final slash). `\t' ! The time, in 24-hour HH:MM:SS format. `\T' ! The time, in 12-hour HH:MM:SS format. `\@' ! The time, in 12-hour am/pm format. ! ! `\u' ! The username of the current user. `\v' ! The version of Bash (e.g., 2.00) `\V' ! The release of Bash, version + patchlevel (e.g., 2.00.0) `\w' ! The current working directory. `\W' ! The basename of `$PWD'. `\!' ! The history number of this command. `\#' ! The command number of this command. `\$' ! If the effective uid is 0, `#', otherwise `$'. ! `\NNN' ! The character whose ASCII code is the octal value NNN. `\\' ! A backslash. `\[' ! Begin a sequence of non-printing characters. This could be used to embed a terminal control sequence into the prompt. `\]' ! End a sequence of non-printing characters.  *************** *** 4043,4046 **** --- 4461,4467 ---- startup. + * Parsing the value of `SHELLOPTS' from the shell environment at + startup. + * Redirecting output using the `>', `>|', `<>', `>&', `&>', and `>>' redirection operators. *************** *** 4053,4057 **** * Specifying the `-p' option to the `command' builtin. ! * Turning off restricted mode with `set +r'.  --- 4474,4478 ---- * Specifying the `-p' option to the `command' builtin. ! * Turning off restricted mode with `set +r' or `set +o restricted'.  *************** *** 4081,4089 **** 5. The POSIX.2 `PS1' and `PS2' expansions of `!' to the history number and `!!' to `!' 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 --- 4502,4510 ---- 5. The POSIX.2 `PS1' and `PS2' expansions of `!' to the history number and `!!' to `!' are enabled, and parameter expansion is ! performed on the values of `PS1' and `PS2' regardless of the ! setting of the `promptvars' option. ! 6. Interactive comments are enabled by default. (Bash has them on by ! default anyway.) 7. The POSIX.2 startup files are executed (`$ENV') rather than the *************** *** 4102,4117 **** found. ! 12. Redirection operators do not perform filename expansion on the word in the redirection unless the shell is interactive. ! 13. Function names must be valid shell `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 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 --- 4523,4541 ---- found. ! 12. Non-interactive shells exit if a syntax error in an arithmetic ! expansion results in an invalid expression. ! ! 13. Redirection operators do not perform filename expansion on the word in the redirection unless the shell is interactive. ! 14. Function names must be valid shell `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. ! 15. POSIX.2 `special' builtins are found before shell functions during command lookup. ! 16. 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 *************** *** 4119,4141 **** assignments preceding the command name, and so on. ! 16. If the `cd' builtin finds a directory to change to using `$CDPATH', the value it assigns to the `PWD' variable does not contain any symbolic links, as if `cd -P' had been executed. ! 17. 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. ! 18. 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. ! 19. Process substitution is not available. ! 20. Assignment statements preceding POSIX.2 `special' builtins persist in the shell environment after the builtin completes. ! 21. The `export' and `readonly' builtin commands display their output in the format required by POSIX.2. --- 4543,4571 ---- assignments preceding the command name, and so on. ! 17. If the `cd' builtin finds a directory to change to using `$CDPATH', the value it assigns to the `PWD' variable does not contain any symbolic links, as if `cd -P' had been executed. ! 18. If `$CDPATH' is set, the `cd' builtin will not implicitly append ! the current directory to it. This means that `cd' will fail if no ! valid directory name can be constructed from any of the entries in ! `$CDPATH', even if the a directory with the same name as the name ! given as an argument to `cd' exists in the current directory. ! ! 19. 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. ! 20. 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 readonly variable. ! 21. Process substitution is not available. ! 22. Assignment statements preceding POSIX.2 special builtins persist in the shell environment after the builtin completes. ! 23. The `export' and `readonly' builtin commands display their output in the format required by POSIX.2. *************** *** 4153,4157 **** *********** ! This chapter disusses what job control is, how it works, and how Bash allows you to access its facilities. --- 4583,4587 ---- *********** ! This chapter discusses what job control is, how it works, and how Bash allows you to access its facilities. *************** *** 4177,4182 **** The shell associates a JOB with each pipeline. It keeps a table of currently executing jobs, which may be listed with the `jobs' command. ! When Bash starts a job asynchronously (in the background), it prints a ! line that looks like: [1] 25647 --- 4607,4611 ---- The shell associates a JOB with each pipeline. It keeps a table of currently executing jobs, which may be listed with the `jobs' command. ! When Bash starts a job asynchronously, it prints a line that looks like: [1] 25647 *************** *** 4200,4213 **** If the operating system on which Bash is running supports job ! control, Bash allows you to use it. Typing the SUSPEND character ! (typically `^Z', Control-Z) while a process is running causes that ! process to be stopped and returns you to Bash. Typing the DELAYED ! SUSPEND character (typically `^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. You may then manipulate the state of this job, ! using the `bg' command to continue it in the background, the `fg' ! command to continue it in the foreground, or the `kill' command to kill ! it. A `^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 --- 4629,4643 ---- If the operating system on which Bash is running supports job ! control, Bash contains facilities to use it. Typing the SUSPEND ! character (typically `^Z', Control-Z) while a process is running causes ! that process to be stopped and returns control to Bash. Typing the ! DELAYED SUSPEND character (typically `^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 `bg' command to continue it in the ! background, the `fg' command to continue it in the foreground, or the ! `kill' command to kill it. A `^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 *************** *** 4220,4227 **** reports an error. The symbols `%%' and `%+' refer to the shell's notion of the current job, which is the last job stopped while it was ! in the foreground. The previous job may be referenced using `%-'. In ! output pertaining to jobs (e.g., the output of the `jobs' command), the ! current job is always flagged with a `+', and the previous job with a ! `-'. Simply naming a job can be used to bring it into the foreground: --- 4650,4657 ---- reports an error. The symbols `%%' and `%+' 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. The previous job may ! be referenced using `%-'. In output pertaining to jobs (e.g., the ! output of the `jobs' command), the current job is always flagged with a ! `+', and the previous job with a `-'. Simply naming a job can be used to bring it into the foreground: *************** *** 4233,4244 **** 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 the `-b' option to the `set' builtin is set, Bash reports such changes immediately (*note The Set Builtin::.). ! If you attempt to exit Bash while jobs are stopped, the shell prints ! a message warning you that you have stopped jobs. You may then use the ! `jobs' command to inspect their status. If you do this, or try to exit ! again immediately, you are not warned again, and the stopped jobs are ! terminated.  --- 4663,4674 ---- 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 the `-b' option to the `set' builtin is enabled, Bash reports such changes immediately (*note The Set Builtin::.). ! If an attempt to exit Bash is while jobs are stopped, the shell ! prints a message warning that there are stopped jobs. The `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 the stopped jobs are terminated.  *************** *** 4250,4264 **** `bg' bg [JOBSPEC] ! Place JOBSPEC into the background, as if it had been started with ! `&'. If JOBSPEC is not supplied, the current job is used. `fg' fg [JOBSPEC] ! Bring JOBSPEC into the foreground and make it the current job. If ! JOBSPEC is not supplied, the current job is used. `jobs' jobs [-lpnrs] [JOBSPEC] ! jobs -x COMMAND [JOBSPEC] The first form lists the active jobs. The options have the --- 4680,4702 ---- `bg' bg [JOBSPEC] ! Resume the suspended job JOBSPEC in the background, as if it had ! been started with `&'. If 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, if ! JOBSPEC was not found or JOBSPEC specifies a job that was started ! without job control. `fg' fg [JOBSPEC] ! Resume the job JOBSPEC in the foreground and make it the current ! job. If 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, JOBSPEC does not specify a valid job or ! JOBSPEC specifies a job that was started without job control. `jobs' jobs [-lpnrs] [JOBSPEC] ! jobs -x COMMAND [ARGUMENTS] The first form lists the active jobs. The options have the *************** *** 4266,4274 **** `-l' ! List process IDs in addition to the normal information `-n' Display information only about jobs that have changed status ! since you were last notified of their status. `-p' --- 4704,4712 ---- `-l' ! List process IDs in addition to the normal information. `-n' Display information only about jobs that have changed status ! since the user was last notified of their status. `-p' *************** *** 4291,4318 **** `kill' ! kill [-s SIGSPEC] [-n SIGNUM] [-SIGSPEC] JOBSPEC ! kill -l [SIGSPEC] Send a signal specified by SIGSPEC or SIGNUM to the process named ! by JOBSPEC. SIGSPEC is either a signal name such as `SIGINT' ! (with or without the `SIG' prefix) or a signal number; SIGNUM is a ! signal number. If SIGSPEC and SIGNUM are not present, `SIGTERM' ! is used. The `-l' option lists the signal names, or the signal ! name corresponding to SIGSPEC. `wait' wait [JOBSPEC|PID] Wait until the child process specified by process ID PID or job ! specification JOBSPEC exits and report its exit status. 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. `disown' ! disown [-h] [JOBSPEC ...] Without options, each JOBSPEC is removed from the table of active jobs. If the `-h' option is given, the job is not removed from the table, but is marked so that `SIGHUP' is not sent to the job ! if the shell receives a `SIGHUP'. If JOBSPEC is not present, the ! current job is used. `suspend' --- 4729,4767 ---- `kill' ! kill [-s SIGSPEC] [-n SIGNUM] [-SIGSPEC] JOBSPEC or PID ! kill -l [EXIT_STATUS] Send a signal specified by SIGSPEC or SIGNUM to the process named ! by job specification JOBSPEC or process ID PID. SIGSPEC is either ! a signal name such as `SIGINT' (with or without the `SIG' prefix) ! or a signal number; SIGNUM is a signal number. If SIGSPEC and ! SIGNUM are not present, `SIGTERM' is used. The `-l' option lists ! the signal names. If any arguments are supplied when `-l' is ! given, the names of the signals corresponding to the arguments are ! listed, and the return status is zero. 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. `wait' wait [JOBSPEC|PID] Wait until the child process specified by process ID PID or job ! specification 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 neither JOBSPEC nor PID specifies an active child process ! of the shell, the return status is 127. `disown' ! disown [-ar] [-h] [JOBSPEC ...] Without options, each JOBSPEC is removed from the table of active jobs. If the `-h' option is given, the job is not removed from the table, but is marked so that `SIGHUP' is not sent to the job ! if the shell receives a `SIGHUP'. If JOBSPEC is not present, and ! neither the `-a' nor `-r' option is supplied, the current job is ! used. If no JOBSPEC is supplied, the `-a' option means to remove ! or mark all jobs; the `-r' option without a JOBSPEC argument ! restricts operation to running jobs. `suspend' *************** *** 4334,4344 **** This variable controls how the shell interacts with the user and job control. If this variable exists then single word simple ! commands without redirects 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 `exact', the string supplied ! must match the name of a stopped job exactly; if set to `substring', the string supplied needs to match a substring of the name of a stopped job. The `substring' value provides --- 4783,4793 ---- 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 `exact', the string ! supplied must match the name of a stopped job exactly; if set to `substring', the string supplied needs to match a substring of the name of a stopped job. The `substring' value provides *************** *** 4356,4361 **** This chapter describes how to use the GNU History Library interactively, from a user's standpoint. It should be considered a ! user's guide. For information on using the GNU History Library in your ! own programs, see the GNU Readline Library Manual. * Menu: --- 4805,4810 ---- This chapter describes how to use the GNU History Library interactively, from a user's standpoint. It should be considered a ! user's guide. For information on using the GNU History Library in ! other programs, see the GNU Readline Library Manual. * Menu: *************** *** 4363,4370 **** * Bash History Facilities:: How Bash lets you manipulate your command history. * History Interaction:: What it feels like using History as a user.  ! File: bashref.info, Node: Bash History Facilities, Next: History Interaction, Up: Using History Interactively Bash History Facilities --- 4812,4821 ---- * Bash History Facilities:: How Bash lets you manipulate your command history. + * Bash History Builtins:: The Bash builtin commands that manipulate + the command history. * History Interaction:: What it feels like using History as a user.  ! File: bashref.info, Node: Bash History Facilities, Next: Bash History Builtins, Up: Using History Interactively Bash History Facilities *************** *** 4391,4400 **** truncation is performed. ! The builtin command `fc' (*note Korn Shell Builtins::.) may be used ! to list or edit and re-execute a portion of the history list. The ! `history' builtin (*note C Shell Builtins::.) can be used to display or ! modify the history list and manipulate the history file. When using ! the command-line editing, search commands are available in each editing ! mode that provide access to the history list. The shell allows control over which commands are saved on the history --- 4842,4850 ---- truncation is performed. ! The builtin command `fc' may be used to list or edit and re-execute ! a portion of the history list. The `history' builtin can be used to ! display or modify the history list and manipulate the history file. ! When using the command-line editing, search commands are available in ! each editing mode that provide access to the history list. The shell allows control over which commands are saved on the history *************** *** 4405,4416 **** where necessary to preserve syntactic correctness. The `lithist' shell option causes the shell to save the command with embedded newlines ! instead of semicolons. *Note Bash Builtins:: for a description of `shopt'.  ! File: bashref.info, Node: History Interaction, Prev: Bash History Facilities, Up: Using History Interactively ! Interactive History Expansion ! ============================= The History library provides a history expansion feature that is --- 4855,4948 ---- where necessary to preserve syntactic correctness. The `lithist' shell option causes the shell to save the command with embedded newlines ! instead of semicolons. *Note Bash Builtins::, for a description of `shopt'.  ! File: bashref.info, Node: Bash History Builtins, Next: History Interaction, Prev: Bash History Facilities, Up: Using History Interactively ! Bash History Builtins ! ===================== ! ! Bash provides two builtin commands that allow you to manipulate the ! history list and history file. ! ! `fc' ! `fc [-e ENAME] [-nlr] [FIRST] [LAST]' ! `fc -s [PAT=REP] [COMMAND]' ! ! Fix Command. In the first form, a range of commands from FIRST to ! LAST is selected from the history list. Both FIRST and LAST may ! be specified as a string (to locate the most recent 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 LAST is not specified it is set to ! FIRST. If FIRST is not specified it is set to the previous ! command for editing and -16 for listing. If the `-l' flag is ! given, the commands are listed on standard output. The `-n' flag ! suppresses the command numbers when listing. The `-r' flag ! reverses the order of the listing. Otherwise, the editor given by ! ENAME is invoked on a file containing those commands. If ENAME is ! not given, the value of the following variable expansion is used: ! `${FCEDIT:-${EDITOR:-vi}}'. This says to use the value of the ! `FCEDIT' variable if set, or the value of the `EDITOR' variable if ! that is set, or `vi' if neither is set. When editing is complete, ! the edited commands are echoed and executed. ! ! In the second form, COMMAND is re-executed after each instance of ! PAT in the selected command is replaced by REP. ! ! A useful alias to use with the `fc' command is `r='fc -s'', so ! that typing `r cc' runs the last command beginning with `cc' and ! typing `r' re-executes the last command (*note Aliases::.). ! ! `history' ! history [-c] [N] ! history [-anrw] [FILENAME] ! history -ps ARG ! ! Display the history list with line numbers. Lines prefixed with ! with a `*' have been modified. An argument of N says to list only ! the last N lines. Options, if supplied, have the following ! meanings: ! ! `-w' ! Write out the current history to the history file. ! ! `-r' ! Read the current history file and append its contents to the ! history list. ! ! `-a' ! Append the new history lines (history lines entered since the ! beginning of the current Bash session) to the history file. ! ! `-n' ! Append the history lines not already read from the history ! file to the current history list. These are lines appended ! to the history file since the beginning of the current Bash ! session. ! ! `-c' ! Clear the history list. This may be combined with the other ! options to replace the history list completely. ! ! `-s' ! The ARGs are added to the end of the history list as a single ! entry. ! ! `-p' ! Perform history substitution on the ARGs and display the ! result on the standard output, without storing the results in ! the history list. ! ! When the `-w', `-r', `-a', or `-n' option is used, if FILENAME is ! given, then it is used as the history file. If not, then the ! value of the `HISTFILE' variable is used. ! !  ! File: bashref.info, Node: History Interaction, Prev: Bash History Builtins, Up: Using History Interactively ! ! History Expansion ! ================= The History library provides a history expansion feature that is *************** *** 4424,4438 **** History expansion takes place in two parts. The first is to ! determine which line from the previous history should be used during substitution. The second is to select portions of that line for ! inclusion into the current one. The line selected from the previous ! history is called the "event", and the portions of that line that are ! acted upon are called "words". Various "modifiers" are available to ! manipulate the selected words. The line is broken into words in the ! same fashion that Bash does, so that several English (or Unix) words ! surrounded by quotes are considered as one word. History expansions ! are introduced by the appearance of the history expansion character, ! which is `!' by default. Only `\' and `'' may be used to escape the ! history expansion character. Several shell options settable with the `shopt' builtin (*note Bash --- 4956,4969 ---- History expansion takes place in two parts. The first is to ! determine which line from the history list should be used during substitution. The second is to select portions of that line for ! inclusion into the current one. The line selected from the history is ! called the "event", and the portions of that line that are acted upon ! are called "words". Various "modifiers" are available to manipulate ! the selected words. The line is broken into words in the same fashion ! that Bash does, so that several words surrounded by quotes are ! considered one word. History expansions are introduced by the ! appearance of the history expansion character, which is `!' by default. ! Only `\' and `'' may be used to escape the history expansion character. Several shell options settable with the `shopt' builtin (*note Bash *************** *** 4448,4452 **** option to the `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. The shell allows control of the various characters used by the --- 4979,4984 ---- option to the `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. This is most useful in conjunction ! with Readline. The shell allows control of the various characters used by the *************** *** 4470,4474 **** `!' Start a history substitution, except when followed by a space, tab, ! the end of the line, <=> or <(>. `!N' --- 5002,5006 ---- `!' Start a history substitution, except when followed by a space, tab, ! the end of the line, `=' or `('. `!N' *************** *** 4503,4507 **** Word designators are used to select desired words from the event. A ! `:' separates the event specification from the word designator. It can be omitted if the word designator begins with a `^', `$', `*', `-', or `%'. Words are numbered from the beginning of the line, with the first --- 5035,5039 ---- Word designators are used to select desired words from the event. A ! `:' separates the event specification from the word designator. It may be omitted if the word designator begins with a `^', `$', `*', `-', or `%'. Words are numbered from the beginning of the line, with the first *************** *** 4699,4704 **** ! Undo the last thing that you did. You can undo all the way back ! to an empty line.  --- 5231,5236 ---- ! Undo the last editing command. You can undo all the way back to an ! empty line.  *************** *** 4721,4725 **** ! Move forward a word. --- 5253,5258 ---- ! Move forward a word, where a word is composed of letters and ! digits. *************** *** 4769,4774 **** different than because the word boundaries differ. ! And, here is how to "yank" the text back into the line. Yanking ! means to copy the most-recently-killed text from the kill buffer. --- 5302,5307 ---- different than because the word boundaries differ. ! Here is how to "yank" the text back into the line. Yanking means to ! copy the most-recently-killed text from the kill buffer. *************** *** 4794,4801 **** The general way to pass numeric arguments to a command is to type ! meta digits before the command. If the first `digit' you type is a ! minus sign (<->), then the sign of the argument will be negative. Once ! you have typed one meta digit to get the argument started, you can type ! the remainder of the digits, and then the command. For example, to give the command an argument of 10, you could type `M-1 0 C-d'. --- 5327,5334 ---- The general way to pass numeric arguments to a command is to type ! meta digits before the command. If the first `digit' typed is a minus ! sign (<->), then the sign of the argument will be negative. Once you ! have typed one meta digit to get the argument started, you can type the ! remainder of the digits, and then the command. For example, to give the command an argument of 10, you could type `M-1 0 C-d'. *************** *** 4812,4833 **** 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 Escape character is ! used to terminate an incremental search. Control-J will also terminate ! the 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. 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 `newline' will terminate the ! search and accept the line, thereby executing the command from the ! history list. 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 part of the contents of the current line.  --- 5345,5366 ---- 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 character is ! used to terminate an incremental search. will also terminate the ! search. 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. To find other ! matching entries in the history list, type or 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 will terminate the search ! and accept the line, thereby executing the command from the history ! list. 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.  *************** *** 4838,4847 **** Although the Readline library comes with a set of `emacs'-like ! keybindings installed by default, it is possible that you would like to ! use a different set of keybindings. You can customize programs that ! use Readline by putting commands in an "inputrc" file in your home ! directory. The name of this file is taken from the value of the shell ! variable `INPUTRC'. If that variable is unset, the default is ! `~/.inputrc'. When a program which uses the Readline library starts up, the init --- 5371,5379 ---- Although the Readline library comes with a set of `emacs'-like ! keybindings installed by default, it is possible to use a different set ! of keybindings. Any user can customize programs that use Readline by ! putting commands in an "inputrc" file in his home directory. The name ! of this file is taken from the value of the shell variable `INPUTRC'. ! If that variable is unset, the default is `~/.inputrc'. When a program which uses the Readline library starts up, the init *************** *** 4872,4883 **** Variable Settings ! You can change the state of a few variables in Readline by using ! the `set' command within the init file. Here is how you would ! specify that you wish to use `vi' line editing commands: set editing-mode vi ! Right now, there are only a few variables which can be set; so ! few, in fact, that we just list them here: `bell-style' --- 5404,5416 ---- Variable Settings ! You can modify the run-time behavior of Readline by altering the ! values of variables in Readline using the `set' command within the ! init file. Here is how to change from the default Emacs-like key ! binding to use `vi' line editing commands: set editing-mode vi ! A great deal of run-time behavior is changeable with the following ! variables. `bell-style' *************** *** 4893,4896 **** --- 5426,5434 ---- `"#"'. + `completion-ignore-case' + If set to `on', Readline performs filename matching and + completion in a case-insensitive fashion. The default value + is `off'. + `completion-query-items' The number of possible completions that determines when the *************** *** 4903,4923 **** `convert-meta' If set to `on', Readline will convert characters with the ! eigth bit set to an ASCII key sequence by stripping the eigth ! bit and prepending an character, converting them to a ! meta-prefixed key sequence. The default value is `on'. `disable-completion' ! If set to `On', readline will inhibit word completion. Completion characters will be inserted into the line as if they had been mapped to `self-insert'. The default is `off'. `editing-mode' ! The `editing-mode' variable controls which editing mode you ! are using. By default, Readline starts up in Emacs editing ! mode, where the keystrokes are most similar to Emacs. This ! variable can be set to either `emacs' or `vi'. `enable-keypad' ! When set to `on', readline will try to enable the application keypad when it is called. Some systems need this to enable the arrow keys. The default is `off'. --- 5441,5461 ---- `convert-meta' If set to `on', Readline will convert characters with the ! eighth bit set to an ASCII key sequence by stripping the ! eighth bit and prepending an character, converting them ! to a meta-prefixed key sequence. The default value is `on'. `disable-completion' ! If set to `On', Readline will inhibit word completion. Completion characters will be inserted into the line as if they had been mapped to `self-insert'. The default is `off'. `editing-mode' ! The `editing-mode' variable controls which default set of key ! bindings is used. By default, Readline starts up in Emacs ! editing mode, where the keystrokes are most similar to Emacs. ! This variable can be set to either `emacs' or `vi'. `enable-keypad' ! When set to `on', Readline will try to enable the application keypad when it is called. Some systems need this to enable the arrow keys. The default is `off'. *************** *** 4929,4933 **** `horizontal-scroll-mode' This variable can be set to either `on' or `off'. Setting it ! to `on' means that the text of the lines that you edit will scroll horizontally on a single screen line when they are longer than the width of the screen, instead of wrapping onto --- 5467,5471 ---- `horizontal-scroll-mode' This variable can be set to either `on' or `off'. Setting it ! to `on' means that the text of the lines being edited will scroll horizontally on a single screen line when they are longer than the width of the screen, instead of wrapping onto *************** *** 4948,4954 **** `mark-modified-lines' ! This variable, when set to `on', says to display an asterisk ! (`*') at the start of history lines which have been modified. ! This variable is `off' by default. `input-meta' --- 5486,5492 ---- `mark-modified-lines' ! This variable, when set to `on', causes Readline to display an ! asterisk (`*') at the start of history lines which have been ! modified. This variable is `off' by default. `input-meta' *************** *** 4964,4967 **** --- 5502,5510 ---- sequence. The default is `off'. + `print-completions-horizontally' + If set to `on', Readline will display completions with matches + sorted horizontally in alphabetical order, rather than down + the screen. The default is `off'. + `show-all-if-ambiguous' This alters the default behavior of the completion functions. *************** *** 4978,4984 **** The syntax for controlling key bindings in the init file is simple. First you have to know the name of the command that you ! want to change. The following pages contain tables of the command ! name, the default keybinding, and a short description of what the ! command does. Once you know the name of the command, simply place the name of --- 5521,5527 ---- The syntax for controlling key bindings in the init file is simple. First you have to know the name of the command that you ! want to change. The following sections contain tables of the ! command name, the default keybinding, if any, and a short ! description of what the command does. Once you know the name of the command, simply place the name of *************** *** 4995,5000 **** Control-o: "> output" ! In the above example, `C-u' is bound to the function ! `universal-argument', and `C-o' is bound to run the macro expressed on the right hand side (that is, to insert the text `> output' into the line). --- 5538,5543 ---- Control-o: "> output" ! In the above example, is bound to the function ! `universal-argument', and is bound to run the macro expressed on the right hand side (that is, to insert the text `> output' into the line). *************** *** 5011,5046 **** "\e[11~": "Function Key 1" ! In the above example, `C-u' is bound to the function `universal-argument' (just as it was in the first example), ! `C-x C-r' is bound to the function `re-read-init-file', and ! `ESC [ 1 1 ~' is bound to insert the text `Function Key 1'. ! The following escape sequences are available when specifying ! key sequences: ! ! `\C-' ! control prefix ! ! `\M-' ! meta prefix ! ! `\e' ! an escape character ! ! `\\' ! backslash ! ! `\"' ! <"> ! ! `\'' ! <'> ! ! When entering the text of a macro, single or double quotes ! should be used to indicate a macro definition. Unquoted text ! is assumed to be a function name. Backslash will quote any ! character in the macro text, including `"' and `''. For ! example, the following binding will make `C-x \' insert a ! single `\' into the line: ! "\C-x\\": "\\"  --- 5554,5627 ---- "\e[11~": "Function Key 1" ! In the above example, is bound to the function `universal-argument' (just as it was in the first example), ! ` ' is bound to the function `re-read-init-file', ! and ` <[> <1> <1> <~>' is bound to insert the text ! `Function Key 1'. ! ! The following GNU Emacs style escape sequences are available when ! specifying key sequences: ! ! `\C-' ! control prefix ! ! `\M-' ! meta prefix ! ! `\e' ! an escape character ! ! `\\' ! backslash ! ! `\"' ! <"> ! ! `\'' ! <'> ! ! In addition to the GNU Emacs style escape sequences, a second set ! of backslash escapes is available: ! ! `\a' ! alert (bell) ! ! `\b' ! backspace ! ! `\d' ! delete ! ! `\f' ! form feed ! ! `\n' ! newline ! ! `\r' ! carriage return ! ! `\t' ! horizontal tab ! ! `\v' ! vertical tab ! ! `\NNN' ! the character whose ASCII code is the octal value NNN (one to ! three digits) ! ! `\xNNN' ! the character whose ASCII code is the hexadecimal value NNN ! (one to three digits) ! ! 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 `''. For example, ! the following binding will make `C-x \' insert a single `\' into ! the line: ! "\C-x\\": "\\"  *************** *** 5053,5057 **** compilation features of the C preprocessor which allows key bindings and variable settings to be performed as the result of tests. There ! are three parser directives used. `$if' --- 5634,5638 ---- 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. `$if' *************** *** 5073,5078 **** bindings, perhaps to bind the key sequences output by the terminal's function keys. The word on the right side of the ! `=' is tested against the full name of the terminal and the ! portion of the terminal name before the first `-'. This allows `sun' to match both `sun' and `sun-cmd', for instance. --- 5654,5659 ---- bindings, perhaps to bind the key sequences output by the terminal's function keys. The word on the right side of the ! `=' is tested against both the full name of the terminal and ! the portion of the terminal name before the first `-'. This allows `sun' to match both `sun' and `sun-cmd', for instance. *************** *** 5091,5096 **** `$endif' ! This command, as you saw in the previous example, terminates an ! `$if' command. `$else' --- 5672,5677 ---- `$endif' ! This command, as seen in the previous example, terminates an `$if' ! command. `$else' *************** *** 5098,5101 **** --- 5679,5687 ---- test fails. + `$include' + This directive takes a single filename as an argument and reads + commands and bindings from that file. + $include /etc/inputrc +  File: bashref.info, Node: Sample Init File, Prev: Conditional Init Constructs, Up: Readline Init File *************** *** 5115,5118 **** --- 5701,5709 ---- # Lines beginning with '#' are comments. # + # First, include any systemwide bindings and variable assignments from + # /etc/Inputrc + $include /etc/Inputrc + + # # Set various bindings for emacs mode. *************** *** 5263,5268 **** Accept the line regardless of where the cursor is. If this line is non-empty, add it to the history list according to the setting of ! the `HISTCONTROL' variable. If this line was a history line, then ! restore the history line to its original state. `previous-history (C-p)' --- 5854,5859 ---- Accept the line regardless of where the cursor is. If this line is non-empty, add it to the history list according to the setting of ! the `HISTCONTROL' and `HISTIGNORE' variables. If this line was a ! history line, then restore the history line to its original state. `previous-history (C-p)' *************** *** 5276,5281 **** `end-of-history (M->)' ! Move to the end of the input history, i.e., the line you are ! entering. `reverse-search-history (C-r)' --- 5867,5872 ---- `end-of-history (M->)' ! Move to the end of the input history, i.e., the line currently ! being entered. `reverse-search-history (C-r)' *************** *** 5301,5305 **** Search forward through the history for the string of characters between the start of the current line and the current cursor ! position (the `point'). This is a non-incremental search. By default, this command is unbound. --- 5892,5896 ---- Search forward through the history for the string of characters between the start of the current line and the current cursor ! position (the POINT). This is a non-incremental search. By default, this command is unbound. *************** *** 5319,5323 **** Insert last argument to the previous command (the last word of the previous history entry). With an argument, behave exactly like ! `yank-nth-arg'.  --- 5910,5916 ---- Insert last argument to the previous command (the last word of the previous history entry). With an argument, behave exactly like ! `yank-nth-arg'. Successive calls to `yank-last-arg' move back ! through the history list, inserting the last argument of each line ! in turn.  *************** *** 5330,5345 **** Delete the character under the cursor. If the cursor is at the beginning of the line, there are no characters in the line, and ! the last character typed was not `C-d', then return `EOF'. `backward-delete-char (Rubout)' ! Delete the character behind the cursor. A numeric arg says to kill ! the characters instead of deleting them. `quoted-insert (C-q, C-v)' ! Add the next character that you type to the line verbatim. This is ! how to insert key sequences like , for example. ! ! `tab-insert (M-TAB)' ! Insert a tab character. `self-insert (a, b, A, 1, !, ...)' --- 5923,5936 ---- Delete the character under the cursor. If the cursor is at the beginning of the line, there are no characters in the line, and ! the last character typed was not bound to `delete-char', then ! return `EOF'. `backward-delete-char (Rubout)' ! Delete the character behind the cursor. A numeric argument means ! to kill the characters instead of deleting them. `quoted-insert (C-q, C-v)' ! Add the next character typed to the line verbatim. This is how to ! insert key sequences like , for example. `self-insert (a, b, A, 1, !, ...)' *************** *** 5350,5354 **** the cursor, moving the cursor forward as well. If the insertion point is at the end of the line, then this transposes the last two ! characters of the line. Negative argumentss don't work. `transpose-words (M-t)' --- 5941,5945 ---- the cursor, moving the cursor forward as well. If the insertion point is at the end of the line, then this transposes the last two ! characters of the line. Negative arguments don't work. `transpose-words (M-t)' *************** *** 5358,5370 **** `upcase-word (M-u)' Uppercase the current (or following) word. With a negative ! argument, do the previous word, but do not move the cursor. `downcase-word (M-l)' Lowercase the current (or following) word. With a negative ! argument, do the previous word, but do not move the cursor. `capitalize-word (M-c)' Capitalize the current (or following) word. With a negative ! argument, do the previous word, but do not move the cursor.  --- 5949,5961 ---- `upcase-word (M-u)' Uppercase the current (or following) word. With a negative ! argument, uppercase the previous word, but do not move the cursor. `downcase-word (M-l)' Lowercase the current (or following) word. With a negative ! argument, lowercase the previous word, but do not move the cursor. `capitalize-word (M-c)' Capitalize the current (or following) word. With a negative ! argument, capitalize the previous word, but do not move the cursor.  *************** *** 5383,5387 **** `unix-line-discard (C-u)' Kill backward from the cursor to the beginning of the current line. ! Save the killed text on the kill-ring. `kill-whole-line ()' --- 5974,5978 ---- `unix-line-discard (C-u)' Kill backward from the cursor to the beginning of the current line. ! The killed text is saved on the kill-ring. `kill-whole-line ()' *************** *** 5408,5425 **** `kill-region ()' Kill the text between the point and the *mark* (saved cursor ! position. This text is referred to as the REGION. By default, this command is unbound. `copy-region-as-kill ()' ! Copy the text in the region to the kill buffer, so you can yank it right away. By default, this command is unbound. `copy-backward-word ()' ! Copy the word before point to the kill buffer. By default, this command is unbound. `copy-forward-word ()' ! Copy the word following point to the kill buffer. By default, ! this command is unbound. `yank (C-y)' --- 5999,6018 ---- `kill-region ()' Kill the text between the point and the *mark* (saved cursor ! position). This text is referred to as the REGION. By default, this command is unbound. `copy-region-as-kill ()' ! Copy the text in the region to the kill buffer, so it can be yanked right away. By default, this command is unbound. `copy-backward-word ()' ! Copy the word before point to the kill buffer. The word ! boundaries are the same as `backward-word'. By default, this command is unbound. `copy-forward-word ()' ! Copy the word following point to the kill buffer. The word ! boundaries are the same as `forward-word'. By default, this ! command is unbound. `yank (C-y)' *************** *** 5464,5469 **** application-specific. Generally, if you are typing a filename argument, you can do filename completion; if you are typing a ! command, you can do command completion, if you are typing in a ! symbol to GDB, you can do symbol name completion, if you are typing in a variable to Bash, you can do variable name completion, and so on. Bash attempts completion treating the text as a --- 6057,6062 ---- application-specific. Generally, if you are typing a filename argument, you can do filename completion; if you are typing a ! command, you can do command completion; if you are typing in a ! symbol to GDB, you can do symbol name completion; if you are typing in a variable to Bash, you can do variable name completion, and so on. Bash attempts completion treating the text as a *************** *** 5480,5483 **** --- 6073,6087 ---- been generated by `possible-completions'. + `menu-complete ()' + Similar to `complete', but replaces the word to be completed with + a single match from the list of possible completions. Repeated + execution of `menu-complete' steps through the list of possible + completions, inserting each match in turn. At the end of the list + of completions, the bell is rung and the original text is restored. + An argument of N moves N 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 `TAB', but is unbound by + default. + `complete-filename (M-/)' Attempt filename completion on the text before point. *************** *** 5514,5519 **** 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, builtins, and ! finally executable filenames, in that order. `possible-command-completions (C-x !)' --- 6118,6123 ---- 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. `possible-command-completions (C-x !)' *************** *** 5567,5573 **** `prefix-meta (ESC)' ! Make the next character that you type be metafied. This is for ! people without a meta key. Typing `ESC f' is equivalent to typing ! `M-f'. `undo (C-_, C-x C-u)' --- 6171,6176 ---- `prefix-meta (ESC)' ! Make the next character typed be metafied. This is for keyboards ! without a meta key. Typing `ESC f' is equivalent to typing `M-f'. `undo (C-_, C-x C-u)' *************** *** 5575,5580 **** `revert-line (M-r)' ! Undo all changes made to this line. This is like typing the `undo' ! command enough times to get back to the beginning. `tilde-expand (M-~)' --- 6178,6183 ---- `revert-line (M-r)' ! Undo all changes made to this line. This is like executing the ! `undo' command enough times to get back to the beginning. `tilde-expand (M-~)' *************** *** 5607,5611 **** `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 INPUTRC --- 6210,6214 ---- `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 INPUTRC *************** *** 5614,5623 **** `dump-variables ()' Print all of the settable 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 INPUTRC file. This command is unbound by default. `dump-macros ()' ! Print all of the readline key sequences bound to macros and the strings they ouput. If a numeric argument is supplied, the output is formatted in such a way that it can be made part of an INPUTRC --- 6217,6226 ---- `dump-variables ()' Print all of the settable 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 INPUTRC file. This command is unbound by default. `dump-macros ()' ! Print all of the Readline key sequences bound to macros and the strings they ouput. If a numeric argument is supplied, the output is formatted in such a way that it can be made part of an INPUTRC *************** *** 5631,5636 **** `glob-list-expansions (C-x g)' The list of expansions that would have been generated by ! `glob-expand-word' is inserted into the line, replacing the word ! before point. `display-shell-version (C-x C-v)' --- 6234,6238 ---- `glob-list-expansions (C-x g)' The list of expansions that would have been generated by ! `glob-expand-word' is displayed, and the line is redrawn. `display-shell-version (C-x C-v)' *************** *** 5638,5652 **** `shell-expand-line (M-C-e)' ! Expand the line the way the shell does when it reads it. This ! performs alias and history expansion as well as all of the shell ! word expansions. `history-expand-line (M-^)' Perform history expansion on the current line. ! `alias-expand-line' Perform alias expansion on the current line (*note Aliases::.). ! `history-and-alias-expand-line' Perform history and alias expansion on the current line. --- 6240,6258 ---- `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 ! (*note Shell Expansions::.). `history-expand-line (M-^)' Perform history expansion on the current line. ! `magic-space ()' ! Perform history expansion on the current line and insert a space ! (*note History Interaction::.). ! ! `alias-expand-line ()' Perform alias expansion on the current line (*note Aliases::.). ! `history-and-alias-expand-line ()' Perform history and alias expansion on the current line. *************** *** 5693,5697 **** various supported platforms. The distribution supports nearly every version of Unix (and, someday, GNU). Other independent ports exist for ! OS/2, Windows 95, and Windows NT. * Menu: --- 6299,6303 ---- various supported platforms. The distribution supports nearly every version of Unix (and, someday, GNU). Other independent ports exist for ! MS-DOS, OS/2, Windows 95, and Windows NT. * Menu: *************** *** 5739,5746 **** remove or edit it. ! If you need to do unusual things to compile the package, please try ! to figure out how `configure' could check whether or not to do them, ! and mail diffs or instructions to `bash-maintainers@prep.ai.mit.edu' so ! they can be considered for the next release. The file `configure.in' is used to create `configure' by a program --- 6345,6352 ---- remove or edit it. ! If you need to do unusual things to compile Bash, please try to ! figure out how `configure' could check whether or not to do them, and ! mail diffs or instructions to so they can be ! considered for the next release. The file `configure.in' is used to create `configure' by a program *************** *** 5848,5853 **** You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you ! give `configure' the option `--exec-prefix=PATH', the package will use ! `PATH' as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. --- 6454,6459 ---- You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you ! give `configure' the option `--exec-prefix=PATH', `make install' will ! use `PATH' as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. *************** *** 5859,5865 **** There may be some features `configure' can not figure out ! automatically, but needs to determine by the type of host the package ! will run on. Usually `configure' can figure that out, but if it prints ! a message saying it can not guess the host type, give it the `--host=TYPE' option. `TYPE' can either be a short name for the system type, such as `sun4', or a canonical name with three fields: --- 6465,6471 ---- There may be some features `configure' can not figure out ! automatically, but needs to determine by the type of host Bash will run ! on. Usually `configure' can figure that out, but if it prints a ! message saying it can not guess the host type, give it the `--host=TYPE' option. `TYPE' can either be a short name for the system type, such as `sun4', or a canonical name with three fields: *************** *** 5923,5932 **** The Bash `configure' has a number of `--enable-FEATURE' options, ! where FEATURE indicates an optional part of the package. There are ! also several `--with-PACKAGE' options, where PACKAGE is something like ! `gnu-malloc' or `purify' (for the Purify memory allocation checker). To ! turn off the default use of a package, use `--without-PACKAGE'. To ! configure Bash without a feature that is enabled by default, use ! `--disable-FEATURE'. Here is a complete list of the `--enable-' and `--with-' options --- 6529,6537 ---- The Bash `configure' has a number of `--enable-FEATURE' options, ! where FEATURE indicates an optional part of Bash. There are also ! several `--with-PACKAGE' options, where PACKAGE is something like ! `gnu-malloc' or `purify'. To turn off the default use of a package, use ! `--without-PACKAGE'. To configure Bash without a feature that is ! enabled by default, use `--disable-FEATURE'. Here is a complete list of the `--enable-' and `--with-' options *************** *** 5943,5948 **** `--with-glibc-malloc' Use the GNU libc version of `malloc' in `lib/malloc/gmalloc.c'. ! This is somewhat slower than the default `malloc', but wastes ! considerably less space. `--with-gnu-malloc' --- 6548,6556 ---- `--with-glibc-malloc' Use the GNU libc version of `malloc' in `lib/malloc/gmalloc.c'. ! This is not the version of `malloc' that appears in glibc version ! 2, but a modified version of the `malloc' from glibc version 1. ! This is somewhat slower than the default `malloc', but wastes less ! space on a per-allocation basis, and will return memory to the ! operating system under some circumstances. `--with-gnu-malloc' *************** *** 5950,5957 **** not the same `malloc' that appears in GNU libc, but an older version derived from the 4.2 BSD `malloc'. This `malloc' is very ! fast, but wastes a lot of space. This option is enabled by ! default. The `NOTES' file contains a list of systems for which ! this should be turned off, and `configure' disables this option ! automatically for a number of systems. `--with-purify' --- 6558,6565 ---- not the same `malloc' that appears in GNU libc, but an older version derived from the 4.2 BSD `malloc'. This `malloc' is very ! fast, but wastes some space on each allocation. This option is ! enabled by default. The `NOTES' file contains a list of systems ! for which this should be turned off, and `configure' disables this ! option automatically for a number of systems. `--with-purify' *************** *** 5963,5969 **** historical Bourne shell. ! The `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 `enable-FEATURE'. All of the following options except for `disabled-builtins' and --- 6571,6588 ---- historical Bourne shell. ! There are several `--enable-' options that alter how Bash is ! compiled and linked, rather than changing run-time features. ! ! `--enable-profiling' ! This builds a Bash binary that produces profiling information to be ! processed by `gprof' each time it is executed. ! ! `--enable-static-link' ! This causes Bash to be linked statically, if `gcc' is being used. ! This could be used to build a version to use as root's shell. ! ! The `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 `enable-FEATURE'. All of the following options except for `disabled-builtins' and *************** *** 5973,5986 **** `--enable-alias' Allow alias expansion and include the `alias' and `unalias' ! builtins. `--enable-array-variables' ! Include support for one-dimensional array shell variables. `--enable-bang-history' ! Include support for `csh'-like history substitution. `--enable-brace-expansion' Include `csh'-like brace expansion ( `b{a,b}c' ==> `bac bbc' ). `--enable-command-timing' --- 6592,6608 ---- `--enable-alias' Allow alias expansion and include the `alias' and `unalias' ! builtins (*note Aliases::.). `--enable-array-variables' ! Include support for one-dimensional array shell variables (*note ! Arrays::.). `--enable-bang-history' ! Include support for `csh'-like history substitution (*note History ! Interaction::.). `--enable-brace-expansion' Include `csh'-like brace expansion ( `b{a,b}c' ==> `bac bbc' ). + See *Note Brace Expansion::, for a complete description. `--enable-command-timing' *************** *** 5990,5996 **** be timed. `--enable-directory-stack' Include support for a `csh'-like directory stack and the `pushd', ! `popd', and `dirs' builtins. `--enable-disabled-builtins' --- 6612,6622 ---- be timed. + `--enable-cond-command' + Include support for the `[[' conditional command (*note + Conditional Constructs::.). + `--enable-directory-stack' Include support for a `csh'-like directory stack and the `pushd', ! `popd', and `dirs' builtins (*note The Directory Stack::.). `--enable-disabled-builtins' *************** *** 6001,6005 **** `--enable-dparen-arithmetic' ! Include support for the `ksh' `((...))' command. `--enable-help-builtin' --- 6627,6636 ---- `--enable-dparen-arithmetic' ! Include support for the `((...))' command (*note Conditional ! Constructs::.). ! ! `--enable-extended-glob' ! Include support for the extended pattern matching features ! described above under *Note Pattern Matching::. `--enable-help-builtin' *************** *** 6012,6029 **** `--enable-job-control' ! This enables job control features, if the OS supports them. `--enable-process-substitution' This enables process substitution (*note Process Substitution::.) ! if the OS provides the necessary support. `--enable-prompt-string-decoding' Turn on the interpretation of a number of backslash-escaped characters in the `$PS1', `$PS2', `$PS3', and `$PS4' prompt ! strings. `--enable-readline' Include support for command-line editing and history with the Bash ! version of the Readline library. `--enable-restricted' --- 6643,6662 ---- `--enable-job-control' ! This enables the job control features (*note Job Control::.), if ! the operating system supports them. `--enable-process-substitution' This enables process substitution (*note Process Substitution::.) ! if the operating system provides the necessary support. `--enable-prompt-string-decoding' Turn on the interpretation of a number of backslash-escaped characters in the `$PS1', `$PS2', `$PS3', and `$PS4' prompt ! strings. See *Note Printing a Prompt::, for a complete list of ! prompt string escape sequences. `--enable-readline' Include support for command-line editing and history with the Bash ! version of the Readline library (*note Command Line Editing::.). `--enable-restricted' *************** *** 6033,6038 **** `--enable-select' ! Include the `ksh' `select' builtin, which allows the generation of ! simple menus. `--enable-usg-echo-default' --- 6666,6671 ---- `--enable-select' ! Include the `select' builtin, which allows the generation of simple ! menus (*note Conditional Constructs::.). `--enable-usg-echo-default' *************** *** 6060,6065 **** `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 `bug-bash@prep.ai.MIT.Edu' or posted to the ! Usenet newsgroup `gnu.bash.bug'. All bug reports should include: --- 6693,6698 ---- `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 or posted to the Usenet ! newsgroup `gnu.bash.bug'. All bug reports should include: *************** *** 6078,6083 **** it provides for filing a bug report. ! Please send all reports concerning this manual to ! `chet@ins.CWRU.Edu'.  --- 6711,6715 ---- it provides for filing a bug report. ! Please send all reports concerning this manual to .  *************** *** 6101,6105 **** * continue: Bourne Shell Builtins. * declare: Bash Builtins. ! * dirs: C Shell Builtins. * disown: Job Control Builtins. * echo: Bash Builtins. --- 6733,6737 ---- * continue: Bourne Shell Builtins. * declare: Bash Builtins. ! * dirs: The Directory Stack. * disown: Job Control Builtins. * echo: Bash Builtins. *************** *** 6109,6127 **** * exit: Bourne Shell Builtins. * export: Bourne Shell Builtins. ! * fc: Korn Shell Builtins. * fg: Job Control Builtins. * getopts: Bourne Shell Builtins. * hash: Bourne Shell Builtins. * help: Bash Builtins. ! * history: C Shell Builtins. * jobs: Job Control Builtins. * kill: Job Control Builtins. ! * let <1>: Arithmetic Builtins. ! * let: Korn Shell Builtins. * local: Bash Builtins. ! * logout <1>: Bash Builtins. ! * logout: C Shell Builtins. ! * popd: C Shell Builtins. ! * pushd: C Shell Builtins. * pwd: Bourne Shell Builtins. * read: Bash Builtins. --- 6741,6758 ---- * exit: Bourne Shell Builtins. * export: Bourne Shell Builtins. ! * fc: Bash History Builtins. * fg: Job Control Builtins. * getopts: Bourne Shell Builtins. * hash: Bourne Shell Builtins. * help: Bash Builtins. ! * history: Bash History Builtins. * jobs: Job Control Builtins. * kill: Job Control Builtins. ! * let: Bash Builtins. * local: Bash Builtins. ! * logout: Bash Builtins. ! * popd: The Directory Stack. ! * printf: Bash Builtins. ! * pushd: The Directory Stack. * pwd: Bourne Shell Builtins. * read: Bash Builtins. *************** *** 6131,6135 **** * shift: Bourne Shell Builtins. * shopt: Bash Builtins. ! * source: C Shell Builtins. * suspend: Job Control Builtins. * test: Bourne Shell Builtins. --- 6762,6766 ---- * shift: Bourne Shell Builtins. * shopt: Bash Builtins. ! * source: Bash Builtins. * suspend: Job Control Builtins. * test: Bourne Shell Builtins. *************** *** 6137,6141 **** * trap: Bourne Shell Builtins. * type: Bash Builtins. ! * typeset: Korn Shell Builtins. * ulimit: Bash Builtins. * umask: Bourne Shell Builtins. --- 6768,6772 ---- * trap: Bourne Shell Builtins. * type: Bash Builtins. ! * typeset: Bash Builtins. * ulimit: Bash Builtins. * umask: Bourne Shell Builtins. *************** *** 6153,6156 **** --- 6784,6789 ---- * !: Pipelines. + * [[: Conditional Constructs. + * ]]: Conditional Constructs. * case: Conditional Constructs. * do: Looping Constructs. *************** *** 6164,6168 **** * if: Conditional Constructs. * in: Conditional Constructs. ! * select: Korn Shell Constructs. * then: Conditional Constructs. * time: Pipelines. --- 6797,6801 ---- * if: Conditional Constructs. * in: Conditional Constructs. ! * select: Conditional Constructs. * then: Conditional Constructs. * time: Pipelines. *************** *** 6205,6209 **** * EUID: Bash Variables. * expand-tilde: Readline Init File Syntax. ! * FCEDIT: Korn Shell Variables. * FIGNORE: Bash Variables. * GLOBIGNORE: Bash Variables. --- 6838,6842 ---- * EUID: Bash Variables. * expand-tilde: Readline Init File Syntax. ! * FCEDIT: Bash Variables. * FIGNORE: Bash Variables. * GLOBIGNORE: Bash Variables. *************** *** 6222,6227 **** * HOSTTYPE: Bash Variables. * IFS: Bourne Shell Variables. ! * IGNOREEOF <1>: Bash Variables. ! * IGNOREEOF: C Shell Variables. * input-meta: Readline Init File Syntax. * INPUTRC: Bash Variables. --- 6855,6859 ---- * HOSTTYPE: Bash Variables. * IFS: Bourne Shell Variables. ! * IGNOREEOF: Bash Variables. * input-meta: Readline Init File Syntax. * INPUTRC: Bash Variables. *************** *** 6230,6235 **** * LC_ALL: Bash Variables. * LC_COLLATE: Bash Variables. * LC_MESSAGES: Bash Variables. ! * LINENO: Korn Shell Variables. * MACHTYPE: Bash Variables. * MAIL: Bourne Shell Variables. --- 6862,6868 ---- * LC_ALL: Bash Variables. * LC_COLLATE: Bash Variables. + * LC_CTYPE: Bash Variables. * LC_MESSAGES: Bash Variables. ! * LINENO: Bash Variables. * MACHTYPE: Bash Variables. * MAIL: Bourne Shell Variables. *************** *** 6238,6242 **** * mark-modified-lines: Readline Init File Syntax. * meta-flag: Readline Init File Syntax. ! * OLDPWD: Korn Shell Variables. * OPTARG: Bourne Shell Variables. * OPTERR: Bash Variables. --- 6871,6875 ---- * mark-modified-lines: Readline Init File Syntax. * meta-flag: Readline Init File Syntax. ! * OLDPWD: Bash Variables. * OPTARG: Bourne Shell Variables. * OPTERR: Bash Variables. *************** *** 6250,6264 **** * PS1: Bourne Shell Variables. * PS2: Bourne Shell Variables. ! * PS3: Korn Shell Variables. ! * PS4: Korn Shell Variables. ! * PWD: Korn Shell Variables. ! * RANDOM: Korn Shell Variables. ! * REPLY: Korn Shell Variables. ! * SECONDS: Korn Shell Variables. * SHELLOPTS: Bash Variables. * SHLVL: Bash Variables. * show-all-if-ambiguous: Readline Init File Syntax. * TIMEFORMAT: Bash Variables. ! * TMOUT: Korn Shell Variables. * UID: Bash Variables. * visible-stats: Readline Init File Syntax. --- 6883,6897 ---- * PS1: Bourne Shell Variables. * PS2: Bourne Shell Variables. ! * PS3: Bash Variables. ! * PS4: Bash Variables. ! * PWD: Bash Variables. ! * RANDOM: Bash Variables. ! * REPLY: Bash Variables. ! * SECONDS: Bash Variables. * SHELLOPTS: Bash Variables. * SHLVL: Bash Variables. * show-all-if-ambiguous: Readline Init File Syntax. * TIMEFORMAT: Bash Variables. ! * TMOUT: Bash Variables. * UID: Bash Variables. * visible-stats: Readline Init File Syntax. *************** *** 6313,6316 **** --- 6946,6950 ---- * kill-whole-line (): Commands For Killing. * kill-word (M-d): Commands For Killing. + * menu-complete (): Commands For Completion. * next-history (C-n): Commands For History. * non-incremental-forward-search-history (M-n): Commands For History. *************** *** 6327,6331 **** * set-mark (C-@): Miscellaneous Commands. * start-kbd-macro (C-x (): Keyboard Macros. - * tab-insert (M-TAB): Commands For Text. * tilde-expand (M-~): Miscellaneous Commands. * transpose-chars (C-t): Commands For Text. --- 6961,6964 ---- *************** *** 6350,6354 **** * alias expansion: Aliases. ! * arithmetic evaluation: Arithmetic Evaluation. * arithmetic expansion: Arithmetic Expansion. * arithmetic, shell: Shell Arithmetic. --- 6983,6987 ---- * alias expansion: Aliases. ! * arithmetic evaluation: Shell Arithmetic. * arithmetic expansion: Arithmetic Expansion. * arithmetic, shell: Shell Arithmetic. *************** *** 6362,6365 **** --- 6995,6999 ---- * command editing: Readline Bare Essentials. * command execution: Command Search and Execution. + * command expansion: Simple Command Expansion. * command history: Bash History Facilities. * command search: Command Search and Execution. *************** *** 6371,6384 **** * commands, looping: Looping Constructs. * commands, pipelines: Pipelines. * commands, simple: Simple Commands. * comments, shell: Comments. * configuration: Basic Installation. * control operator: Definitions. * editing command lines: Readline Bare Essentials. * environment: Environment. ! * evaluation, arithmetic: Arithmetic Evaluation. * event designators: Event Designators. ! * exit status <1>: Definitions. ! * exit status: Exit Status. * expansion: Shell Expansions. * expansion, arithmetic: Arithmetic Expansion. --- 7005,7021 ---- * commands, looping: Looping Constructs. * commands, pipelines: Pipelines. + * commands, shell: Shell Commands. * commands, simple: Simple Commands. * comments, shell: Comments. * configuration: Basic Installation. * control operator: Definitions. + * directory stack: The Directory Stack. * editing command lines: Readline Bare Essentials. * environment: Environment. ! * evaluation, arithmetic: Shell Arithmetic. * event designators: Event Designators. ! * execution environment: Command Execution Environment. ! * exit status <1>: Exit Status. ! * exit status: Definitions. * expansion: Shell Expansions. * expansion, arithmetic: Arithmetic Expansion. *************** *** 6388,6392 **** * expansion, pathname: Filename Expansion. * expansion, tilde: Tilde Expansion. ! * expressions, arithmetic: Arithmetic Evaluation. * expressions, conditional: Bash Conditional Expressions. * field: Definitions. --- 7025,7029 ---- * expansion, pathname: Filename Expansion. * expansion, tilde: Tilde Expansion. ! * expressions, arithmetic: Shell Arithmetic. * expressions, conditional: Bash Conditional Expressions. * field: Definitions. *************** *** 6395,6398 **** --- 7032,7036 ---- * foreground: Job Control Basics. * functions, shell: Shell Functions. + * history builtins: Bash History Builtins. * history events: Event Designators. * history expansion: History Interaction. *************** *** 6411,6414 **** --- 7049,7053 ---- * killing text: Readline Killing Commands. * localization: Locale Translation. + * matching, pattern: Pattern Matching. * metacharacter: Definitions. * name: Definitions. *************** *** 6420,6423 **** --- 7059,7063 ---- * parameters, special: Special Parameters. * pathname expansion: Filename Expansion. + * pattern matching: Pattern Matching. * pipeline: Pipelines. * POSIX: Definitions. *************** *** 6434,6437 **** --- 7074,7078 ---- * restricted shell: The Restricted Shell. * return status: Definitions. + * shell arithmetic: Shell Arithmetic. * shell function: Shell Functions. * shell script: Shell Scripts. *************** *** 6452,6573 ****  Tag Table: ! Node: Top1179 ! Node: Introduction3283 ! Node: What is Bash?3508 ! Node: What is a shell?4592 ! Node: Definitions6473 ! Node: Basic Shell Features9134 ! Node: Shell Syntax10655 ! Node: Shell Operation10945 ! Node: Quoting12179 ! Node: Escape Character13214 ! Node: Single Quotes13645 ! Node: Double Quotes13974 ! Node: ANSI-C Quoting14670 ! Node: Locale Translation15402 ! Node: Comments15823 ! Node: Simple Commands16347 ! Node: Pipelines16936 ! Node: Lists18007 ! Node: Looping Constructs19282 ! Node: Conditional Constructs20459 ! Node: Command Grouping22526 ! Node: Shell Functions23912 ! Node: Shell Parameters25685 ! Node: Positional Parameters27008 ! Node: Special Parameters27702 ! Node: Shell Expansions30268 ! Node: Shell Parameter Expansion32272 ! Node: Command Substitution38280 ! Node: Process Substitution39280 ! Node: Word Splitting40186 ! Node: Filename Expansion41638 ! Node: Quote Removal44004 ! Node: Redirections44290 ! Node: Executing Commands50031 ! Node: Command Search and Execution50486 ! Node: Environment52220 ! Node: Exit Status53856 ! Node: Signals54873 ! Node: Shell Scripts56084 ! Node: Bourne Shell Features57953 ! Node: Bourne Shell Builtins58623 ! Node: Bourne Shell Variables66977 ! Node: Other Bourne Shell Features68514 ! Node: Major Differences From The Bourne Shell69271 ! Node: Csh Features79631 ! Node: Brace Expansion80549 ! Node: Tilde Expansion82104 ! Node: C Shell Builtins82736 ! Node: C Shell Variables87292 ! Node: Korn Shell Features87700 ! Node: Korn Shell Constructs88428 ! Node: Korn Shell Builtins90143 ! Node: Korn Shell Variables92301 ! Node: Aliases93860 ! Node: Alias Builtins96326 ! Node: Bash Features96942 ! Node: Invoking Bash97933 ! Node: Bash Startup Files101798 ! Node: Is This Shell Interactive?105373 ! Node: Bash Builtins106356 ! Node: The Set Builtin122211 ! Node: Bash Conditional Expressions127586 ! Node: Bash Variables132237 ! Node: Shell Arithmetic142271 ! Node: Arithmetic Evaluation142739 ! Node: Arithmetic Expansion144769 ! Node: Arithmetic Builtins145573 ! Node: Arrays146044 ! Node: Printing a Prompt149071 ! Node: The Restricted Shell150669 ! Node: Bash POSIX Mode151899 ! Node: Job Control155583 ! Node: Job Control Basics156048 ! Node: Job Control Builtins160191 ! Node: Job Control Variables163114 ! Node: Using History Interactively164261 ! Node: Bash History Facilities164850 ! Node: History Interaction167248 ! Node: Event Designators169810 ! Node: Word Designators170737 ! Node: Modifiers171986 ! Node: Command Line Editing173303 ! Node: Introduction and Notation173963 ! Node: Readline Interaction175001 ! Node: Readline Bare Essentials176193 ! Node: Readline Movement Commands177736 ! Node: Readline Killing Commands178648 ! Node: Readline Arguments180368 ! Node: Searching181345 ! Node: Readline Init File182981 ! Node: Readline Init File Syntax184037 ! Node: Conditional Init Constructs191820 ! Node: Sample Init File194101 ! Node: Bindable Readline Commands197134 ! Node: Commands For Moving197884 ! Node: Commands For History198731 ! Node: Commands For Text201404 ! Node: Commands For Killing203148 ! Node: Numeric Arguments205174 ! Node: Commands For Completion206300 ! Node: Keyboard Macros209262 ! Node: Miscellaneous Commands209820 ! Node: Readline vi Mode214036 ! Node: Installing Bash214914 ! Node: Basic Installation215983 ! Node: Compilers and Options218908 ! Node: Compiling For Multiple Architectures219642 ! Node: Installation Names221299 ! Node: Specifying the System Type222021 ! Node: Sharing Defaults222732 ! Node: Operation Controls223397 ! Node: Optional Features224302 ! Node: Reporting Bugs229185 ! Node: Builtin Index230265 ! Node: Reserved Word Index233732 ! Node: Variable Index235059 ! Node: Function Index240327 ! Node: Concept Index244750  End Tag Table --- 7093,7211 ----  Tag Table: ! Node: Top1197 ! Node: Introduction3153 ! Node: What is Bash?3378 ! Node: What is a shell?4472 ! Node: Definitions6494 ! Node: Basic Shell Features9155 ! Node: Shell Syntax10378 ! Node: Shell Operation10667 ! Node: Quoting11961 ! Node: Escape Character12986 ! Node: Single Quotes13458 ! Node: Double Quotes13787 ! Node: ANSI-C Quoting14685 ! Node: Locale Translation15554 ! Node: Comments15975 ! Node: Shell Commands16589 ! Node: Simple Commands17100 ! Node: Pipelines17659 ! Node: Lists19186 ! Node: Looping Constructs20641 ! Node: Conditional Constructs22246 ! Node: Command Grouping28184 ! Node: Shell Functions29561 ! Node: Shell Parameters31525 ! Node: Positional Parameters32851 ! Node: Special Parameters33600 ! Node: Shell Expansions36221 ! Node: Brace Expansion38144 ! Node: Tilde Expansion39705 ! Node: Shell Parameter Expansion42037 ! Node: Command Substitution48379 ! Node: Arithmetic Expansion49653 ! Node: Process Substitution50498 ! Node: Word Splitting51392 ! Node: Filename Expansion52844 ! Node: Pattern Matching54808 ! Node: Quote Removal57197 ! Node: Redirections57483 ! Node: Executing Commands63553 ! Node: Simple Command Expansion64220 ! Node: Command Search and Execution66143 ! Node: Command Execution Environment68146 ! Node: Environment70600 ! Node: Exit Status72257 ! Node: Signals73454 ! Node: Shell Scripts75349 ! Node: Bourne Shell Features77385 ! Node: Bourne Shell Builtins78115 ! Node: Bourne Shell Variables92056 ! Node: Other Bourne Shell Features93761 ! Node: Major Differences From The Bourne Shell94504 ! Node: Bash Features106693 ! Node: Invoking Bash107796 ! Node: Bash Startup Files111981 ! Node: Is This Shell Interactive?115540 ! Node: Bash Builtins116511 ! Node: The Set Builtin137351 ! Node: Bash Conditional Expressions143960 ! Node: Bash Variables147033 ! Node: Shell Arithmetic159463 ! Node: Aliases161511 ! Node: Alias Builtins164086 ! Node: Arrays164702 ! Node: The Directory Stack167723 ! Node: Printing a Prompt171073 ! Node: The Restricted Shell172736 ! Node: Bash POSIX Mode174072 ! Node: Job Control178233 ! Node: Job Control Basics178699 ! Node: Job Control Builtins182898 ! Node: Job Control Variables187190 ! Node: Using History Interactively188340 ! Node: Bash History Facilities189019 ! Node: Bash History Builtins191360 ! Node: History Interaction194728 ! Node: Event Designators197280 ! Node: Word Designators198207 ! Node: Modifiers199456 ! Node: Command Line Editing200773 ! Node: Introduction and Notation201433 ! Node: Readline Interaction202471 ! Node: Readline Bare Essentials203663 ! Node: Readline Movement Commands205203 ! Node: Readline Killing Commands206168 ! Node: Readline Arguments207883 ! Node: Searching208857 ! Node: Readline Init File210475 ! Node: Readline Init File Syntax211514 ! Node: Conditional Init Constructs220379 ! Node: Sample Init File222817 ! Node: Bindable Readline Commands225986 ! Node: Commands For Moving226736 ! Node: Commands For History227583 ! Node: Commands For Text230412 ! Node: Commands For Killing232146 ! Node: Numeric Arguments234295 ! Node: Commands For Completion235421 ! Node: Keyboard Macros238991 ! Node: Miscellaneous Commands239549 ! Node: Readline vi Mode243869 ! Node: Installing Bash244747 ! Node: Basic Installation245824 ! Node: Compilers and Options248734 ! Node: Compiling For Multiple Architectures249468 ! Node: Installation Names251125 ! Node: Specifying the System Type251850 ! Node: Sharing Defaults252554 ! Node: Operation Controls253219 ! Node: Optional Features254124 ! Node: Reporting Bugs260319 ! Node: Builtin Index261390 ! Node: Reserved Word Index264793 ! Node: Variable Index266251 ! Node: Function Index271456 ! Node: Concept Index275885  End Tag Table diff -Nrc2 bash-2.01.1/doc/bashref.texi bash-2.02/doc/bashref.texi *** bash-2.01.1/doc/bashref.texi Mon Jul 21 13:57:04 1997 --- bash-2.02/doc/bashref.texi Wed Apr 1 13:17:06 1998 *************** *** 6,16 **** @ignore ! last change: Mon May 19 12:55:22 EDT 1997 @end ignore ! @set EDITION 2.0 ! @set VERSION 2.01 ! @set UPDATED 19 May 1997 ! @set UPDATE-MONTH May 1997 @iftex --- 6,16 ---- @ignore ! last change: Wed Mar 25 11:36:48 EST 1998 @end ignore ! @set EDITION 2.2 ! @set VERSION 2.02 ! @set UPDATED 1 April 1998 ! @set UPDATE-MONTH April 1998 @iftex *************** *** 23,32 **** @set BashFeatures @dircategory Utilities @direntry ! * Bash: (bash). GNU Bourne-Again SHell @end direntry - @ifinfo @format This text is a brief description of the features that are present in --- 23,32 ---- @set BashFeatures + @ifinfo @dircategory Utilities @direntry ! * Bash: (bash). The GNU Bourne-Again SHell. @end direntry @format This text is a brief description of the features that are present in *************** *** 37,41 **** for @code{Bash}, Version @value{VERSION}. ! Copyright (C) 1991, 1993, 1996 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of --- 37,41 ---- for @code{Bash}, Version @value{VERSION}. ! Copyright (C) 1991, 1993, 1996, 1997 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of *************** *** 58,62 **** into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved ! by the Foundation. @end format @end ifinfo --- 58,62 ---- into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved ! by the Free Software Foundation. @end format @end ifinfo *************** *** 126,135 **** Bourne shell. - * Csh Features:: Features originally found in the - Berkeley C-Shell. - - * Korn Shell Features:: Features originally found in the Korn - Shell. - * Bash Features:: Features found only in Bash. --- 126,129 ---- *************** *** 182,189 **** Bash is an @code{sh}-compatible shell that incorporates useful features from the Korn shell @code{ksh} and the C shell @code{csh}. ! It is ultimately intended to be a ! conformant implementation of the @sc{IEEE} @sc{POSIX} Shell and Tools ! specification (@sc{IEEE} Working Group 1003.2). It offers functional ! improvements over @code{sh} for both interactive and programming use. While the @sc{GNU} operating system will include a version --- 176,183 ---- Bash is an @code{sh}-compatible shell that 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 specification (@sc{IEEE} Working Group 1003.2). ! It offers functional improvements over @code{sh} for both interactive and ! programming use. While the @sc{GNU} operating system will include a version *************** *** 191,195 **** 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{OS/2} and Windows @sc{NT}. @node What is a shell? --- 185,190 ---- 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}, ! Windows @sc{95}, and Windows @sc{NT}. @node What is a shell? *************** *** 200,205 **** provides the user interface to the rich set of Unix utilities, and a programming language, allowing these utilitites to be ! combined. The shell reads commands either from a terminal or a ! file. Files containing commands can be created, and become commands themselves. These new commands have the same status as system commands in directories like @file{/bin}, allowing users --- 195,199 ---- provides the user interface to the rich set of Unix utilities, and a programming language, allowing these utilitites 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 like @file{/bin}, allowing users *************** *** 207,211 **** A shell allows execution of Unix commands, both synchronously and ! asynchronously. The @dfn{redirection} constructs permit fine-grained control of the input and output of those commands, and the shell allows control over the contents of their --- 201,209 ---- A shell allows execution of Unix 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, and the shell allows control over the contents of their *************** *** 352,356 **** 1003.2 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, --- 350,354 ---- 1003.2 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, *************** *** 360,370 **** @menu * Shell Syntax:: What your input means to the shell. ! * Simple Commands:: The most common type of command. ! * Pipelines:: Connecting the input and output of several ! commands. ! * Lists:: How to execute commands sequentially. ! * Looping Constructs:: Shell commands for iterative action. ! * Conditional Constructs:: Shell commands for conditional execution. ! * Command Grouping:: Ways to group commands. * Shell Functions:: Grouping commands by name. * Shell Parameters:: Special shell variables. --- 358,362 ---- @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:: Special shell variables. *************** *** 401,410 **** @item Breaks the input into words and operators, obeying the quoting rules ! described in @ref{Quoting}. Tokens are separated by @code{metacharacters}. Alias expansion is performed by this step (@pxref{Aliases}). @item ! Parses the tokens into simple and compound commands. @item --- 393,403 ---- @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 *************** *** 422,426 **** @item Optionally waits for the command to complete and collects its exit ! status. @end enumerate --- 415,419 ---- @item Optionally waits for the command to complete and collects its exit ! status (@pxref{Exit Status}). @end enumerate *************** *** 447,453 **** parameter expansion. ! Each of the shell @code{metacharacters} (@pxref{Definitions}) ! has special meaning to the shell and must be quoted if they are to ! represent themselves. There are three quoting mechanisms: the @var{escape character}, single quotes, and double quotes. --- 440,446 ---- 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. There are three quoting mechanisms: the @var{escape character}, single quotes, and double quotes. *************** *** 457,462 **** 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 is not quoted, the @code{\newline} ! is treated as a line continuation (that is, it is effectively ignored). @node Single Quotes --- 450,456 ---- 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 *************** *** 474,481 **** @samp{$}, @samp{`}, and @samp{\}. The characters @samp{$} and @samp{`} ! retain their special meaning within double quotes. The backslash ! retains its special meaning only when followed by one of the following ! characters: @samp{$}, @samp{`}, @samp{"}, @samp{\}, or @code{newline}. A double quote may be quoted within double quotes by preceding it with a backslash. --- 468,478 ---- @samp{$}, @samp{`}, and @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. *************** *** 513,517 **** backslash @item \@var{nnn} ! the character whose @code{ASCII} code is @var{nnn} in octal @end table --- 510,518 ---- backslash @item \@var{nnn} ! the character whose @code{ASCII} code is the octal value @var{nnn} ! (one to three digits) ! @item \x@var{nnn} ! the character whose @code{ASCII} code is the hexadecimal value @var{nnn} ! (one to three digits) @end table *************** *** 542,553 **** option enabled does not allow comments. The @code{interactive_comments} option is on by default in interactive shells. @node Simple Commands ! @section Simple Commands @cindex commands, simple ! A simple command is the kind of command you'll encounter most often. It's just a sequence of words separated by @code{blank}s, terminated ! by one of the shell control operators (@pxref{Definitions}). The first word generally specifies a command to be executed. --- 543,569 ---- option enabled does not allow comments. The @code{interactive_comments} option is on by default in interactive shells. + @xref{Is This Shell Interactive?}, for a description of what makes + a shell interactive. + + @node Shell Commands + @section Shell Commands + @cindex commands, shell + @menu + * Simple Commands:: The most common type of command. + * Pipelines:: Connecting the input and output of several + commands. + * Lists:: How to execute commands sequentially. + * Looping Constructs:: Shell commands for iterative action. + * Conditional Constructs:: Shell commands for conditional execution. + * Command Grouping:: Ways to group commands. + @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. *************** *** 558,562 **** @node Pipelines ! @section Pipelines @cindex pipeline @cindex commands, pipelines --- 574,578 ---- @node Pipelines ! @subsection Pipelines @cindex pipeline @cindex commands, pipelines *************** *** 580,583 **** --- 596,601 ---- 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 @samp{-p} option changes the output format to that specified by @sc{POSIX}. *************** *** 585,596 **** specifies how the timing information should be displayed. @xref{Bash Variables}, for a description of the available formats. ! Each command in a pipeline is executed in its own subshell. The exit status of a pipeline is the exit status of the last command in the pipeline. If the reserved word @samp{!} precedes the pipeline, the ! exit status is the logical @sc{NOT} of the exit status of the last command. @node Lists ! @section Lists of Commands @cindex commands, lists --- 603,621 ---- 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. + + 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. If the reserved word @samp{!} precedes the pipeline, the ! exit status is the logical negation of the exit status of the last command. @node Lists ! @subsection Lists of Commands @cindex commands, lists *************** *** 605,613 **** If a command is terminated by the control operator @samp{&}, ! the shell executes the command in the @var{background} ! in a subshell. The shell does not wait for the command to ! finish, and the return status is 0 (true). 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. --- 630,642 ---- 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). ! 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. *************** *** 629,633 **** @noindent ! @var{command2} is executed if and only if @var{command} returns a non-zero exit status. --- 658,662 ---- @noindent ! @var{command2} is executed if, and only if, @var{command} returns a non-zero exit status. *************** *** 637,649 **** @node Looping Constructs ! @section Looping Constructs @cindex commands, looping - Note that wherever you see a @samp{;} in the description of a - command's syntax, it may be replaced indiscriminately with - one or more newlines. - Bash supports the following looping constructs. @table @code @item until --- 666,677 ---- @node Looping Constructs ! @subsection Looping Constructs @cindex commands, looping Bash supports the following looping constructs. + Note that wherever you see a @samp{;} in the description of a + command's syntax, it may be replaced with one or more newlines. + @table @code @item until *************** *** 655,660 **** until @var{test-commands}; do @var{consequent-commands}; done @end example ! Execute @var{consequent-commands} as long as the final command in @var{test-commands} has an exit status which is not zero. @item while --- 683,690 ---- 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 *************** *** 665,670 **** @end example ! Execute @var{consequent-commands} as long as the final command in @var{test-commands} has an exit status of zero. @item for --- 695,702 ---- @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 *************** *** 675,682 **** for @var{name} [in @var{words} @dots{}]; do @var{commands}; done @end example ! Execute @var{commands} for each member in @var{words}, with @var{name} ! bound to the current member. If @samp{in @var{words}} is not ! present, @samp{in "$@@"} is assumed. ! @end table --- 707,716 ---- 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, @samp{in "$@@"} is assumed. ! 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. @end table *************** *** 685,689 **** @node Conditional Constructs ! @section Conditional Constructs @cindex commands, conditional --- 719,723 ---- @node Conditional Constructs ! @subsection Conditional Constructs @cindex commands, conditional *************** *** 706,718 **** @end example ! Execute @var{consequent-commands} only if the final command in ! @var{test-commands} has an exit status of zero. ! Otherwise, 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 execute @var{alternate-consequents}. @item case --- 740,754 ---- @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 *************** *** 723,731 **** @example ! @code{case @var{word} in [ ( @var{pattern} [| @var{pattern}]@dots{}) @var{commands} ;;]@dots{} esac} @end example ! Selectively execute @var{commands} based upon @var{word} matching ! @var{pattern}. The @samp{|} is used to separate multiple patterns. Here is an example using @code{case} in a script that could be used to --- 759,779 ---- @example ! @code{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}. ! 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{;;}. ! 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{;;}. The first pattern that matches determines the ! command-list that is executed. Here is an example using @code{case} in a script that could be used to *************** *** 744,747 **** --- 792,839 ---- @end example + @noindent + 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 specifed. + The @code{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 @code{REPLY}. + + The @var{commands} are executed after each selection until a + @code{break} or @code{return} 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 *************** *** 749,754 **** @end example ! The @var{expression} is evaluated according to the rules described ! below (@pxref{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 --- 841,846 ---- @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 *************** *** 756,768 **** let "@var{expression}" @end example @end table ! The @code{select} construct, which allows users to choose from a list ! of items presented as a menu, is also available. ! @xref{Korn Shell Constructs}, for a full description of @code{select}. @node Command Grouping ! @section Grouping Commands @cindex commands, grouping --- 848,904 ---- 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 @samp{[[} and @samp{]]}; tilde expansion, parameter and + variable expansion, arithmetic expansion, command substitution, process + substitution, and quote removal are performed. + + 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}. + The return value is 0 if the string matches or does not match + the pattern, respectively, and 1 otherwise. + Any part of the pattern may be quoted to force it to be matched as a + string. + + 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 && and || commands do not execute @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 ! @subsection Grouping Commands @cindex commands, grouping *************** *** 779,785 **** Placing a list of commands between parentheses causes a subshell ! to be created, and each of the commands 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 @{@} --- 915,921 ---- Placing a list of commands between parentheses causes a subshell ! to be created, 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 @{@} *************** *** 792,796 **** 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 following @var{list} is required. @end table --- 928,932 ---- 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 *************** *** 822,828 **** This defines a shell function named @var{name}. The reserved ! word @code{function} is optional. The @var{body} of the ! function is the @var{command-list} between @{ and @}. This list ! is executed whenever @var{name} is specified as the name of a command. The exit status of a function is the exit status of the last command executed in the body. --- 958,966 ---- 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 @var{command-list} between @{ and @}. ! This list is executed whenever @var{name} is specified as the name of a command. The exit status of a function is the exit status of the last command executed in the body. *************** *** 840,846 **** call. When a function completes, the values of the positional parameters and the special parameter @samp{#} ! are restored to the values they had prior to function execution. If a numeric argument is given to @code{return}, ! that is the function return status. Variables local to the function may be declared with the --- 978,986 ---- call. 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 functions'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 *************** *** 881,889 **** @var{value}s undergo tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote ! removal (detailed below). If the variable has its @samp{-i} attribute ! set (see the description of the @code{declare} builtin in @ref{Bash Builtins}), then @var{value} is subject to arithmetic expansion even if the @code{$((@dots{}))} ! syntax does not appear (@pxref{Arithmetic Expansion}). Word splitting is not performed, with the exception of @code{"$@@"} as explained below. --- 1021,1029 ---- @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 (see the description of the @code{declare} builtin in @ref{Bash Builtins}), then @var{value} is subject to arithmetic expansion 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. *************** *** 894,903 **** @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 parameters may not be assigned to with assignment statements. The positional parameters are temporarily replaced when a shell function is executed --- 1034,1043 ---- @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@}}. ! Positional parameters may not be assigned to with assignment statements. The positional parameters are temporarily replaced when a shell function is executed *************** *** 932,936 **** @item @@ Expands to the positional parameters, starting from one. When the ! expansion occurs within double quotes, each parameter expands as a separate word. That is, @code{"$@@"} is equivalent to @code{"$1" "$2" @dots{}}. --- 1072,1076 ---- @item @@ 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{}}. *************** *** 954,959 **** @item $ Expands to the process @sc{ID} of the shell. In a @code{()} subshell, it ! expands to the process @sc{ID} of the current shell, not the ! subshell. @item ! --- 1094,1098 ---- @item $ 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 ! *************** *** 963,970 **** @item 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, ! @code{$0} is set to the name of that file. If Bash ! is started with the @samp{-c} option, 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. --- 1102,1109 ---- @item 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 @samp{-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. *************** *** 975,979 **** Subsequently, expands to the last argument to the previous command, after expansion. ! Also set to the full filename of each command executed and placed in the environment exported to that command. When checking mail, this parameter holds the name of the mail file. --- 1114,1118 ---- Subsequently, expands to the last argument to the previous command, after expansion. ! Also set to the full pathname of each command executed and placed in the environment exported to that command. When checking mail, this parameter holds the name of the mail file. *************** *** 997,1002 **** --- 1136,1144 ---- @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. *************** *** 1008,1016 **** @end menu - Brace expansion, tilde expansion, and arithmetic expansion are described - in other sections. For brace expansion, see @ref{Brace Expansion}; for - tilde expansion, see @ref{Tilde Expansion}; and for arithmetic expansion, - see @ref{Arithmetic Expansion}. - The order of expansions is: brace expansion, tilde expansion, parameter, variable, and arithmetic expansion and --- 1150,1153 ---- *************** *** 1021,1025 **** On systems that can support it, there is an additional expansion available: @var{process substitution}. This is performed at the ! same time as parameter, variable, and arithemtic expansion and command substitution. --- 1158,1162 ---- On systems that can support it, there is an additional expansion available: @var{process substitution}. This is performed at the ! same time as parameter, variable, and arithmetic expansion and command substitution. *************** *** 1034,1037 **** --- 1171,1292 ---- 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 file names generated + need not exist. Patterns to be brace expanded take + the form of an optional @var{preamble}, + followed by a series of comma-separated strings + between a pair of braces, followed by an optional @var{postscript}. + The preamble is prepended 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 + + 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. + + A correctly-formed brace expansion must contain unquoted opening + and closing braces, and at least one unquoted comma. + Any incorrectly formed brace expansion is left unchanged. + + 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 @code{HOME} shell variable. + If @code{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 @code{PWD} replaces the tilde-prefix. + If the tilde-prefix is @samp{~-}, the value of the shell variable + @code{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 @samp{=}. + In these cases, tilde expansion is also performed. + Consequently, one may use file names with tildes in assignments to + @code{PATH}, @code{MAILPATH}, and @code{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 *************** *** 1046,1049 **** --- 1301,1309 ---- 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 braces are required *************** *** 1099,1107 **** @itemx $@{@var{parameter}:@var{offset}:@var{length}@} Expands to up to @var{length} characters of @var{parameter}, ! starting at @var{offset}. If @var{length} is omitted, expands to the substring of @var{parameter}, starting at the character specified by @var{offset}. @var{length} and @var{offset} are arithmetic expressions ! (@pxref{Arithmetic Evaluation}). This is referred to as Substring Expansion. --- 1359,1367 ---- @itemx $@{@var{parameter}:@var{offset}:@var{length}@} Expands to up to @var{length} characters of @var{parameter}, ! starting at the character specified by @var{offset}. If @var{length} is omitted, expands to the substring of @var{parameter}, starting at the character specified by @var{offset}. @var{length} and @var{offset} are arithmetic expressions ! (@pxref{Shell Arithmetic}). This is referred to as Substring Expansion. *************** *** 1113,1129 **** If @var{parameter} is an array name indexed by @samp{@@} or @samp{*}, the result is the @var{length} ! members of the array beginning with $@{@var{parameter}[@var{offset}]@}. ! Substring indexing is zero-based unless the positional parameters are ! used, in which case the indexing starts at 1. @item $@{#@var{parameter}@} ! The length in characters of the value of @var{parameter} is substituted. ! If @var{parameter} ! is @samp{*} or @samp{@@}, ! the length substituted is the number of positional parameters. ! If @var{parameter} ! is an array name subscripted ! by @samp{*} or @samp{@@}, ! the length substituted is the number of elements in the array. @item $@{@var{parameter}#@var{word}@} --- 1373,1387 ---- If @var{parameter} is an array name indexed by @samp{@@} or @samp{*}, the result is the @var{length} ! members of the array beginning with @code{$@{@var{parameter}[@var{offset}]@}}. ! Substring indexing is zero-based unless the positional parameters ! are used, in which case the indexing starts at 1. @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. @item $@{@var{parameter}#@var{word}@} *************** *** 1132,1137 **** is expanded to produce a pattern just as in filename expansion (@pxref{Filename Expansion}). If the pattern matches ! the beginning of the value of @var{parameter}, ! then 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. --- 1390,1395 ---- 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. *************** *** 1148,1155 **** The @var{word} is expanded to produce a pattern just as in filename expansion. ! If the pattern matches a trailing portion of the value of ! @var{parameter}, then 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 --- 1406,1413 ---- 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 *************** *** 1205,1221 **** replacing the command substitution with the standard output of the command, with any trailing newlines deleted. When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by ! @samp{$}, @samp{`}, or @samp{\}. 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 old 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 Process Substitution @subsection Process Substitution --- 1463,1508 ---- 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 expansion, command + substitution, and quote removal. + Arithmetic substitutions 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 *************** *** 1242,1248 **** argument should be read to obtain the output of @var{list}. ! On systems that support it, process substitution is performed ! simultaneously with parameter and variable expansion, ! command substitution, and arithmetic expansion. @node Word Splitting --- 1529,1535 ---- argument should be read to obtain the output of @var{list}. ! When available, process substitution is performed simultaneously with ! parameter and variable expansion, command substitution, and arithmetic ! expansion. @node Word Splitting *************** *** 1283,1286 **** --- 1570,1576 ---- @node Filename Expansion @subsection Filename Expansion + @menu + * Pattern Matching:: How the shell matches patterns. + @end menu @cindex expansion, filename @cindex expansion, pathname *************** *** 1288,1296 **** @cindex pathname expansion ! After word splitting, ! unless the @samp{-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}, --- 1578,1584 ---- @cindex pathname expansion ! After word splitting, unless the @samp{-f} option has been set ! (@pxref{The Set Builtin}), Bash scans each word for the characters ! @samp{*}, @samp{?}, @samp{(}, and @samp{[}. If one of these characters appears, then the word is regarded as a @var{pattern}, *************** *** 1298,1318 **** file names matching the pattern. If no matching file names are found, and the shell option @code{nullglob} is disabled, the word is left ! unchanged. If the option is set, and no matches are found, the word ! is removed. When a pattern is used for filename generation, ! 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. 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{Bash Builtins}, ! for a description of the @code{nullglob} and @code{dotglob} options. The @code{GLOBIGNORE} shell variable may be used to restrict the set of filenames matching a ! @var{pattern}. If @code{GLOBIGNORE} is set, each matching filename that also matches one of the patterns in @code{GLOBIGNORE} is removed from the list of matches. The filenames @file{.} and @file{..} ! are always ignored, even when @code{GLOBIGNORE}. is set. However, setting @code{GLOBIGNORE} has the effect of enabling the @code{dotglob} --- 1586,1613 ---- file names matching the pattern. If no matching file names 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 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 generation, 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 file name, 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{Bash Builtins}, ! for a description of the @code{nocaseglob}, @code{nullglob}, ! and @code{dotglob} options. The @code{GLOBIGNORE} shell variable may be used to restrict the set of filenames matching a ! pattern. If @code{GLOBIGNORE} is set, each matching filename that also matches one of the patterns in @code{GLOBIGNORE} is removed from the list of matches. The filenames @file{.} and @file{..} ! are always ignored, even when @code{GLOBIGNORE} is set. However, setting @code{GLOBIGNORE} has the effect of enabling the @code{dotglob} *************** *** 1324,1327 **** --- 1619,1632 ---- 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 NUL character may not + occur in a pattern. The special pattern characters must be quoted if + they are to be matched literally. + The special pattern characters have the following meanings: @table @code *************** *** 1340,1343 **** --- 1645,1691 ---- in the set. A @samp{]} may be matched by including it as the first character in the set. + + 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.2} standard: + @example + alnum alpha ascii blank cntrl digit graph lower + print punct space upper xdigit + @end example + @noindent + A character class matches any character belonging to that class. + + 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 exactly one of the given patterns. + + @item !(@var{pattern-list}) + Matches anything except one of the given patterns. @end table *************** *** 1370,1378 **** descriptor 1). ! The word that follows the redirection operator in the following ! descriptions is subjected to brace expansion, tilde expansion, ! parameter expansion, command substitution, arithmetic expansion, ! quote removal, and filename expansion. If it expands to more ! than one word, Bash reports an error. Note that the order of redirections is significant. For example, --- 1718,1726 ---- 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, and filename expansion. ! If it expands to more than one word, Bash reports an error. Note that the order of redirections is significant. For example, *************** *** 1392,1395 **** --- 1740,1745 ---- before the standard output was redirected to @var{dirlist}. + A failure to open or create a file causes the redirection to fail. + @subsection Redirecting Input Redirection of input causes the file whose name results from *************** *** 1417,1427 **** @end example ! If the redirection operator is @samp{>}, and the @samp{-C} option to the ! @code{set} builtin has been enabled, the redirection will fail if the ! filename whose name results from the expansion of @var{word} exists. ! If the redirection operator is @samp{>|}, ! then the value of the @samp{-C} option to the @code{set} ! builtin command is not tested, and the redirection is attempted even ! if the file named by @var{word} exists. @subsection Appending Redirected Output --- 1767,1777 ---- @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 filename 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 *************** *** 1480,1484 **** @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. Otherwise, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion. In the latter --- 1830,1835 ---- @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. In the latter *************** *** 1502,1506 **** If @var{word} expands to one or more digits, the file descriptor denoted by @code{n} ! is made to be a copy of that file descriptor. If @var{word} evaluates to @samp{-}, file descriptor @code{n} is closed. If @code{n} is not specified, the standard input (file descriptor 0) is used. --- 1853,1860 ---- If @var{word} expands to one or more digits, the file descriptor denoted by @code{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 @code{n} is closed. If @code{n} is not specified, the standard input (file descriptor 0) is used. *************** *** 1514,1517 **** --- 1868,1873 ---- @code{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. As a special case, if @code{n} is omitted, and @var{word} does not expand to one or more digits, the standard output and standard *************** *** 1533,1538 **** --- 1889,1901 ---- @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. *************** *** 1542,1547 **** --- 1905,1956 ---- * 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 *************** *** 1569,1583 **** @code{$PATH} for a directory containing an executable file by that name. Bash uses a hash table to remember the full ! filenames of executable files (see the description of ! @code{hash} in @ref{Bourne Shell Builtins}) to avoid multiple ! @code{PATH} searches. A full search of the directories in @code{$PATH} is performed only if the command is not found in the hash table. If the search is unsuccessful, the shell prints an error ! message and returns a nonzero exit status. @item If the search is successful, or if the command name contains ! one or more slashes, the shell executes the named program. Argument 0 is set to the name given, and the remaining arguments to the command are set to the arguments supplied, if any. --- 1978,1992 ---- @code{$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 @code{PATH} searches ! (see the description of @code{hash} in @ref{Bourne Shell Builtins}). A full search of the directories in @code{$PATH} is performed only if the command is not found in the hash table. If the search is unsuccessful, 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. *************** *** 1585,1592 **** @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 ! @var{shell script} (@pxref{Shell Scripts}). @end enumerate @node Environment @subsection Environment --- 1994,2093 ---- @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} + + @item + shell aliases defined with @code{alias} (@pxref{Aliases}) + + @item + various process IDs, including those of background jobs + (@pxref{Lists}), the value of @code{$$}, and the value of + @code{$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 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 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. + @node Environment @subsection Environment *************** *** 1609,1614 **** 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} command, plus any ! additions via the @code{export} and @samp{declare -x} commands. The environment for any simple command --- 2110,2116 ---- 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 *************** *** 1618,1622 **** by that command. ! If the @samp{-k} flag 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. --- 2120,2124 ---- by that command. ! If the @samp{-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. *************** *** 1630,1634 **** @cindex exit status ! For the purposes of the shell, a command which exits with a zero exit status has succeeded. A non-zero exit status indicates failure. --- 2132,2136 ---- @cindex exit status ! For the shell's purposes, a command which exits with a zero exit status has succeeded. A non-zero exit status indicates failure. *************** *** 1643,1646 **** --- 2145,2151 ---- 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 *************** *** 1650,1653 **** --- 2155,2159 ---- 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. @node Signals *************** *** 1655,1659 **** @cindex signal handling ! When Bash is interactive, it ignores @code{SIGTERM} (so that @samp{kill 0} does not kill an interactive shell), and @code{SIGINT} --- 2161,2165 ---- @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} *************** *** 1664,1682 **** ignores @code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}. ! Synchronous jobs started by Bash have signals set to the ! values inherited by the shell from its parent. When job control ! is not in effect, background jobs (commands terminated with @samp{&}) ! ignore @code{SIGINT} and @code{SIGQUIT}. ! 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, it resends the @code{SIGHUP} ! to all jobs, running or stopped. To prevent the shell from ! sending the @code{SIGHUP} signal to a particular job, remove it ! from the jobs table with the @code{disown} builtin ! (@pxref{Job Control Builtins}) ! or use @code{disown -h} to mark it to not receive @code{SIGHUP}. @node Shell Scripts --- 2170,2204 ---- ignores @code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}. ! 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} as well. ! 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, it 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{Bash Builtins}), Bash sends a @code{SIGHUP} to all jobs when ! an interactive login shell exits. ! ! When Bash receives a signal for which a trap has been set while waiting ! for a command to complete, 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 *************** *** 1712,1716 **** 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. Most versions of Unix make this a part of the kernel's command --- 2234,2241 ---- 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 kernel's command *************** *** 1738,1744 **** This section briefly summarizes things which Bash inherits from ! the Bourne Shell: builtins, variables, ! and other features. It also lists the significant differences ! between Bash and the Bourne Shell. @node Bourne Shell Builtins --- 2263,2269 ---- This section briefly summarizes things which Bash inherits from ! the Bourne Shell: builtins, variables, and other features. ! It also lists the significant differences between Bash and the Bourne Shell. ! Many of the builtins have been extended by @sc{POSIX} or Bash. @node Bourne Shell Builtins *************** *** 1756,1759 **** --- 2281,2285 ---- @end example Do nothing beyond expanding @var{arguments} and performing redirections. + The return status is zero. @item . *************** *** 1763,1767 **** @end example Read and execute commands from the @var{filename} argument in the ! current shell context. @item break --- 2289,2299 ---- @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 @code{$PATH} variable is used to find ! @var{filename}. The current directory is searched if @var{filename} ! is not found in @code{$PATH}. ! 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. @item break *************** *** 1772,1775 **** --- 2304,2309 ---- 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 *************** *** 1783,1788 **** @var{directory} begins with a slash, @code{CDPATH} is not used. The @samp{-P} option means ! to not follow symbolic links; symlinks are followed by default or with the ! @samp{-L} option. @item continue --- 2317,2325 ---- @var{directory} begins with a slash, @code{CDPATH} is not used. The @samp{-P} option means ! to not follow symbolic links; symbolic links are followed by default ! or with the @samp{-L} option. ! If @var{directory} is @samp{-}, it is equivalent to @code{$OLDPWD}. ! The return status is zero if the directory is successfully changed, ! non-zero otherwise. @item continue *************** *** 1793,1798 **** 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. @item eval --- 2330,2337 ---- 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 *************** *** 1801,1823 **** eval [@var{arguments}] @end example ! The arguments are concatenated together into a single ! command, which is then read and executed. @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. ! If the @samp{-l} option is supplied, ! the shell places a dash in the zeroth arg passed to @var{command}. This is what the @code{login} program does. ! The @samp{-c} option causes @var{command} ! to be executed with an empty environment. ! If @samp{-a} is supplied, the shell passes @var{name} ! as the zeroth argument to @var{command}. If no @var{command} is specified, redirections may be used to affect ! the current shell environment. @item exit --- 2340,2366 ---- 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 @samp{-l} option is supplied, the shell places a dash in the ! zeroth arg passed to @var{command}. This is what the @code{login} program does. ! The @samp{-c} option causes @var{command} to be executed with an empty ! environment. ! If @samp{-a} is supplied, the shell passes @var{name} as the zeroth ! argument to @var{command}. 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 *************** *** 1827,1830 **** --- 2370,2374 ---- @end example Exit the shell, returning a status of @var{n} to the shell's parent. + Any trap on @code{EXIT} is executed before the shell terminates. @item export *************** *** 1835,1842 **** Mark each @var{name} to be passed to child processes in the environment. If the @samp{-f} option is supplied, the @var{name}s ! refer to shell functions. The @samp{-n} option means to no longer mark ! each @var{name} for export. If no @var{names} are supplied, or if the @samp{-p} option is given, a list of exported names is displayed. @item getopts --- 2379,2390 ---- Mark each @var{name} to be passed to child processes in the environment. If the @samp{-f} option is supplied, the @var{name}s ! refer to shell functions; otherwise the names refer to shell variables. ! The @samp{-n} option means to no longer mark each @var{name} for export. If no @var{names} are supplied, or if the @samp{-p} option is given, a list of exported names is displayed. + The @samp{-p} option displays output in a form that may be reused as input. + The return status is zero unless an invalid option is supplied, one of + the names is not a valid shell variable name, or @samp{-f} is supplied + with a name that is not a shell function. @item getopts *************** *** 1853,1876 **** @var{name} if it does not exist, and the index of the next argument to be processed into the ! variable @code{OPTIND}. @code{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 @code{OPTARG}. ! The shell does not reset @code{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. @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 illegal options or missing option arguments are encountered. If the variable @code{OPTERR} ! is set to 0, no error message will be displayed, even if the first character of @code{optstring} is not a colon. ! If an illegal option is seen, @code{getopts} places @samp{?} into @var{name} and, if not silent, prints an error message and unsets @code{OPTARG}. --- 2401,2432 ---- @var{name} if it does not exist, and the index of the next argument to be processed into the ! variable @code{OPTIND}. ! @code{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 @code{OPTARG}. ! The shell does not reset @code{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. ! @code{OPTIND} is set to the index of the first non-option argument, ! and @code{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 @code{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 @code{OPTARG}. *************** *** 1884,1891 **** @var{name} and @code{OPTARG} is set to the option character found. - @code{getopts} - normally parses the positional parameters, but if more arguments are - given in @var{args}, @code{getopts} parses those instead. - @item hash @btindex hash --- 2440,2443 ---- *************** *** 1893,1904 **** hash [-r] [-p @var{filename}] [@var{name}] @end example ! Remember the full filenames of commands specified as arguments, ! so they need not be searched for on subsequent invocations. The ! commands are found by searching through the directories listed in ! @code{$PATH}. The @samp{-p} option inhibits the path search, and ! @var{filename} is used as the location of @var{name}. ! The @samp{-r} option causes the shell to forget ! all remembered locations. If no arguments are given, information ! about remembered commands is printed. @item pwd --- 2445,2458 ---- hash [-r] [-p @var{filename}] [@var{name}] @end example ! Remember the full pathnames of 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 ! @code{$PATH}. ! The @samp{-p} option inhibits the path search, and @var{filename} is ! used as the location of @var{name}. ! The @samp{-r} option causes the shell to forget all remembered locations. ! If no arguments are given, 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 *************** *** 1907,1913 **** pwd [-LP] @end example ! Print the current working directory. If the @samp{-P} option is supplied, ! the path printed will not contain symbolic links. If the @samp{-L} option ! is supplied, the path printed may contain symbolic links. @item readonly --- 2461,2472 ---- pwd [-LP] @end example ! Print the current working directory. ! If the @samp{-P} option is supplied, the path printed will not ! contain symbolic links. ! If the @samp{-L} option is supplied, the path 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 *************** *** 1916,1925 **** readonly [-apf] [@var{name}] @dots{} @end example ! Mark each @var{name} as unchangable. The values of these names may not ! be changed by subsequent assignment. If the @samp{-f} option is supplied, ! each @var{name} refers to a shell function. The @samp{-a} option means ! each @var{name} refers to an array variable. If no @var{name} arguments are given, or if the @samp{-p} option is supplied, a list of all readonly names is printed. @item return --- 2475,2490 ---- readonly [-apf] [@var{name}] @dots{} @end example ! Mark each @var{name} as readonly. ! The values of these names may not be changed by subsequent assignment. ! If the @samp{-f} option is supplied, each @var{name} refers to a shell ! function. ! The @samp{-a} option means each @var{name} refers to an array variable. If no @var{name} arguments are given, or if the @samp{-p} option is supplied, a list of all readonly names is printed. + The @samp{-p} option causes output to be displayed in a format that + may be reused as input. + 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 @samp{-f} option is supplied with a name that is not a shell function. @item return *************** *** 1928,1934 **** return [@var{n}] @end example ! Cause a shell function to exit with value @var{n}. This may also be used ! to terminate execution of a script being executed with the @code{.} ! builtin. @item shift --- 2493,2503 ---- return [@var{n}] @end example ! Cause a shell function to exit with the return value @var{n}. ! This may also be used to terminate execution of a script being executed ! with the @code{.} builtin, returning either @var{n} or the exit status ! of the last command executed within the script as the exit status of the ! script. ! The return status is false if @code{return} is used outside a function ! and not during the execution of a script by @samp{.}. @item shift *************** *** 1937,1947 **** shift [@var{n}] @end example ! Shift positional parameters to the left by @var{n}. ! The positional parameters from @var{n}+1 @dots{} ! are renamed to ! @code{$1} @dots{} . ! Parameters represented by the numbers ! @code{$#} to @var{n}+1 are unset. @var{n} ! must be a non-negative number less than or equal to @code{$#}. @item test --- 2506,2518 ---- 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}+1. ! Parameters represented by the numbers @code{$#} to @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. ! The return status is zero unless @var{n} is greater than @code{$#} or ! less than zero, non-zero otherwise. @item test *************** *** 1949,1960 **** @btindex test @btindex [ ! Evaluate a conditional expression (@pxref{Bash Conditional Expressions}). ! @item times ! @btindex times ! @example times @end example Print out the user and system times used by the shell and its children. @item trap --- 2520,2597 ---- @btindex test @btindex [ ! Evaluate a conditional expression @var{expr}. ! Each operator and operand must be a separate argument. ! Expressions are composed of the primaries described below in ! @ref{Bash Conditional Expressions}. ! Expressions may be combined using the following operators, listed in ! decreasing order of precedence. ! ! @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 ! 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. ! 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. ! The @samp{-a} and @samp{-o} operators are considered binary operators ! in this case. ! ! @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 ! ! @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 *************** *** 1972,1976 **** associated with each @var{sigspec}. If no arguments are supplied, or only @samp{-p} is given, @code{trap} prints the list of commands ! associated with each signal number. Each @var{sigspec} is either a signal name such as @code{SIGINT} (with or without the @code{SIG} prefix) or a signal number. --- 2609,2614 ---- associated with each @var{sigspec}. If no arguments are supplied, or only @samp{-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. Each @var{sigspec} is either a signal name such as @code{SIGINT} (with or without the @code{SIG} prefix) or a signal number. *************** *** 1986,1993 **** process when it is created. @item umask @btindex umask @example ! umask [-S] [@var{mode}] @end example Set the shell process's file creation mask to @var{mode}. If --- 2624,2634 ---- process when it 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 *************** *** 1998,2001 **** --- 2639,2646 ---- option is supplied without a @var{mode} argument, the mask is printed in a symbolic format. + If the @samp{-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. @item unset *************** *** 2009,2014 **** If the @samp{-f} option is given, the @var{name}s refer to shell functions, and the function definition is removed. ! Read-only variables and functions may not be unset. ! @end table --- 2654,2660 ---- If the @samp{-f} option is given, the @var{name}s refer to shell functions, and the function definition is removed. ! Readonly variables and functions may not be unset. ! The return status is zero unless a @var{name} does not exist or is ! readonly. @end table *************** *** 2021,2046 **** @vtable @code ! @item IFS ! A list of characters that separate fields; used when the shell splits ! words as part of expansion. ! ! @item PATH ! A colon-separated list of directories in which the shell looks for ! commands. @item HOME The current user's home directory; the default for the @code{cd} builtin command. ! @item CDPATH ! A colon-separated list of directories used as a search path for ! the @code{cd} command. ! ! @item MAILPATH ! A colon-separated list of files which the shell periodically checks ! for new mail. You can ! also specify what message is printed by separating the file name from ! the message with a @samp{?}. When used in the text of the message, ! @code{$_} stands for the name of the current mailfile. @item MAIL --- 2667,2683 ---- @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 *************** *** 2049,2052 **** --- 2686,2708 ---- the specified file. + @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 file name 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. + @item PS1 The primary prompt string. The default value is @samp{\s-\v\$ }. *************** *** 2055,2066 **** The secondary prompt string. The default value is @samp{> }. - @item OPTIND - The index of the last option processed by the - @code{getopts} builtin. - - @item OPTARG - The value of the last option argument processed by the - @code{getopts} builtin. - @end vtable --- 2711,2714 ---- *************** *** 2073,2126 **** @end menu ! Bash implements essentially the same grammar, parameter and variable ! expansion, redirection, and quoting as the Bourne Shell. Bash uses the ! @sc{POSIX} 1003.2 standard as the specification of how these features are to be ! implemented. There are some differences between the traditional Bourne ! shell and the @sc{POSIX} standard; this section quickly details the differences ! of significance. A number of these differences are explained in greater ! depth in subsequent sections. @node Major Differences From The Bourne Shell @subsection Major Differences From The SVR4.2 Bourne Shell Bash is @sc{POSIX}-conformant, even where the @sc{POSIX} specification differs from traditional @code{sh} behavior. Bash has multi-character invocation options (@pxref{Invoking Bash}). Bash has command-line editing (@pxref{Command Line Editing}) and the @code{bind} builtin. Bash has command history (@pxref{Bash History Facilities}) and the @code{history} and @code{fc} builtins to manipulate it. ! Bash implements @code{csh}-like history expansion (@pxref{History Interaction}). Bash has one-dimensional array variables (@pxref{Arrays}), and the appropriate variable expansions and assignment syntax to use them. ! Some of the Bash builtins take options to act on arrays. Bash provides ! some built-in array variables. 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. Bash includes the @code{select} compound command, which allows the ! generation of simple menus (@pxref{Korn Shell Constructs}). Bash includes brace expansion (@pxref{Brace Expansion}) and tilde expansion (@pxref{Tilde Expansion}). Bash implements command aliases and the @code{alias} and @code{unalias} builtins (@pxref{Aliases}). ! Bash provides shell arithmetic and arithmetic expansion ! (@pxref{Shell Arithmetic}). ! ! The @sc{POSIX} and @code{ksh}-style @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). Variables present in the shell's initial environment are automatically exported to child processes. The Bourne shell does not normally do --- 2721,2807 ---- @end menu ! Bash implements essentially the same grammar, parameter and ! variable expansion, redirection, and quoting as the Bourne Shell. ! Bash uses the @sc{POSIX} 1003.2 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 ! subsequent sections. @node Major Differences From The Bourne Shell @subsection Major Differences From The SVR4.2 Bourne Shell + @itemize @bullet + + @item Bash is @sc{POSIX}-conformant, even where the @sc{POSIX} specification differs from traditional @code{sh} behavior. + @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 has command history (@pxref{Bash History Facilities}) and the @code{history} and @code{fc} builtins to manipulate 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 @samp{-D}, @samp{--dump-strings}, and @samp{--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. + @item + Bash has the @code{time} reserved word and command timing (@pxref{Pipelines}). + The display of the timing statistics may be controlled with the + @code{TIMEFORMAT} variable. + + @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}). + @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 *************** *** 2128,2154 **** command. ! Bash includes the @sc{POSIX} and @code{ksh}-style pattern removal ! @samp{%}, @samp{#}, @samp{%%} and @samp{##} constructs to remove ! leading or trailing substrings from variable values ! (@pxref{Shell Parameter Expansion}). ! The expansion @code{$@{#xx@}}, which returns the length of @code{$xx}, is supported (@pxref{Shell Parameter Expansion}). ! 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}). ! ! Bash supports the @code{$"@dots{}"} quoting syntax to do ! locale-specific translation of the characters between the double ! quotes. The @samp{-D} and @samp{--dump-strings} invocation options ! list the translatable strings found in a script ! (@pxref{Locale Translation}). ! The expansion @code{$@{var:}@var{offset}@code{[:}@var{length}@code{]@}}, which expands to the substring of @code{var}'s value of length ! @var{length}, optionally beginning at @var{offset}, is present (@pxref{Shell Parameter Expansion}). The expansion @code{$@{var/[/]}@var{pattern}@code{[/}@var{replacement}@code{]@}}, --- 2809,2828 ---- command. ! @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{]@}}, *************** *** 2156,2184 **** the value of @code{var}, is available (@pxref{Shell Parameter Expansion}). Bash has @var{indirect} variable expansion using @code{$@{!word@}} (@pxref{Shell Parameter Expansion}). Bash can expand positional parameters beyond @code{$9} using @code{$@{@var{num}@}}. Bash has process substitution (@pxref{Process Substitution}). Bash automatically assigns variables that provide information about the current user (@code{UID}, @code{EUID}, and @code{GROUPS}), the current host (@code{HOSTTYPE}, @code{OSTYPE}, @code{MACHTYPE}, and @code{HOSTNAME}), and the instance of Bash that is running (@code{BASH}, ! @code{BASH_VERSION}, and @code{BASH_VERSINFO}. @xref{Bash Variables}, for details. The @code{IFS} variable is used to split only the results of expansion, not all words (@pxref{Word Splitting}). This closes a longstanding shell security hole. It is possible to have a variable and a function with the same name; @code{sh} does not separate the two name spaces. Bash functions are permitted to have local variables using the @code{local} builtin, and thus useful recursive functions may be written. Variable assignments preceding commands affect only that command, even builtins and functions (@pxref{Environment}). --- 2830,2881 ---- the value of @code{var}, 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 (@code{UID}, @code{EUID}, and @code{GROUPS}), the current host (@code{HOSTTYPE}, @code{OSTYPE}, @code{MACHTYPE}, and @code{HOSTNAME}), and the instance of Bash that is running (@code{BASH}, ! @code{BASH_VERSION}, and @code{BASH_VERSINFO}). @xref{Bash Variables}, for details. + @item The @code{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 + Bash implements the full set of @sc{POSIX.2} 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. + @item Variable assignments preceding commands affect only that command, even builtins and functions (@pxref{Environment}). *************** *** 2187,2193 **** file system. Bash performs filename expansion on filenames specified as operands ! to output redirection operators. Bash contains the @samp{<>} redirection operator, allowing a file to be opened for both reading and writing, and the @samp{&>} redirection --- 2884,2892 ---- file system. + @item Bash performs filename expansion on filenames specified as operands ! to input and output redirection operators. + @item Bash contains the @samp{<>} redirection operator, allowing a file to be opened for both reading and writing, and the @samp{&>} redirection *************** *** 2195,2225 **** file (@pxref{Redirections}). 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}. ! Bash interprets special backslash-escaped characters in the prompt ! strings when interactive (@pxref{Printing a Prompt}). ! Bash allows you to write a function to override a builtin, and provides access to that builtin's functionality within the function via the @code{builtin} and @code{command} builtins (@pxref{Bash Builtins}). The @code{command} builtin allows selective disabling of functions when command lookup is performed (@pxref{Bash Builtins}). Individual builtins may be enabled or disabled using the @code{enable} builtin (@pxref{Bash Builtins}). ! 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 @code{$PATH}, using @samp{hash -p}. Shell functions may be exported to children via the environment ! (@pxref{Shell Functions}). Bash includes a @code{help} builtin for quick reference to shell facilities (@pxref{Bash Builtins}). The Bash @code{read} builtin (@pxref{Bash Builtins}) will read a line ending in @samp{\} with --- 2894,2953 ---- file (@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 @samp{-L} and @samp{-P} builtins 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 @samp{-f} option to act on shell functions, a @samp{-p} option to ! display variables with various attributes set in a format that can be ! used as shell input, a @samp{-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 @code{$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 *************** *** 2229,2250 **** Readline to obtain the line when given the @samp{-e} option. Bash includes the @code{shopt} builtin, for finer control of shell optional capabilities (@pxref{Bash Builtins}). Bash has much more optional behavior controllable with the @code{set} builtin (@pxref{The Set Builtin}). ! The @code{disown} builtin can remove a job from the internal shell ! job table (@pxref{Job Control Builtins}). ! ! The @code{return} builtin may be used to abort execution of scripts ! executed with the @code{.} or @code{source} builtins ! (@pxref{Bourne Shell Builtins}). ! The @code{test} builtin (@pxref{Bourne Shell Builtins}) ! is slightly different, as it implements the ! @sc{POSIX} 1003.2 algorithm, which specifies the behavior based on the ! number of arguments. The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows a @code{DEBUG} pseudo-signal specification, --- 2957,2979 ---- Readline to obtain the line when given the @samp{-e} option. + @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{Bash Builtins}). + @item Bash has much more optional behavior controllable with the @code{set} builtin (@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 The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows a @code{DEBUG} pseudo-signal specification, *************** *** 2253,2295 **** inherited by shell functions. ! The Bash @code{export}, @code{readonly}, and @code{declare} builtins can ! take a @samp{-f} option to act on shell functions, a @samp{-p} option to ! display variables with various attributes set in a format that can be ! used as shell input, a @samp{-n} option to remove various variable ! attributes, and @samp{name=value} arguments to set variable attributes ! and values simultaneously. ! ! The Bash @code{cd} and @code{pwd} builtins (@pxref{Bourne Shell Builtins}) ! each take @samp{-L} and @samp{-P} builtins to switch between logical and ! physical modes. ! The Bash @code{type} builtin is more extensive and gives more information about the names it finds (@pxref{Bash Builtins}). Bash implements a @code{csh}-like directory stack, and provides the @code{pushd}, @code{popd}, and @code{dirs} builtins to manipulate it ! (@pxref{C Shell Builtins}). Bash also makes the directory stack visible as the value of the @code{DIRSTACK} shell variable. The Bash restricted mode is more useful (@pxref{The Restricted Shell}); the @sc{SVR4.2} shell restricted mode is too limited. ! Bash has the @code{time} reserved word and command timing (@pxref{Pipelines}). ! The display of the timing statistics may be controlled with the ! @code{TIMEFORMAT} variable. The @sc{SVR4.2} shell has two privilege-related builtins (@code{mldmode} and @code{priv}) not present in Bash. Bash does not have the @code{stop} or @code{newgrp} builtins. Bash does not use the @code{SHACCT} variable or perform shell accounting. The @sc{SVR4.2} @code{sh} uses a @code{TIMEOUT} variable like Bash uses @code{TMOUT}. ! More features unique to Bash may be found in ! @ref{Bash Features}. @subsection Implementation Differences From The SVR4.2 Shell --- 2982,3033 ---- inherited by shell functions. ! @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 @samp{-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 @code{DIRSTACK} shell variable. + @item + Bash interprets special backslash-escaped characters in the prompt + strings when interactive (@pxref{Printing a Prompt}). + + @item The Bash restricted mode is more useful (@pxref{The Restricted Shell}); the @sc{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 The @sc{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 @code{SHACCT} variable or perform shell accounting. + @item The @sc{SVR4.2} @code{sh} uses a @code{TIMEOUT} variable like Bash uses @code{TMOUT}. ! @end itemize ! ! @noindent ! More features unique to Bash may be found in @ref{Bash Features}. @subsection Implementation Differences From The SVR4.2 Shell *************** *** 2314,2318 **** 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), the shell misbehaves badly. @item --- 3052,3056 ---- 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 *************** *** 2324,2333 **** @item ! The @sc{SVR4.2} shell does not allow users to trap @code{SIGALRM} or ! @code{SIGCHLD}. @item ! For some reason, the @sc{SVR4.2} shell does not allow the @code{MAILCHECK} ! variable to be unset. @item --- 3062,3071 ---- @item ! The @sc{SVR4.2} shell does not allow users to trap @code{SIGSEGV}, ! @code{SIGALRM}, or @code{SIGCHLD}. @item ! The @sc{SVR4.2} shell does not allow the @code{IFS}, @code{MAILCHECK}, ! @code{PATH}, @code{PS1}, or @code{PS2} variables to be unset. @item *************** *** 2351,2889 **** @end itemize ! @node Csh Features ! @chapter C-Shell Style Features ! ! The C-Shell (@dfn{@code{csh}}) was created by Bill Joy at The ! University of California at Berkeley. It ! is generally considered to have better features for interactive use than ! the original Bourne shell. Some of the @code{csh} features present in ! Bash include job control, history expansion, `protected' redirection, and ! several variables to control the interactive behaviour of the shell ! (e.g., @code{IGNOREEOF}). ! @xref{Using History Interactively}, for details on history expansion. @menu ! * Brace Expansion:: Expansion of expressions within braces. ! * Tilde Expansion:: Expansion of the ~ character. ! * C Shell Builtins:: Builtin commands adopted from the C Shell. ! * C Shell Variables:: Variables which Bash uses in essentially ! the same way as the C Shell. @end menu ! @node Brace Expansion ! @section 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 file names generated ! need not exist. Patterns to be brace expanded take ! the form of an optional @var{preamble}, ! followed by a series of comma-separated strings ! between a pair of braces, followed by an optional @var{postamble}. ! The preamble is prepended to each string contained ! within the braces, and the postamble 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 ! ! 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. ! ! A correctly-formed brace expansion must contain unquoted opening ! and closing braces, and at least one unquoted comma. ! Any incorrectly formed brace expansion is left unchanged. ! ! 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 ! @section Tilde Expansion ! @cindex tilde expansion ! @cindex expansion, tilde ! ! Bash has tilde (~) expansion, similar, but not identical, to that of ! @code{csh}. The following table shows what unquoted words beginning ! with a tilde expand to. ! ! @table @code ! @item ~ ! The current 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} ! @end table ! ! Bash will also tilde expand words following redirection operators ! and words following @samp{=} in assignment statements. ! ! @node C Shell Builtins ! @section C Shell Builtins ! ! Bash has several builtin commands whose definition is very similar ! to @code{csh}. ! ! @table @code ! @btindex pushd ! @item pushd ! @example ! pushd [@var{dir} | @var{+N} | @var{-N}] [-n] ! @end example ! ! Save the current directory on a list and then @code{cd} to ! @var{dir}. With no ! arguments, exchanges the top two directories. ! ! @table @code ! @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 -n ! Suppresses the normal change of directory when adding directories ! to the stack, so that only the stack is manipulated. ! @item @var{dir} ! Makes the current working directory be the top of the stack, and then ! @code{cd}s to @var{dir}. You can see the saved directory list ! with the @code{dirs} command. ! @end table ! ! @item popd ! @btindex popd ! @example ! popd [+@var{N} | -@var{N}] [-n] ! @end example ! ! Pop 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}; i.e., @code{popd} is equivalent to @code{popd +0}. ! @table @code ! @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. ! @item -n ! Suppresses the normal change of directory when removing directories ! from the stack, so that only the stack is manipulated. ! @end table ! ! @item dirs ! @btindex dirs ! @example ! dirs [+@var{N} | -@var{N}] [-clvp] ! @end example ! Display the list of currently remembered directories. Directories ! find their way onto the list with the @code{pushd} command; you can get ! back up through the list with the @code{popd} command. ! @table @code ! @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. ! @item -c ! Clears the directory stack by deleting all of the elements. ! @item -l ! Produces a longer listing; 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, prepending each entry with its index in the stack. ! @end table ! ! @item history ! @btindex history ! @example ! history [-c] [@var{n}] ! history [-anrw] [@var{filename}] ! history -ps @var{arg} ! @end example ! ! Display the history list with line numbers. Lines prefixed with ! with a @samp{*} have been modified. An argument of @var{n} says ! to list only the last @var{n} lines. Options, if supplied, have ! the following meanings: ! ! @table @code ! @item -w ! Write out the current history to the history file. ! ! @item -r ! Read the current history file and append its contents to ! the history list. ! ! @item -a ! Append the new ! history lines (history lines entered since the beginning of the ! current Bash session) to the history file. ! ! @item -n ! Append the history lines not already read from the history file ! to the current history list. These are lines appended to the history ! file since the beginning of the current Bash session. ! ! @item -c ! Clear the history list. This may be combined ! with the other options to replace the history list completely. ! ! @item -s ! The @var{arg}s are added to the end of ! the history list as a single entry. ! ! @item -p ! Perform history substitution on the @var{arg}s and display the result ! on the standard output, without storing the results in the history list. ! @end table ! ! When the @samp{-w}, @samp{-r}, @samp{-a}, or @samp{-n} option is ! used, if @var{filename} ! is given, then it is used as the history file. If not, then ! the value of the @code{HISTFILE} variable is used. ! ! @item logout ! @btindex logout ! Exit a login shell. ! ! @item source ! @btindex source ! A synonym for @code{.} (@pxref{Bourne Shell Builtins}). ! ! @end table ! ! @node C Shell Variables ! @section C Shell Variables ! ! @vtable @code ! ! @item IGNOREEOF ! If this variable is set, its value is used the number of consecutive ! @code{EOF}s Bash will read before exiting. By default, Bash will exit ! upon reading a single @code{EOF}. If @code{IGNOREEOF} is not set to ! a numeric value, Bash acts as if its value were 10. ! ! @end vtable ! ! @node Korn Shell Features ! @chapter Korn Shell Style Features ! ! This section describes features primarily inspired by the ! Korn Shell (@code{ksh}). In some cases, the @sc{POSIX} 1003.2 ! standard has adopted these commands and variables from the ! Korn Shell; Bash implements those features using the @sc{POSIX} ! standard as a guide. ! ! @menu ! * Korn Shell Constructs:: Shell grammar constructs adopted from the ! Korn Shell ! * Korn Shell Builtins:: Builtin commands adopted from the Korn Shell. ! * Korn Shell Variables:: Variables which Bash uses in essentially ! the same way as the Korn Shell. ! * Aliases:: Substituting one command for another. ! @end menu ! ! @node Korn Shell Constructs ! @section Korn Shell Constructs ! ! Bash includes the Korn Shell @code{select} construct. This construct ! allows the easy generation of menus. It has almost the same syntax as ! the @code{for} command. ! ! The syntax of the @code{select} command is: ! @rwindex select ! @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, each preceded by a number. If the @samp{in @var{words}} ! is omitted, the positional parameters are printed. The ! @code{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 ! @code{REPLY}. ! ! The @var{commands} are executed after each selection until a ! @code{break} or @code{return} command is executed, at which ! point the @code{select} command completes. ! ! Bash also has adopted command timing from the Korn shell. If the ! @code{time} reserved word precedes a pipeline, which may consist ! of a single command, timing statistics for the pipeline are displayed ! when it completes. ! The statistics currently consist of elapsed (wall-clock) time and ! user and system time consumed by the command's execution. ! ! 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. ! ! @node Korn Shell Builtins ! @section Korn Shell Builtins ! ! This section describes Bash builtin commands taken from @code{ksh}. ! ! @table @code ! ! @item fc ! @btindex fc ! @example ! @code{fc [-e @var{ename}] [-nlr] [@var{first}] [@var{last}]} ! @code{fc -s [@var{pat}=@var{rep}] [@var{command}]} ! @end example ! ! Fix Command. In the first form, a range of commands from @var{first} to ! @var{last} is selected from the history list. Both @var{first} and ! @var{last} may be specified as a string (to locate the most recent ! 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 @var{last} is not specified it is set to ! @var{first}. If @var{first} is not specified it is set to the previous ! command for editing and @minus{}16 for listing. If the @samp{-l} flag is ! given, the commands are listed on standard output. The @samp{-n} flag ! suppresses the command numbers when listing. The @samp{-r} flag ! reverses the order of the listing. Otherwise, the editor given by ! @var{ename} is invoked on a file containing those commands. If ! @var{ename} is not given, the value of the following variable expansion ! is used: @code{$@{FCEDIT:-$@{EDITOR:-vi@}@}}. This says to use the ! value of the @code{FCEDIT} variable if set, or the value of the ! @code{EDITOR} variable if that is set, or @code{vi} if neither is set. ! When editing is complete, the edited commands are echoed and executed. ! ! In the second form, @var{command} is re-executed after each instance ! of @var{pat} in the selected command is replaced by @var{rep}. ! ! A useful alias to use with the @code{fc} command is @code{r='fc -s'}, so ! that typing @samp{r cc} runs the last command beginning with @code{cc} ! and typing @samp{r} re-executes the last command (@pxref{Aliases}). ! ! @item let ! @btindex let ! The @code{let} builtin allows arithmetic to be performed on shell variables. ! For details, refer to @ref{Arithmetic Builtins}. ! ! @item typeset ! @btindex typeset ! The @code{typeset} command is supplied for compatibility with the Korn ! shell; however, it has been deprecated in favor of the ! @code{declare} command (@pxref{Bash Builtins}). ! ! @end table ! ! @node Korn Shell Variables ! @section Korn Shell Variables ! ! @vtable @code ! ! @item REPLY ! The default variable for the @code{read} 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 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 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 ! This is the prompt printed before the command line is echoed ! when the @samp{-x} option is set (@pxref{The Set Builtin}). ! The default is @samp{+ }. ! ! @item PWD ! The current working directory as set by the @code{cd} builtin. ! ! @item OLDPWD ! The previous working directory as set by the @code{cd} builtin. ! ! @item TMOUT ! If set to a value greater than zero, the value is interpreted as ! the number of seconds to wait for input after issuing the primary ! prompt. ! Bash terminates after that number of seconds if input does ! not arrive. ! ! @item LINENO ! The line number in the script or shell function currently executing. ! ! @item FCEDIT ! The editor used as a default by the @code{fc} builtin command. ! ! @end vtable ! ! @node Aliases ! @section Aliases ! @cindex alias expansion ! ! @menu ! * Alias Builtins:: Builtins commands to maniuplate aliases. ! @end menu ! ! The shell maintains a list of @var{aliases} ! that may be set and unset with the @code{alias} and ! @code{unalias} builtin commands. ! ! The first word of each 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 alias name and the replacement text may contain any valid ! shell input, including shell metacharacters, with the exception ! that the alias name may not contain @key{=}. ! 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 ! space or tab character, 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{Bash Builtins}). ! ! 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 the function definition is read, ! not when the function is executed, because a function definition ! is itself a compound 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. ! ! Note that for almost every purpose, aliases are superseded by ! shell functions. ! ! @node Alias Builtins ! @subsection Alias Builtins ! ! @table @code ! ! @item alias ! @btindex alias ! @example ! alias [@code{-p}] [@var{name}[=@var{value}] @dots{}] ! @end example ! ! Without arguments or with the @samp{-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. ! ! @item unalias ! @btindex unalias ! @example ! unalias [-a] [@var{name} @dots{} ] ! @end example ! ! Remove each @var{name} from the list of aliases. If @samp{-a} is ! supplied, all aliases are removed. ! @end table ! ! @node Bash Features ! @chapter Bash Features ! ! This section 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. ! * Is This Shell Interactive?:: Determining the state of a running Bash. ! * Bash Builtins:: Table of builtins specific to Bash. ! * The Set Builtin:: This builtin is so overloaded it ! deserves its own section. ! * Bash Conditional Expressions:: Primitives used in composing expressions for ! the @code{test} builtin. ! * Bash Variables:: List of variables that exist in Bash. ! * Shell Arithmetic:: Arithmetic on shell variables. ! * Arrays:: Array Variables ! * Printing a Prompt:: Controlling the PS1 string. ! * 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 --- 3089,3120 ---- @end itemize ! @node Bash Features ! @chapter Bash Features ! This section 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. ! * Is This Shell Interactive?:: Determining the state of a running Bash. ! * Bash Builtins:: Table of builtins specific to Bash. ! * The Set Builtin:: This builtin is so overloaded it ! deserves its own section. ! * Bash Conditional Expressions:: Primitives used in composing expressions for ! the @code{test} builtin. ! * Bash Variables:: List of variables that exist in Bash. ! * Shell Arithmetic:: Arithmetic on shell variables. ! * Aliases:: Substituting one command for another. ! * Arrays:: Array Variables. ! * The Directory Stack:: History of visited directories. ! * Printing a Prompt:: Controlling the PS1 string. ! * 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 *************** *** 2900,2903 **** --- 3131,3138 ---- @table @code + @item --dump-po-strings + Equivalent to @samp{-D}, but the output is in the GNU @code{gettext} + PO (portable object) file format. + @item --dump-strings Equivalent to @samp{-D}. *************** *** 2909,2915 **** Make this shell act as if it were directly invoked by login. This is equivalent to @samp{exec -l bash} but can be issued from ! another shell, such as @code{csh}. If you wanted to replace your ! current login shell with a Bash login shell, you would say ! @samp{exec bash --login}. @item --noediting --- 3144,3149 ---- Make this shell act as if it were directly invoked by login. This is equivalent to @samp{exec -l bash} but can be issued from ! another shell, such as @code{csh}. @samp{exec bash --login} ! will replace the current shell with a Bash login shell. @item --noediting *************** *** 2951,2956 **** @end table ! There are several single-character options you can give which are ! not available with the @code{set} builtin. @table @code --- 3185,3190 ---- @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 *************** *** 2964,2971 **** @item -r ! Make the shell restricted. @item -s ! If this flag 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 --- 3198,3205 ---- @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 *************** *** 2980,2988 **** This implies the @samp{-n} option; no commands will be executed. @end table @cindex interactive shell An @emph{interactive} shell is one whose input and output are both ! connected to terminals (as determined by @code{isatty()}), or one started with the @samp{-i} option. --- 3214,3227 ---- This implies the @samp{-n} option; no commands will be executed. + @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 interactive shell An @emph{interactive} shell is one whose input and output are both ! connected to terminals (as determined by @code{isatty(3)}), or one started with the @samp{-i} option. *************** *** 3047,3057 **** possible, while conforming to the @sc{POSIX} standard as well. ! When invoked as a login shell, it first attempts to read and execute ! commands from @file{/etc/profile} and @file{~/.profile}, in that order. The @samp{--noprofile} option may be used to inhibit this behavior. ! When invoked as an interactive shell with the name @code{sh}, ! @code{bash} looks for the variable @code{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 @samp{--rcfile} option has --- 3286,3296 ---- possible, while conforming to the @sc{POSIX} standard as well. ! When invoked as an interactive login shell, it first attempts to read ! and execute commands from @file{/etc/profile} and @file{~/.profile}, in ! that order. The @samp{--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 @code{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 @samp{--rcfile} option has *************** *** 3066,3073 **** @samp{--posix} command line option, it follows the @sc{POSIX} standard for startup files. ! In this mode, the @code{ENV} variable is expanded and commands are read ! and executed from the file whose name is the expanded value. No other startup files are read. - This is done by interactive shells only. Bash attempts to determine when it is being run by the remote shell --- 3305,3312 ---- @samp{--posix} command line option, it follows the @sc{POSIX} standard for startup files. ! In this mode, interactive shells expand the @code{ENV} variable ! and commands are read and executed from the file whose name is the ! expanded value. No other startup files are read. Bash attempts to determine when it is being run by the remote shell *************** *** 3078,3083 **** The @samp{--norc} option may be used to inhibit this behavior, and the @samp{--rcfile} option may be used to force another file to be read, but ! rshd does not generally invoke the shell with those options or allow ! them to be specified. @node Is This Shell Interactive? --- 3317,3322 ---- The @samp{--norc} option may be used to inhibit this behavior, and the @samp{--rcfile} option may be used to force another file to be read, but ! @code{rshd} does not generally invoke the shell with those options or ! allow them to be specified. @node Is This Shell Interactive? *************** *** 3090,3095 **** or one started with the @samp{-i} option. ! You may wish to determine within a startup script whether Bash is ! running interactively or not. To do this, examine the variable @code{$PS1}; it is unset in non-interactive shells, and set in interactive shells. Thus: --- 3329,3334 ---- or one started with the @samp{-i} option. ! To determine within a startup script whether Bash is ! running interactively or not, examine the variable @code{$PS1}; it is unset in non-interactive shells, and set in interactive shells. Thus: *************** *** 3103,3107 **** @end example ! Alternatively, you may test the value of the @samp{-} special parameter. It contains @code{i} when the shell is interactive. For example: --- 3342,3347 ---- @end example ! Alternatively, startup scripts may test the value of the @samp{-} ! special parameter. It contains @code{i} when the shell is interactive. For example: *************** *** 3124,3128 **** @btindex bind @example ! bind [-m @var{keymap}] [-lpsvPSV] [-q @var{name}] [-r @var{keyseq}] bind [-m @var{keymap}] -f @var{filename} bind [-m @var{keymap}] @var{keyseq:function-name} --- 3364,3369 ---- @btindex bind @example ! bind [-m @var{keymap}] [-lpsvPSV] ! bind [-m @var{keymap}] [-q @var{function}] [-u @var{function}] [-r @var{keyseq}] bind [-m @var{keymap}] -f @var{filename} bind [-m @var{keymap}] @var{keyseq:function-name} *************** *** 3154,3191 **** @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 re-read @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 re-read @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 re-read @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 ! Query about which keys invoke the named @var{function} @item -r @var{keyseq} ! Remove any current binding for @var{keyseq} @end table @item builtin @btindex builtin --- 3395,3439 ---- @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 re-read. @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 re-read. @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 re-read. @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}. @end table + @noindent + The return status is zero unless an invalid option is supplied or an + error occurs. + @item builtin @btindex builtin *************** *** 3193,3216 **** builtin [@var{shell-builtin} [@var{args}]] @end example ! Run a shell builtin. This is useful when you wish to define a ! shell function with the same name as a shell builtin, but need the ! functionality of the builtin within the function itself. @item command @btindex command @example ! command [-pVv] @var{command} [@var{args} @dots{}] @end example ! Runs @var{command} with @var{arg} ignoring shell functions. If ! you have a shell function called @code{ls}, and you wish to call ! the command @code{ls}, you can say @samp{command ls}. The ! @samp{-p} option means to use a default value for @code{$PATH} that is guaranteed to find all of the standard utilities. If either the @samp{-V} or @samp{-v} option is supplied, a description of @var{command} is printed. The @samp{-v} option causes a single word indicating the command or file name used to ! invoke @var{command} to be printed; the @samp{-V} option produces ! a more verbose description. @item declare --- 3441,3475 ---- 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 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 ! @code{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 @samp{-p} option means to use a default value for @code{$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 @samp{-V} or @samp{-v} option is supplied, a description of @var{command} is printed. The @samp{-v} option causes a single word indicating the command or file name used to ! invoke @var{command} to be displayed; the @samp{-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 *************** *** 3245,3249 **** @item -r Make @var{name}s readonly. These names cannot then be assigned values ! by subsequent assignment statements. @item -x --- 3504,3508 ---- @item -r Make @var{name}s readonly. These names cannot then be assigned values ! by subsequent assignment statements or unset. @item -x *************** *** 3252,3272 **** @end table ! Using @samp{+} ! instead of @samp{-} turns off the attribute instead. When used in ! a function, @code{declare} makes each @var{name} local, as with the ! @code{local} command. @item echo @btindex echo @example ! echo [-neE] [arg @dots{}] @end example ! Output the @code{arg}s, separated by spaces, terminated with a ! newline. The return status is always 0. If @samp{-n} is ! specified, the trailing newline is suppressed. If the @samp{-e} ! option is given, interpretation of the following backslash-escaped ! characters is enabled. The @samp{-E} option disables the interpretation ! of these escape characters, even on systems where they are interpreted ! by default. @code{echo} interprets the following escape sequences: @table @code --- 3511,3541 ---- @end table ! Using @samp{+} instead of @samp{-} turns off the attribute instead. ! When used in a function, @code{declare} makes each @var{name} local, ! as with the @code{local} command. ! ! The return status is zero unless an invalid option is encountered, ! an attempt is made to define a function using @code{-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 @samp{-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 always 0. ! If @samp{-n} is specified, the trailing newline is suppressed. ! If the @samp{-e} option is given, interpretation of the following ! backslash-escaped characters is enabled. ! The @samp{-E} option disables the interpretation of these escape characters, ! even on systems where they are interpreted by default. @code{echo} interprets the following escape sequences: @table @code *************** *** 3291,3296 **** @item \\ backslash ! @item \nnn ! the character whose ASCII code is @code{nnn} (octal) @end table --- 3560,3569 ---- @item \\ backslash ! @item \@var{nnn} ! the character whose @code{ASCII} code is the octal value @var{nnn} ! (one to three digits) ! @item \x@var{nnn} ! the character whose @code{ASCII} code is the hexadecimal value @var{nnn} ! (one to three digits) @end table *************** *** 3300,3305 **** enable [-n] [-p] [-f @var{filename}] [-ads] [@var{name} @dots{}] @end example ! Enable and disable builtin shell commands. This allows you to ! use a disk command which has the same name as a shell builtin. If @samp{-n} is used, the @var{name}s become disabled. Otherwise @var{name}s are enabled. For example, to use the @code{test} binary --- 3573,3580 ---- enable [-n] [-p] [-f @var{filename}] [-ads] [@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 with specifying a full pathname, ! even though the shell normally searches for builtins before disk commands. If @samp{-n} is used, the @var{name}s become disabled. Otherwise @var{name}s are enabled. For example, to use the @code{test} binary *************** *** 3316,3324 **** from shared object @var{filename}, on systems that support dynamic loading. The @samp{-d} option will delete a builtin loaded with @samp{-f}. If there are no options, a list of the shell builtins is displayed. ! The @samp{-s} option restricts @code{enable} to the @sc{POSIX.2} special builtins. If @samp{-s} is used with @samp{-f}, the new builtin becomes a special builtin. @item help @btindex help --- 3591,3603 ---- from shared object @var{filename}, on systems that support dynamic loading. The @samp{-d} option will delete a builtin loaded with @samp{-f}. + If there are no options, a list of the shell builtins is displayed. ! The @samp{-s} option restricts @code{enable} to the @sc{POSIX} special builtins. If @samp{-s} is used with @samp{-f}, the new builtin becomes a special builtin. + 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 *************** *** 3326,3333 **** help [@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. @item local --- 3605,3624 ---- help [@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. The return status is zero unless no ! command matches @var{pattern}. ! ! @item let ! @btindex let ! @example ! let @var{expression} [@var{expression}] ! @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 *************** *** 3336,3344 **** local @var{name}[=@var{value}] @end example ! For each argument, create a local variable called @var{name}, and ! give it @var{value}. @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. @item logout --- 3627,3636 ---- local @var{name}[=@var{value}] @end example ! For each argument, a local variable named @var{name} is created, ! and assigned @var{value}. @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 or an invalid @var{name} is supplied. @item logout *************** *** 3350,3353 **** --- 3642,3667 ---- parent. + @item printf + @btindex printf + @example + @code{printf} @var{format} [@var{arguments}] + @end example + Write the formatted @var{arguments} to the standard output under the + control of the @var{format}. + 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, @samp{%b} causes + @code{printf} to expand backslash escape sequences in the corresponding + @var{argument}, and @samp{%q} causes @code{printf} to output the + corresponding @var{argument} in a format that can be reused as shell input. + + 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. + @item read @btindex read *************** *** 3356,3367 **** @end example One line is read from the standard input, 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 assigned to the last @var{name}. ! Only the characters in the value of the @code{IFS} variable ! are recognized as word delimiters. If no names ! are supplied, the line read is assigned to the variable @code{REPLY}. ! The return code is zero, unless end-of-file is encountered. Options, ! if supplied, have the following meanings: @table @code --- 3670,3684 ---- @end example One line is read from the standard input, 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 standard input than names, ! the remaining names are assigned empty values. ! The characters in the value of the @code{IFS} variable ! are used to split the line into words. ! If no names are supplied, the line read is assigned to the ! variable @code{REPLY}. ! The return code is zero, unless end-of-file is encountered. ! Options, if supplied, have the following meanings: @table @code *************** *** 3371,3381 **** @item -p @var{prompt} ! Display @code{prompt}, without a trailing newline, before attempting to read any input. The prompt is displayed only if input is coming from a terminal. @item -a @var{aname} ! The words are assigned to ! sequential indices of the array variable @var{aname}, starting at 0. @item -e --- 3688,3700 ---- @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 -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 -e *************** *** 3390,3401 **** @end example Toggle the values of variables controlling optional shell behavior. ! With no options, or with the @samp{-p} ! option, a list of all settable options is displayed, with ! an indication of whether or not each is set. Other options have ! the following meanings: @table @code @item -s ! Enable (set) each @var{optname} @item -u --- 3709,3721 ---- @end example Toggle the values of variables controlling optional shell behavior. ! With no options, or with the @samp{-p} option, a list of all settable ! options is displayed, with an indication of whether or not each is set. ! The @samp{-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 *************** *** 3415,3420 **** @end table ! If either of ! @samp{-s} or @samp{-u} is used with no @var{optname} arguments, the display is limited to those options which are set or unset, respectively. --- 3735,3739 ---- @end table ! If either @samp{-s} or @samp{-u} is used with no @var{optname} arguments, the display is limited to those options which are set or unset, respectively. *************** *** 3425,3429 **** 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 legal shell option. --- 3744,3748 ---- 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. *************** *** 3471,3474 **** --- 3790,3802 ---- fails. + @item expand_aliases + If set, aliases are expanded as described below< under Aliases + (@pxref{Aliases}). + This option is enabled by default for interactive shells. + + @item extglob + If set, the extended pattern matching features described above + (@pxref{Pattern Matching}) are enabled. + @item histappend If set, the history list is appended to the file named by the value *************** *** 3489,3496 **** @item hostcomplete If set, and Readline is being used, Bash will attempt to perform ! hostname completion when a word beginning with @samp{@@} is being completed (@pxref{Commands For Completion}). This option is enabled by default. @item interactive_comments Allow a word beginning with @samp{#} --- 3817,3828 ---- @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{#} *************** *** 3509,3512 **** --- 3841,3848 ---- @code{"The mail in @var{mailfile} has been read"} is displayed. + @item nocaseglob + If set, Bash matches filenames in a case-insensitive fashion when + performing filename expansion. + @item nullglob If set, Bash allows filename patterns which match no *************** *** 3526,3541 **** If set, the @code{source} builtin uses the value of @code{PATH} to find the directory containing the file supplied as an argument. ! This is enabled by default. @end table @item type @btindex type @example ! type [-all] [-type | -path] [@var{name} @dots{}] @end example For each @var{name}, indicate how it would be interpreted if used as a command name. ! If the @samp{-type} flag is used, @code{type} returns a single word which is one of @samp{alias}, @samp{function}, @samp{builtin}, @samp{file} or @samp{keyword}, --- 3862,3890 ---- If set, the @code{source} builtin uses the value of @code{PATH} to find the directory containing the file supplied as an argument. ! This option is enabled 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. + + @item source + @btindex source + @example + source @var{filename} + @end example + A synonym for @code{.} (@pxref{Bourne Shell Builtins}). + @item type @btindex type @example ! type [-atp] [@var{name} @dots{}] @end example For each @var{name}, indicate how it would be interpreted if used as a command name. ! If the @samp{-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}, *************** *** 3545,3558 **** @code{type} returns a failure status. ! If the @samp{-path} flag is used, @code{type} either returns the name ! of the disk file that would be executed, or nothing if @samp{-type} would not return @samp{file}. ! If the @samp{-all} flag is used, returns all of the places that contain ! an executable named @var{file}. This includes aliases and functions, ! if and only if the @samp{-path} flag is not also used. ! @code{type} accepts @samp{-a}, @samp{-t}, and @samp{-p} as equivalent to ! @samp{-all}, @samp{-type}, and @samp{-path}, respectively. @item ulimit --- 3894,3917 ---- @code{type} returns a failure status. ! If the @samp{-p} option is used, @code{type} either returns the name ! of the disk file that would be executed, or nothing if @samp{-t} would not return @samp{file}. ! If the @samp{-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 @samp{-p} option ! is not also used. ! ! The return status is zero if any of the @var{names} are found, non-zero ! if none are found. ! @item typeset ! @btindex typeset ! @example ! typeset [-afFrxi] [-p] [@var{name}[=@var{value}]] ! @end example ! The @code{typeset} command is supplied for compatibility with the Korn ! shell; however, it has been deprecated in favor of the @code{declare} ! builtin command. @item ulimit *************** *** 3566,3585 **** @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 -c ! the maximum size of core files created. @item -d ! the maximum size of a process's data segment. @item -f ! the maximum size of files created by the shell. @item -l --- 3925,3944 ---- @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 -c ! The maximum size of core files created. @item -d ! The maximum size of a process's data segment. @item -f ! The maximum size of files created by the shell. @item -l *************** *** 3587,3609 **** @item -m ! the maximum resident set size. @item -n ! the maximum number of open file descriptors. @item -p ! the pipe buffer size. @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 process. @end table --- 3946,3968 ---- @item -m ! The maximum resident set size. @item -n ! The maximum number of open file descriptors. @item -p ! The pipe buffer size. @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 process. @end table *************** *** 3619,3622 **** --- 3978,3985 ---- are unscaled values. + The return status is zero unless an invalid option is supplied, a + non-numeric argument other than @code{unlimited} is supplied as a + @var{limit}, or an error occurs while setting a new limit. + @end table *************** *** 3624,3628 **** @section The Set Builtin ! This builtin is so overloaded that it deserves its own section. @table @code --- 3987,3991 ---- @section The Set Builtin ! This builtin is so complicated that it deserves its own section. @table @code *************** *** 3630,3636 **** @btindex set @example ! set [-abefhkmnptuvxdBCHP] [-o @var{option}] [@var{argument} @dots{}] @end example @table @code @item -a --- 3993,4006 ---- @btindex set @example ! set [--abefhkmnptuvxBCHP] [-o @var{option}] [@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. + + When options are supplied, they set or unset shell attributes. + Options, if specified, have the following meanings: + @table @code @item -a *************** *** 3642,3646 **** @item -e ! Exit immediately if a simple command exits with a non-zero status. @item -f --- 4012,4020 ---- @item -e ! Exit immediately if a simple command (@pxref{Simple Commands}) exits ! with a non-zero status, unless the command that fails is part of an ! @code{until} or @code{while} loop, part of an @code{if} statement, ! part of a @code{&&} or @code{||} list, or if the command's return ! status is being inverted using @code{!}. @item -f *************** *** 3649,3652 **** --- 4023,4027 ---- @item -h Locate and remember (hash) commands as they are looked up for execution. + This option is enabled by default. @item -k *************** *** 3659,3686 **** @item -n ! Read commands but do not execute them. @item -o @var{option-name} ! Set the flag 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}). @item errexit ! same as @code{-e}. @item hashall ! same as @code{-h}. @item histexpand ! same as @code{-H}. @item history --- 4034,4063 ---- @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}). @item errexit ! Same as @code{-e}. @item hashall ! Same as @code{-h}. @item histexpand ! Same as @code{-H}. @item history *************** *** 3689,3745 **** @item ignoreeof ! the 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 notify ! same as @code{-b}. @item nounset ! same as @code{-u}. @item onecmd ! same as @code{-t}. @item physical ! same as @code{-P}. @item posix ! change the behavior of Bash where the default operation differs ! from the @sc{POSIX} 1003.2 standard to match the standard. 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. @item xtrace ! same as @code{-x}. @end table @item -p Turn on privileged mode. ! In this mode, the @code{$BASH_ENV} ! file is not processed, and shell functions ! are not inherited from the environment. This is enabled automatically on startup if the effective user (group) id is not equal to the real user (group) id. Turning this option off causes the effective user --- 4066,4125 ---- @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 notify ! Same as @code{-b}. @item nounset ! Same as @code{-u}. @item onecmd ! Same as @code{-t}. @item physical ! Same as @code{-P}. @item posix ! Change the behavior of Bash where the default operation differs ! from the @sc{POSIX} 1003.2 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. @item xtrace ! Same as @code{-x}. @end table @item -p Turn on privileged mode. ! In this mode, the @code{$BASH_ENV} and @code{$ENV} files are not ! processed, shell functions are not inherited from the environment, ! and the @code{SHELLOPTS} variable, if it appears in the environment, ! is ignored. ! This is enabled automatically on startup if the effective user (group) id is not equal to the real user (group) id. Turning this option off causes the effective user *************** *** 3750,3754 **** @item -u ! Treat unset variables as an error when substituting. @item -v --- 4130,4136 ---- @item -u ! Treat unset variables 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 *************** *** 3756,3760 **** @item -x ! Print commands and their arguments as they are executed. @item -B --- 4138,4143 ---- @item -x ! Print a trace of simple commands and their arguments after they are ! expanded and before they are executed. @item -B *************** *** 3763,3771 **** @item -C ! Disallow output redirection to existing files. @item -H Enable @samp{!} style history substitution (@pxref{History Interaction}). ! This flag is on by default for interactive shells. @item -P --- 4146,4155 ---- @item -C ! Prevent output redirection using @samp{>}, @samp{>&}, and @samp{<>} ! from overwriting existing files. @item -H Enable @samp{!} style history substitution (@pxref{History Interaction}). ! This option is on by default for interactive shells. @item -P *************** *** 3776,3780 **** which change the current directory. ! For example, if @file{/usr/sys} is a link to @file{/usr/local/sys} then: @example $ cd /usr/sys; echo $PWD --- 4160,4165 ---- 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 *************** *** 3794,3798 **** @item -- ! If no arguments follow this flag, 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{-}. --- 4179,4183 ---- @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{-}. *************** *** 3805,3815 **** @end table ! Using @samp{+} rather than @samp{-} 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 @code{$-}. The remaining N @var{arguments} are positional parameters and are ! assigned, in order, to @code{$1}, @code{$2}, @dots{} @code{$N}. If ! no arguments are given, all shell variables are printed. @end table --- 4190,4202 ---- @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 *************** *** 3818,3831 **** @cindex expressions, conditional ! Conditional expressions are used by the @code{test} and @code{[} builtins. ! 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. Each ! operator and operand must be a separate argument. If @var{file} ! is of the form @file{/dev/fd/@var{N}}, then file descriptor @var{N} is ! checked. Expressions are composed of the following primaries: @table @code @item -b @var{file} True if @var{file} exists and is a block special file. --- 4205,4221 ---- @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 any @var{file} argument to one of the primaries is of the form ! @file{/dev/fd/@var{N}}, then file descriptor @var{N} is checked. @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. *************** *** 3844,3857 **** @item -g @var{file} ! True if @var{file} exists and is set-group-id. @item -k @var{file} ! True if @var{file} has its "sticky" bit set. ! ! @item -L @var{file} ! True if @var{file} exists and is a symbolic link. @item -p @var{file} ! True if @var{file} exists and is a named pipe. @item -r @var{file} --- 4234,4244 ---- @item -g @var{file} ! True if @var{file} exists and its set-group-id bit is set. @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} *************** *** 3861,3869 **** True if @var{file} exists and has a size greater than zero. - @item -S @var{file} - True if @var{file} exists and is a socket. - @item -t @var{fd} ! True if @var{fd} is opened on a terminal. @item -u @var{file} --- 4248,4253 ---- 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} *************** *** 3882,3885 **** --- 4266,4278 ---- 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 -S @var{file} + True if @var{file} exists and is a socket. + + @item -N @var{file} + True if @var{file} exists and has been modified since it was last read. + @item @var{file1} -nt @var{file2} True if @var{file1} is newer (according to *************** *** 3905,3911 **** True if the length of @var{string} is non-zero. ! @item @var{string1} = @var{string2} ! True if the strings are equal. @samp{==} may be used in place of ! @samp{=}. @item @var{string1} != @var{string2} --- 4298,4304 ---- True if the length of @var{string} is non-zero. ! @item @var{string1} == @var{string2} ! True if the strings are equal. ! @samp{=} may be used in place of @samp{==}. @item @var{string1} != @var{string2} *************** *** 3913,3929 **** @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{expr} ! True if @var{expr} is false. ! ! @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} and @var{expr2} is true. @item @var{arg1} OP @var{arg2} --- 4306,4315 ---- @item @var{string1} < @var{string2} ! True if @var{string1} sorts before @var{string2} lexicographically ! in the current locale. @item @var{string1} > @var{string2} ! True if @var{string1} sorts after @var{string2} lexicographically ! in the current locale. @item @var{arg1} OP @var{arg2} *************** *** 3938,3978 **** @end table - The Bash @code{test} and @code{[} builtins evaluate conditional - expressions using a set of rules based on the number of arguments. - These are the rules: - - @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 listed unary operators, the expression is true if the - unary test is true. If the first argument is not a legal unary - operator, the expression is false. - @item 3 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 second argument is one of the binary operators, the result - of the expression is the result of the binary test using the first - and third arguments as operands. - 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. - The @samp{-a} and @samp{-o} operators are considered binary operators - in this case. - @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. @samp{-a} has a higher precedence than @samp{-o}. - @item 5 or more arguments - The expression is parsed and evaluated according to precedence, - with @samp{-a} having a higher precedence than @samp{-o}. - @end table - @node Bash Variables @section Bash Variables --- 4324,4327 ---- *************** *** 3983,3986 **** --- 4332,4338 ---- @vtable @code + @item BASH + The full pathname used to execute the current instance of Bash. + @item BASH_ENV If this variable is set when Bash is invoked to execute a shell *************** *** 3988,4036 **** to read before executing the script. @xref{Bash Startup Files}. ! @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 HISTCONTROL --- 4340,4430 ---- to read before executing the script. @xref{Bash Startup Files}. ! @item BASH_VERSION ! The version number of the current instance of Bash. ! ! @item BASH_VERSINFO ! A readonly array variable 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 @code{MACHTYPE}. @end table ! @item DIRSTACK ! An array variable (@pxref{Arrays}) ! 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 @code{DIRSTACK} is unset, it loses its special properties, even if ! it is subsequently reset. ! @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 @samp{-e} option to the @code{fc} ! builtin command. ! ! @item FIGNORE ! A colon-separated list of suffixes to ignore when performing ! filename completion. ! A file name whose suffix matches one of the entries in ! @code{FIGNORE} ! is excluded from the list of matched file names. A sample ! value is @samp{.o:~} ! ! @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 @code{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. This variable is readonly. ! ! @item histchars ! Up to three characters which control history expansion, quick ! substitution, and tokenization (@pxref{History Interaction}). ! The first character is the ! @dfn{history-expansion-char}, 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 @code{HISTCMD} is unset, it loses its special properties, ! even if it is subsequently reset. @item HISTCONTROL *************** *** 4041,4044 **** --- 4435,4441 ---- Unset, or set to any other value than those above, means to save all lines on the history list. + 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 + @code{HISTCONTROL}. @item HISTIGNORE *************** *** 4052,4055 **** --- 4449,4455 ---- 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 + @code{HISTIGNORE}. @code{HISTIGNORE} subsumes the function of @code{HISTCONTROL}. A *************** *** 4064,4069 **** @item HISTSIZE ! If set, this is the maximum number of commands to remember in the ! history. @item HISTFILESIZE --- 4464,4469 ---- @item HISTSIZE ! The maximum number of commands to remember on the history list. ! The default value is 500. @item HISTFILESIZE *************** *** 4074,4096 **** writing it when an interactive shell exits. - @item histchars - Up to three characters which control history expansion, quick - substitution, and tokenization (@pxref{History Interaction}). - The first character is the - @dfn{history-expansion-char}, 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 signifies 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 @code{HISTCMD} is unset, it loses its special properties, - even if it is subsequently reset. - @item HOSTFILE Contains the name of a file in the same format as @file{/etc/hosts} that --- 4474,4477 ---- *************** *** 4100,4132 **** existing database. ! @item MAILCHECK ! How often (in seconds) that the shell should check for mail ! in the files specified in @code{MAILPATH}. ! @item PROMPT_COMMAND ! If present, this contains a string which is a command to execute ! before the printing of each primary prompt (@code{$PS1}). ! @item UID ! The numeric real user id of the current user. ! @item EUID ! The numeric effective user id of the current user. ! @item GROUPS ! An array variable containing the list of groups of which the current ! user is a member. ! @item PPID ! The process id of the shell's parent process. ! @item HOSTNAME ! The name of the current host. ! @item HOSTTYPE ! A string describing the machine Bash is running on. ! @item OSTYPE ! A string describing the operating system Bash is running on. @item MACHTYPE --- 4481,4530 ---- existing database. ! @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 startup 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 @code{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 LINENO ! The line number in the script or shell function currently executing. @item MACHTYPE *************** *** 4134,4173 **** is executing, in the standard GNU @var{cpu-company-system} format. ! @item SHELLOPTS ! A colon-separated list of enabled shell options. Each word in ! the list is a valid argument for the @samp{-o} option to the ! @code{set} builtin command (@pxref{The Set Builtin}). ! The options appearing in @code{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 FIGNORE ! A colon-separated list of suffixes to ignore when performing ! filename completion. ! A file name whose suffix matches one of the entries in ! @code{FIGNORE} ! is excluded from the list of matched file names. A sample ! value is @samp{.o:~} ! @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 @code{GLOBIGNORE}, it is removed from the list ! of matches. ! @item DIRSTACK ! An array variable (@pxref{Arrays}) ! 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 @code{DIRSTACK} is unset, it loses its special properties, even if ! it is subsequently reset. @item PIPESTATUS --- 4532,4548 ---- is executing, in the standard 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 @code{MAILPATH} or @code{MAIL} variables. ! @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 *************** *** 4177,4250 **** contain only a single command). ! @item INPUTRC ! The name of the Readline startup file, overriding the default ! of @file{~/.inputrc}. ! @item BASH ! The full filename used to execute the current instance of Bash. ! @item BASH_VERSION ! The version number of the current instance of Bash. ! @item BASH_VERSINFO ! An array variable 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 @code{MACHTYPE}. ! @end table ! @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 OPTERR ! If set to the value 1, Bash displays error messages ! generated by the @code{getopts} builtin command. ! @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 @code{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 (@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 IGNOREEOF ! Controls the action of the shell on receipt of an @code{EOF} character ! as the sole input. If set, then the value of it is 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. @end vtable --- 4552,4662 ---- contain only a single command). ! @item PPID ! The process id of the shell's parent process. This variable ! is readonly. ! @item PROMPT_COMMAND ! If present, this contains a string which is a command to execute ! before the printing of each primary prompt (@code{$PS1}). ! @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 ! This is the prompt printed before the command line is echoed ! when the @samp{-x} option is set (@pxref{The Set Builtin}). ! The first character of @code{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 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 SHELLOPTS ! A colon-separated list of enabled shell options. Each word in ! the list is a valid argument for the @samp{-o} option to the ! @code{set} builtin command (@pxref{The Set Builtin}). ! The options appearing in @code{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, the value is interpreted as ! the number of seconds to wait for input after issuing the primary ! prompt. ! Bash terminates after that number of seconds if input does ! not arrive. ! @item UID ! The numeric real user id of the current user. This variable is readonly. @end vtable *************** *** 4253,4268 **** @section Shell Arithmetic @cindex arithmetic, shell ! ! @menu ! * Arithmetic Evaluation:: How shell arithmetic works. ! * Arithmetic Expansion:: How to use arithmetic in shell expansions. ! * Arithmetic Builtins:: Builtin commands that use shell arithmetic. ! @end menu ! ! Bash includes several mechanisms to evaluate arithmetic expressions ! and display the result or use it as part of a command. ! ! @node Arithmetic Evaluation ! @subsection Arithmetic Evaluation @cindex expressions, arithmetic @cindex evaluation, arithmetic --- 4665,4669 ---- @section Shell Arithmetic @cindex arithmetic, shell ! @cindex shell arithmetic @cindex expressions, arithmetic @cindex evaluation, arithmetic *************** *** 4285,4288 **** --- 4686,4692 ---- logical and bitwise negation + @item ** + exponentiation + @item * / % multiplication, division, remainder *************** *** 4344,4384 **** rules above. ! @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 braces or parentheses is not treated ! specially. All tokens in the expression undergo parameter ! expansion, command substitution, and quote removal. Arithmetic ! substitutions may be nested. ! ! The evaluation is performed according to the rules listed above. ! If the expression is invalid, Bash ! prints a message indicating failure and no substitution occurs. ! @node Arithmetic Builtins ! @subsection Arithmetic Builtins @table @code ! @item let ! @btindex let @example ! let @var{expression} [@var{expression}] @end example ! The @code{let} builtin allows arithmetic to be performed on shell ! variables. Each @var{expression} is evaluated according to the ! rules given previously (@pxref{Arithmetic Evaluation}). If the ! last @var{expression} evaluates to 0, @code{let} returns 1; ! otherwise 0 is returned. @end table --- 4748,4840 ---- rules above. ! @node Aliases ! @section Aliases ! @cindex alias expansion ! @menu ! * Alias Builtins:: Builtins commands to maniuplate aliases. ! @end menu ! 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 @var{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 alias name and the replacement text may contain any valid ! shell input, including shell metacharacters, with the exception ! that the alias name may not contain @samp{=}. ! 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 ! space or tab character, 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{Bash Builtins}). ! ! 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 compound 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, aliases are superseded by ! shell functions. ! @node Alias Builtins ! @subsection Alias Builtins @table @code ! @item alias ! @btindex alias @example ! alias [@code{-p}] [@var{name}[=@var{value}] @dots{}] @end example ! ! Without arguments or with the @samp{-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. ! ! @item unalias ! @btindex unalias ! @example ! unalias [-a] [@var{name} @dots{} ] ! @end example ! ! Remove each @var{name} from the list of aliases. If @samp{-a} is ! supplied, all aliases are removed. @end table *************** *** 4452,4456 **** The @code{unset} builtin is used to destroy arrays. ! @code{unset} @var{name[subscript]} destroys the array element at index @var{subscript}. @code{unset} @var{name}, where @var{name} is an array, removes the --- 4908,4912 ---- The @code{unset} builtin is used to destroy arrays. ! @code{unset} @code{name[@var{subscript}]} destroys the array element at index @var{subscript}. @code{unset} @var{name}, where @var{name} is an array, removes the *************** *** 4468,4471 **** --- 4924,5028 ---- reused as input. + @node The Directory Stack + @section The Directory Stack + @cindex directory stack + + 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 @code{DIRSTACK} shell variable. + + @table @code + + @item dirs + @btindex dirs + @example + dirs [+@var{N} | -@var{N}] [-clvp] + @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 +@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. + @item -c + Clears the directory stack by deleting all of the elements. + @item -l + Produces a longer listing; 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. + @end table + + @item popd + @btindex popd + @example + popd [+@var{N} | -@var{N}] [-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}; i.e., @code{popd} is equivalent to @code{popd +0}. + @table @code + @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. + @item -n + Suppresses the normal change of directory when removing directories + from the stack, so that only the stack is manipulated. + @end table + + @btindex pushd + @item pushd + @example + pushd [@var{dir} | @var{+N} | @var{-N}] [-n] + @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 +@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 -n + Suppresses the normal change of directory when adding directories + to the stack, so that only the stack is manipulated. + @item @var{dir} + Makes the current working directory be the top of the stack, and then + executes the equivalent of `@code{cd} @var{dir}'. + @code{cd}s to @var{dir}. + @end table + + @end table + @node Printing a Prompt @section Controlling the Prompt *************** *** 4474,4478 **** The value of the variable @code{PROMPT_COMMAND} is examined just before Bash prints each primary prompt. If it is set and non-null, then the ! value is executed just as if you had typed it on the command line. In addition, the following table describes the special characters which --- 5031,5035 ---- The value of the variable @code{PROMPT_COMMAND} is examined just before Bash prints each primary prompt. If it is set and non-null, 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 *************** *** 4481,4529 **** @table @code @item \a ! a bell character. @item \d ! the date, in "Weekday Month Date" format (e.g., "Tue May 26"). @item \e ! an escape character. @item \h ! the hostname, up to the first `.'. @item \H ! the hostname. @item \n ! newline. @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 \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. @item \W ! the basename of @code{$PWD}. ! @item \u ! your username. @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 \nnn ! the character corresponding to the octal number @code{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 --- 5038,5088 ---- @table @code @item \a ! A bell character. @item \d ! The date, in "Weekday Month Date" format (e.g., "Tue May 26"). @item \e ! An escape character. @item \h ! The hostname, up to the first `.'. @item \H ! The hostname. @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 \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. @item \W ! The basename of @code{$PWD}. @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 *************** *** 4553,4556 **** --- 5112,5117 ---- Importing function definitions from the shell environment at startup. @item + Parsing the value of @code{SHELLOPTS} from the shell environment at startup. + @item Redirecting output using the @samp{>}, @samp{>|}, @samp{<>}, @samp{>&}, @samp{&>}, and @samp{>>} redirection operators. *************** *** 4563,4567 **** Specifying the @samp{-p} option to the @code{command} builtin. @item ! Turning off restricted mode with @samp{set +r}. @end itemize --- 5124,5128 ---- Specifying the @samp{-p} option to the @code{command} builtin. @item ! Turning off restricted mode with @samp{set +r} or @samp{set +o restricted}. @end itemize *************** *** 4596,4605 **** The @sc{POSIX.2} @code{PS1} and @code{PS2} expansions of @samp{!} to the history number and @samp{!!} to @samp{!} are enabled, ! and parameter expansion is performed on ! the value regardless of the setting of the @code{promptvars} option. @item ! Interactive comments are enabled by default. (Note that Bash has ! them on by default anyway.) @item --- 5157,5166 ---- The @sc{POSIX.2} @code{PS1} and @code{PS2} expansions of @samp{!} to the history number and @samp{!!} to @samp{!} are enabled, ! and parameter expansion is performed on the values of @code{PS1} and ! @code{PS2} regardless of the setting of the @code{promptvars} option. @item ! Interactive comments are enabled by default. (Bash has them on by ! default anyway.) @item *************** *** 4624,4627 **** --- 5185,5192 ---- @item + Non-interactive shells exit if a syntax error in an arithmetic expansion + results in an invalid expression. + + @item Redirection operators do not perform filename expansion on the word in the redirection unless the shell is interactive. *************** *** 4630,4634 **** 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 illegal name causes a fatal syntax error in non-interactive shells. --- 5195,5199 ---- 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. *************** *** 4651,4664 **** @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 read-only variable. @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 read-only variable. @item --- 5216,5237 ---- @item + If @code{$CDPATH} is set, the @code{cd} builtin will not implicitly + append the current directory to it. This means that @code{cd} will + fail if no valid directory name can be constructed from + any of the entries in @code{$CDPATH}, even if the a directory with + the same name as the name given as an argument to @code{cd} exists + in the current directory. + + @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 the iteration variable in a @code{for} statement or the selection variable in a ! @code{select} statement is a readonly variable. @item *************** *** 4666,4670 **** @item ! Assignment statements preceding @sc{POSIX.2} @code{special} builtins persist in the shell environment after the builtin completes. --- 5239,5243 ---- @item ! Assignment statements preceding @sc{POSIX.2} special builtins persist in the shell environment after the builtin completes. *************** *** 4687,4691 **** @chapter Job Control ! This chapter disusses what job control is, how it works, and how Bash allows you to access its facilities. --- 5260,5264 ---- @chapter Job Control ! This chapter discusses what job control is, how it works, and how Bash allows you to access its facilities. *************** *** 4715,4719 **** table of currently executing jobs, which may be listed with the @code{jobs} command. When Bash starts a job ! asynchronously (in the background), it prints a line that looks like: @example --- 5288,5292 ---- 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 *************** *** 4742,4752 **** If the operating system on which Bash is running supports ! job control, Bash allows you 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 ! you 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. You may then manipulate 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 --- 5315,5325 ---- 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 *************** *** 4765,4769 **** Bash reports an error. 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. The previous job may be referenced using @samp{%-}. In output pertaining to jobs (e.g., the output of the @code{jobs} command), --- 5338,5343 ---- Bash reports an error. 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. The previous job may be referenced using @samp{%-}. In output pertaining to jobs (e.g., the output of the @code{jobs} command), *************** *** 4780,4792 **** before reporting changes in a job's status so as to not interrupt any other output. If the ! the @samp{-b} option to the @code{set} builtin is set, Bash reports such changes immediately (@pxref{The Set Builtin}). ! If you attempt to exit Bash while jobs are stopped, the ! shell prints a message warning you that you have stopped jobs. ! You may then use the ! @code{jobs} command to inspect their status. If you do this, or ! try to exit again immediately, you are not warned again, and the ! stopped jobs are terminated. @node Job Control Builtins --- 5354,5365 ---- before reporting changes in a job's status so as to not interrupt any other output. If the ! the @samp{-b} option to the @code{set} builtin is enabled, Bash reports such changes immediately (@pxref{The Set Builtin}). ! If an attempt to exit Bash is while jobs are stopped, the ! shell prints a message warning that there are stopped jobs. ! 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 the stopped jobs are terminated. @node Job Control Builtins *************** *** 4800,4806 **** bg [@var{jobspec}] @end example ! Place @var{jobspec} into the background, as if it had been started ! with @samp{&}. If @var{jobspec} is not supplied, the current job ! is used. @item fg --- 5373,5383 ---- bg [@var{jobspec}] @end example ! Resume the 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, if @var{jobspec} was ! not found or @var{jobspec} specifies a job that was started without ! job control. @item fg *************** *** 4809,4814 **** fg [@var{jobspec}] @end example ! Bring @var{jobspec} into the foreground and make it the current job. If @var{jobspec} is not supplied, the current job is used. @item jobs --- 5386,5395 ---- 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 *************** *** 4816,4820 **** @example jobs [-lpnrs] [@var{jobspec}] ! jobs -x @var{command} [@var{jobspec}] @end example --- 5397,5401 ---- @example jobs [-lpnrs] [@var{jobspec}] ! jobs -x @var{command} [@var{arguments}] @end example *************** *** 4824,4836 **** @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 ! you were last notified of their status. @item -p ! List only the process @sc{ID} of the job's process group ! leader. @item -r --- 5405,5416 ---- @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 *************** *** 4854,4867 **** @btindex kill @example ! kill [-s @var{sigspec}] [-n @var{signum}] [-@var{sigspec}] @var{jobspec} ! kill -l [@var{sigspec}] @end example Send a signal specified by @var{sigspec} or @var{signum} to the process ! named by @var{jobspec}. @var{sigspec} is either a 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 @samp{-l} option lists the signal names, or the signal name ! corresponding to @var{sigspec}. @item wait --- 5434,5453 ---- @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 ID @var{pid}. @var{sigspec} is either a 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 @samp{-l} option lists the signal names. ! If any arguments are supplied when @samp{-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 *************** *** 4871,4882 **** @end example Wait until the child process specified by process @sc{ID} @var{pid} or job ! specification @var{jobspec} exits and report its exit status. 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. @item disown @btindex disown @example ! disown [-h] [@var{jobspec} @dots{}] @end example Without options, each @var{jobspec} is removed from the table of --- 5457,5472 ---- @end example Wait until the child process specified by 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 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, each @var{jobspec} is removed from the table of *************** *** 4885,4889 **** 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, the current job is used. @item suspend --- 5475,5483 ---- 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 @samp{-a} nor @samp{-r} ! option is supplied, the current job is used. ! If no @var{jobspec} is supplied, the @samp{-a} option means to remove or ! mark all jobs; the @samp{-r} option without a @var{jobspec} ! argument restricts operation to running jobs. @item suspend *************** *** 4910,4914 **** This variable controls how the shell interacts with the user and job control. If this variable exists then single word simple ! commands without redirects 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 --- 5504,5508 ---- 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 *************** *** 4942,4946 **** the various supported platforms. The distribution supports nearly every version of Unix (and, someday, @sc{GNU}). Other independent ports exist for ! @sc{OS/2}, Windows 95, and Windows @sc{NT}. @menu --- 5536,5540 ---- the various supported platforms. The distribution supports nearly every version of Unix (and, someday, @sc{GNU}). Other independent ports exist for ! @sc{MS-DOS}, @sc{OS/2}, Windows @sc{95}, and Windows @sc{NT}. @menu *************** *** 4992,4999 **** may remove or edit it. ! If you need to do unusual things to compile the package, please try to figure out how @code{configure} could check whether or not to do them, and mail diffs or instructions to ! @code{bash-maintainers@@prep.ai.mit.edu} so they can be considered for the next release. --- 5586,5593 ---- may remove or edit it. ! 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. *************** *** 5113,5117 **** architecture-specific files and architecture-independent files. If you give @code{configure} the option ! @samp{--exec-prefix=PATH}, the package will use @samp{PATH} as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. --- 5707,5711 ---- architecture-specific files and architecture-independent files. If you give @code{configure} the option ! @samp{--exec-prefix=PATH}, @samp{make install} will use @samp{PATH} as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. *************** *** 5121,5126 **** There may be some features @code{configure} can not figure out ! automatically, but needs to determine by the type of host the ! package 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 @samp{--host=TYPE} option. @samp{TYPE} can --- 5715,5720 ---- There may be some features @code{configure} can not figure out ! automatically, but needs 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 @samp{--host=TYPE} option. @samp{TYPE} can *************** *** 5183,5191 **** The Bash @code{configure} has a number of @samp{--enable-@var{FEATURE}} ! options, where @var{FEATURE} indicates an optional part of the ! package. There are also several @samp{--with-@var{PACKAGE}} options, ! where @var{PACKAGE} is something like @samp{gnu-malloc} or ! @samp{purify} (for the Purify memory allocation checker). To ! turn off the default use of a package, use @samp{--without-@var{PACKAGE}}. To configure Bash without a feature that is enabled by default, use @samp{--disable-@var{FEATURE}}. --- 5777,5784 ---- The Bash @code{configure} has a number of @samp{--enable-@var{FEATURE}} ! options, where @var{FEATURE} indicates an optional part of Bash. ! There are also several @samp{--with-@var{PACKAGE}} options, ! where @var{PACKAGE} is something like @samp{gnu-malloc} or @samp{purify}. ! To turn off the default use of a package, use @samp{--without-@var{PACKAGE}}. To configure Bash without a feature that is enabled by default, use @samp{--disable-@var{FEATURE}}. *************** *** 5205,5210 **** @item --with-glibc-malloc Use the @sc{GNU} libc version of @code{malloc} in ! @file{lib/malloc/gmalloc.c}. This is somewhat slower than the ! default @code{malloc}, but wastes considerably less space. @item --with-gnu-malloc --- 5798,5807 ---- @item --with-glibc-malloc Use the @sc{GNU} libc version of @code{malloc} in ! @file{lib/malloc/gmalloc.c}. This is not the version of @code{malloc} ! that appears in glibc version 2, but a modified version of the ! @code{malloc} from glibc version 1. This is somewhat slower than the ! default @code{malloc}, but wastes less space on a per-allocation ! basis, and will return memory to the operating system under ! some circumstances. @item --with-gnu-malloc *************** *** 5213,5218 **** @code{malloc} that appears in @sc{GNU} libc, but an older version derived from the 4.2 @sc{BSD} @code{malloc}. This @code{malloc} is ! very fast, but wastes a lot of space. 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. --- 5810,5816 ---- @code{malloc} that appears in @sc{GNU} libc, but an older version 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. *************** *** 5227,5231 **** @end table ! @noindent The @samp{minimal-config} option can be used to disable all of the following options, but it is processed first, so individual --- 5825,5841 ---- @end table ! There are several @samp{--enable-} options that alter how Bash is ! compiled and linked, rather than changing run-time features. ! ! @table @code ! @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 *************** *** 5240,5254 **** @item --enable-alias Allow alias expansion and include the @code{alias} and @code{unalias} ! builtins. @item --enable-array-variables ! Include support for one-dimensional array shell variables. @item --enable-bang-history ! Include support for @code{csh}-like history substitution. @item --enable-brace-expansion Include @code{csh}-like brace expansion ( @code{b@{a,b@}c} @expansion{} @code{bac bbc} ). @item --enable-command-timing --- 5850,5867 ---- @item --enable-alias Allow alias expansion and include the @code{alias} and @code{unalias} ! builtins (@pxref{Aliases}). @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-command-timing *************** *** 5257,5263 **** allows pipelines as well as shell builtins and functions to be timed. @item --enable-directory-stack Include support for a @code{csh}-like directory stack and the ! @code{pushd}, @code{popd}, and @code{dirs} builtins. @item --enable-disabled-builtins --- 5870,5881 ---- 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-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 *************** *** 5268,5272 **** @item --enable-dparen-arithmetic ! Include support for the @code{ksh} @code{((@dots{}))} command. @item --enable-help-builtin --- 5886,5895 ---- @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-help-builtin *************** *** 5279,5296 **** @item --enable-job-control ! This enables job control features, if the @sc{OS} supports them. @item --enable-process-substitution This enables process substitution (@pxref{Process Substitution}) if ! the @sc{OS} provides the necessary support. @item --enable-prompt-string-decoding Turn on the interpretation of a number of backslash-escaped characters in the @code{$PS1}, @code{$PS2}, @code{$PS3}, and @code{$PS4} prompt ! strings. @item --enable-readline Include support for command-line editing and history with the Bash ! version of the Readline library. @item --enable-restricted --- 5902,5921 ---- @item --enable-job-control ! This enables the job control features (@pxref{Job Control}), ! if the operating system supports them. @item --enable-process-substitution This enables process substitution (@pxref{Process Substitution}) if ! the operating system provides the necessary support. @item --enable-prompt-string-decoding Turn on the interpretation of a number of backslash-escaped characters in the @code{$PS1}, @code{$PS2}, @code{$PS3}, and @code{$PS4} prompt ! strings. See @ref{Printing a 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 *************** *** 5300,5305 **** @item --enable-select ! Include the @code{ksh} @code{select} builtin, which allows the ! generation of simple menus. @item --enable-usg-echo-default --- 5925,5930 ---- @item --enable-select ! Include the @code{select} builtin, which allows the generation of simple ! menus (@pxref{Conditional Constructs}). @item --enable-usg-echo-default *************** *** 5330,5334 **** If you have a fix, you are encouraged to mail that as well! Suggestions and `philosophical' bug reports may be mailed ! to @code{bug-bash@@prep.ai.MIT.Edu} or posted to the Usenet newsgroup @code{gnu.bash.bug}. --- 5955,5959 ---- 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}. *************** *** 5353,5357 **** Please send all reports concerning this manual to ! @code{chet@@ins.CWRU.Edu}. @node Builtin Index --- 5978,5982 ---- Please send all reports concerning this manual to ! @email{chet@@po.CWRU.Edu}. @node Builtin Index diff -Nrc2 bash-2.01.1/doc/htmlpost.sh bash-2.02/doc/htmlpost.sh *** bash-2.01.1/doc/htmlpost.sh Wed Dec 31 19:00:00 1969 --- bash-2.02/doc/htmlpost.sh Tue Mar 3 15:01:14 1998 *************** *** 0 **** --- 1,19 ---- + #! /bin/sh + # + # Some of these should really be done by man2html + # + # The ~/xxx links don't really work -- netscape doesn't expand the home + # directory of the user running navigator + # + + sed -e 's|gnu.bash.bug|gnu.bash.bug|' \ + -e 's|/bin/bash|/bin/bash|' \ + -e 's|/etc/profile|/etc/profile|' \ + -e 's|~/.bash_profile|~/.bash_profile|' \ + -e 's|~/.bash_login|~/.bash_login|' \ + -e 's|~/.profile|~/.profile|' \ + -e 's|~/.bashrc|~/.bashrc|' \ + -e 's|~/.bash_logout|~/.bash_logout|' \ + -e 's|~/.bash_history|~/.bash_history|' \ + -e 's|~/.inputrc|~/.inputrc|' \ + -e 's|/etc/inputrc|/etc/inputrc|' diff -Nrc2 bash-2.01.1/doc/readline.3 bash-2.02/doc/readline.3 *** bash-2.01.1/doc/readline.3 Wed Feb 5 14:14:01 1997 --- bash-2.02/doc/readline.3 Thu Feb 19 10:26:51 1998 *************** *** 7,13 **** .\" chet@ins.CWRU.Edu .\" ! .\" Last Change: Wed Feb 5 14:13:22 EST 1997 .\" ! .TH READLINE 3 "1997 Feb 5" GNU .\" .\" File Name macro. This used to be `.PN', for Path Name, --- 7,13 ---- .\" chet@ins.CWRU.Edu .\" ! .\" Last Change: Thu Feb 19 10:26:47 EST 1998 .\" ! .TH READLINE 3 "1998 Feb 19" GNU .\" .\" File Name macro. This used to be `.PN', for Path Name, *************** *** 160,164 **** as a symbolic key name, possibly with \fIMeta\-\fP or \fIControl\-\fP prefixes, or as a key sequence. ! 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: --- 160,164 ---- as a symbolic key name, possibly with \fIMeta\-\fP or \fIControl\-\fP prefixes, or as a key sequence. ! 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: *************** *** 186,190 **** into the line). .PP ! In the second form, \fB"keyseq"\fP:\fIfunction\-name\fP or \fImacro\fP, .B keyseq differs from --- 186,190 ---- into the line). .PP ! In the second form, \fB"keyseq"\fP:\^\fIfunction\-name\fP or \fImacro\fP, .B keyseq differs from *************** *** 214,219 **** is bound to insert the text .BR "Function Key 1" . ! The full set of escape sequences is .RS .TP .B \eC\- --- 214,220 ---- is bound to insert the text .BR "Function Key 1" . ! The full set of GNU Emacs style escape sequences is .RS + .PD 0 .TP .B \eC\- *************** *** 235,243 **** literal ' .RE .PP When entering the text of a macro, single or double quotes should be used to indicate a macro definition. Unquoted text ! is assumed to be a function name. Backslash ! will quote any character in the macro text, including " and '. .PP .B Bash --- 236,286 ---- literal ' .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 character whose ASCII code is the octal value \fInnn\fP + (one to three digits) + .TP + .B \ex\fInnn\fP + the character whose ASCII code is the hexadecimal value \fInnn\fP + (one to three digits) + .RE + .PD .PP When entering the text of a macro, single or double quotes should 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 '. .PP .B Bash *************** *** 289,292 **** --- 332,339 ---- .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\-query\-items (100) *************** *** 347,351 **** .TP .B mark\-directories (On) ! If set to \fBOn\fP, completed directory names have a slash appended. .TP --- 394,398 ---- .TP .B mark\-directories (On) ! If set to \fBOn\fP, complete + # endif # include #endif *************** *** 257,259 **** --- 260,297 ---- return (result); + } + + /* Take a string and run it through the shell parser, returning the + resultant word list. Used by compound array assignment. */ + WORD_LIST * + parse_string_to_word_list (s, whom) + char *s, *whom; + { + WORD_LIST *wl; + COMMAND *saved_global; + + push_stream (1); + + saved_global = global_command; + global_command = (COMMAND *)0; + + with_input_from_string (s, whom); + if (parse_command () != 0 || global_command == 0 || global_command->type != cm_simple) + { + if (global_command) + dispose_command (global_command); + wl = (WORD_LIST *)NULL; + } + else + { + wl = global_command->value.Simple->words; + free (global_command->value.Simple); + free (global_command); + } + + global_command = saved_global; + + pop_stream (); + + return (wl); } diff -Nrc2 bash-2.01.1/examples/functions/basename2 bash-2.02/examples/functions/basename2 *** bash-2.01.1/examples/functions/basename2 Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/functions/basename2 Fri Feb 6 15:43:46 1998 *************** *** 0 **** --- 1,43 ---- + #From: "Grigoriy Strokin" + #Newsgroups: comp.unix.shell + #Subject: fast basename and dirname functions for BASH/SH + #Date: Sat, 27 Dec 1997 21:18:40 +0300 + # + #Please send your comments to grg@philol.msu.ru + + function basename() + { + local name="${1##*/}" + echo "${name%$2}" + } + + function dirname() + { + local dir="${1%${1##*/}}" + [ "${dir:=./}" != "/" ] && dir="${dir%?}" + echo "$dir" + } + + # Two additional functions: + # 1) namename prints the basename without extension + # 2) ext prints extension of a file, including "." + + function namename() + { + local name=${1##*/} + local name0="${name%.*}" + echo "${name0:-$name}" + } + function ext() + { + local name=${1##*/} + local name0="${name%.*}" + local ext=${name0:+${name#$name0}} + echo "${ext:-.}" + } + + + + + + diff -Nrc2 bash-2.01.1/examples/functions/getoptx.bash bash-2.02/examples/functions/getoptx.bash *** bash-2.01.1/examples/functions/getoptx.bash Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/functions/getoptx.bash Fri Feb 6 15:46:36 1998 *************** *** 0 **** --- 1,302 ---- + #From: "Grigoriy Strokin" + #Newsgroups: comp.unix.shell + #Subject: BASH: getopt function that parses long-named options + #Date: Mon, 22 Dec 1997 20:35:18 +0300 + + #Hi, I have written a BASH function named getoptex, that is like bash builtin + #"getopts", but does parse long-named options and optional arguments. It only + #uses builtin bash commands, so it is very fast. In order to use it in your + #bash scripts, include a command ". getopt.sh" ( getopt.sh) to the file + #containing your script, and that will define functions getopt, getoptex, and + #optlistex (the file getopt.sh with its detailed description is listed + #below). + + #*** file getopt.sh *** + + #! /bin/bash + # + # getopt.sh: + # functions like getopts but do long-named options parsing + # and support optional arguments + # + # Version 1.0 1997 by Grigoriy Strokin (grg@philol.msu.ru), Public Domain + # Date created: December 21, 1997 + # Date modified: December 21, 1997 + # + # IMPORTANT FEATURES + # + # 1) Parses both short and long-named options + # 2) Supports optional arguments + # 3) Only uses bash builtins, thus no calls to external + # utilities such as expr or sed is done. Therefore, + # parsing speed is high enough + # + # + # DESCRIPTION + # + # FUNCTION getopt + # Usage: getopt OPTLIST {"$@"|ALTERNATIVE_PARAMETERS} + # + # like getopts, but parse options with both required and optional arguments, + # Options with optional arguments must have "." instead of ":" after them. + # Furthemore, a variable name to place option name cannot be specified + # and is always placed in OPTOPT variable + # + # This function is provided for compatibility with getopts() + # OPTLIST style, and it actually calls getoptex (see bellow) + # + # NOTE that a list of parameters is required and must be either "$@", + # if processing command line arguments, or some alternative parameters. + # + # FUNCTION getoptex + # Usage: getoptex OPTION_LIST {"$@"|ALTERNATIVE_PARAMETERS} + # + # like getopts, but parse long-named options. + # + # Both getopt and getoptex return 0 if an option has been parsed, + # and 1 if all options are already parsed or an error occured + # + # Both getopt and getoptex set or test the following variables: + # + # OPTERR -- tested for whether error messages must be given for invalid + options + # + # OPTOPT -- set to the name of an option parsed, + # or to "?" if no more options or error + # OPTARG -- set to the option argument, if any; + # unset if ther is no argument; + # on error, set to the erroneous option name + # + # OPTIND -- Initialized to 1. + # Then set to the number of the next parameter to be parsed + # when getopt or getoptex will be called next time. + # When all options are parsed, contains a number of + # the first non-option argument. + # + # + # OPTOFS -- If a parameter number $OPTIND containg an option parsed + # does not contain any more options, OPTOFS is unset; + # otherwise, OPTOFS is set to such a number of "?" signs + # which is equal to the number of options parsed + # + # You might not set variables OPTIND and OPTOFS yourself + # unless you want to parse a list of parameters more than once. + # Otherwise, you whould unset OPTIND (or set it to 1) + # and unset OPTOFS each time you want to parse a new parameters + list + # + # Option list format is DIFFERENT from one for getopts or getopt. + getopts-style + # option list can be converted to getoptex-style using a function optlistex + # (see bellow) + # + # DESCRIPTION of option list used with getoptex: + # Option names are separated by whitespace. Options consiting of + # more than one character are treated as long-named (--option) + # + # Special characters can appear at the and of option names specifying + # whether an argument is required (default is ";"): + # ";" (default) -- no argument + # ":" -- required argument + # "," -- optional argument + # + # For example, an option list "a b c help version f: file: separator." + # defines the following options: + # -a, -b, -c, --help, --version -- no argument + # -f, --file -- argument required + # --separator -- optional argument + # + # FUNCTION optlistex + # Usage new_style_optlist=`optlistex OLD_STYLE_OPTLIST` + # + # Converts getopts-style option list in a format suitable for use with getoptex + # Namely, it inserts spaces after each option name. + # + # + # HOW TO USE + # + # In order o use in your bash scripts the functions described, + # include a command ". getopt.sh" to the file containing the script, + # which will define functions getopt, getoptex, and optlistex + # + # EXAMPLES + # + # See files 'getopt1' and 'getopt2' that contain sample scripts that use + # getopt and getoptex functions respectively + # + # + # Please send your comments to grg@philol.msu.ru + + function getoptex() + { + let $# || return 1 + local optlist="${1#;}" + let OPTIND || OPTIND=1 + [ $OPTIND -lt $# ] || return 1 + shift $OPTIND + if [ "$1" != "-" -a "$1" != "${1#-}" ] + then OPTIND=$[OPTIND+1]; if [ "$1" != "--" ] + then + local o + o="-${1#-$OPTOFS}" + for opt in ${optlist#;} + do + OPTOPT="${opt%[;.:]}" + unset OPTARG + local opttype="${opt##*[^;:.]}" + [ -z "$opttype" ] && opttype=";" + if [ ${#OPTOPT} -gt 1 ] + then # long-named option + case $o in + "--$OPTOPT") + if [ "$opttype" != ":" ]; then return 0; fi + OPTARG="$2" + if [ -z "$OPTARG" ]; + then # error: must have an agrument + let OPTERR && echo "$0: error: $OPTOPT must have an argument" >&2 + OPTARG="$OPTOPT"; + OPTOPT="?" + return 1; + fi + OPTIND=$[OPTIND+1] # skip option's argument + return 0 + ;; + "--$OPTOPT="*) + if [ "$opttype" = ";" ]; + then # error: must not have arguments + let OPTERR && echo "$0: error: $OPTOPT must not have arguments" >&2 + OPTARG="$OPTOPT" + OPTOPT="?" + return 1 + fi + OPTARG=${o#"--$OPTOPT="} + return 0 + ;; + esac + else # short-named option + case "$o" in + "-$OPTOPT") + unset OPTOFS + [ "$opttype" != ":" ] && return 0 + OPTARG="$2" + if [ -z "$OPTARG" ] + then + echo "$0: error: -$OPTOPT must have an argument" >&2 + OPTARG="$OPTOPT" + OPTOPT="?" + return 1 + fi + OPTIND=$[OPTIND+1] # skip option's argument + return 0 + ;; + "-$OPTOPT"*) + if [ $opttype = ";" ] + then # an option with no argument is in a chain of options + OPTOFS="$OPTOFS?" # move to the next option in the chain + OPTIND=$[OPTIND-1] # the chain still has other options + return 0 + else + unset OPTOFS + OPTARG="${o#-$OPTOPT}" + return 0 + fi + ;; + esac + fi + done + echo "$0: error: invalid option: $o" + fi; fi + OPTOPT="?" + unset OPTARG + return 1 + } + function optlistex + { + local l="$1" + local m # mask + local r # to store result + while [ ${#m} -lt $[${#l}-1] ]; do m="$m?"; done # create a "???..." mask + while [ -n "$l" ] + do + r="${r:+"$r "}${l%$m}" # append the first character of $l to $r + l="${l#?}" # cut the first charecter from $l + m="${m#?}" # cut one "?" sign from m + if [ -n "${l%%[^:.;]*}" ] + then # a special character (";", ".", or ":") was found + r="$r${l%$m}" # append it to $r + l="${l#?}" # cut the special character from l + m="${m#?}" # cut one more "?" sign + fi + done + echo $r + } + function getopt() + { + local optlist=`optlistex "$1"` + shift + getoptex "$optlist" "$@" + return $? + } + + #************************************** + # cut here + #************************************** + #*** (end of getopt.sh) *** + + + #*** file getopt1 *** + + #! /bin/bash + # getopt1: + # Sample script using the function getopt + # + # Type something like "getopt1 -ab -d 10 -e20 text1 text2" + # on the command line to see how it works + # + # See getopt.sh for more information + #. getopt.sh + #echo Using getopt to parse arguments: + #while getopt "abcd:e." "$@" + #do + # echo "Option <$OPTOPT> ${OPTARG:+has an arg <$OPTARG>}" + #done + #shift $[OPTIND-1] + #for arg in "$@" + #do + # echo "Non option argument <$arg>" + #done + # + #************************************** + # cut here + #************************************** + #*** (end of getopt1) *** + # + # + #*** file getopt2 *** + # + #! /bin/bash + # getopt2: + # Sample script using the function getoptex + # + # Type something like "getopt2 -ab -d 10 -e20 --opt1 --opt4=100 text1 text2" + # to see how it works + # + # See getopt.sh for more information + . getopt.sh + #echo Using getoptex to parse arguments: + #while getoptex "a; b; c; d: e. opt1 opt2 opt3 opt4: opt5." "$@" + #do + # echo "Option <$OPTOPT> ${OPTARG:+has an arg <$OPTARG>}" + #done + #shift $[OPTIND-1] + #for arg in "$@" + #do + # echo "Non option argument <$arg>" + #done + # + #************************************** + # cut here + #************************************** + #*** (end of getopt2) *** + + diff -Nrc2 bash-2.01.1/examples/functions/inetaddr bash-2.02/examples/functions/inetaddr *** bash-2.01.1/examples/functions/inetaddr Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/functions/inetaddr Mon Nov 3 15:04:16 1997 *************** *** 0 **** --- 1,44 ---- + # + # inet2hex - Internet address conversion, dotted-decimal to hex + # + inet2hex () + { + local IFS + + IFS=. + set -- $1 + + if (( $# != 4 )); then + echo "inet2hex: incorrect input format: $1" >&2 + echo "inet2hex: usage: inet2hex XX.XX.XX.XX" >&2 + return 2 + fi + + printf "0x%02x%02x%02x%02x\n" $1 $2 $3 $4 + } + + # + # hex2inet - Internet address conversion, hex to dotted-decimal + # + hex2inet () + { + local x1 x2 x3 x4 + + case "$1" in + 0x*) h=${1#??} ;; + *) h=$1 ;; + esac + + if (( ${#h} != 8 )); then + echo "hex2inet: $h not in inet format" >&2 + echo "hex2inet: usage: hex2inet [0x]XXXXXXXX" >&2 + return 2 + fi + + x1=$(( 0x${h:0:2} )) + x2=$(( 0x${h:2:2} )) + x3=$(( 0x${h:4:2} )) + x4=$(( 0x${h:6:2} )) + + printf "%d.%d.%d.%d\n" $x1 $x2 $x3 $x4 + } diff -Nrc2 bash-2.01.1/examples/functions/inpath bash-2.02/examples/functions/inpath *** bash-2.01.1/examples/functions/inpath Thu Sep 1 15:14:43 1994 --- bash-2.02/examples/functions/inpath Tue Mar 3 12:57:14 1998 *************** *** 1,4 **** --- 1,5 ---- inpath() { + local PROG path=$(echo $PATH | sed 's/^:/.:/ s/::/:.:/g *************** *** 10,15 **** [ -x $x/$1 ] && { PROG=$x/$1; break; } done ! [ -z "$PROG" ] ! return } - --- 11,14 ---- [ -x $x/$1 ] && { PROG=$x/$1; break; } done ! [ -n "$PROG" ] } diff -Nrc2 bash-2.01.1/examples/functions/isnum.bash bash-2.02/examples/functions/isnum.bash *** bash-2.01.1/examples/functions/isnum.bash Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/functions/isnum.bash Fri Feb 6 15:53:08 1998 *************** *** 0 **** --- 1,23 ---- + #From: jrmartin@rainey.blueneptune.com (James R. Martin) + #Newsgroups: comp.unix.shell + #Subject: Re: testing user input on numeric or character value + #Date: 26 Nov 1997 01:28:43 GMT + + # isnum returns True if its argument is a valid number, + # and False (retval=1) if it is any other string. + # The first pattern requires a digit before the decimal + # point, and the second after the decimal point. + + # BASH NOTE: make sure you have executed `shopt -s extglob' before + # trying to use this function, or it will not work + + function isnum # string + { + case $1 in + ?([-+])+([0-9])?(.)*([0-9])?([Ee]?([-+])+([0-9])) ) + return 0;; + ?([-+])*([0-9])?(.)+([0-9])?([Ee]?([-+])+([0-9])) ) + return 0;; + *) return 1;; + esac + } diff -Nrc2 bash-2.01.1/examples/functions/isnum2 bash-2.02/examples/functions/isnum2 *** bash-2.01.1/examples/functions/isnum2 Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/functions/isnum2 Mon Feb 16 14:30:04 1998 *************** *** 0 **** --- 1,22 ---- + isnum2() + { + case "$1" in + '[-+]' | '') return 1;; # empty or bare `-' or `+' + [-+]*[!0-9]*) return 1;; # non-digit with leading sign + [-+]*) return 0;; # OK + *[!0-9]*) return 1;; # non-digit + *) return 0;; # OK + esac + } + + # this one handles floating point + isnum3() + { + case "$1" in + '') return 1;; # empty + *[!0-9.+-]*) return 1;; # non-digit, +, -, or . + *?[-+]*) return 1;; # sign as second or later char + *.*.*) return 1;; # multiple decimal points + *) return 0;; # OK + esac + } diff -Nrc2 bash-2.01.1/examples/functions/jdate.bash bash-2.02/examples/functions/jdate.bash *** bash-2.01.1/examples/functions/jdate.bash Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/functions/jdate.bash Tue Mar 3 12:46:10 1998 *************** *** 0 **** --- 1,78 ---- + #From: damatex@CAM.ORG (Mario Boudreault) + #Newsgroups: comp.unix.shell + #Subject: JULIAN DATE CONVERSION SUB + #Date: 4 Aug 1995 10:23:28 -0400 + #Message-ID: <3vtah0$jb3@ocean.CAM.ORG> + + #For those using shells and who want to convert dates to a julian number + #here is a shell script (wihtout validation) that can be used as a base + #program for your shell scripts. + + #Special thanks to Ed Ferguson@ti.com who sent me the algorithm to compute + #that date. + + # + # MODIFIED BY CHET RAMEY TO CONVERT TO bash v2 SYNTAX + # + + # cnvdate - Conversion de dates en julienne et vice et versa... + # + # Par : Mario Boudreault Damatex Inc Montreal, Canada + # Date: 2 Aout 1995 + # Rev.: 2 Aout 1995 + # + # Usage: + # cvdate [-j] YYYMMDD pour convertir en nbre de jours + # cvdate -d {julian number} pour convertir en AAAAMMJJ + # + + jul_date() + { + # + # Separe ANNEE, MOIS et JOUR... + # + YEAR=`echo $DATE | awk ' { print substr($0,1,4) } '` + MONTH=`echo $DATE | awk ' { print substr($0,5,2) } '` + DAY=`echo $DATE | awk ' { print substr($0,7,2) } '` + # + # Execute la formule magique... + # + A=$(( $DAY - 32075 + 1461 * ( $YEAR + 4800 - ( 14 - $MONTH ) / 12 ) \ + / 4 + 367 * ( $MONTH - 2 + ( 14 - $MONTH ) / 12 * 12 ) / 12 - \ + 3 * ( ( $YEAR + 4900 - ( 14 - $MONTH ) / 12 ) / 100 ) / 4 )) + echo $A + } + + day_date() + { + TEMP1=$(( $DATE + 68569 )) + TEMP2=$(( 4 * $TEMP1 / 146097 )) + TEMP1=$(( $TEMP1 - ( 146097 * $TEMP2 + 3 ) / 4 )) + Y=$(( 4000 * ( $TEMP1 + 1 ) / 1461001 )) + TEMP1=$(( $TEMP1 - 1461 * $Y / 4 + 31 )) + M=$(( 80 * $TEMP1 / 2447 )) + D=$(( $TEMP1 - 2447 * $M / 80 )) + TEMP1=$(( $M / 11 )) + M=$(( $M + 2 - 12 * $TEMP1 )) + Y=$(( 100 * ( $TEMP2 - 49 ) + $Y + $TEMP1 )) + M=`echo $M | awk ' { M=$0 ; if ( length($0) == 1 ) M="0"$0 } END { print M } '` + D=`echo $D | awk ' { D=$0 ; if ( length($0) == 1 ) D="0"$0 } END { print D } '` + echo $Y$M$D + } + + # main() + + if [ $# -eq 1 ]; then + DATE=$1 + jul_date + elif [ "$1" = '-j' ]; then + DATE=$2 + jul_date + elif [ "$1" = '-d' ]; then + DATE=$2 + day_date + fi + # + # Termine + # + exit 0 diff -Nrc2 bash-2.01.1/examples/functions/pathfuncs bash-2.02/examples/functions/pathfuncs *** bash-2.01.1/examples/functions/pathfuncs Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/functions/pathfuncs Tue Mar 3 12:54:30 1998 *************** *** 0 **** --- 1,48 ---- + #From: "Simon J. Gerraty" + #Message-Id: <199510091130.VAA01188@zen.void.oz.au> + #Subject: Re: a shell idea? + #Date: Mon, 09 Oct 1995 21:30:20 +1000 + + + # NAME: + # add_path.sh - add dir to path + # + # DESCRIPTION: + # These functions originated in /etc/profile and ksh.kshrc, but + # are more useful in a separate file. + # + # SEE ALSO: + # /etc/profile + # + # AUTHOR: + # Simon J. Gerraty + + # RCSid: + # $Id: add_path.sh,v 1.1 1995/09/30 12:45:23 sjg Exp $ + # + # @(#)Copyright (c) 1991 Simon J. Gerraty + # + # This file is provided in the hope that it will + # be of use. There is absolutely NO WARRANTY. + # Permission to copy, redistribute or otherwise + # use this file is hereby granted provided that + # the above copyright notice and this notice are + # left intact. + + # is $1 missing from $2 (or PATH) ? + no_path() { + eval "case :\$${2-PATH}: in *:$1:*) return 1;; *) return 0;; esac" + } + # if $1 exists and is not in path, append it + add_path () { + [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="\$${2:-PATH}:$1" + } + # if $1 exists and is not in path, prepend it + pre_path () { + [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$1:\$${2:-PATH}" + } + # if $1 is in path, remove it + del_path () { + no_path $* || eval ${2:-PATH}=`eval echo :'$'${2:-PATH}: | + sed -e "s;:$1:;:;g" -e "s;^:;;" -e "s;:\$;;"` + } diff -Nrc2 bash-2.01.1/examples/functions/shcat2 bash-2.02/examples/functions/shcat2 *** bash-2.01.1/examples/functions/shcat2 Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/functions/shcat2 Tue Mar 3 12:23:26 1998 *************** *** 0 **** --- 1,19 ---- + shcat() + { + while read -r line + do + echo "$line" + done + } + + shcat2() + { + while [ $# -ge 1 ]; do + case "$1" in + -) shcat ;; + *) shcat < "$1" ;; + esac + shift + done + exit 0 + } diff -Nrc2 bash-2.01.1/examples/loadables/Makefile bash-2.02/examples/loadables/Makefile *** bash-2.01.1/examples/loadables/Makefile Thu Oct 31 10:53:23 1996 --- bash-2.02/examples/loadables/Makefile Wed Dec 31 19:00:00 1969 *************** *** 1,112 **** - # - # Simple makefile for the sample loadable builtins - # - CC = cc - - # SunOS 4 - PICFLAG = -pic - # Some versions of gcc, esp. on NetBSD and FreeBSD - #PICFLAG = -fpic - # Linux -- could also be -fpic - #PICFLAG = -fPIC - # SunOS 5 - #PICFLAG = -K pic - # SVR4, SVR4.2, Irix - #PICFLAG = -K PIC - # BSD/OS 2.1 - #PICFLAG = - # AIX 4.2 - #PICFLAG = -K - - # SunOS 4, BSD/OS 2.1, SVR4.2, SVR4, Linux, AIX 4.2, etc. - LD = ld - # SunOS 5, Linux - #LD = cc - - # SunOS 4 - LDOPT = -assert pure-text - # OSF/1, Digital UNIX - #LDOPT = -shared -soname $@ -expect_unresolved '*' - # SunOS 5 - #LDOPT = -dy -z text -G -i -h $@ - # SVR4, SVR4.2 - #LDOPT = -dy -z text -G -h $@ - # NetBSD, FreeBSD -- might also need -r - #LDOPT = -x -Bshareable - # Linux - #LDOPT = -shared - # BSD/OS 2.1 - #LDOPT = -r - # AIX 4.2 - #LDOPT = -bdynamic -bnoentry -bexpall -G - - # other libraries to link the shared object against - # BSD/OS 2.1 - #LDLIBS = -lc_s.2.1.0 - - srcdir = ../.. - INC= -I$(srcdir) -I$(srcdir)/builtins -I$(srcdir)/lib - - .c.o: - $(CC) $(PICFLAG) $(CFLAGS) $(INC) -c -o $@ $< - - all: printf print truefalse sleep pushd finfo logname basename dirname \ - tty pathchk tee head rmdir sprintf - others: necho getconf hello cat - - printf: printf.o - $(LD) $(LDOPT) -o $@ printf.o $(LDLIBS) - - sprintf: sprintf.o - $(LD) $(LDOPT) -o $@ sprintf.o $(LDLIBS) - - print: print.o - $(LD) $(LDOPT) -o $@ print.o $(LDLIBS) - - necho: necho.o - $(LD) $(LDOPT) -o $@ necho.o $(LDLIBS) - - getconf: getconf.o - $(LD) $(LDOPT) -o $@ getconf.o $(LDLIBS) - - hello: hello.o - $(LD) $(LDOPT) -o $@ hello.o $(LDLIBS) - - truefalse: truefalse.o - $(LD) $(LDOPT) -o $@ truefalse.o $(LDLIBS) - - sleep: sleep.o - $(LD) $(LDOPT) -o $@ sleep.o $(LDLIBS) - - pushd: pushd.o - $(LD) $(LDOPT) -o $@ pushd.o $(LDLIBS) - - finfo: finfo.o - $(LD) $(LDOPT) -o $@ finfo.o $(LDLIBS) - - cat: cat.o - $(LD) $(LDOPT) -o $@ cat.o $(LDLIBS) - - logname: logname.o - $(LD) $(LDOPT) -o $@ logname.o $(LDLIBS) - - basename: basename.o - $(LD) $(LDOPT) -o $@ basename.o $(LDLIBS) - - dirname: dirname.o - $(LD) $(LDOPT) -o $@ dirname.o $(LDLIBS) - - tty: tty.o - $(LD) $(LDOPT) -o $@ tty.o $(LDLIBS) - - pathchk: pathchk.o - $(LD) $(LDOPT) -o $@ pathchk.o $(LDLIBS) - - tee: tee.o - $(LD) $(LDOPT) -o $@ tee.o $(LDLIBS) - - rmdir: rmdir.o - $(LD) $(LDOPT) -o $@ rmdir.o $(LDLIBS) - - head: head.o - $(LD) $(LDOPT) -o $@ head.o $(LDLIBS) --- 0 ---- diff -Nrc2 bash-2.01.1/examples/loadables/Makefile.in bash-2.02/examples/loadables/Makefile.in *** bash-2.01.1/examples/loadables/Makefile.in Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/loadables/Makefile.in Thu Feb 19 15:12:52 1998 *************** *** 0 **** --- 1,169 ---- + # + # Simple makefile for the sample loadable builtins + # + # This includes some boilerplate definitions added by configure, but will + # still need hand-editing + # + # 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 = /bin/sh + + # SunOS 4 + #PICFLAG = -pic + # Some versions of gcc, esp. on NetBSD and FreeBSD + PICFLAG = -fpic + # Linux -- could also be -fpic + #PICFLAG = -fPIC + # SunOS 5 + #PICFLAG = -K pic + # SVR4, SVR4.2, Irix + #PICFLAG = -K PIC + # BSD/OS 2.1, BSD/OS 3.x + #PICFLAG = + # AIX 4.2 + #PICFLAG = -K + + # SunOS 4, BSD/OS 2.1, BSD/OS 3.x, SVR4.2, SVR4, Linux, AIX 4.2, etc. + LD = ld + # SunOS 5, Linux + #LD = ${CC} + + # SunOS 4 + #LDOPT = -assert pure-text + # OSF/1, Digital UNIX + #LDOPT = -shared -soname $@ -expect_unresolved '*' + # SunOS 5 using sun cc + #LDOPT = -dy -z text -G -i -h $@ + # SunOS 5 using gcc with Sun ld + #LDOPT = -shared -Wl,-dy -Wl,-G -Wl,-i + # SVR4, SVR4.2 + #LDOPT = -dy -z text -G -h $@ + # NetBSD, FreeBSD -- might also need -r + LDOPT = -x -Bshareable + # Linux + #LDOPT = -shared + # BSD/OS 2.1, BSD/OS 3.x + #LDOPT = -r + # AIX 4.2 + #LDOPT = -bdynamic -bnoentry -bexpall -G + + # other libraries to link the shared object against + # BSD/OS 2.1 + #LDLIBS = -lc_s.2.1.0 + # BSD/OS 3.0, BSD/OS 3.1 + #LDLIBS = -lc_s.3.0.0 + + + INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \ + -I$(BUILD_DIR) -I$(BUILD_DIR)/lib -I$(BUILD_DIR)/builtins + + .c.o: + $(CC) $(PICFLAG) $(CFLAGS) $(INC) -c -o $@ $< + + + ALLPROG = print truefalse sleep pushd finfo logname basename dirname \ + tty pathchk tee head rmdir sprintf + OTHERPROG = necho getconf hello cat + + all: $(ALLPROG) + others: $(OTHERPROG) + + everything: all others + + sprintf: sprintf.o + $(LD) $(LDOPT) -o $@ sprintf.o $(LDLIBS) + + print: print.o + $(LD) $(LDOPT) -o $@ print.o $(LDLIBS) + + necho: necho.o + $(LD) $(LDOPT) -o $@ necho.o $(LDLIBS) + + getconf: getconf.o + $(LD) $(LDOPT) -o $@ getconf.o $(LDLIBS) + + hello: hello.o + $(LD) $(LDOPT) -o $@ hello.o $(LDLIBS) + + truefalse: truefalse.o + $(LD) $(LDOPT) -o $@ truefalse.o $(LDLIBS) + + sleep: sleep.o + $(LD) $(LDOPT) -o $@ sleep.o $(LDLIBS) + + pushd: pushd.o + $(LD) $(LDOPT) -o $@ pushd.o $(LDLIBS) + + finfo: finfo.o + $(LD) $(LDOPT) -o $@ finfo.o $(LDLIBS) + + cat: cat.o + $(LD) $(LDOPT) -o $@ cat.o $(LDLIBS) + + logname: logname.o + $(LD) $(LDOPT) -o $@ logname.o $(LDLIBS) + + basename: basename.o + $(LD) $(LDOPT) -o $@ basename.o $(LDLIBS) + + dirname: dirname.o + $(LD) $(LDOPT) -o $@ dirname.o $(LDLIBS) + + tty: tty.o + $(LD) $(LDOPT) -o $@ tty.o $(LDLIBS) + + pathchk: pathchk.o + $(LD) $(LDOPT) -o $@ pathchk.o $(LDLIBS) + + tee: tee.o + $(LD) $(LDOPT) -o $@ tee.o $(LDLIBS) + + rmdir: rmdir.o + $(LD) $(LDOPT) -o $@ rmdir.o $(LDLIBS) + + head: head.o + $(LD) $(LDOPT) -o $@ head.o $(LDLIBS) + + clean: + $(RM) $(ALLPROG) $(OTHERPROG) *.o + + mostlyclean: clean + + distclean maintainer-clean: clean + $(RM) Makefile + + print.o: print.c + truefalse.o: truefalse.c + sleep.o: sleep.c + pushd.o: pushd.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 + sprintf.o: sprintf.c + necho.o: necho.c + getconf.o: getconf.c + hello.o: hello.c + cat.o: cat.c + diff -Nrc2 bash-2.01.1/examples/loadables/getconf.c bash-2.02/examples/loadables/getconf.c *** bash-2.01.1/examples/loadables/getconf.c Thu Jul 25 12:54:39 1996 --- bash-2.02/examples/loadables/getconf.c Mon Mar 2 14:41:43 1998 *************** *** 1,3 **** --- 1,5 ---- /* + * ORIGINAL COPYRIGHT STATEMENT: + * * Copyright (c) 1994 Winning Strategies, Inc. * All rights reserved. *************** *** 32,43 **** * POSIX.2 getconf utility * ! * Written by: * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc. */ - #ifndef lint - static char rcsid[] = "$Id: getconf.c,v 1.2 1994/05/10 00:04:12 jtc Exp $"; - #endif /* not lint */ - #include #include --- 34,44 ---- * POSIX.2 getconf utility * ! * Originally Written by: * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc. + * + * Heavily modified for inclusion in bash by + * Chet Ramey */ #include #include *************** *** 49,53 **** #include "builtins.h" #include "stdc.h" ! struct conf_variable --- 50,55 ---- #include "builtins.h" #include "stdc.h" ! #include "common.h" ! #include "bashgetopt.h" struct conf_variable *************** *** 58,71 **** }; ! /* BSD/OS does not define this; use Posix.2 recommended minimum value. */ #ifndef _POSIX2_COLL_WEIGHTS_MAX ! #define _POSIX2_COLL_WEIGHTS_MAX 2 #endif static const struct conf_variable conf_table[] = { { "PATH", CONFSTR, _CS_PATH }, ! /* Utility Limit Minimum Values */ { "POSIX2_BC_BASE_MAX", CONSTANT, _POSIX2_BC_BASE_MAX }, { "POSIX2_BC_DIM_MAX", CONSTANT, _POSIX2_BC_DIM_MAX }, --- 60,109 ---- }; ! /* Some systems do not define these; use POSIX.2 minimum recommended values. */ #ifndef _POSIX2_COLL_WEIGHTS_MAX ! # define _POSIX2_COLL_WEIGHTS_MAX 2 #endif static const struct conf_variable conf_table[] = { + /* POSIX.2 Configurable Variable Values */ { "PATH", CONFSTR, _CS_PATH }, + { "CS_PATH", CONFSTR, _CS_PATH }, + + /* POSIX.1 Configurable Variable Values (only Solaris?) */ + #if defined (_CS_LFS_CFLAGS) + { "LFS_CFLAGS", CONFSTR, _CS_LFS_CFLAGS }, + { "LFS_LDFLAGS", CONFSTR, _CS_LFS_LDFLAGS }, + { "LFS_LIBS", CONFSTR, _CS_LFS_LIBS }, + { "LFS_LINTFLAGS", CONFSTR, _CS_LFS_LINTFLAGS }, + #endif + #if defined (_CS_LFS64_CFLAGS) + { "LFS64_CFLAGS", CONFSTR, _CS_LFS64_CFLAGS }, + { "LFS64_LDFLAGS", CONFSTR, _CS_LFS64_LDFLAGS }, + { "LFS64_LIBS", CONFSTR, _CS_LFS64_LIBS }, + { "LFS64_LINTFLAGS", CONFSTR, _CS_LFS64_LINTFLAGS }, + #endif + + /* Single UNIX Specification version 2 Configurable Variable Values */ + #if defined (_CS_XBS5_ILP32_OFF32_CFLAGS) + { "XBS5_ILP32_OFF32_CFLAGS", CONFSTR, _CS_XBS5_ILP32_OFF32_CFLAGS }, + { "XBS5_ILP32_OFF32_LDFLAGS", CONFSTR, _CS_XBS5_ILP32_OFF32_LDFLAGS }, + { "XBS5_ILP32_OFF32_LIBS", CONFSTR, _CS_XBS5_ILP32_OFF32_LIBS }, + { "XBS5_ILP32_OFF32_LINTFLAGS", CONFSTR, _CS_XBS5_ILP32_OFF32_LINTFLAGS }, + { "XBS5_ILP32_OFFBIG_CFLAGS", CONFSTR, _CS_XBS5_ILP32_OFFBIG_CFLAGS }, + { "XBS5_ILP32_OFFBIG_LDFLAGS", CONFSTR, _CS_XBS5_ILP32_OFFBIG_LDFLAGS }, + { "XBS5_ILP32_OFFBIG_LIBS", CONFSTR, _CS_XBS5_ILP32_OFFBIG_LIBS }, + { "XBS5_ILP32_OFFBIG_LINTFLAGS", CONFSTR, _CS_XBS5_ILP32_OFFBIG_LINTFLAGS }, + { "XBS5_LP64_OFF64_CFLAGS", CONFSTR, _CS_XBS5_LP64_OFF64_CFLAGS }, + { "XBS5_LP64_OFF64_LDFLAGS", CONFSTR, _CS_XBS5_LP64_OFF64_LDFLAGS }, + { "XBS5_LP64_OFF64_LIBS", CONFSTR, _CS_XBS5_LP64_OFF64_LIBS }, + { "XBS5_LP64_OFF64_LINTFLAGS", CONFSTR, _CS_XBS5_LP64_OFF64_LINTFLAGS }, + { "XBS5_LPBIG_OFFBIG_CFLAGS", CONFSTR, _CS_XBS5_LPBIG_OFFBIG_CFLAGS }, + { "XBS5_LPBIG_OFFBIG_LDFLAGS", CONFSTR, _CS_XBS5_LPBIG_OFFBIG_LDFLAGS }, + { "XBS5_LPBIG_OFFBIG_LIBS", CONFSTR, _CS_XBS5_LPBIG_OFFBIG_LIBS }, + { "XBS5_LPBIG_OFFBIG_LINTFLAGS", CONFSTR, _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS }, + #endif /* _CS_XBS5_ILP32_OFF32_CFLAGS */ ! /* POSIX.2 Utility Limit Minimum Values */ { "POSIX2_BC_BASE_MAX", CONSTANT, _POSIX2_BC_BASE_MAX }, { "POSIX2_BC_DIM_MAX", CONSTANT, _POSIX2_BC_DIM_MAX }, *************** *** 73,80 **** --- 111,123 ---- { "POSIX2_BC_STRING_MAX", CONSTANT, _POSIX2_BC_STRING_MAX }, { "POSIX2_COLL_WEIGHTS_MAX", CONSTANT, _POSIX2_COLL_WEIGHTS_MAX }, + #if defined (_POSIX2_EQUIV_CLASS_MAX) + { "POSIX2_EQUIV_CLASS_MAX", CONSTANT, _POSIX2_EQUIV_CLASS_MAX }, + #endif { "POSIX2_EXPR_NEST_MAX", CONSTANT, _POSIX2_EXPR_NEST_MAX }, { "POSIX2_LINE_MAX", CONSTANT, _POSIX2_LINE_MAX }, { "POSIX2_RE_DUP_MAX", CONSTANT, _POSIX2_RE_DUP_MAX }, + #if defined (_POSIX2_VERSION) { "POSIX2_VERSION", CONSTANT, _POSIX2_VERSION }, + #endif /* POSIX.1 Minimum Values */ *************** *** 93,97 **** { "_POSIX_TZNAME_MAX", CONSTANT, _POSIX_TZNAME_MAX }, ! /* Symbolic Utility Limits */ { "BC_BASE_MAX", SYSCONF, _SC_BC_BASE_MAX }, { "BC_DIM_MAX", SYSCONF, _SC_BC_DIM_MAX }, --- 136,140 ---- { "_POSIX_TZNAME_MAX", CONSTANT, _POSIX_TZNAME_MAX }, ! /* POSIX.2 Symbolic Utility Limits */ { "BC_BASE_MAX", SYSCONF, _SC_BC_BASE_MAX }, { "BC_DIM_MAX", SYSCONF, _SC_BC_DIM_MAX }, *************** *** 103,115 **** { "RE_DUP_MAX", SYSCONF, _SC_RE_DUP_MAX }, ! /* Optional Facility Configuration Values */ { "POSIX2_C_BIND", SYSCONF, _SC_2_C_BIND }, { "POSIX2_C_DEV", SYSCONF, _SC_2_C_DEV }, { "POSIX2_CHAR_TERM", SYSCONF, _SC_2_CHAR_TERM }, { "POSIX2_FORT_DEV", SYSCONF, _SC_2_FORT_DEV }, { "POSIX2_FORT_RUN", SYSCONF, _SC_2_FORT_RUN }, { "POSIX2_LOCALEDEF", SYSCONF, _SC_2_LOCALEDEF }, { "POSIX2_SW_DEV", SYSCONF, _SC_2_SW_DEV }, { "POSIX2_UPE", SYSCONF, _SC_2_UPE }, /* POSIX.1 Configurable System Variables */ --- 146,168 ---- { "RE_DUP_MAX", SYSCONF, _SC_RE_DUP_MAX }, ! /* POSIX.2 Optional Facility Configuration Values */ { "POSIX2_C_BIND", SYSCONF, _SC_2_C_BIND }, { "POSIX2_C_DEV", SYSCONF, _SC_2_C_DEV }, + #if defined (_SC_2_C_VERSION) + { "POSIX2_C_VERSION", SYSCONF, _SC_2_C_VERSION }, + #endif + #if defined (_SC_2_CHAR_TERM) { "POSIX2_CHAR_TERM", SYSCONF, _SC_2_CHAR_TERM }, + #endif { "POSIX2_FORT_DEV", SYSCONF, _SC_2_FORT_DEV }, { "POSIX2_FORT_RUN", SYSCONF, _SC_2_FORT_RUN }, { "POSIX2_LOCALEDEF", SYSCONF, _SC_2_LOCALEDEF }, { "POSIX2_SW_DEV", SYSCONF, _SC_2_SW_DEV }, + #if defined (_SC2_UPE) { "POSIX2_UPE", SYSCONF, _SC_2_UPE }, + #endif + #if !defined (_POSIX2_VERSION) && defined (_SC_2_VERSION) + { "POSIX2_VERSION" SYSCONF, _SC_2_VERSION }, + #endif /* POSIX.1 Configurable System Variables */ *************** *** 125,128 **** --- 178,315 ---- { "_POSIX_VERSION", SYSCONF, _SC_VERSION }, + /* POSIX.1 Optional Facility Configuration Values */ + #if defined (_SC_ASYNCHRONOUS_IO) + { "_POSIX_ASYNCHRONOUS_IO", SYSCONF, _SC_ASYNCHRONOUS_IO }, + #endif + #if defined (_SC_FSYNC) + { "_POSIX_FSYNC", SYSCONF, _SC_FSYNC }, + #endif + #if defined (_SC_MAPPED_FILES) + { "_POSIX_MAPPED_FILES", SYSCONF, _SC_MAPPED_FILES }, + #endif + #if defined (_SC_MEMLOCK) + { "_POSIX_MEMLOCK", SYSCONF, _SC_MEMLOCK }, + #endif + #if defined (_SC_MEMLOCK_RANGE) + { "_POSIX_MEMLOCK_RANGE", SYSCONF, _SC_MEMLOCK_RANGE }, + #endif + #if defined (_SC_MEMORY_PROTECTION) + { "_POSIX_MEMORY_PROTECTION", SYSCONF, _SC_MEMORY_PROTECTION }, + #endif + #if defined (_SC_MESSAGE_PASSING) + { "_POSIX_MESSAGE_PASSING", SYSCONF, _SC_MESSAGE_PASSING }, + #endif + #if defined (SC_PRIORITIZED_IO) + { "_POSIX_PRIORITIZED_IO", SYSCONF, _SC_PRIORITIZED_IO }, + #endif + #if defined (_SC_PRIORITY_SCHEDULING) + { "_POSIX_PRIORITY_SCHEDULING", SYSCONF, _SC_PRIORITY_SCHEDULING }, + #endif + #if defined (_SC_REALTIME_SIGNALS) + { "_POSIX_REALTIME_SIGNALS", SYSCONF, _SC_REALTIME_SIGNALS }, + #endif + #if defined (_SC_SEMAPHORES) + { "_POSIX_SEMAPHORES", SYSCONF, _SC_SEMAPHORES }, + #endif + #if defined (_SC_SHARED_MEMORY_OBJECTS) + { "_POSIX_SHARED_MEMORY_OBJECTS", SYSCONF, _SC_SHARED_MEMORY_OBJECTS }, + #endif + #if defined (_SC_SYNCHRONIZED_IO) + { "_POSIX_SYNCHRONIZED_IO", SYSCONF, _SC_SYNCHRONIZED_IO }, + #endif + #if defined (_SC_TIMERS) + { "_POSIX_TIMERS", SYSCONF, _SC_TIMERS }, + #endif + #if defined (_SC_THREADS) + { "_POSIX_THREADS", SYSCONF, _SC_THREADS }, + { "_POSIX_THREAD_ATTR_STACKADDR", SYSCONF, _SC_THREAD_ATTR_STACKADDR }, + { "_POSIX_THREAD_ATTR_STACKSIZE", SYSCONF, _SC_THREAD_ATTR_STACKSIZE }, + { "_POSIX_THREAD_PRIORITY_SCHEDULING", SYSCONF, _SC_THREAD_PRIORITY_SCHEDULING }, + { "_POSIX_THREAD_PRIO_INHERIT", SYSCONF, _SC_THREAD_PRIO_INHERIT }, + { "_POSIX_THREAD_PRIO_PROTECT", SYSCONF, _SC_THREAD_PRIO_PROTECT }, + { "_POSIX_THREAD_PROCESS_SHARED", SYSCONF, _SC_THREAD_PROCESS_SHARED }, + # if defined (_SC_THREAD_SAFE_FUNCTIONS) + { "_POSIX_THREAD_SAFE_FUNCTIONS", SYSCONF, _SC_THREAD_SAFE_FUNCTIONS }, + # endif + #endif /* _SC_THREADS */ + + /* XPG 4.2 Configurable System Variables. */ + #if defined (_SC_ATEXIT_MAX) + { "ATEXIT_MAX", SYSCONF, _SC_ATEXIT_MAX }, + #endif + #if defined (_SC_IOV_MAX) + { "IOV_MAX", SYSCONF, _SC_IOV_MAX }, + #endif + #if defined (_SC_PAGESIZE) + { "PAGESIZE", SYSCONF, _SC_PAGESIZE }, + #endif + #if defined (_SC_PAGE_SIZE) + { "PAGE_SIZE", SYSCONF, _SC_PAGE_SIZE }, + #endif + + #if defined (_SC_AIO_LISTIO_MAX) + { "AIO_LISTIO_MAX", SYSCONF, _SC_AIO_LISTIO_MAX }, + { "AIO_MAX", SYSCONF, _SC_AIO_MAX }, + { "AIO_PRIO_DELTA_MAX", SYSCONF, _SC_AIO_PRIO_DELTA_MAX }, + { "DELAYTIMER_MAX", SYSCONF, _SC_DELAYTIMER_MAX }, + #if defined (_SC_GETGR_R_SIZE_MAX) + { "GETGR_R_SIZE_MAX", SYSCONF, _SC_GETGR_R_SIZE_MAX }, + #endif + #if defined (_SC_GETPW_R_SIZE_MAX) + { "GETPW_R_SIZE_MAX", SYSCONF, _SC_GETPW_R_SIZE_MAX }, + #endif + { "MQ_OPEN_MAX", SYSCONF, _SC_MQ_OPEN_MAX }, + { "MQ_PRIO_MAX", SYSCONF, _SC_MQ_PRIO_MAX }, + { "RTSIG_MAX", SYSCONF, _SC_RTSIG_MAX }, + { "SEM_NSEMS_MAX", SYSCONF, _SC_SEM_NSEMS_MAX }, + { "SEM_VALUE_MAX", SYSCONF, _SC_SEM_VALUE_MAX }, + { "SIGQUEUE_MAX", SYSCONF, _SC_SIGQUEUE_MAX }, + { "TIMER_MAX", SYSCONF, _SC_TIMER_MAX }, + #endif /* _SC_AIO_LISTIO_MAX */ + #if defined (_SC_LOGIN_NAME_MAX) + { "LOGIN_NAME_MAX", SYSCONF, _SC_LOGIN_NAME_MAX }, + #endif + #if defined (_SC_LOGNAME_MAX) + { "LOGNAME_MAX", SYSCONF, _SC_LOGNAME_MAX }, + #endif + #if defined (_SC_TTY_NAME_MAX) + { "TTY_NAME_MAX", SYSCONF, _SC_TTY_NAME_MAX }, + #endif + + #if defined (_SC_PTHREAD_DESTRUCTOR_ITERATIONS) + { "PTHREAD_DESTRUCTOR_ITERATIONS", SYSCONF, _SC_THREAD_DESTRUCTOR_ITERATIONS }, + { "PTHREAD_KEYS_MAX", SYSCONF, _SC_THREAD_KEYS_MAX }, + { "PTHREAD_STACK_MIN", SYSCONF, _SC_THREAD_STACK_MIN }, + { "PTHREAD_THREADS_MAX", SYSCONF, _SC_THREAD_THREADS_MAX }, + #endif /* _SC_PTHREAD_DESTRUCTOR_ITERATIONS */ + + /* XPG 4.2 Optional Facility Configuration Values */ + #if defined (_SC_XOPEN_UNIX) + { "_XOPEN_UNIX", SYSCONF, _SC_XOPEN_UNIX }, + { "_XOPEN_CRYPT", SYSCONF, _SC_XOPEN_CRYPT }, + { "_XOPEN_ENH_I18N", SYSCONF, _SC_XOPEN_ENH_I18N }, + { "_XOPEN_SHM", SYSCONF, _SC_XOPEN_SHM }, + { "_XOPEN_VERSION", SYSCONF, _SC_XOPEN_VERSION }, + # if defined (_SC_XOPEN_XCU_VERSION) + { "_XOPEN_XCU_VERSION", SYSCONF, _SC_XOPEN_XCU_VERSION }, + # endif + #endif + #if defined (_SC_XOPEN_REALTIME) + { "_XOPEN_REALTIME", SYSCONF, _SC_XOPEN_REALTIME }, + { "_XOPEN_REALTIME_THREADS", SYSCONF, _SC_XOPEN_REALTIME_THREADS }, + #endif + #if defined (_SC_XOPEN_LEGACY) + { "_XOPEN_LEGACY", SYSCONF, _SC_XOPEN_LEGACY }, + #endif /* _SC_XOPEN_LEGACY */ + + /* Single UNIX Specification version 2 Optional Facility Configuration Values */ + #if defined (_SC_XBS5_ILP32_OFF32) + { "_XBS5_ILP32_OFF32", SYSCONF, _SC_XBS5_ILP32_OFF32 }, + { "_XBS5_ILP32_OFFBIG", SYSCONF, _SC_XBS5_ILP32_OFFBIG }, + { "_XBS5_LP64_OFF64", SYSCONF, _SC_XBS5_LP64_OFF64 }, + { "_XBS5_LPBIG_OFFBIG", SYSCONF, _SC_XBS5_LPBIG_OFFBIG }, + #endif /* _SC_XBS5_ILP32_OFF32 */ + + /* POSIX.1 Configurable Pathname Values */ { "LINK_MAX", PATHCONF, _PC_LINK_MAX }, { "MAX_CANON", PATHCONF, _PC_MAX_CANON }, *************** *** 135,145 **** { "_POSIX_VDISABLE", PATHCONF, _PC_VDISABLE }, { NULL } }; extern char *this_command_name; extern char *xmalloc (); extern char **make_builtin_argv (); ! static int getconf_main (); int --- 322,352 ---- { "_POSIX_VDISABLE", PATHCONF, _PC_VDISABLE }, + /* XPG 4.2 Configurable Pathname Values */ + #if defined (_PC_FILESIZEBITS) + { "FILESIZEBITS", PATHCONF, _PC_FILESIZEBITS }, + #endif + #if defined (_PC_ASYNC_IO) + { "_POSIX_ASYNC_IO", PATHCONF, _PC_ASYNC_IO }, + #endif + #if defined (_PC_PRIO_IO) + { "_POSIX_PRIO_IO", PATHCONF, _PC_PRIO_IO }, + #endif + #if defined (_PC_SYNC_IO) + { "_POSIX_SYNC_IO", PATHCONF, _PC_SYNC_IO }, + #endif + { NULL } }; + static int num_getconf_variables = sizeof(conf_table) / sizeof(struct conf_variable) - 1; + extern char *this_command_name; extern char *xmalloc (); extern char **make_builtin_argv (); ! ! static void getconf_help (); ! static int getconf_print (); ! static int getconf_one (); ! static int getconf_all (); int *************** *** 147,213 **** WORD_LIST *list; { ! int c, r; char **v; - WORD_LIST *l; ! v = make_builtin_argv (list, &c); ! r = getconf_main (c, v); ! free (v); return r; } ! static int ! getconf_main(argc, argv) ! int argc; ! char **argv; { - int ch; const struct conf_variable *cp; ! long val; ! size_t slen; ! char *sval; ! ! setlocale(LC_ALL, ""); ! ! while ((ch = getopt(argc, argv, "")) != -1) { ! switch (ch) { ! case '?': ! default: ! builtin_usage(); ! return(EX_USAGE); ! /* NOTREACHED */ ! } ! } ! argc -= optind; ! argv += optind; ! ! if (argc < 1 || argc > 2) { ! builtin_usage(); ! return(EX_USAGE); ! /* NOTREACHED */ ! } ! for (cp = conf_table; cp->name != NULL; cp++) { ! if (strcmp(*argv, cp->name) == 0) ! break; ! } ! if (cp->name == NULL) { ! builtin_error ("%s: unknown variable", *argv); ! return (EXECUTION_FAILURE); } ! if (cp->type == PATHCONF) { ! if (argc != 2) { ! builtin_usage(); ! return(EX_USAGE); ! } ! } else { ! if (argc != 1) { ! builtin_usage(); ! return(EX_USAGE); ! } ! } switch (cp->type) { --- 354,412 ---- WORD_LIST *list; { ! int c, r, opt, aflag; char **v; ! aflag = 0; ! reset_internal_getopt(); ! while ((opt = internal_getopt (list, "ah")) != -1) { ! switch (opt) { ! case 'a': ! aflag = 1; ! break; ! case 'h': ! getconf_help(); ! return(EXECUTION_SUCCESS); ! default: ! builtin_usage(); ! return(EX_USAGE); ! } ! } ! ! list = loptend; ! if ((aflag == 0 && list == 0) || (aflag && list) || list_length(list) > 2) { ! builtin_usage(); ! return(EX_USAGE); ! } ! ! r = aflag ? getconf_all() : getconf_one(list); return r; } ! static void ! getconf_help() { const struct conf_variable *cp; + register int i, column; ! builtin_usage(); ! printf("Acceptable variable names are:\n"); for (cp = conf_table; cp->name != NULL; cp++) { ! if (cp->type == PATHCONF) ! printf("%s pathname\n", cp->name); ! else ! printf("%s\n", cp->name); } + } ! static int ! getconf_print(cp, vpath, all) ! struct conf_variable *cp; ! char *vpath; ! int all; ! { ! long val; ! char *sval; ! size_t slen; switch (cp->type) { *************** *** 217,226 **** case CONFSTR: slen = confstr (cp->value, (char *) 0, (size_t) 0); ! sval = xmalloc(slen); confstr(cp->value, sval, slen); printf("%s\n", sval); break; --- 416,436 ---- case CONFSTR: + errno = 0; slen = confstr (cp->value, (char *) 0, (size_t) 0); ! if (slen == 0) { ! if (errno != 0) { ! if (all) ! printf ("getconf: %s\n", strerror(errno)); ! else ! builtin_error ("%s", strerror(errno)); ! } else ! printf ("undefined\n"); ! return (EXECUTION_FAILURE); ! } sval = xmalloc(slen); confstr(cp->value, sval, slen); printf("%s\n", sval); + free(sval); break; *************** *** 229,233 **** if ((val = sysconf(cp->value)) == -1) { if (errno != 0) { ! builtin_error ("%s", strerror (errno)); return (EXECUTION_FAILURE); } --- 439,446 ---- if ((val = sysconf(cp->value)) == -1) { if (errno != 0) { ! if (all) ! printf("getconf: %s\n", strerror (errno)); ! else ! builtin_error ("%s", strerror (errno)); return (EXECUTION_FAILURE); } *************** *** 241,247 **** case PATHCONF: errno = 0; ! if ((val = pathconf(argv[1], cp->value)) == -1) { if (errno != 0) { ! builtin_error ("%s: %s", argv[1], strerror (errno)); return (EXECUTION_FAILURE); } --- 454,463 ---- case PATHCONF: errno = 0; ! if ((val = pathconf(vpath, cp->value)) == -1) { if (errno != 0) { ! if (all) ! printf("getconf: %s: %s\n", vpath, strerror (errno)); ! else ! builtin_error ("%s: %s", vpath, strerror (errno)); return (EXECUTION_FAILURE); } *************** *** 257,260 **** --- 473,526 ---- } + static int + getconf_all() + { + const struct conf_variable *cp; + int ret; + + ret = EXECUTION_SUCCESS; + for (cp = conf_table; cp->name != NULL; cp++) { + printf("%-35s", cp->name); + if (getconf_print(cp, ".", 1) == EXECUTION_FAILURE) + ret = EXECUTION_FAILURE; + } + return ret; + } + + static int + getconf_one(list) + WORD_LIST *list; + { + const struct conf_variable *cp; + char *vname, *vpath; + + vname = list->word->word; + vpath = (list->next && list->next->word) ? list->next->word->word + : (char *)NULL; + + for (cp = conf_table; cp->name != NULL; cp++) { + if (strcmp(vname, cp->name) == 0) + break; + } + if (cp->name == NULL) { + builtin_error ("%s: unknown variable", vname); + return (EXECUTION_FAILURE); + } + + if (cp->type == PATHCONF) { + if (list->next == 0) { + builtin_usage(); + return(EX_USAGE); + } + } else { + if (list->next) { + builtin_usage(); + return(EX_USAGE); + } + } + + return (getconf_print(cp, vpath, 0)); + } + static char *getconf_doc[] = { "getconf writes the current value of a configurable system limit or", *************** *** 268,272 **** BUILTIN_ENABLED, getconf_doc, ! "getconf sysvar or getconf pathvar pathname", 0 }; --- 534,538 ---- BUILTIN_ENABLED, getconf_doc, ! "getconf -a or getconf -h or getconf sysvar or getconf pathvar pathname", 0 }; diff -Nrc2 bash-2.01.1/examples/loadables/print.c bash-2.02/examples/loadables/print.c *** bash-2.01.1/examples/loadables/print.c Wed Oct 23 11:00:58 1996 --- bash-2.02/examples/loadables/print.c Thu Feb 19 11:06:26 1998 *************** *** 1,36 **** ! /* ! * Copyright (c) 1989, 1993 ! * The Regents of the University of California. All rights reserved. ! * ! * Redistribution and use in source and binary forms, with or without ! * modification, are permitted provided that the following conditions ! * are met: ! * 1. Redistributions of source code must retain the above copyright ! * notice, this list of conditions and the following disclaimer. ! * 2. Redistributions in binary form must reproduce the above copyright ! * notice, this list of conditions and the following disclaimer in the ! * documentation and/or other materials provided with the distribution. ! * 3. All advertising materials mentioning features or use of this software ! * must display the following acknowledgement: ! * This product includes software developed by the University of ! * California, Berkeley and its contributors. ! * 4. Neither the name of the University nor the names of its contributors ! * may be used to endorse or promote products derived from this software ! * without specific prior written permission. ! * ! * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! * SUCH DAMAGE. ! */ ! ! #include #include --- 1,3 ---- ! #include "bashtypes.h" #include *************** *** 48,77 **** #endif - #define PF(f, func) { \ - if (fieldwidth) \ - if (precision) \ - (void)fprintf(ofp, f, fieldwidth, precision, func); \ - else \ - (void)fprintf(ofp, f, fieldwidth, func); \ - else if (precision) \ - (void)fprintf(ofp, f, precision, func); \ - else \ - (void)fprintf(ofp, f, func); \ - } - - static int asciicode __P((void)); - static void escape __P((char *)); - static int getchr __P((void)); - static double getdouble __P((void)); - static int getint __P((int *)); - static int getlong __P((long *)); - static char *getstr __P((void)); - static char *mklong __P((char *, int)); - static void usage __P((void)); - - static char **gargv; - int print_builtin (); - static int printf_main (); static int printargs (); --- 15,19 ---- *************** *** 79,89 **** extern char *ansicstr (); - extern char *single_quote (); - extern char **make_builtin_argv (); extern char *this_command_name; - extern int optind; - static char *print_doc[] = { "Output the arguments. The -f option means to use the argument as a", --- 21,27 ---- *************** *** 169,178 **** if (pfmt) { ! v = word_list_to_argv (list, 0, 2, &c); ! v[0] = this_command_name; ! v[1] = pfmt; ! r = printf_main (c, v); ! free (v); ! return r; } --- 107,119 ---- if (pfmt) { ! WORD_DESC *w; ! WORD_LIST *nlist; ! ! w = make_word (pfmt); ! nlist = make_word_list (w, list); ! r = printf_builtin (nlist); ! nlist->next = (WORD_LIST *)NULL; ! dispose_words (nlist); ! return (r); } *************** *** 199,203 **** } ! static int printargs (list, ofp) WORD_LIST *list; FILE *ofp; --- 140,145 ---- } ! static int ! printargs (list, ofp) WORD_LIST *list; FILE *ofp; *************** *** 209,213 **** for (sawc = 0, l = list; l; l = l->next) { ! ostr = ansicstr (l->word->word, strlen (l->word->word), &sawc); fprintf (ofp, "%s", ostr); free (ostr); --- 151,155 ---- for (sawc = 0, l = list; l; l = l->next) { ! ostr = ansicstr (l->word->word, strlen (l->word->word), &sawc, (int *)0); fprintf (ofp, "%s", ostr); free (ostr); *************** *** 220,553 **** } - static int - printf_main(argc, argv) - int argc; - char *argv[]; - { - static char *skip1, *skip2; - int ch, end, fieldwidth, precision; - char convch, nextch, *format, *fmt, *start; - - while ((ch = getopt(argc, argv, "")) != EOF) - switch (ch) { - case '?': - default: - usage(); - return (1); - } - argc -= optind; - argv += optind; - - if (argc < 1) { - usage(); - return (1); - } - - /* - * Basic algorithm is to scan the format string for conversion - * specifications -- once one is found, find out if the field - * width or precision is a '*'; if it is, gather up value. Note, - * format strings are reused as necessary to use up the provided - * arguments, arguments of zero/null string are provided to use - * up the format string. - */ - skip1 = "#-+ 0"; - skip2 = "*0123456789"; - - escape(fmt = format = *argv); /* backslash interpretation */ - gargv = ++argv; - for (;;) { - end = 0; - /* find next format specification */ - next: for (start = fmt;; ++fmt) { - if (!*fmt) { - /* avoid infinite loop */ - if (end == 1) { - warnx("missing format character", - NULL, NULL); - return (1); - } - end = 1; - if (fmt > start) - (void)printf("%s", start); - if (!*gargv) - return (0); - fmt = format; - goto next; - } - /* %% prints a % */ - if (*fmt == '%') { - if (*++fmt != '%') - break; - *fmt++ = '\0'; - (void)printf("%s", start); - goto next; - } - } - - /* skip to field width */ - for (; strchr(skip1, *fmt); ++fmt); - if (*fmt == '*') { - if (getint(&fieldwidth)) - return (1); - } else - fieldwidth = 0; - - /* skip to possible '.', get following precision */ - for (; strchr(skip2, *fmt); ++fmt); - if (*fmt == '.') - ++fmt; - if (*fmt == '*') { - if (getint(&precision)) - return (1); - } else - precision = 0; - - /* skip to conversion char */ - for (; strchr(skip2, *fmt); ++fmt); - if (!*fmt) { - warnx("missing format character", NULL, NULL); - return (1); - } - - convch = *fmt; - nextch = *++fmt; - *fmt = '\0'; - switch(convch) { - case 'c': { - char p; - - p = getchr(); - PF(start, p); - break; - } - case 's': { - char *p; - - p = getstr(); - PF(start, p); - break; - } - case 'b': { /* expand escapes in argument */ - char *p; - - p = getstr(); - escape(p); - PF(start, p); - break; - } - case 'q': { /* print with shell single quoting */ - char *p, *p2; - - p = getstr(); - p2 = single_quote(p); - PF(start, p2); - free(p2); - break; - } - case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': { - long p; - char *f; - - if ((f = mklong(start, convch)) == NULL) - return (1); - if (getlong(&p)) - return (1); - PF(f, p); - break; - } - case 'e': case 'E': case 'f': case 'g': case 'G': { - double p; - - p = getdouble(); - PF(start, p); - break; - } - default: - warnx("illegal format character", NULL, NULL); - return (1); - } - *fmt = nextch; - } - /* NOTREACHED */ - } - - static char * - mklong(str, ch) - char *str; - int ch; - { - static char copy[64]; - int len; - - len = strlen(str) + 2; - memmove(copy, str, len - 3); - copy[len - 3] = 'l'; - copy[len - 2] = ch; - copy[len - 1] = '\0'; - return (copy); - } - - static void - escape(fmt) - register char *fmt; - { - register char *store; - register int value, c; - - for (store = fmt; c = *fmt; ++fmt, ++store) { - if (c != '\\') { - *store = c; - continue; - } - switch (*++fmt) { - case '\0': /* EOS, user error */ - *store = '\\'; - *++store = '\0'; - return; - case '\\': /* backslash */ - case '\'': /* single quote */ - *store = *fmt; - break; - case 'a': /* bell/alert */ - *store = '\7'; - break; - case 'b': /* backspace */ - *store = '\b'; - break; - case 'c': - return; - case 'e': - case 'E': - *store = '\033'; - break; - case 'f': /* form-feed */ - *store = '\f'; - break; - case 'n': /* newline */ - *store = '\n'; - break; - case 'r': /* carriage-return */ - *store = '\r'; - break; - case 't': /* horizontal tab */ - *store = '\t'; - break; - case 'v': /* vertical tab */ - *store = '\13'; - break; - /* octal constant */ - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - for (c = 3, value = 0; - c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) { - value <<= 3; - value += *fmt - '0'; - } - --fmt; - *store = value; - break; - default: - *store = *fmt; - break; - } - } - *store = '\0'; - } - - static int - getchr() - { - if (!*gargv) - return ('\0'); - return ((int)**gargv++); - } - - static char * - getstr() - { - if (!*gargv) - return (""); - return (*gargv++); - } - - static char *Number = "+-.0123456789"; - static int - getint(ip) - int *ip; - { - long val; - - if (getlong(&val)) - return (1); - if (val > INT_MAX) { - warnx("%s: %s", *gargv, strerror(ERANGE)); - return (1); - } - *ip = val; - return (0); - } - - static int - getlong(lp) - long *lp; - { - long val; - char *ep; - - if (!*gargv) { - *lp = 0; - return (0); - } - if (strchr(Number, **gargv)) { - errno = 0; - val = strtol(*gargv, &ep, 0); - if (*ep != '\0') { - warnx("%s: illegal number", *gargv, NULL); - return (1); - } - if (errno == ERANGE) - if (val == LONG_MAX) { - warnx("%s: %s", *gargv, strerror(ERANGE)); - return (1); - } - if (val == LONG_MIN) { - warnx("%s: %s", *gargv, strerror(ERANGE)); - return (1); - } - - *lp = val; - ++gargv; - return (0); - } - *lp = (long)asciicode(); - return (0); - } - - static double - getdouble() - { - if (!*gargv) - return ((double)0); - if (strchr(Number, **gargv)) - return (atof(*gargv++)); - return ((double)asciicode()); - } - - static int - asciicode() - { - register int ch; - - ch = **gargv; - if (ch == '\'' || ch == '"') - ch = (*gargv)[1]; - ++gargv; - return (ch); - } - - static void - usage() - { - (void)fprintf(stderr, "usage: print [-Rnprs] [-u unit] [-f format] [arg ...]\n"); - } --- 162,163 ---- diff -Nrc2 bash-2.01.1/examples/loadables/printf.c bash-2.02/examples/loadables/printf.c *** bash-2.01.1/examples/loadables/printf.c Wed Jun 26 15:06:55 1996 --- bash-2.02/examples/loadables/printf.c Wed Dec 31 19:00:00 1969 *************** *** 1,460 **** - /* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - #if !defined(BUILTIN) && !defined(SHELL) - #ifndef lint - static char copyright[] = - "@(#) Copyright (c) 1989, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; - #endif /* not lint */ - #endif - - #ifndef lint - static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 7/20/93"; - #endif /* not lint */ - - #include - - #include - #include - #include - - #include "bashansi.h" - #include "shell.h" - #include "builtins.h" - #include "stdc.h" - - #if !defined (errno) - extern int errno; - #endif - - #define PF(f, func) { \ - if (fieldwidth) \ - if (precision) \ - (void)printf(f, fieldwidth, precision, func); \ - else \ - (void)printf(f, fieldwidth, func); \ - else if (precision) \ - (void)printf(f, precision, func); \ - else \ - (void)printf(f, func); \ - } - - static int asciicode __P((void)); - static void escape __P((char *)); - static int getchr __P((void)); - static double getdouble __P((void)); - static int getint __P((int *)); - static int getlong __P((long *)); - static char *getstr __P((void)); - static char *mklong __P((char *, int)); - static void usage __P((void)); - - static char **gargv; - - int printf_builtin (); - static int printf_main (); - extern char *this_command_name; - extern char *single_quote (); - extern char **make_builtin_argv (); - - static char *printf_doc[] = { - "printf formats and prints its arguments, after the first, under control", - "of the format. The 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 argument. In addition to the standard printf(1)", - "formats, %%b means to expand escapes in the corresponding argument, and", - "%%q means to quote the argument in a way that can be reused as shell input.", - (char *)NULL - }; - - struct builtin printf_struct = { - "printf", - printf_builtin, - BUILTIN_ENABLED, - printf_doc, - "printf format [arguments]", - (char *)0 - }; - - int - printf_builtin (list) - WORD_LIST *list; - { - int c, r; - char **v; - WORD_LIST *l; - - v = make_builtin_argv (list, &c); - r = printf_main (c, v); - free (v); - fflush(stdout); - - return r; - } - - static int - printf_main(argc, argv) - int argc; - char *argv[]; - { - extern int optind; - static char *skip1, *skip2; - int ch, end, fieldwidth, precision; - char convch, nextch, *format, *fmt, *start; - - while ((ch = getopt(argc, argv, "")) != EOF) - switch (ch) { - case '?': - default: - usage(); - return (1); - } - argc -= optind; - argv += optind; - - if (argc < 1) { - usage(); - return (1); - } - - /* - * Basic algorithm is to scan the format string for conversion - * specifications -- once one is found, find out if the field - * width or precision is a '*'; if it is, gather up value. Note, - * format strings are reused as necessary to use up the provided - * arguments, arguments of zero/null string are provided to use - * up the format string. - */ - skip1 = "#-+ 0"; - skip2 = "*0123456789"; - - escape(fmt = format = *argv); /* backslash interpretation */ - gargv = ++argv; - for (;;) { - end = 0; - /* find next format specification */ - next: for (start = fmt;; ++fmt) { - if (!*fmt) { - /* avoid infinite loop */ - if (end == 1) { - warnx("missing format character", - NULL, NULL); - return (1); - } - end = 1; - if (fmt > start) - (void)printf("%s", start); - if (!*gargv) - return (0); - fmt = format; - goto next; - } - /* %% prints a % */ - if (*fmt == '%') { - if (*++fmt != '%') - break; - *fmt++ = '\0'; - (void)printf("%s", start); - goto next; - } - } - - /* skip to field width */ - for (; strchr(skip1, *fmt); ++fmt); - if (*fmt == '*') { - if (getint(&fieldwidth)) - return (1); - } else - fieldwidth = 0; - - /* skip to possible '.', get following precision */ - for (; strchr(skip2, *fmt); ++fmt); - if (*fmt == '.') - ++fmt; - if (*fmt == '*') { - if (getint(&precision)) - return (1); - } else - precision = 0; - - /* skip to conversion char */ - for (; strchr(skip2, *fmt); ++fmt); - if (!*fmt) { - warnx("missing format character", NULL, NULL); - return (1); - } - - convch = *fmt; - nextch = *++fmt; - *fmt = '\0'; - switch(convch) { - case 'c': { - char p; - - p = getchr(); - PF(start, p); - break; - } - case 's': { - char *p; - - p = getstr(); - PF(start, p); - break; - } - case 'b': { /* expand escapes in argument */ - char *p; - - p = getstr(); - escape(p); - PF("%s", p); - break; - } - case 'q': { /* print with shell single quoting */ - char *p, *p2; - - p = getstr(); - p2 = single_quote(p); - PF("%s", p2); - free(p2); - break; - } - case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': { - long p; - char *f; - - if ((f = mklong(start, convch)) == NULL) - return (1); - if (getlong(&p)) - return (1); - PF(f, p); - break; - } - case 'e': case 'E': case 'f': case 'g': case 'G': { - double p; - - p = getdouble(); - PF(start, p); - break; - } - default: - warnx("illegal format character", NULL, NULL); - return (1); - } - *fmt = nextch; - } - /* NOTREACHED */ - } - - static char * - mklong(str, ch) - char *str; - int ch; - { - static char copy[64]; - int len; - - len = strlen(str) + 2; - memmove(copy, str, len - 3); - copy[len - 3] = 'l'; - copy[len - 2] = ch; - copy[len - 1] = '\0'; - return (copy); - } - - static void - escape(fmt) - register char *fmt; - { - register char *store; - register int value, c; - - for (store = fmt; c = *fmt; ++fmt, ++store) { - if (c != '\\') { - *store = c; - continue; - } - switch (*++fmt) { - case '\0': /* EOS, user error */ - *store = '\\'; - *++store = '\0'; - return; - case '\\': /* backslash */ - case '\'': /* single quote */ - *store = *fmt; - break; - case 'a': /* bell/alert */ - *store = '\7'; - break; - case 'b': /* backspace */ - *store = '\b'; - break; - case 'c': - return; - case 'e': - case 'E': - *store = '\033'; - break; - case 'f': /* form-feed */ - *store = '\f'; - break; - case 'n': /* newline */ - *store = '\n'; - break; - case 'r': /* carriage-return */ - *store = '\r'; - break; - case 't': /* horizontal tab */ - *store = '\t'; - break; - case 'v': /* vertical tab */ - *store = '\13'; - break; - /* octal constant */ - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - for (c = 3, value = 0; - c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) { - value <<= 3; - value += *fmt - '0'; - } - --fmt; - *store = value; - break; - default: - *store = *fmt; - break; - } - } - *store = '\0'; - } - - static int - getchr() - { - if (!*gargv) - return ('\0'); - return ((int)**gargv++); - } - - static char * - getstr() - { - if (!*gargv) - return (""); - return (*gargv++); - } - - static char *Number = "+-.0123456789"; - static int - getint(ip) - int *ip; - { - long val; - - if (getlong(&val)) - return (1); - if (val > INT_MAX) { - warnx("%s: %s", *gargv, strerror(ERANGE)); - return (1); - } - *ip = val; - return (0); - } - - static int - getlong(lp) - long *lp; - { - long val; - char *ep; - - if (!*gargv) { - *lp = 0; - return (0); - } - if (strchr(Number, **gargv)) { - errno = 0; - val = strtol(*gargv, &ep, 0); - if (*ep != '\0') { - warnx("%s: illegal number", *gargv, NULL); - return (1); - } - if (errno == ERANGE) - if (val == LONG_MAX) { - warnx("%s: %s", *gargv, strerror(ERANGE)); - return (1); - } - if (val == LONG_MIN) { - warnx("%s: %s", *gargv, strerror(ERANGE)); - return (1); - } - - *lp = val; - ++gargv; - return (0); - } - *lp = (long)asciicode(); - return (0); - } - - static double - getdouble() - { - if (!*gargv) - return ((double)0); - if (strchr(Number, **gargv)) - return (atof(*gargv++)); - return ((double)asciicode()); - } - - static int - asciicode() - { - register int ch; - - ch = **gargv; - if (ch == '\'' || ch == '"') - ch = (*gargv)[1]; - ++gargv; - return (ch); - } - - static void - usage() - { - (void)fprintf(stderr, "usage: printf format [arg ...]\n"); - } --- 0 ---- diff -Nrc2 bash-2.01.1/examples/misc/alias-conv.bash bash-2.02/examples/misc/alias-conv.bash *** bash-2.01.1/examples/misc/alias-conv.bash Fri Jul 19 14:49:43 1996 --- bash-2.02/examples/misc/alias-conv.bash Wed Dec 31 19:00:00 1969 *************** *** 1,38 **** - #! /bin/bash - # - # alias-conv.sh - convert csh aliases to bash aliases and functions - # - # usage: alias-conv.sh - # - # Chet Ramey - # chet@po.cwru.edu - # - trap 'rm -f /tmp/cb$$.?' 0 1 2 3 6 15 - - T=$'\t' - - cat << \EOF >/tmp/cb$$.1 - mkalias () - { - if [ "x$2" = "x" ]; then - echo alias ${1}="''" - elif echo "$2" | egrep -s '(\!|#)' >/dev/null 2>&1; then - comm=$(echo $2 | sed 's/\!\*/"$\@"/g - s/\!:\([1-9]\)/"$\1"/g - s/#/\#/g') - echo $1 \(\) "{" command "$comm" "; }" - else - echo alias ${1}=\'$(echo "${2}" | sed "s:':'\\\\'':")\' - fi - } - EOF - - sed "s/^\([a-zA-Z0-9_-]*\)$T\(.*\)$/mkalias \1 '\2'/" >>/tmp/cb$$.1 - - $BASH /tmp/cb$$.1 | sed -e 's/\$cwd/\$PWD/g' \ - -e 's/\$term/\$TERM/g' \ - -e 's/\$home/\$HOME/g' \ - -e 's/\$user/\$USER/g' \ - -e 's/\$prompt/\$PS1/g' - - exit 0 --- 0 ---- diff -Nrc2 bash-2.01.1/examples/misc/alias-conv.sh bash-2.02/examples/misc/alias-conv.sh *** bash-2.01.1/examples/misc/alias-conv.sh Fri Jul 19 14:49:36 1996 --- bash-2.02/examples/misc/alias-conv.sh Wed Dec 31 19:00:00 1969 *************** *** 1,38 **** - #! /bin/bash - # - # alias-conv.sh - convert csh aliases to bash aliases and functions - # - # usage: alias-conv.sh - # - # Chet Ramey - # chet@po.cwru.edu - # - trap 'rm -f /tmp/cb$$.?' 0 1 2 3 6 15 - - T=' ' - - cat << \EOF >/tmp/cb$$.1 - mkalias () - { - if [ "x$2" = "x" ]; then - echo alias ${1}="''" - elif echo "$2" | egrep -s '(\!|#)' >/dev/null 2>&1; then - comm=`echo $2 | sed 's/\\!\*/"$\@"/g - s/\\!:\([1-9]\)/"$\1"/g - s/#/\#/g'` - echo $1 \(\) "{" command "$comm" "; }" - else - echo alias ${1}=\'`echo "${2}" | sed "s:':'\\\\\\\\'':"`\' - fi - } - EOF - - sed "s/^\([a-zA-Z0-9_-]*\)$T\(.*\)$/mkalias \1 '\2'/" >>/tmp/cb$$.1 - - sh /tmp/cb$$.1 | sed -e 's/\$cwd/\$PWD/g' \ - -e 's/\$term/\$TERM/g' \ - -e 's/\$home/\$HOME/g' \ - -e 's/\$user/\$USER/g' \ - -e 's/\$prompt/\$PS1/g' - - exit 0 --- 0 ---- diff -Nrc2 bash-2.01.1/examples/misc/aliasconv.bash bash-2.02/examples/misc/aliasconv.bash *** bash-2.01.1/examples/misc/aliasconv.bash Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/misc/aliasconv.bash Fri Jul 19 14:49:43 1996 *************** *** 0 **** --- 1,38 ---- + #! /bin/bash + # + # alias-conv.sh - convert csh aliases to bash aliases and functions + # + # usage: alias-conv.sh + # + # Chet Ramey + # chet@po.cwru.edu + # + trap 'rm -f /tmp/cb$$.?' 0 1 2 3 6 15 + + T=$'\t' + + cat << \EOF >/tmp/cb$$.1 + mkalias () + { + if [ "x$2" = "x" ]; then + echo alias ${1}="''" + elif echo "$2" | egrep -s '(\!|#)' >/dev/null 2>&1; then + comm=$(echo $2 | sed 's/\!\*/"$\@"/g + s/\!:\([1-9]\)/"$\1"/g + s/#/\#/g') + echo $1 \(\) "{" command "$comm" "; }" + else + echo alias ${1}=\'$(echo "${2}" | sed "s:':'\\\\'':")\' + fi + } + EOF + + sed "s/^\([a-zA-Z0-9_-]*\)$T\(.*\)$/mkalias \1 '\2'/" >>/tmp/cb$$.1 + + $BASH /tmp/cb$$.1 | sed -e 's/\$cwd/\$PWD/g' \ + -e 's/\$term/\$TERM/g' \ + -e 's/\$home/\$HOME/g' \ + -e 's/\$user/\$USER/g' \ + -e 's/\$prompt/\$PS1/g' + + exit 0 diff -Nrc2 bash-2.01.1/examples/misc/aliasconv.sh bash-2.02/examples/misc/aliasconv.sh *** bash-2.01.1/examples/misc/aliasconv.sh Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/misc/aliasconv.sh Fri Jul 19 14:49:36 1996 *************** *** 0 **** --- 1,38 ---- + #! /bin/bash + # + # alias-conv.sh - convert csh aliases to bash aliases and functions + # + # usage: alias-conv.sh + # + # Chet Ramey + # chet@po.cwru.edu + # + trap 'rm -f /tmp/cb$$.?' 0 1 2 3 6 15 + + T=' ' + + cat << \EOF >/tmp/cb$$.1 + mkalias () + { + if [ "x$2" = "x" ]; then + echo alias ${1}="''" + elif echo "$2" | egrep -s '(\!|#)' >/dev/null 2>&1; then + comm=`echo $2 | sed 's/\\!\*/"$\@"/g + s/\\!:\([1-9]\)/"$\1"/g + s/#/\#/g'` + echo $1 \(\) "{" command "$comm" "; }" + else + echo alias ${1}=\'`echo "${2}" | sed "s:':'\\\\\\\\'':"`\' + fi + } + EOF + + sed "s/^\([a-zA-Z0-9_-]*\)$T\(.*\)$/mkalias \1 '\2'/" >>/tmp/cb$$.1 + + sh /tmp/cb$$.1 | sed -e 's/\$cwd/\$PWD/g' \ + -e 's/\$term/\$TERM/g' \ + -e 's/\$home/\$HOME/g' \ + -e 's/\$user/\$USER/g' \ + -e 's/\$prompt/\$PS1/g' + + exit 0 diff -Nrc2 bash-2.01.1/examples/scripts/fixfiles.bash bash-2.02/examples/scripts/fixfiles.bash *** bash-2.01.1/examples/scripts/fixfiles.bash Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/scripts/fixfiles.bash Thu Sep 4 14:44:06 1997 *************** *** 0 **** --- 1,92 ---- + #! /bin/bash + # + # From: c2a192@ugrad.cs.ubc.ca (Kazimir Kylheku) + # Newsgroups: comp.unix.shell,comp.os.linux.misc + # Subject: GNU Bash Script to fix filenames + # Date: 28 Mar 1996 14:54:43 -0800 + # Organization: Computer Science, University of B.C., Vancouver, B.C., Canada + # + #This is a script which takes a list of directories, descends through each one + #and ``corrects'' filenames that: + # + # - contain filename globbing characters: * ? [ ] + # - quote characters: ' " + # - control characters: 0-31 (127 is not dealt with---oops) + # - - or + as the first character + # + # The GNU version of 'tr' is required. Also requires 'sed'. + # + # Script to process a given list of directories recursively + # and rename each file to something that is reasonable. + # + # The rules are: + # + # 1. replace each space, [, ], *, ", and ' character in the name with a + # period. + # 2. replace each control character 1..31 with a printable character obtained + # by adding 64 to the ascii value. ^A becomes A, ^B becomes B and so on. + # 3. replace a - or + occuring at the beginning of the name with a # + # + # 4. if the resulting name has been changed in any way, then + # 5. if a file of the new name already exists, then + # 6. add a . to the new name and goto step 5. + # 7. rename the old name to the new name + # + # written by Kaz Kylheku + # March 1996 + # Vancouver, Canada + # + # requires GNU 'bash', GNU 'tr', and some sort of 'sed' program. + # + # minimal conversion to bash v2 syntax done by Chet Ramey + + processfile() + { + new_name="`echo -n $1 | tr '\173\175\052\077\042\047 ' '.......' | + tr '[\000-\037]' '[\100-\137]' | + sed -e 's/^-/#/' -e 's/+/#/'`" + if [ "$new_name" != "$1" ] ; then + while [ -e "$new_name" ] ; do + new_name="${new_name}." + done + echo changing \"$1\" to \"$new_name\" in `pwd` + mv -- "$1" "$new_name" + fi + } + + processdir() + { + set -f + local savepwd="$PWD" + if cd "$1" ; then + set +f + for file in * ; do + set -f + if [ "$file" != "." -a "$file" != ".." ] ; then + if [ -L "$file" ] ; then + echo "skipping symlink" $file in `pwd` + elif [ -d "$file" ] ; then + processdir "$file" + elif [ -f "$file" ] ; then + processfile "$file" + fi + fi + done + cd "$savepwd" + fi + } + + shopt -s nullglob dotglob + + if [ $# = 0 ] ; then + echo "$0: must specify a list of directories" >&2 + echo "$0: usage: $0 directory [directory ...]" >&2 + exit 2 + fi + + while [ $# != 0 ] ; do + processdir "$1" + shift + done + + exit 0 diff -Nrc2 bash-2.01.1/examples/scripts/hanoi.bash bash-2.02/examples/scripts/hanoi.bash *** bash-2.01.1/examples/scripts/hanoi.bash Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/scripts/hanoi.bash Thu Sep 4 14:25:48 1997 *************** *** 0 **** --- 1,21 ---- + # Towers of Hanoi in bash + # + # cribbed from the ksh93 book, example from exercises on page 85 + # + # Chet Ramey + # chet@po.cwru.edu + + hanoi() # n from to spare + { + typeset -i nm1=$1-1 + ((nm1>0)) && hanoi $nm1 $2 $4 $3 + echo "Move disc $2 to $3" + ((nm1>0)) && hanoi $nm1 $4 $3 $2 + } + + case $1 in + [1-9]) + hanoi $1 1 2 3;; + *) echo "${0##*/}: Argument must be from 1 to 9" + exit 1;; + esac diff -Nrc2 bash-2.01.1/examples/scripts/krand.bash bash-2.02/examples/scripts/krand.bash *** bash-2.01.1/examples/scripts/krand.bash Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/scripts/krand.bash Thu Sep 4 14:18:40 1997 *************** *** 0 **** --- 1,74 ---- + # Originally + # + # From: bsh20858@news.fhda.edu (Brian S Hiles) + # Newsgroups: comp.unix.shell + # Subject: Re: getting random numbers + # Date: 23 Jan 1997 23:27:30 GMT + # Message-ID: <5c8s52$eif@tiptoe.fhda.edu> + + # @(#) krand Produces a random number within integer limits + # "krand" Korn shell script generates a random number in a + # specified range with an optionally specified ``seed'' value. + # Author: Peter Turnbull, May 1993 + # Modified by: Becca Thomas, January 1994 + + # changed the optional third argument to a -s option, converted to + # bash v2 syntax -- chet@po.cwru.edu + + PROGNAME=${0##*/} + USAGE="usage: $PROGNAME [-s seed] lower-limit upper-limit" + + Seed=$$ # Initialize random-number seed value with PID + + usage() + { + echo ${PROGNAME}: "$USAGE" >&2 + } + + errexit() + { + echo ${PROGNAME}: "$@" >&2 + exit 1 + } + + # Process command-line arguments: + while getopts "s:" opt; do + case "$opt" in + s) Seed=$OPTARG ;; + *) usage ; exit 2;; + esac + done + + shift $(($OPTIND - 1)) + + case $# in + 2) Lower=$1; Upper=$2 ;; + *) usage ; exit 2;; + esac + + # Check that specified values are integers: + expr "$Lower" + 0 >/dev/null 2>&1 + [ $? -eq 2 ] && { errexit "lower ($Lower) not an integer"; } + expr "$Upper" + 0 >/dev/null 2>&1 + [ $? -eq 2 ] && { errexit "upper ($Upper) not an integer"; } + expr "$Seed" + 0 >/dev/null 2>&1 + [ $? -eq 2 ] && { errexit "seed ($Seed) not an integer"; } + + # Check that values are in the correct range: + if (( "$Lower" < 0 )) || [ ${#Lower} -gt 5 ]; then + errexit "lower limit ($Lower) less than zero" + fi + if (( "$Upper" > 32767 )) || [ ${#Upper} -gt 5 ]; then + errexit "upper limit ($Upper) greater than 32767" + fi + if (( "$Seed" < 0 )) || (( "$Seed" > 32767 )) || [ ${#Seed} -gt 5 ]; then + errexit "seed value ($Seed) out of range (0 to 32767)" + fi + (( "$Upper" <= "$Lower" )) && errexit "upper limit ($Upper) <= lower limit ($Lower)" + + # Seed the random-number generator: + RANDOM=$Seed + # Compute value, scaled within range: + let rand="$RANDOM % ($Upper - $Lower + 1) + $Lower" + # Report result: + echo $rand diff -Nrc2 bash-2.01.1/examples/scripts/randomcard.bash bash-2.02/examples/scripts/randomcard.bash *** bash-2.01.1/examples/scripts/randomcard.bash Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/scripts/randomcard.bash Thu Sep 4 14:28:48 1997 *************** *** 0 **** --- 1,18 ---- + # The following prints a random card from a card deck. + # + # cribbed from the ksh93 book, example from page 70 + # + # chet@po.cwru.edu + # + declare -i i=0 + + # load the deck + for suit in clubs diamonds hearts spades; do + for n in ace 2 3 4 5 6 7 8 9 10 jack queen king; do + card[i]="$n of $suit" + i=i+1 # let is not required with integer variables + done + done + + # and print a random card + echo ${card[RANDOM%52]} diff -Nrc2 bash-2.01.1/examples/scripts/scrollbar bash-2.02/examples/scripts/scrollbar *** bash-2.01.1/examples/scripts/scrollbar Fri Mar 29 12:47:56 1996 --- bash-2.02/examples/scripts/scrollbar Thu Sep 4 14:39:48 1997 *************** *** 10,25 **** WIDTH=${COLUMNS:-80} [ $# -lt 1 ] && set -- TESTING ! # Posix.2 compatible printf command or bash loadable builtin ! # in examples/loadables/printf Text=$(printf "%-${WIDTH}s" "$*") ! Text=$(echo "$Text" | tr ' ' '_') while : do printf "%-.${WIDTH}s\r" "$Text" ! LastC=$(expr "$Text" : '.*\(.\)$') ! Text=$(printf "%-.${WIDTH}s" "$LastC$Text") done --- 10,25 ---- WIDTH=${COLUMNS:-80} + WMINUS=$(( $WIDTH - 1 )) [ $# -lt 1 ] && set -- TESTING ! # use the bash-2.02 printf builtin Text=$(printf "%-${WIDTH}s" "$*") ! Text=${Text// /_} while : do printf "%-.${WIDTH}s\r" "$Text" ! LastC=${Text:${WMINUS}:1} ! Text="$LastC""${Text%?}" done diff -Nrc2 bash-2.01.1/examples/scripts/scrollbar2 bash-2.02/examples/scripts/scrollbar2 *** bash-2.01.1/examples/scripts/scrollbar2 Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/scripts/scrollbar2 Thu Sep 4 14:42:00 1997 *************** *** 0 **** --- 1,24 ---- + #!/bin/bash + # + # scrollbar - display scrolling text + # + # usage: scrollbar args + # + # A cute hack originally from Heiner Steven + # + # converted from ksh syntax to bash v2 syntax by Chet Ramey + + WIDTH=${COLUMNS:-80} + WMINUS=$(( $WIDTH - 1 )) + + [ $# -lt 1 ] && set -- TESTING + + # use the bash-2.02 printf builtin + Text=$(printf "%-${WIDTH}s" "$*") + + while : + do + printf "%-.${WIDTH}s\r" "$Text" + LastC=${Text:${WMINUS}:1} + Text="$LastC""${Text%?}" + done diff -Nrc2 bash-2.01.1/examples/scripts/showperm.bash bash-2.02/examples/scripts/showperm.bash *** bash-2.01.1/examples/scripts/showperm.bash Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/scripts/showperm.bash Tue Mar 3 13:09:13 1998 *************** *** 0 **** --- 1,53 ---- + #Newsgroups: comp.unix.shell + #From: gwc@root.co.uk (Geoff Clare) + #Subject: Re: Determining permissions on a file + #Message-ID: + #Date: Fri, 10 May 1996 17:23:56 GMT + + #Here's a bit of Korn shell that converts the symbolic permissions produced + #by "ls -l" into octal, using only shell builtins. How to create a script + #combining this with an "ls -l" is left as an exercise... + # + # + # Converted to Bash v2 syntax by Chet Ramey + # + # usage: showperm modestring + # + # example: showperm '-rwsr-x--x' + # + + [ -z "$1" ] && { + echo "showperm: usage: showperm modestring" >&2 + exit 2 + } + + tmode="$1" + + typeset -i omode sbits + typeset pmode + + # check for set-uid, etc. bits + sbits=0 + case $tmode in + ???[sS]*) (( sbits += 8#4000 )) ;; # set-uid + ??????[sSl]*) (( sbits += 8#2000 )) ;; # set-gid or mand. lock + ?????????[tT]*) (( sbits += 8#1000 )) ;; # sticky + esac + + omode=0 + while : + do + tmode=${tmode#?} + case $tmode in + "") break ;; + [-STl]*) (( omode *= 2 )) ;; + [rwxst]*) (( omode = omode*2 + 1 )) ;; + *) echo "$0: first letter of \"$tmode\" is unrecognized" >&2 + (( omode *= 2 )) + ;; + esac + done + + (( omode += sbits )) + + printf "0%o\n" $omode diff -Nrc2 bash-2.01.1/examples/scripts/timeout bash-2.02/examples/scripts/timeout *** bash-2.01.1/examples/scripts/timeout Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/scripts/timeout Tue Mar 3 13:29:53 1998 *************** *** 0 **** --- 1,53 ---- + #Newsgroups: comp.unix.admin,comp.unix.solaris,comp.unix.shell + #From: gwc@root.co.uk (Geoff Clare) + #Subject: Re: timeout -t (Re: How to give rsh a shorter timeout?) + #Message-ID: + #Date: Fri, 13 Feb 1998 18:23:52 GMT + + # + # Conversion to bash v2 syntax done by Chet Ramey &2 ; exit 2 ;; + esac + + ( + for t in $timeout $delay + do + while (( $t > $interval )) + do + sleep $interval + kill -0 $$ || exit + t=$(( $t - $interval )) + done + sleep $t + kill $SIG $$ && kill -0 $$ || exit + SIG=-KILL + done + ) 2> /dev/null & + + exec "$@" diff -Nrc2 bash-2.01.1/examples/scripts.v2/cal2day.bash bash-2.02/examples/scripts.v2/cal2day.bash *** bash-2.01.1/examples/scripts.v2/cal2day.bash Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/scripts.v2/cal2day.bash Tue Nov 25 15:53:28 1997 *************** *** 0 **** --- 1,49 ---- + #!/bin/bash + # cal2day - "parse" appropriate calendar output to match date number + # with day name. + # + # usage: cal2day month day [year] + # + # ORIGINAL *TAG:33239 3:Dec 9 1997:0755:sh.d/cal2day: + # + # Obtained from usenet + # + # Converted to bash v2 syntax by Chet Ramey + + #1 PARSE OPTIONS + while getopts :dls _inst + do case $_inst in + (d) format='%1d%.0s\n' ;; # 0, 1, ..., 7 + (l) format='%0.s%-s\n' ;; # Sunday, Monday, ..., Saturday + (s) format='%0.s%-.3s\n' ;; # Sun, Mon, ..., Sat + esac + done + shift $((OPTIND-1)) + + #2 PARAMETER VALUES + ((!$#)) && set -- $(date '+%m %d') + : ${format:='%0.s%-.3s\n'} + : ${1:?missing month parameter [1-12]} + : ${2:?missing day parameter [1-31]} + + #3 CALCULATE DAY-OF-WEEK FROM DATE + cal $1 ${3:-$(date +%Y)} | gawk -FX ' + BEGIN { day="Sunday Monday Tuesday WednesdayThursday Friday Saturday" + sub(/^0/, "", daynum) + dayre="(^| )" daynum "( |$)" + } + #NR==2 { print length($0) } + NR==1 || NR==2 \ + { next } + dayre { if (match($0, dayre)) + { #print RSTART, RLENGTH, substr($0, RSTART, RLENGTH) + if (daynum<=9 || RSTART==1) RSTART-=1 + exit + } + } + END { # 20/21 char width assumed + printf format, RSTART/3, substr(day, RSTART*3+1, 9) + } + ' daynum=$2 format=$format - + + exit 0 diff -Nrc2 bash-2.01.1/examples/startup-files/Bashrc bash-2.02/examples/startup-files/Bashrc *** bash-2.01.1/examples/startup-files/Bashrc Tue Aug 1 12:53:45 1995 --- bash-2.02/examples/startup-files/Bashrc Wed Dec 31 19:00:00 1969 *************** *** 1,70 **** - # Bourne Again SHell init file. - # - # Files you make look like rw-rw-r - umask 002 - - # Don't make useless coredump files. If you want a coredump, - # say "ulimit -c unlimited" and then cause a segmentation fault. - ulimit -c 0 - - # Sometimes, there are lots of places that one can find tex inputs. - export TEXINPUTS=.:$HOME/bin:/usr/lib/tex/inputs:/usr/local/lib/tex/inputs - - # Where's the Gnu stuff at? - GNU=/usr/gnu/bin - X11=/usr/bin/X11 - - UTIL_PATH=$GNU:$X11 - STANDARD_PATH=/usr/local/bin:/usr/ucb:/bin:/usr/bin:/usr/etc:/etc:/usr/games - - if [ -d $HOME/bin/$HOSTTYPE ]; then - MY_PATH=$HOME/bin/$HOSTTYPE - fi - - if [ -d $HOME/bin ]; then - MY_PATH=$MY_PATH:$HOME/bin - fi - - if [ -d /usr/hosts ]; then - STANDARD_PATH=$STANDARD_PATH:/usr/hosts - fi - - PATH=.:$MY_PATH:$UTIL_PATH:$STANDARD_PATH - - # If not running interactively, then return - if [ -z "$PS1" ]; then - return - fi - - # Set ignoreeof if you don't want EOF as the sole input to the shell to - # immediately signal a quit condition. This only happens at the start - # of a line if the line is empty, and you haven't just deleted a character - # with C-d. I turn this on in ~/.bash_profile so that only login shells - # have the right to be obnoxious. - # set -o ignoreeof - - # Set auto_resume if you want to resume on "emacs", as well as on - # "%emacs". - auto_resume=exact - - # Set notify if you want to be asynchronously notified about background - # job completion. - set -o notify - - # Make it so that failed `exec' commands don't flush this shell. - shopt -s execfail - - if [ -z "$LOGIN_SHELL" ]; then - PS1="\u@\h\$ " - fi - - HISTSIZE=256 - MAILCHECK=60 - - # A couple of default aliases. - alias j='jobs -l' - alias po=popd - alias pu=pushd - alias ls='ls -F' - - [ -f ~/.bash_aliases ] && . ~/.bash_aliases --- 0 ---- diff -Nrc2 bash-2.01.1/examples/startup-files/Bashrc.bfox bash-2.02/examples/startup-files/Bashrc.bfox *** bash-2.01.1/examples/startup-files/Bashrc.bfox Wed Dec 31 19:00:00 1969 --- bash-2.02/examples/startup-files/Bashrc.bfox Tue Aug 1 12:53:45 1995 *************** *** 0 **** --- 1,70 ---- + # Bourne Again SHell init file. + # + # Files you make look like rw-rw-r + umask 002 + + # Don't make useless coredump files. If you want a coredump, + # say "ulimit -c unlimited" and then cause a segmentation fault. + ulimit -c 0 + + # Sometimes, there are lots of places that one can find tex inputs. + export TEXINPUTS=.:$HOME/bin:/usr/lib/tex/inputs:/usr/local/lib/tex/inputs + + # Where's the Gnu stuff at? + GNU=/usr/gnu/bin + X11=/usr/bin/X11 + + UTIL_PATH=$GNU:$X11 + STANDARD_PATH=/usr/local/bin:/usr/ucb:/bin:/usr/bin:/usr/etc:/etc:/usr/games + + if [ -d $HOME/bin/$HOSTTYPE ]; then + MY_PATH=$HOME/bin/$HOSTTYPE + fi + + if [ -d $HOME/bin ]; then + MY_PATH=$MY_PATH:$HOME/bin + fi + + if [ -d /usr/hosts ]; then + STANDARD_PATH=$STANDARD_PATH:/usr/hosts + fi + + PATH=.:$MY_PATH:$UTIL_PATH:$STANDARD_PATH + + # If not running interactively, then return + if [ -z "$PS1" ]; then + return + fi + + # Set ignoreeof if you don't want EOF as the sole input to the shell to + # immediately signal a quit condition. This only happens at the start + # of a line if the line is empty, and you haven't just deleted a character + # with C-d. I turn this on in ~/.bash_profile so that only login shells + # have the right to be obnoxious. + # set -o ignoreeof + + # Set auto_resume if you want to resume on "emacs", as well as on + # "%emacs". + auto_resume=exact + + # Set notify if you want to be asynchronously notified about background + # job completion. + set -o notify + + # Make it so that failed `exec' commands don't flush this shell. + shopt -s execfail + + if [ -z "$LOGIN_SHELL" ]; then + PS1="\u@\h\$ " + fi + + HISTSIZE=256 + MAILCHECK=60 + + # A couple of default aliases. + alias j='jobs -l' + alias po=popd + alias pu=pushd + alias ls='ls -F' + + [ -f ~/.bash_aliases ] && . ~/.bash_aliases diff -Nrc2 bash-2.01.1/execute_cmd.c bash-2.02/execute_cmd.c *** bash-2.01.1/execute_cmd.c Fri Sep 19 12:05:41 1997 --- bash-2.02/execute_cmd.c Wed Mar 25 11:36:22 1998 *************** *** 27,35 **** #include #include "bashtypes.h" ! #include #include "filecntl.h" #include "posixstat.h" #include ! #include #if defined (HAVE_UNISTD_H) --- 27,39 ---- #include #include "bashtypes.h" ! #ifndef _MINIX ! # include ! #endif #include "filecntl.h" #include "posixstat.h" #include ! #ifndef _MINIX ! # include ! #endif #if defined (HAVE_UNISTD_H) *************** *** 55,59 **** #endif ! #if defined (HAVE_SYS_RESOURCE_H) # include #endif --- 59,63 ---- #endif ! #if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE) # include #endif *************** *** 79,86 **** --- 83,96 ---- #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 */ *************** *** 122,131 **** static void close_pipes (), do_piping (), bind_lastarg (); static void cleanup_redirects (); - static void add_undo_close_redirect (), add_exec_redirect (); - static int add_undo_redirect (); - static int do_redirection_internal (), do_redirections (); - static int expandable_redirection_filename (); - static char *find_user_command_internal (), *find_user_command_in_path (); - static char *find_in_path_element (), *find_absolute_program (); static int execute_for_command (); --- 132,135 ---- *************** *** 133,136 **** --- 137,146 ---- static int execute_select_command (); #endif + #if defined (DPAREN_ARITHMETIC) + static int execute_arith_command (); + #endif + #if defined (COND_COMMAND) + static int execute_cond_command (); + #endif #if defined (COMMAND_TIMING) static int time_command (); *************** *** 166,184 **** static int special_builtin_failed; - /* Spare redirector used when translating [N]>&WORD or [N]<&WORD to a new - redirection and when creating the redirection undo list. */ - static REDIRECTEE rd; - - /* Set to errno when a here document cannot be created for some reason. - Used to print a reasonable error message. */ - static int heredoc_errno; - - /* 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; - /* For catching RETURN in a function. */ int return_catch_flag; --- 176,179 ---- *************** *** 202,209 **** int subshell_environment; - /* Non-zero if we should stat every command found in the hash table to - make sure it still exists. */ - int check_hashed_filenames; - struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL; --- 197,200 ---- *************** *** 314,317 **** --- 305,314 ---- 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: *************** *** 346,350 **** #endif ! static void dispose_exec_redirects () { --- 343,347 ---- #endif ! void dispose_exec_redirects () { *************** *** 385,423 **** } - static int - stdin_redirects (redirs) - REDIRECT *redirs; - { - REDIRECT *rp; - int n; - - for (n = 0, rp = redirs; rp; rp = rp->next) - switch (rp->instruction) - { - case r_input_direction: - case r_inputa_direction: - case r_input_output: - case r_reading_until: - case r_deblank_reading_until: - n++; - break; - case r_duplicating_input: - case r_duplicating_input_word: - case r_close_this: - n += (rp->redirector == 0); - break; - case r_output_direction: - case r_appending_to: - case r_duplicating_output: - case r_err_and_out: - case r_output_force: - case r_duplicating_output_word: - break; - } - - return n; - } - - static void async_redirect_stdin () --- 382,385 ---- *************** *** 459,463 **** int exec_result, invert, ignore_return, was_debug_trap; REDIRECT *my_undo_list, *exec_undo_list; ! pid_t last_pid; if (command == 0 || breaking || continuing || read_but_dont_execute) --- 421,425 ---- int exec_result, invert, ignore_return, was_debug_trap; REDIRECT *my_undo_list, *exec_undo_list; ! volatile pid_t last_pid; if (command == 0 || breaking || continuing || read_but_dont_execute) *************** *** 783,787 **** if (ignore_return == 0 && invert == 0 && ! ((posixly_correct && interactive == 0 && special_builtin_failed) || (exit_immediately_on_error && (exec_result != EXECUTION_SUCCESS)))) { --- 745,749 ---- if (ignore_return == 0 && invert == 0 && ! ((posixly_correct && interactive == 0 && special_builtin_failed) || (exit_immediately_on_error && (exec_result != EXECUTION_SUCCESS)))) { *************** *** 880,883 **** --- 842,861 ---- break; + #if defined (DPAREN_ARITHMETIC) + case cm_arith: + if (ignore_return) + command->value.Arith->flags |= CMD_IGNORE_RETURN; + exec_result = execute_arith_command (command->value.Arith); + break; + #endif + + #if defined (COND_COMMAND) + case cm_cond: + if (ignore_return) + command->value.Cond->flags |= CMD_IGNORE_RETURN; + exec_result = execute_cond_command (command->value.Cond); + break; + #endif + case cm_function_def: exec_result = execute_intern_function (command->value.Function_def->name, *************** *** 978,982 **** t1.tv_sec *= 10; else ! t2.tv_sec /= 10; } --- 956,960 ---- t1.tv_sec *= 10; else ! t2.tv_sec /= 10; } *************** *** 1016,1020 **** aind++; while (abuf[aind]) ! buf[ind++] = abuf[aind++]; buf[ind++] = 'm'; } --- 994,998 ---- aind++; while (abuf[aind]) ! buf[ind++] = abuf[aind++]; buf[ind++] = 'm'; } *************** *** 1087,1100 **** { 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') { --- 1065,1078 ---- { 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') { *************** *** 1190,1193 **** --- 1168,1174 ---- command->flags = old_flags; + rs = us = ss = 0L; + rsf = usf = ssf = cpu = 0; + #if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY) gettimeofday (&after, &dtz); *************** *** 1305,1309 **** /* 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. */ --- 1286,1290 ---- /* 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. */ *************** *** 1536,1543 **** { if (posixly_correct && interactive_shell == 0) ! { ! last_command_exit_value = EX_USAGE; ! jump_to_top_level (EXITPROG); ! } return (EXECUTION_FAILURE); } --- 1517,1524 ---- { if (posixly_correct && interactive_shell == 0) ! { ! last_command_exit_value = EX_USAGE; ! jump_to_top_level (EXITPROG); ! } return (EXECUTION_FAILURE); } *************** *** 1756,1760 **** len = STRLEN (l->word->word); if (len > max_elem_len) ! max_elem_len = len; } indices_len = NUMBER_LEN (list_len); --- 1737,1741 ---- len = STRLEN (l->word->word); if (len > max_elem_len) ! max_elem_len = len; } indices_len = NUMBER_LEN (list_len); *************** *** 1777,1781 **** continue; if (legal_number (repl_string, &reply) == 0) ! continue; if (reply < 1 || reply > list_len) return ""; --- 1758,1762 ---- continue; if (legal_number (repl_string, &reply) == 0) ! return ""; if (reply < 1 || reply > list_len) return ""; *************** *** 1859,1868 **** if (return_val) ! { retval = return_catch_value; break; ! } else ! retval = execute_command (select_command->action); REAP (); --- 1840,1849 ---- if (return_val) ! { retval = return_catch_value; break; ! } else ! retval = execute_command (select_command->action); REAP (); *************** *** 1934,1938 **** if (es && es->word && es->word->word && *(es->word->word)) ! pattern = quote_string_for_globbing (es->word->word, 1); else { --- 1915,1919 ---- if (es && es->word && es->word->word && *(es->word->word)) ! pattern = quote_string_for_globbing (es->word->word, QGLOB_CVTNULL); else { *************** *** 1944,1948 **** Posix.2, section 3.9.4.3), the fnmatch () call must be able to recognize backslashes as escape characters. */ ! match = fnmatch (pattern, word, 0) != FNM_NOMATCH; free (pattern); --- 1925,1929 ---- Posix.2, section 3.9.4.3), the fnmatch () call must be able to recognize backslashes as escape characters. */ ! match = fnmatch (pattern, word, FNMATCH_EXTFLAG) != FNM_NOMATCH; free (pattern); *************** *** 2071,2074 **** --- 2052,2183 ---- } + #if defined (DPAREN_ARITHMETIC) + static int + execute_arith_command (arith_command) + ARITH_COM *arith_command; + { + int result, expok, expresult; + WORD_LIST *new, *p, *printit; + WORD_DESC *w; + + result = 0; + + this_command_name = "(("; + /* If we're in a function, update the line number information. */ + if (variable_context) + line_number = arith_command->line - function_line_number; + + new = expand_words (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); + + result = evalexp (new->word->word, &expok); + dispose_words (new); + + if (expok == 0) + return (EXECUTION_FAILURE); + + return (result == 0 ? EXECUTION_FAILURE : EXECUTION_SUCCESS); + } + #endif /* DPAREN_ARITHMETIC */ + + #if defined (COND_COMMAND) + + static char *nullstr = ""; + + static int + execute_cond_node (cond) + COND_COM *cond; + { + int result, invert, patmatch; + char *arg1, *arg2, *print2; + + invert = (cond->flags & CMD_INVERT_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) + { + arg1 = cond_expand_word (cond->left->op, 0); + 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) + { + patmatch = (cond->op->word[1] == '=') && (cond->op->word[2] == '\0') && + (cond->op->word[0] == '!' || cond->op->word[0] == '='); + + arg1 = cond_expand_word (cond->left->op, 0); + if (arg1 == 0) + arg1 = nullstr; + arg2 = cond_expand_word (cond->right->op, patmatch); + if (arg2 == 0) + arg2 = nullstr; + + if (echo_command_at_execute) + xtrace_print_cond_term (cond->type, invert, cond->op, arg1, arg2); + + result = binary_test (cond->op->word, arg1, arg2, TEST_PATMATCH|TEST_ARITHEXP) + ? EXECUTION_SUCCESS + : EXECUTION_FAILURE; + if (arg1 != nullstr) + free (arg1); + if (arg2 != nullstr) + free (arg2); + } + else + { + programming_error ("execute_cond_node: %d: unknown conditional command type", cond->type); + 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 result; + + result = EXECUTION_SUCCESS; + + this_command_name = "[["; + /* If we're in a function, update the line number information. */ + if (variable_context) + line_number = cond_command->line - function_line_number; + + #if 0 + debug_print_cond_command (cond_command); + #endif + last_command_exit_value = result = execute_cond_node (cond_command); + return (result); + } + #endif /* COND_COMMAND */ + static void bind_lastarg (arg) *************** *** 2168,2172 **** WORD_LIST *words, *lastword; char *command_line, *lastarg, *temp; ! int first_word_quoted, result, builtin_is_special; pid_t old_last_command_subst_pid; Function *builtin; --- 2277,2281 ---- WORD_LIST *words, *lastword; char *command_line, *lastarg, *temp; ! int first_word_quoted, result, builtin_is_special, already_forked; pid_t old_last_command_subst_pid; Function *builtin; *************** *** 2175,2178 **** --- 2284,2288 ---- result = EXECUTION_SUCCESS; special_builtin_failed = builtin_is_special = 0; + command_line = (char *)0; /* If we're in a function, update the line number information. */ *************** *** 2183,2188 **** command_string_index = 0; print_simple_command (simple_command); - command_line = xmalloc (1 + strlen (the_printed_command)); - strcpy (command_line, the_printed_command); /* XXX memory leak on errors */ first_word_quoted = --- 2293,2296 ---- *************** *** 2191,2194 **** --- 2299,2330 ---- old_last_command_subst_pid = last_command_subst_pid; + already_forked = 0; + if (pipe_in != NO_PIPE || pipe_out != NO_PIPE || async) + { + /* XXX memory leak if expand_words() error causes a jump_to_top_level */ + command_line = savestring (the_printed_command); + + if (make_child (command_line, async) == 0) + { + already_forked = 1; + simple_command->flags |= CMD_NO_FORK; + + do_piping (pipe_in, pipe_out); + pipe_in = pipe_out = -1; + + subshell_environment = SUBSHELL_ASYNC; + } + else + { + close_pipes (pipe_in, pipe_out); + #if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD) + unlink_fifo_list (); + #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. */ *************** *** 2209,2217 **** { result = execute_null_command (simple_command->redirects, ! pipe_in, pipe_out, async, old_last_command_subst_pid); ! FREE (command_line); ! bind_lastarg ((char *)NULL); ! return (result); } --- 2345,2359 ---- { result = execute_null_command (simple_command->redirects, ! pipe_in, pipe_out, ! already_forked ? 0 : async, old_last_command_subst_pid); ! if (already_forked) ! exit (result); ! else ! { ! bind_lastarg ((char *)NULL); ! set_pipestatus_from_exit (result); ! return (result); ! } } *************** *** 2253,2257 **** #if defined (JOB_CONTROL) /* Is this command a job control related thing? */ ! if (words->word->word[0] == '%') { this_command_name = async ? "bg" : "fg"; --- 2395,2399 ---- #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"; *************** *** 2265,2269 **** If they do, find out whether this word is a candidate for a running job. */ ! if (job_control && async == 0 && !first_word_quoted && !words->next && --- 2407,2411 ---- 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 && *************** *** 2338,2372 **** if (builtin || func) { ! if ((pipe_in != NO_PIPE) || (pipe_out != NO_PIPE) || async) { ! if (make_child (command_line, async) == 0) ! { ! /* reset_terminating_signals (); */ /* XXX */ ! /* Cancel traps, in trap.c. */ ! restore_original_signals (); ! ! 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 (); ! } ! execute_subshell_builtin_or_function ! (words, simple_command->redirects, builtin, func, ! pipe_in, pipe_out, async, fds_to_close, ! simple_command->flags); ! } ! else { ! close_pipes (pipe_in, pipe_out); ! #if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD) ! unlink_fifo_list (); ! #endif ! command_line = (char *)NULL; /* don't free this. */ ! goto return_result; } } else --- 2480,2502 ---- if (builtin || func) { ! if (already_forked) { ! /* reset_terminating_signals (); */ /* XXX */ ! /* Cancel traps, in trap.c. */ ! restore_original_signals (); ! 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 (); } + + execute_subshell_builtin_or_function + (words, simple_command->redirects, builtin, func, + pipe_in, pipe_out, async, fds_to_close, + simple_command->flags); } else *************** *** 2379,2385 **** if (result > EX_SHERRBASE) { ! result = builtin_status (result); ! if (builtin_is_special) ! special_builtin_failed = 1; } /* In POSIX mode, if there are assignment statements preceding --- 2509,2515 ---- if (result > EX_SHERRBASE) { ! result = builtin_status (result); ! if (builtin_is_special) ! special_builtin_failed = 1; } /* In POSIX mode, if there are assignment statements preceding *************** *** 2394,2404 **** result = EX_BADUSAGE; else if (result > EX_SHERRBASE) ! result = EXECUTION_FAILURE; } goto return_result; } } execute_disk_command (words, simple_command->redirects, command_line, pipe_in, pipe_out, async, fds_to_close, --- 2524,2539 ---- result = EX_BADUSAGE; else if (result > EX_SHERRBASE) ! result = EXECUTION_FAILURE; } + set_pipestatus_from_exit (result); + goto return_result; } } + if (command_line == 0) + command_line = savestring (the_printed_command); + execute_disk_command (words, simple_command->redirects, command_line, pipe_in, pipe_out, async, fds_to_close, *************** *** 2493,2498 **** --- 2628,2637 ---- if (posixly_correct && builtin_env) merge_builtin_env (); + #if 0 dispose_builtin_env (); discard_unwind_frame ("builtin_env"); + #else + run_unwind_frame ("builtin_env"); + #endif } *************** *** 2541,2546 **** { debug_trap = savestring (debug_trap); add_unwind_protect (set_debug_trap, debug_trap); - /* XXX - small memory leak here -- hard to fix */ } restore_default_signal (DEBUG_TRAP); --- 2680,2689 ---- { debug_trap = savestring (debug_trap); + /* XXX order is important here! unwind-protect commands are run + in reverse order of registering. If this causes problems, + take out the xfree unwind-protect and live with the small + memory leak. */ + add_unwind_protect (xfree, debug_trap); add_unwind_protect (set_debug_trap, debug_trap); } restore_default_signal (DEBUG_TRAP); *************** *** 2658,2667 **** exit (EXECUTION_FAILURE); else ! { ! r = execute_builtin (builtin, words, flags, 1); ! if (r == EX_USAGE) ! r = EX_BADUSAGE; ! exit (r); ! } } else --- 2801,2810 ---- exit (EXECUTION_FAILURE); else ! { ! r = execute_builtin (builtin, words, flags, 1); ! if (r == EX_USAGE) ! r = EX_BADUSAGE; ! exit (r); ! } } else *************** *** 2828,2833 **** /* 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) { --- 2971,2976 ---- /* 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) { *************** *** 3001,3017 **** /* If we're not interactive, close the file descriptor from which we're reading the current shell script. */ ! #if defined (BUFFERED_INPUT) ! if (interactive_shell == 0 && default_buffered_input >= 0) ! { ! close_buffered_fd (default_buffered_input); ! default_buffered_input = bash_input.location.buffered_fd = -1; ! } ! #else ! if (interactive_shell == 0 && default_input) ! { ! fclose (default_input); ! default_input = (FILE *)NULL; ! } ! #endif } --- 3144,3149 ---- /* 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 (1); } *************** *** 3198,3202 **** sys_error ("cannot duplicate fd %d to fd 0", pipe_in); if (pipe_in > 0) ! close (pipe_in); } if (pipe_out != NO_PIPE) --- 3330,3337 ---- sys_error ("cannot duplicate fd %d to fd 0", pipe_in); if (pipe_in > 0) ! close (pipe_in); ! #ifdef __CYGWIN32__ ! setmode (0, O_TEXT); ! #endif } if (pipe_out != NO_PIPE) *************** *** 3208,4432 **** if (pipe_out == 0 || pipe_out > 1) close (pipe_out); } else - if (dup2 (1, 2) < 0) - sys_error ("cannot duplicate fd 1 to fd 2"); - } - } - - static void - redirection_error (temp, error) - REDIRECT *temp; - int error; - { - char *filename; - - if (expandable_redirection_filename (temp)) - { - if (posixly_correct && !interactive_shell) - disallow_filename_globbing++; - filename = redirection_expand (temp->redirectee.filename); - if (posixly_correct && !interactive_shell) - disallow_filename_globbing--; - if (filename == 0) - filename = savestring (temp->redirectee.filename->word); - if (filename == 0) - { - filename = xmalloc (1); - filename[0] = '\0'; - } - } - else - filename = itos (temp->redirectee.dest); - - switch (error) - { - case AMBIGUOUS_REDIRECT: - internal_error ("%s: ambiguous redirect", filename); - break; - - case NOCLOBBER_REDIRECT: - internal_error ("%s: cannot overwrite existing file", filename); - break; - - #if defined (RESTRICTED_SHELL) - case RESTRICTED_REDIRECT: - internal_error ("%s: restricted: cannot redirect output", filename); - break; - #endif /* RESTRICTED_SHELL */ - - case HEREDOC_REDIRECT: - internal_error ("cannot create temp file for here document: %s", strerror (heredoc_errno)); - break; - - default: - internal_error ("%s: %s", filename, strerror (error)); - break; - } - - FREE (filename); - } - - /* Perform the redirections on LIST. If FOR_REAL, then actually make - input and output file descriptors, otherwise just do whatever is - neccessary for side effecting. INTERNAL says to remember how to - undo the redirections later, if non-zero. If SET_CLEXEC is non-zero, - file descriptors opened in do_redirection () have their close-on-exec - flag set. */ - static int - do_redirections (list, for_real, internal, set_clexec) - REDIRECT *list; - int for_real, internal, set_clexec; - { - int error; - REDIRECT *temp; - - if (internal) - { - if (redirection_undo_list) - { - dispose_redirects (redirection_undo_list); - redirection_undo_list = (REDIRECT *)NULL; - } - if (exec_redirection_undo_list) - dispose_exec_redirects (); - } - - for (temp = list; temp; temp = temp->next) - { - error = do_redirection_internal (temp, for_real, internal, set_clexec); - if (error) { ! redirection_error (temp, error); ! return (error); ! } ! } ! return (0); ! } ! ! /* Return non-zero if the redirection pointed to by REDIRECT has a ! redirectee.filename that can be expanded. */ ! static int ! expandable_redirection_filename (redirect) ! REDIRECT *redirect; ! { ! switch (redirect->instruction) ! { ! case r_output_direction: ! case r_appending_to: ! case r_input_direction: ! case r_inputa_direction: ! case r_err_and_out: ! case r_input_output: ! case r_output_force: ! case r_duplicating_input_word: ! case r_duplicating_output_word: ! return 1; ! ! default: ! return 0; ! } ! } ! ! /* Expand the word in WORD returning a string. If WORD expands to ! multiple words (or no words), then return NULL. */ ! char * ! redirection_expand (word) ! WORD_DESC *word; ! { ! char *result; ! WORD_LIST *tlist1, *tlist2; ! ! tlist1 = make_word_list (copy_word (word), (WORD_LIST *)NULL); ! tlist2 = expand_words_no_vars (tlist1); ! dispose_words (tlist1); ! ! if (!tlist2 || tlist2->next) ! { ! /* We expanded to no words, or to more than a single word. ! Dispose of the word list and return NULL. */ ! if (tlist2) ! dispose_words (tlist2); ! return ((char *)NULL); ! } ! result = string_list (tlist2); /* XXX savestring (tlist2->word->word)? */ ! dispose_words (tlist2); ! return (result); ! } ! ! /* Write the text of the here document pointed to by REDIRECTEE to the file ! descriptor FD, which is already open to a temp file. Return 0 if the ! write is successful, otherwise return errno. */ ! static int ! write_here_document (fd, redirectee) ! int fd; ! WORD_DESC *redirectee; ! { ! char *document; ! int document_len, fd2; ! FILE *fp; ! register WORD_LIST *t, *tlist; ! ! /* Expand the text if the word that was specified had ! no quoting. The text that we expand is treated ! exactly as if it were surrounded by double quotes. */ ! ! if (redirectee->flags & W_QUOTED) ! { ! document = redirectee->word; ! document_len = strlen (document); ! /* Set errno to something reasonable if the write fails. */ ! if (write (fd, document, document_len) < document_len) ! { ! if (errno == 0) ! errno = ENOSPC; ! return (errno); ! } ! else ! return 0; ! } ! ! tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT); ! if (tlist) ! { ! /* Try using buffered I/O (stdio) and writing a word ! at a time, letting stdio do the work of buffering ! for us rather than managing our own strings. Most ! stdios are not particularly fast, however -- this ! may need to be reconsidered later. */ ! if ((fd2 = dup (fd)) < 0 || (fp = fdopen (fd2, "w")) == NULL) ! { ! if (fd2 >= 0) ! close (fd2); ! return (errno); ! } ! errno = 0; ! for (t = tlist; t; t = t->next) ! { ! /* This is essentially the body of ! string_list_internal expanded inline. */ ! document = t->word->word; ! document_len = strlen (document); ! if (t != tlist) ! putc (' ', fp); /* separator */ ! fwrite (document, document_len, 1, fp); ! if (ferror (fp)) ! { ! if (errno == 0) ! errno = ENOSPC; ! fd2 = errno; ! fclose(fp); ! dispose_words (tlist); ! return (fd2); ! } } - fclose (fp); - dispose_words (tlist); - } - return 0; - } - - /* Create a temporary file holding the text of the here document pointed to - by REDIRECTEE, and return a file descriptor open for reading to the temp - file. Return -1 on any error, and make sure errno is set appropriately. */ - static int - here_document_to_fd (redirectee) - WORD_DESC *redirectee; - { - char filename[24]; - int r, fd; - - /* Make the filename for the temp file. */ - sprintf (filename, "/tmp/t%d-sh", (int)time ((time_t *) 0) + (int)getpid ()); - - /* Make sure we open it exclusively. */ - fd = open (filename, O_TRUNC | O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) - return (fd); - - errno = r = 0; /* XXX */ - /* write_here_document returns 0 on success, errno on failure. */ - if (redirectee->word) - r = write_here_document (fd, redirectee); - - close (fd); - if (r) - { - unlink (filename); - errno = r; - return (-1); - } - - /* XXX - this is raceable */ - /* Make the document really temporary. Also make it the input. */ - fd = open (filename, O_RDONLY, 0600); - - if (fd < 0) - { - r = errno; - unlink (filename); - errno = r; - return -1; - } - - if (unlink (filename) < 0) - { - r = errno; - close (fd); - errno = r; - return (-1); } - - return (fd); - } - - /* Open FILENAME with FLAGS in noclobber mode, hopefully avoiding most - race conditions and avoiding the problem where the file is replaced - between the stat(2) and open(2). */ - static int - noclobber_open (filename, flags, ri) - char *filename; - int flags; - enum r_instruction ri; - { - int r, fd; - struct stat finfo, finfo2; - - /* If the file exists and is a regular file, return an error - immediately. */ - r = stat (filename, &finfo); - if (r == 0 && (S_ISREG (finfo.st_mode))) - return (NOCLOBBER_REDIRECT); - - /* If the file was not present (r != 0), make sure we open it - exclusively so that if it is created before we open it, our open - will fail. Make sure that we do not truncate an existing file. - Note that we don't turn on O_EXCL unless the stat failed -- if - the file was not a regular file, we leave O_EXCL off. */ - flags &= ~O_TRUNC; - if (r != 0) - { - fd = open (filename, flags|O_EXCL, 0666); - return ((fd < 0 && errno == EEXIST) ? NOCLOBBER_REDIRECT : fd); - } - fd = open (filename, flags, 0666); - - /* If the open failed, return the file descriptor right away. */ - if (fd < 0) - return (errno == EEXIST ? NOCLOBBER_REDIRECT : fd); - - /* OK, the open succeeded, but the file may have been changed from a - non-regular file to a regular file between the stat and the open. - We are assuming that the O_EXCL open handles the case where FILENAME - did not exist and is symlinked to an existing file between the stat - and open. */ - - /* If we can open it and fstat the file descriptor, and neither check - revealed that it was a regular file, and the file has not been replaced, - return the file descriptor. */ - if ((fstat (fd, &finfo2) == 0) && (S_ISREG (finfo2.st_mode) == 0) && - r == 0 && (S_ISREG (finfo.st_mode) == 0) && - same_file (filename, filename, &finfo, &finfo2)) - return fd; - - /* The file has been replaced. badness. */ - close (fd); - errno = EEXIST; - return (NOCLOBBER_REDIRECT); - } - - /* Do the specific redirection requested. Returns errno or one of the - special redirection errors (*_REDIRECT) in case of error, 0 on success. - If FOR_REAL is zero, then just do whatever is neccessary to produce the - appropriate side effects. REMEMBERING, if non-zero, says to remember - how to undo each redirection. If SET_CLEXEC is non-zero, then - we set all file descriptors > 2 that we open to be close-on-exec. */ - static int - do_redirection_internal (redirect, for_real, remembering, set_clexec) - REDIRECT *redirect; - int for_real, remembering, set_clexec; - { - WORD_DESC *redirectee; - int redir_fd, fd, redirector, r; - char *redirectee_word; - enum r_instruction ri; - REDIRECT *new_redirect; - - redirectee = redirect->redirectee.filename; - redir_fd = redirect->redirectee.dest; - redirector = redirect->redirector; - ri = redirect->instruction; - - if (ri == r_duplicating_input_word || ri == r_duplicating_output_word) - { - /* We have [N]>&WORD or [N]<&WORD. Expand WORD, then translate - the redirection into a new one and continue. */ - redirectee_word = redirection_expand (redirectee); - - if (redirectee_word == 0) - return (AMBIGUOUS_REDIRECT); - else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0') - { - rd.dest = 0L; - new_redirect = make_redirection (redirector, r_close_this, rd); - } - else if (all_digits (redirectee_word)) - { - if (ri == r_duplicating_input_word) - { - rd.dest = atol (redirectee_word); - new_redirect = make_redirection (redirector, r_duplicating_input, rd); - } - else - { - rd.dest = atol (redirectee_word); - new_redirect = make_redirection (redirector, r_duplicating_output, rd); - } - } - else if (ri == r_duplicating_output_word && redirector == 1) - { - if (posixly_correct == 0) - { - rd.filename = make_bare_word (redirectee_word); - new_redirect = make_redirection (1, r_err_and_out, rd); - } - else - new_redirect = copy_redirect (redirect); - } - else - { - free (redirectee_word); - return (AMBIGUOUS_REDIRECT); - } - - free (redirectee_word); - - /* Set up the variables needed by the rest of the function from the - new redirection. */ - if (new_redirect->instruction == r_err_and_out) - { - char *alloca_hack; - - /* Copy the word without allocating any memory that must be - explicitly freed. */ - redirectee = (WORD_DESC *)alloca (sizeof (WORD_DESC)); - xbcopy ((char *)new_redirect->redirectee.filename, - (char *)redirectee, sizeof (WORD_DESC)); - - alloca_hack = (char *) - alloca (1 + strlen (new_redirect->redirectee.filename->word)); - redirectee->word = alloca_hack; - strcpy (redirectee->word, new_redirect->redirectee.filename->word); - } - else - /* It's guaranteed to be an integer, and shouldn't be freed. */ - redirectee = new_redirect->redirectee.filename; - - redir_fd = new_redirect->redirectee.dest; - redirector = new_redirect->redirector; - ri = new_redirect->instruction; - - /* Overwrite the flags element of the old redirect with the new value. */ - redirect->flags = new_redirect->flags; - dispose_redirects (new_redirect); - } - - switch (ri) - { - case r_output_direction: - case r_appending_to: - case r_input_direction: - case r_inputa_direction: - case r_err_and_out: /* command &>filename */ - case r_input_output: - case r_output_force: - if (posixly_correct && !interactive_shell) - disallow_filename_globbing++; - redirectee_word = redirection_expand (redirectee); - if (posixly_correct && !interactive_shell) - disallow_filename_globbing--; - - if (redirectee_word == 0) - return (AMBIGUOUS_REDIRECT); - - #if defined (RESTRICTED_SHELL) - if (restricted && (WRITE_REDIRECT (ri))) - { - free (redirectee_word); - return (RESTRICTED_REDIRECT); - } - #endif /* RESTRICTED_SHELL */ - - /* If we are in noclobber mode, you are not allowed to overwrite - existing files. Check before opening. */ - if (noclobber && OUTPUT_REDIRECT (ri)) - { - fd = noclobber_open (redirectee_word, redirect->flags, ri); - if (fd == NOCLOBBER_REDIRECT) - { - free (redirectee_word); - return (NOCLOBBER_REDIRECT); - } - } - else - { - fd = open (redirectee_word, redirect->flags, 0666); - #if defined (AFS) - if ((fd < 0) && (errno == EACCES)) - fd = open (redirectee_word, redirect->flags & ~O_CREAT, 0666); - #endif /* AFS */ - } - free (redirectee_word); - - if (fd < 0) - return (errno); - - if (for_real) - { - if (remembering) - /* Only setup to undo it if the thing to undo is active. */ - if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1)) - add_undo_redirect (redirector); - else - add_undo_close_redirect (redirector); - - #if defined (BUFFERED_INPUT) - check_bash_input (redirector); - #endif - - if ((fd != redirector) && (dup2 (fd, redirector) < 0)) - return (errno); - - #if defined (BUFFERED_INPUT) - /* Do not change the buffered stream for an implicit redirection - of /dev/null to fd 0 for asynchronous commands without job - control (r_inputa_direction). */ - if (ri == r_input_direction || ri == r_input_output) - duplicate_buffered_stream (fd, redirector); - #endif /* BUFFERED_INPUT */ - - /* - * If we're remembering, then this is the result of a while, for - * or until loop with a loop redirection, or a function/builtin - * executing in the parent shell with a redirection. In the - * function/builtin case, we want to set all file descriptors > 2 - * to be close-on-exec to duplicate the effect of the old - * for i = 3 to NOFILE close(i) loop. In the case of the loops, - * both sh and ksh leave the file descriptors open across execs. - * The Posix standard mentions only the exec builtin. - */ - if (set_clexec && (redirector > 2)) - SET_CLOSE_ON_EXEC (redirector); - } - - if (fd != redirector) - { - #if defined (BUFFERED_INPUT) - if (INPUT_REDIRECT (ri)) - close_buffered_fd (fd); - else - #endif /* !BUFFERED_INPUT */ - close (fd); /* Don't close what we just opened! */ - } - - /* If we are hacking both stdout and stderr, do the stderr - redirection here. */ - if (ri == r_err_and_out) - { - if (for_real) - { - if (remembering) - add_undo_redirect (2); - if (dup2 (1, 2) < 0) - return (errno); - } - } - break; - - case r_reading_until: - case r_deblank_reading_until: - /* REDIRECTEE is a pointer to a WORD_DESC containing the text of - the new input. Place it in a temporary file. */ - if (redirectee) - { - fd = here_document_to_fd (redirectee); - - if (fd < 0) - { - heredoc_errno = errno; - return (HEREDOC_REDIRECT); - } - - if (for_real) - { - if (remembering) - /* Only setup to undo it if the thing to undo is active. */ - if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1)) - add_undo_redirect (redirector); - else - add_undo_close_redirect (redirector); - - #if defined (BUFFERED_INPUT) - check_bash_input (redirector); - #endif - if (fd != redirector && dup2 (fd, redirector) < 0) - { - r = errno; - close (fd); - return (r); - } - - #if defined (BUFFERED_INPUT) - duplicate_buffered_stream (fd, redirector); - #endif - - if (set_clexec && (redirector > 2)) - SET_CLOSE_ON_EXEC (redirector); - } - - #if defined (BUFFERED_INPUT) - close_buffered_fd (fd); - #else - close (fd); - #endif - } - break; - - case r_duplicating_input: - case r_duplicating_output: - if (for_real && (redir_fd != redirector)) - { - if (remembering) - /* Only setup to undo it if the thing to undo is active. */ - if (fcntl (redirector, F_GETFD, 0) != -1) - add_undo_redirect (redirector); - else - add_undo_close_redirect (redirector); - - #if defined (BUFFERED_INPUT) - check_bash_input (redirector); - #endif - /* This is correct. 2>&1 means dup2 (1, 2); */ - if (dup2 (redir_fd, redirector) < 0) - return (errno); - - #if defined (BUFFERED_INPUT) - if (ri == r_duplicating_input) - duplicate_buffered_stream (redir_fd, redirector); - #endif /* BUFFERED_INPUT */ - - /* First duplicate the close-on-exec state of redirectee. dup2 - leaves the flag unset on the new descriptor, which means it - stays open. Only set the close-on-exec bit for file descriptors - greater than 2 in any case, since 0-2 should always be open - unless closed by something like `exec 2<&-'. */ - /* if ((already_set || set_unconditionally) && (ok_to_set)) - set_it () */ - if (((fcntl (redir_fd, F_GETFD, 0) == 1) || set_clexec) && - (redirector > 2)) - SET_CLOSE_ON_EXEC (redirector); - } - break; - - case r_close_this: - if (for_real) - { - if (remembering && (fcntl (redirector, F_GETFD, 0) != -1)) - add_undo_redirect (redirector); - - #if defined (BUFFERED_INPUT) - check_bash_input (redirector); - close_buffered_fd (redirector); - #else /* !BUFFERED_INPUT */ - close (redirector); - #endif /* !BUFFERED_INPUT */ - } - break; - - case r_duplicating_input_word: - case r_duplicating_output_word: - break; - } - return (0); - } - - #define SHELL_FD_BASE 10 - - /* Remember the file descriptor associated with the slot FD, - on REDIRECTION_UNDO_LIST. Note that the list will be reversed - before it is executed. Any redirections that need to be undone - even if REDIRECTION_UNDO_LIST is discarded by the exec builtin - are also saved on EXEC_REDIRECTION_UNDO_LIST. */ - static int - add_undo_redirect (fd) - int fd; - { - int new_fd, clexec_flag; - REDIRECT *new_redirect, *closer, *dummy_redirect; - - new_fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE); - - if (new_fd < 0) - { - sys_error ("redirection error"); - return (-1); - } - - clexec_flag = fcntl (fd, F_GETFD, 0); - - rd.dest = 0L; - closer = make_redirection (new_fd, r_close_this, rd); - dummy_redirect = copy_redirects (closer); - - rd.dest = (long)new_fd; - new_redirect = make_redirection (fd, r_duplicating_output, rd); - new_redirect->next = closer; - - closer->next = redirection_undo_list; - redirection_undo_list = new_redirect; - - /* Save redirections that need to be undone even if the undo list - is thrown away by the `exec' builtin. */ - add_exec_redirect (dummy_redirect); - - /* File descriptors used only for saving others should always be - marked close-on-exec. Unfortunately, we have to preserve the - close-on-exec state of the file descriptor we are saving, since - fcntl (F_DUPFD) sets the new file descriptor to remain open - across execs. If, however, the file descriptor whose state we - are saving is <= 2, we can just set the close-on-exec flag, - because file descriptors 0-2 should always be open-on-exec, - and the restore above in do_redirection() will take care of it. */ - if (clexec_flag || fd < 3) - SET_CLOSE_ON_EXEC (new_fd); - - return (0); - } - - /* Set up to close FD when we are finished with the current command - and its redirections. */ - static void - add_undo_close_redirect (fd) - int fd; - { - REDIRECT *closer; - - rd.dest = 0L; - closer = make_redirection (fd, r_close_this, rd); - closer->next = redirection_undo_list; - redirection_undo_list = closer; - } - - static void - add_exec_redirect (dummy_redirect) - REDIRECT *dummy_redirect; - { - dummy_redirect->next = exec_redirection_undo_list; - exec_redirection_undo_list = dummy_redirect; - } - - #define u_mode_bits(x) (((x) & 0000700) >> 6) - #define g_mode_bits(x) (((x) & 0000070) >> 3) - #define o_mode_bits(x) (((x) & 0000007) >> 0) - #define X_BIT(x) ((x) & 1) - - /* 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) - char *name; - { - struct stat finfo; - - /* 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); - - #if 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) - return (FS_EXISTS | FS_EXECABLE); - else - return (FS_EXISTS); - #else /* !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. */ - - /* Root only requires execute permission for any of owner, group or - others to be able to exec a file. */ - if (current_user.euid == (uid_t)0) - { - int bits; - - bits = (u_mode_bits (finfo.st_mode) | - g_mode_bits (finfo.st_mode) | - o_mode_bits (finfo.st_mode)); - - if (X_BIT (bits)) - return (FS_EXISTS | FS_EXECABLE); - } - - /* If we are the owner of the file, the owner execute bit applies. */ - if (current_user.euid == finfo.st_uid && X_BIT (u_mode_bits (finfo.st_mode))) - return (FS_EXISTS | FS_EXECABLE); - - /* If we are in the owning group, the group permissions apply. */ - if (group_member (finfo.st_gid) && X_BIT (g_mode_bits (finfo.st_mode))) - return (FS_EXISTS | FS_EXECABLE); - - /* If `others' have execute permission to the file, then so do we, - since we are also `others'. */ - if (X_BIT (o_mode_bits (finfo.st_mode))) - return (FS_EXISTS | FS_EXECABLE); - - return (FS_EXISTS); - #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) - char *file; - { - int s; - - s = file_status (file); - return ((s & FS_EXECABLE) && ((s & FS_DIRECTORY) == 0)); - } - - int - is_directory (file) - char *file; - { - return (file_status (file) & FS_DIRECTORY); - } - - /* 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; - - /* 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) - 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 file found. */ - char * - find_path_file (name) - char *name; - { - return (find_user_command_internal (name, FS_EXISTS)); - } - - static char * - _find_user_command_internal (name, flags) - char *name; - int flags; - { - char *path_list; - SHELL_VAR *var; - - /* Search for the value of PATH in both the temporary environment, and - in the regular list of variables. */ - if (var = find_variable_internal ("PATH", 1)) /* XXX could be array? */ - path_list = value_cell (var); - else - path_list = (char *)NULL; - - if (path_list == 0 || *path_list == '\0') - return (savestring (name)); - - return (find_user_command_in_path (name, path_list, flags)); - } - - static char * - find_user_command_internal (name, flags) - char *name; - int flags; - { - #ifdef __WIN32__ - char *res, *dotexe; - - dotexe = 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) - return (path); - - if (!*path) - { - 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. Returns a newly-allocated string. */ - char * - search_for_command (pathname) - char *pathname; - { - 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_tempenv_variable ("PATH"); - temp_path = path != 0; - - /* 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 = find_hashed_filename (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)) != 0) - { - remove_hashed_filename (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) - remember_filename (pathname, command, dot_found_in_search, 1); - } - return (command); - } - - char * - user_command_matches (name, flags, state) - 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 = (char **)xmalloc (match_list_size * sizeof(char *)); - } - - /* 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; - stat (".", &dotinfo); - 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 = (char **)xrealloc (match_list, (match_list_size + 1) * sizeof (char *)); - } - - 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); - } - - /* Turn PATH, a directory, and NAME, a filename, into a full pathname. - This allocates new memory and returns it. */ - static char * - make_full_pathname (path, name, name_len) - char *path, *name; - int name_len; - { - char *full_path; - int path_len; - - path_len = strlen (path); - full_path = xmalloc (2 + path_len + name_len); - strcpy (full_path, path); - full_path[path_len] = '/'; - strcpy (full_path + path_len + 1, name); - return (full_path); - } - - static char * - find_absolute_program (name, flags) - 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 ((char *)NULL); - } - - static char * - find_in_path_element (name, path, flags, name_len, dotinfop) - char *name, *path; - int flags, name_len; - struct stat *dotinfop; - { - int status; - char *full_path, *xpath; - - xpath = (*path == '~') ? bash_tilde_expand (path) : 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 = make_full_pathname (xpath, name, name_len); - - 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 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_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, fail. */ - if ((flags & FS_EXEC_ONLY) || (flags & FS_EXEC_PREFERRED) || - ((flags & FS_NODIRS) && (status & FS_DIRECTORY))) - { - 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) - 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); - stat (".", &dotinfo); - 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. */ - return (file_to_lose_on); } --- 3343,3359 ---- if (pipe_out == 0 || pipe_out > 1) close (pipe_out); + #ifdef __CYGWIN32__ + setmode (1, O_TEXT); + #endif } else { ! if (dup2 (1, 2) < 0) ! sys_error ("cannot duplicate fd 1 to fd 2"); ! #ifdef __CYGWIN32__ ! setmode (1, O_TEXT); ! setmode (2, O_TEXT); ! #endif } } } diff -Nrc2 bash-2.01.1/execute_cmd.h bash-2.02/execute_cmd.h *** bash-2.01.1/execute_cmd.h Wed Dec 20 16:29:33 1995 --- bash-2.02/execute_cmd.h Thu Jul 10 12:29:39 1997 *************** *** 31,43 **** extern int execute_command_internal __P((COMMAND *, int, int, int, struct fd_bitmap *)); extern int shell_execve __P((char *, char **, char **)); - extern char *redirection_expand __P((WORD_DESC *)); - extern int file_status __P((char *)); - extern int executable_file __P((char *)); - extern int is_directory __P((char *)); - extern char *search_for_command __P((char *)); - extern char *find_user_command __P((char *)); - extern char *find_path_file __P((char *)); - extern char *user_command_matches __P((char *, int, int)); extern void setup_async_signals __P((void)); #if defined (PROCESS_SUBSTITUTION) --- 31,36 ---- extern int execute_command_internal __P((COMMAND *, int, int, int, struct fd_bitmap *)); extern int shell_execve __P((char *, char **, char **)); extern void setup_async_signals __P((void)); + extern void dispose_exec_redirects __P ((void)); #if defined (PROCESS_SUBSTITUTION) diff -Nrc2 bash-2.01.1/expr.c bash-2.02/expr.c *** bash-2.01.1/expr.c Thu Apr 24 16:16:18 1997 --- bash-2.02/expr.c Tue Nov 11 12:15:27 1997 *************** *** 28,31 **** --- 28,32 ---- "-", "+" [(unary operators)] "!", "~" + "**" [(exponentiation)] "*", "/", "%" "+", "-" *************** *** 39,45 **** "||" "expr ? expr : expr" ! "=", "*=", "/=", "%=", ! "+=", "-=", "<<=", ">>=", ! "&=", "^=", "|=" (Note that most of these operators have special meaning to bash, and an --- 40,44 ---- "||" "expr ? expr : expr" ! "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|=" (Note that most of these operators have special meaning to bash, and an *************** *** 69,73 **** --- 68,76 ---- #include #include "bashansi.h" + #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 100,104 **** #define RSH 10 /* ">>" Right SHift */ #define OP_ASSIGN 11 /* op= expassign as in Posix.2 */ ! #define COND 12 #define EQ '=' #define GT '>' --- 103,108 ---- #define RSH 10 /* ">>" Right SHift */ #define OP_ASSIGN 11 /* op= expassign as in Posix.2 */ ! #define COND 12 /* exp1 ? exp2 : exp3 */ ! #define POWER 13 /* exp1**exp2 */ #define EQ '=' #define GT '>' *************** *** 133,137 **** static long subexpr (), expassign (), exp0 (), exp1 (), exp2 (), exp3 (), exp4 (), exp5 (), expshift (), expland (), explor (), ! expband (), expbor (), expbxor (), expcond (); static long strlong (); static void evalerror (); --- 137,141 ---- static long subexpr (), expassign (), exp0 (), exp1 (), exp2 (), exp3 (), exp4 (), exp5 (), expshift (), expland (), explor (), ! expband (), expbor (), expbxor (), expcond (), exppower (); static long strlong (); static void evalerror (); *************** *** 666,670 **** register long val1, val2; ! val1 = exp1 (); while ((curtok == MUL) || --- 670,674 ---- register long val1, val2; ! val1 = exppower (); while ((curtok == MUL) || *************** *** 676,680 **** readtok (); ! val2 = exp1 (); if (((op == DIV) || (op == MOD)) && (val2 == 0)) --- 680,684 ---- readtok (); ! val2 = exppower (); if (((op == DIV) || (op == MOD)) && (val2 == 0)) *************** *** 692,695 **** --- 696,718 ---- static long + exppower () + { + register long val1, val2, c; + + val1 = exp1 (); + if (curtok == POWER) + { + readtok (); + val2 = exp1 (); + if (val2 == 0) + return (1L); + for (c = 1; val2--; c *= val1) + ; + val1 = c; + } + return (val1); + } + + static long exp1 () { *************** *** 876,879 **** --- 899,904 ---- else if ((c == BOR) && (c1 == BOR)) c = LOR; + else if ((c == '*') && (c1 == '*')) + c = POWER; else if (c1 == EQ && member(c, "*/%+-&^|")) { *************** *** 906,910 **** /* Convert a string to a long integer, with an arbitrary base. 0nnn -> base 8 ! 0xnn -> base 16 Anything else: [base#]number (this is implemented to match ksh93) --- 931,935 ---- /* Convert a string to a long integer, with an arbitrary base. 0nnn -> base 8 ! 0[Xx]nn -> base 16 Anything else: [base#]number (this is implemented to match ksh93) diff -Nrc2 bash-2.01.1/externs.h bash-2.02/externs.h *** bash-2.01.1/externs.h Fri Jul 18 13:52:54 1997 --- bash-2.02/externs.h Tue Feb 24 15:51:02 1998 *************** *** 30,38 **** extern long evalexp __P((char *, int *)); - /* Functions from getcwd.c */ - #if !defined (HAVE_GETCWD) - extern char *getcwd __P((char *, size_t)); - #endif - /* Functions from print_cmd.c. */ extern char *make_command_string __P((COMMAND *)); --- 30,33 ---- *************** *** 42,48 **** extern void print_word_list __P((WORD_LIST *, char *)); extern void xtrace_print_word_list __P((WORD_LIST *)); /* Functions from shell.c. */ ! extern int exit_shell __P((int)); extern void disable_priv_mode __P((void)); extern void unbind_args __P((void)); --- 37,49 ---- extern void print_word_list __P((WORD_LIST *, char *)); extern void xtrace_print_word_list __P((WORD_LIST *)); + #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)); extern void disable_priv_mode __P((void)); extern void unbind_args __P((void)); *************** *** 52,55 **** --- 53,57 ---- #endif + extern void unset_bash_input __P((int)); extern void get_current_user_info __P((void)); *************** *** 58,64 **** extern int parse_command __P((void)); extern int read_command __P((void)); ! ! /* Functions from test.c. */ ! extern int test_command (); /* Functions from braces.c. */ --- 60,64 ---- extern int parse_command __P((void)); extern int read_command __P((void)); ! extern WORD_LIST *parse_string_to_word_list __P((char *, char *)); /* Functions from braces.c. */ *************** *** 91,95 **** extern GENERIC_LIST *delete_element (); ! /* Declarations for functions defined in oslib.c */ extern long get_clk_tck __P((void)); --- 91,123 ---- extern GENERIC_LIST *delete_element (); ! /* Declarations for functions defined in stringlib.c */ ! extern char *ansicstr __P((char *, int, int *, int *)); ! extern int find_name_in_array __P((char *, char **)); ! extern int array_len __P((char **)); ! extern void free_array_members __P((char **)); ! extern void free_array __P((char **)); ! extern char **copy_array __P((char **)); ! extern int qsort_string_compare (); ! extern void sort_char_array __P((char **)); ! extern char **word_list_to_argv __P((WORD_LIST *, int, int, int *)); ! extern WORD_LIST *argv_to_word_list __P((char **, int, int)); ! ! extern char *strsub __P((char *, char *, char *, int)); ! extern void strip_leading __P((char *)); ! extern void strip_trailing __P((char *, int, int)); ! extern char *strindex __P((char *, char *)); ! extern void xbcopy __P((char *, char *, 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/getcwd.c */ ! #if !defined (HAVE_GETCWD) ! extern char *getcwd __P((char *, size_t)); ! #endif ! ! /* Declarations for functions defined in lib/sh/itos.c */ ! extern char *itos __P((int)); ! ! /* Declarations for functions defined in lib/sh/oslib.c */ extern long get_clk_tck __P((void)); *************** *** 117,137 **** #endif ! /* Declarations for functions defined in stringlib.c */ ! extern char *ansicstr __P((char *, int, int *, int *)); ! extern int find_name_in_array __P((char *, char **)); ! extern int array_len __P((char **)); ! extern void free_array_members __P((char **)); ! extern void free_array __P((char **)); ! extern char **copy_array __P((char **)); ! extern int qsort_string_compare (); ! extern void sort_char_array __P((char **)); ! extern char **word_list_to_argv __P((WORD_LIST *, int, int, int *)); ! extern WORD_LIST *argv_to_word_list __P((char **, int, int)); ! extern char *strsub __P((char *, char *, char *, int)); ! extern void strip_leading __P((char *)); ! extern void strip_trailing __P((char *, int, int)); ! extern char *strindex __P((char *, char *)); ! extern void xbcopy __P((char *, char *, int)); #endif /* _EXTERNS_H_ */ --- 145,162 ---- #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 !defined (HAVE_STRTOL) ! extern long strtol __P((const char *, char **, int)); ! #endif ! ! /* declarations for functions defined in lib/sh/strtoul.c */ ! #if !defined (HAVE_STRTOUL) ! extern unsigned long strtoul __P((const char *, char **, int)); ! #endif #endif /* _EXTERNS_H_ */ diff -Nrc2 bash-2.01.1/findcmd.c bash-2.02/findcmd.c *** bash-2.01.1/findcmd.c Wed Dec 31 19:00:00 1969 --- bash-2.02/findcmd.c Wed Oct 15 11:55:20 1997 *************** *** 0 **** --- 1,580 ---- + /* findcmd.c -- Functions to search for commands by name. */ + + /* Copyright (C) 1997 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 Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ + + #include "config.h" + + #include + #include + #include "bashtypes.h" + #ifndef _MINIX + # include + #endif + #include "filecntl.h" + #include "posixstat.h" + + #if defined (HAVE_UNISTD_H) + # include + #endif + + #if defined (HAVE_LIMITS_H) + # include + #endif + + #include "bashansi.h" + + #include "memalloc.h" + #include "shell.h" + #include "flags.h" + #include "hashlib.h" + #include "pathexp.h" + #include "hashcmd.h" + + extern int posixly_correct; + + /* Static functions defined and used in this file. */ + static char *find_user_command_internal (), *find_user_command_in_path (); + static char *find_in_path_element (), *find_absolute_program (); + + /* 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; + + #define u_mode_bits(x) (((x) & 0000700) >> 6) + #define g_mode_bits(x) (((x) & 0000070) >> 3) + #define o_mode_bits(x) (((x) & 0000007) >> 0) + #define X_BIT(x) ((x) & 1) + + /* 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) + char *name; + { + struct stat finfo; + + /* 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); + + #if 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) + return (FS_EXISTS | FS_EXECABLE); + else + return (FS_EXISTS); + #else /* !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. */ + + /* Root only requires execute permission for any of owner, group or + others to be able to exec a file. */ + if (current_user.euid == (uid_t)0) + { + int bits; + + bits = (u_mode_bits (finfo.st_mode) | + g_mode_bits (finfo.st_mode) | + o_mode_bits (finfo.st_mode)); + + if (X_BIT (bits)) + return (FS_EXISTS | FS_EXECABLE); + } + + /* If we are the owner of the file, the owner execute bit applies. */ + if (current_user.euid == finfo.st_uid && X_BIT (u_mode_bits (finfo.st_mode))) + return (FS_EXISTS | FS_EXECABLE); + + /* If we are in the owning group, the group permissions apply. */ + if (group_member (finfo.st_gid) && X_BIT (g_mode_bits (finfo.st_mode))) + return (FS_EXISTS | FS_EXECABLE); + + /* If `others' have execute permission to the file, then so do we, + since we are also `others'. */ + if (X_BIT (o_mode_bits (finfo.st_mode))) + return (FS_EXISTS | FS_EXECABLE); + + return (FS_EXISTS); + #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) + char *file; + { + int s; + + s = file_status (file); + return ((s & FS_EXECABLE) && ((s & FS_DIRECTORY) == 0)); + } + + int + is_directory (file) + char *file; + { + return (file_status (file) & 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) + 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 file found. */ + char * + find_path_file (name) + char *name; + { + return (find_user_command_internal (name, FS_EXISTS)); + } + + static char * + _find_user_command_internal (name, flags) + char *name; + int flags; + { + char *path_list, *cmd; + SHELL_VAR *var; + + /* Search for the value of PATH in both the temporary environment, and + in the regular list of variables. */ + if (var = find_variable_internal ("PATH", 1)) /* 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); + + if (var && tempvar_p (var)) + dispose_variable (var); + + return (cmd); + } + + static char * + find_user_command_internal (name, flags) + char *name; + int flags; + { + #ifdef __WIN32__ + char *res, *dotexe; + + dotexe = 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) + return (path); + + if (!*path) + { + 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. Returns a newly-allocated string. */ + char * + search_for_command (pathname) + char *pathname; + { + 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_tempenv_variable ("PATH"); + temp_path = path != 0; + + /* 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 = find_hashed_filename (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)) != 0) + { + remove_hashed_filename (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); + if (tempvar_p (path)) + dispose_variable (path); + } + else + command = find_user_command (pathname); + if (command && hashing_enabled && temp_path == 0) + remember_filename (pathname, command, dot_found_in_search, 1); + } + return (command); + } + + char * + user_command_matches (name, flags, state) + 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 = (char **)xmalloc (match_list_size * sizeof(char *)); + } + + /* 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; + stat (".", &dotinfo); + 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 = (char **)xrealloc (match_list, (match_list_size + 1) * sizeof (char *)); + } + + 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); + } + + /* Turn PATH, a directory, and NAME, a filename, into a full pathname. + This allocates new memory and returns it. */ + static char * + make_full_pathname (path, name, name_len) + char *path, *name; + int name_len; + { + char *full_path; + int path_len; + + path_len = strlen (path); + full_path = xmalloc (2 + path_len + name_len); + strcpy (full_path, path); + full_path[path_len] = '/'; + strcpy (full_path + path_len + 1, name); + return (full_path); + } + + static char * + find_absolute_program (name, flags) + 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 ((char *)NULL); + } + + static char * + find_in_path_element (name, path, flags, name_len, dotinfop) + char *name, *path; + int flags, name_len; + struct stat *dotinfop; + { + int status; + char *full_path, *xpath; + + xpath = (*path == '~') ? bash_tilde_expand (path) : 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 = make_full_pathname (xpath, name, name_len); + + 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 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_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, fail. */ + if ((flags & FS_EXEC_ONLY) || (flags & FS_EXEC_PREFERRED) || + ((flags & FS_NODIRS) && (status & FS_DIRECTORY))) + { + 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) + 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); + stat (".", &dotinfo); + 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. */ + return (file_to_lose_on); + } diff -Nrc2 bash-2.01.1/findcmd.h bash-2.02/findcmd.h *** bash-2.01.1/findcmd.h Wed Dec 31 19:00:00 1969 --- bash-2.02/findcmd.h Thu Jul 10 11:42:02 1997 *************** *** 0 **** --- 1,34 ---- + /* findcmd.h - functions from findcmd.c. */ + + /* Copyright (C) 1997 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 (_FINDCMD_H_) + #define _FINDCMD_H_ + + #include "stdc.h" + + extern int file_status __P((char *)); + extern int executable_file __P((char *)); + extern int is_directory __P((char *)); + extern char *find_user_command __P((char *)); + extern char *find_path_file __P((char *)); + extern char *search_for_command __P((char *)); + extern char *user_command_matches __P((char *, int, int)); + + #endif /* _FINDCMD_H_ */ diff -Nrc2 bash-2.01.1/flags.c bash-2.02/flags.c *** bash-2.01.1/flags.c Mon Jul 14 16:10:29 1997 --- bash-2.02/flags.c Tue Nov 18 11:26:39 1997 *************** *** 210,215 **** /* Change the state of a flag, and return it's original value, or return ! FLAG_ERROR if there is no flag called NAME. ON_OR_OFF should be one ! of FLAG_ON or FLAG_OFF. */ int change_flag (flag, on_or_off) --- 210,215 ---- /* Change the state of a flag, and return it's original value, or return ! FLAG_ERROR if there is no flag FLAG. ON_OR_OFF must be either ! FLAG_ON or FLAG_OFF. */ int change_flag (flag, on_or_off) *************** *** 227,241 **** #endif /* RESTRICTED_SHELL */ ! if (value == (int *)FLAG_UNKNOWN) return (FLAG_ERROR); old_value = *value; ! if (on_or_off == FLAG_ON) ! *value = 1; ! else if (on_or_off == FLAG_OFF) ! *value = 0; ! else ! return (FLAG_ERROR); /* Special cases for a few flags. */ --- 227,236 ---- #endif /* RESTRICTED_SHELL */ ! if ((value == (int *)FLAG_UNKNOWN) || (on_or_off != FLAG_ON && on_or_off != FLAG_OFF)) return (FLAG_ERROR); old_value = *value; ! *value = (on_or_off == FLAG_ON) ? 1 : 0; /* Special cases for a few flags. */ diff -Nrc2 bash-2.01.1/general.c bash-2.02/general.c *** bash-2.01.1/general.c Mon Aug 25 14:18:06 1997 --- bash-2.02/general.c Tue Feb 24 15:51:25 1998 *************** *** 23,27 **** #include "bashtypes.h" ! #include #include "posixstat.h" --- 23,29 ---- #include "bashtypes.h" ! #ifndef _MINIX ! # include ! #endif #include "posixstat.h" *************** *** 64,68 **** extern int interrupt_immediately; extern int interactive_comments; ! extern char *bash_getcwd_errstr; /* Do whatever is necessary to initialize `Posix mode'. */ --- 66,72 ---- extern int interrupt_immediately; extern int interactive_comments; ! ! /* A standard error message to use when getcwd() returns NULL. */ ! char *bash_getcwd_errstr = "getcwd: cannot access parent directories"; /* Do whatever is necessary to initialize `Posix mode'. */ *************** *** 76,141 **** /* **************************************************************** */ /* */ - /* Integer to String Conversion */ - /* */ - /* **************************************************************** */ - - /* Number of characters that can appear in a string representation - of an integer. 32 is larger than the string rep of 2^^31 - 1. */ - #define MAX_INT_LEN 32 - - /* Integer to string conversion. This conses the string; the - caller should free it. */ - char * - itos (i) - int i; - { - char buf[MAX_INT_LEN], *p, *ret; - int negative = 0; - unsigned int ui; - - if (i < 0) - { - negative++; - i = -i; - } - - ui = (unsigned int) i; - - p = buf + MAX_INT_LEN - 2; - p[1] = '\0'; - - do - *p-- = (ui % 10) + '0'; - while (ui /= 10); - - if (negative) - *p-- = '-'; - - ret = savestring (p + 1); - return (ret); - } - - /* atol(3) is not universal */ - long - string_to_long (s) - char *s; - { - long ret = 0L; - int neg = 0; - - while (s && *s && whitespace (*s)) - s++; - if (*s == '-' || *s == '+') - { - neg = *s == '-'; - s++; - } - for ( ; s && *s && digit (*s); s++) - ret = (ret * 10) + digit_value (*s); - return (neg ? -ret : ret); - } - - /* **************************************************************** */ - /* */ /* Functions to convert to and from and display non-standard types */ /* */ --- 80,83 ---- *************** *** 147,153 **** char *s; { ! RLIMTYPE ret = 0; ! int neg = 0; while (s && *s && whitespace (*s)) s++; --- 89,97 ---- char *s; { ! RLIMTYPE ret; ! int neg; + ret = 0; + neg = 0; while (s && *s && whitespace (*s)) s++; *************** *** 168,172 **** { char s[sizeof (RLIMTYPE) * 3 + 1]; ! int len = sizeof (RLIMTYPE) * 3 + 1; if (n == 0) --- 112,116 ---- { char s[sizeof (RLIMTYPE) * 3 + 1]; ! int len; if (n == 0) *************** *** 182,185 **** --- 126,130 ---- } + len = sizeof (RLIMTYPE) * 3 + 1; s[--len] = '\0'; for ( ; n != 0; n /= 10) *************** *** 296,346 **** long *result; { - int sign; long value; ! ! sign = 1; ! value = 0; if (result) *result = 0; ! /* Skip leading whitespace characters. */ ! while (whitespace (*string)) ! string++; ! ! if (!*string) ! return (0); ! /* We allow leading `-' or `+'. */ ! if (*string == '-' || *string == '+') ! { ! if (!digit (string[1])) ! return (0); ! ! if (*string == '-') ! sign = -1; ! ! string++; ! } ! ! while (digit (*string)) { if (result) ! value = (value * 10) + digit_value (*string); ! string++; } ! ! /* Skip trailing whitespace, if any. */ ! while (whitespace (*string)) ! string++; ! ! /* Error if not at end of string. */ ! if (*string) ! return (0); ! ! if (result) ! *result = value * sign; ! ! return (1); } --- 241,265 ---- long *result; { long value; ! char *ep; if (result) *result = 0; ! value = strtol (string, &ep, 10); ! /* If *string is not '\0' but *ep is '\0' on return, the entire string ! is valid. */ ! if (string && *string && *ep == '\0') { if (result) ! *result = value; ! /* The SunOS4 implementation of strtol() will happily ignore ! overflow conditions, so this cannot do overflow correctly ! on those systems. */ ! return 1; } ! ! return (0); } *************** *** 701,704 **** --- 620,630 ---- result[1] = '\0'; } + + #if 1 + /* Turn `//' into `/' -- XXX experimental */ + if (result[0] == '/' && result[1] == '/' && result[2] == '\0') + result[1] = '\0'; + #endif + return (result); } *************** *** 912,918 **** /* **************************************************************** */ /* If tilde_expand hasn't been able to expand the text, perhaps it is a special shell expansion. This function is installed as the ! tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+. */ static char * bash_special_tilde_expansions (text) --- 838,850 ---- /* **************************************************************** */ + #if defined (PUSHD_AND_POPD) + extern char *get_dirstack_from_string __P((char *)); + #endif + /* If tilde_expand hasn't been able to expand the text, perhaps it is a special shell expansion. This function is installed as the ! tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+. ! If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the ! directory stack. */ static char * bash_special_tilde_expansions (text) *************** *** 922,932 **** result = (char *)NULL; ! if (text[1] == '\0') ! { ! if (*text == '+') ! result = get_string_value ("PWD"); ! else if (*text == '-') ! result = get_string_value ("OLDPWD"); ! } return (result ? savestring (result) : (char *)NULL); --- 854,866 ---- result = (char *)NULL; ! ! if (text[0] == '+' && text[1] == '\0') ! result = get_string_value ("PWD"); ! else if (text[0] == '-' && text[1] == '\0') ! result = get_string_value ("OLDPWD"); ! #if defined (PUSHD_AND_POPD) ! else if (isdigit (*text) || ((*text == '+' || *text == '-') && isdigit (text[1]))) ! result = get_dirstack_from_string (text); ! #endif return (result ? savestring (result) : (char *)NULL); *************** *** 947,951 **** expansion, and the special strings that end one. Only do this once. tilde_initialize () is called from within bashline_reinitialize (). */ ! if (times_called == 0) { tilde_additional_prefixes = (char **)xmalloc (3 * sizeof (char *)); --- 881,885 ---- expansion, and the special strings that end one. Only do this once. tilde_initialize () is called from within bashline_reinitialize (). */ ! if (times_called++ == 0) { tilde_additional_prefixes = (char **)xmalloc (3 * sizeof (char *)); *************** *** 959,963 **** tilde_additional_suffixes[2] = (char *)NULL; } - times_called++; } --- 893,896 ---- *************** *** 1040,1049 **** --- 973,1001 ---- ngroups++; } + + /* If the primary group is not group_array[0], swap group_array[0] and + whatever the current group is. The vast majority of systems should + not need this; a notable exception is Linux. */ + if (group_array[0] != current_user.gid) + { + for (i = 0; i < ngroups; i++) + if (group_array[i] == current_user.gid) + break; + if (i < ngroups) + { + group_array[i] = group_array[0]; + group_array[0] = current_user.gid; + } + } } /* Return non-zero if GID is one that we have in our groups list. */ int + #if defined (__STDC__) || defined ( _MINIX) + group_member (gid_t gid) + #else group_member (gid) gid_t gid; + #endif /* !__STDC__ && !_MINIX */ { #if defined (HAVE_GETGROUPS) diff -Nrc2 bash-2.01.1/general.h bash-2.02/general.h *** bash-2.01.1/general.h Thu Apr 17 13:57:12 1997 --- bash-2.02/general.h Tue Feb 24 15:51:04 1998 *************** *** 26,29 **** --- 26,36 ---- #include "bashtypes.h" + #if defined (HAVE_SYS_RESOURCE_H) && defined (RLIMTYPE) + # if defined (HAVE_SYS_TIME_H) + # include + # endif + # include + #endif + #if defined (HAVE_STRING_H) # include *************** *** 132,136 **** #define STRLEN(s) (((s) && (s)[0]) ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0) #define FREE(s) do { if (s) free (s); } while (0) ! #define MEMBER(c, s) (((c) && !(s)[1] && c == s[0]) || (member(c, s))) /* A fairly hairy macro to check whether an allocated string has more room, --- 139,143 ---- #define STRLEN(s) (((s) && (s)[0]) ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0) #define FREE(s) do { if (s) free (s); } while (0) ! #define MEMBER(c, s) (((c) && c == (s)[0] && !(s)[1]) || (member(c, s))) /* A fairly hairy macro to check whether an allocated string has more room, *************** *** 179,185 **** extern void posix_initialize __P((int)); - extern char *itos __P((int)); - extern long string_to_long __P((char *)); - #if defined (RLIMTYPE) extern RLIMTYPE string_to_rlimtype __P((char *)); --- 186,189 ---- *************** *** 216,224 **** extern char *bash_tilde_expand __P((char *)); - #if defined (__STDC__) && defined (gid_t) - extern int group_member __P((int)); - #else extern int group_member __P((gid_t)); - #endif extern char **get_group_list __P((int *)); --- 220,224 ---- diff -Nrc2 bash-2.01.1/getcwd.c bash-2.02/getcwd.c *** bash-2.01.1/getcwd.c Mon Feb 17 14:25:30 1997 --- bash-2.02/getcwd.c Wed Dec 31 19:00:00 1969 *************** *** 1,308 **** - /* getcwd.c -- stolen from the GNU C library and modified to work with bash. */ - - /* Copyright (C) 1991 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If - not, write to the Free Software Foundation, Inc., 675 Mass Ave, - Cambridge, MA 02139, USA. */ - - #include "config.h" - - #if !defined (HAVE_GETCWD) - - #include "bashtypes.h" - #include - - #if defined (HAVE_LIMITS_H) - # include - #endif - - #if defined (HAVE_UNISTD_H) - # include - #endif - - #include "posixdir.h" - #include "posixstat.h" - #include "maxpath.h" - #include "memalloc.h" - - #include "bashansi.h" - - #if !defined (errno) - extern int errno; - #endif /* !errno */ - - #if defined (__STDC__) - # define CONST const - # define PTR void * - #else /* !__STDC__ */ - # define CONST - # define PTR char * - #endif /* !__STDC__ */ - - #if !defined (PATH_MAX) - # if defined (MAXPATHLEN) - # define PATH_MAX MAXPATHLEN - # else /* !MAXPATHLEN */ - # define PATH_MAX 1024 - # endif /* !MAXPATHLEN */ - #endif /* !PATH_MAX */ - - #if !defined (HAVE_LSTAT) - # define lstat stat - #endif - - /* Get the pathname of the current working directory, - and put it in SIZE bytes of BUF. Returns NULL if the - directory couldn't be determined or SIZE was too small. - If successful, returns BUF. In GNU, if BUF is NULL, - an array is allocated with `malloc'; the array is SIZE - bytes long, unless SIZE <= 0, in which case it is as - big as necessary. */ - #if defined (__STDC__) - char * - getcwd (char *buf, size_t size) - #else /* !__STDC__ */ - char * - getcwd (buf, size) - char *buf; - size_t size; - #endif /* !__STDC__ */ - { - static CONST char dots[] - = "../../../../../../../../../../../../../../../../../../../../../../../\ - ../../../../../../../../../../../../../../../../../../../../../../../../../../\ - ../../../../../../../../../../../../../../../../../../../../../../../../../.."; - CONST char *dotp, *dotlist; - size_t dotsize; - dev_t rootdev, thisdev; - ino_t rootino, thisino; - char path[PATH_MAX + 1]; - register char *pathp; - char *pathbuf; - size_t pathsize; - struct stat st; - - if (buf != NULL && size == 0) - { - errno = EINVAL; - return ((char *)NULL); - } - - pathsize = sizeof (path); - pathp = &path[pathsize]; - *--pathp = '\0'; - pathbuf = path; - - if (stat (".", &st) < 0) - return ((char *)NULL); - thisdev = st.st_dev; - thisino = st.st_ino; - - if (stat ("/", &st) < 0) - return ((char *)NULL); - rootdev = st.st_dev; - rootino = st.st_ino; - - dotsize = sizeof (dots) - 1; - dotp = &dots[sizeof (dots)]; - dotlist = dots; - while (!(thisdev == rootdev && thisino == rootino)) - { - register DIR *dirstream; - register struct dirent *d; - dev_t dotdev; - ino_t dotino; - char mount_point; - int namlen; - - /* Look at the parent directory. */ - if (dotp == dotlist) - { - /* My, what a deep directory tree you have, Grandma. */ - char *new; - if (dotlist == dots) - { - new = malloc (dotsize * 2 + 1); - if (new == NULL) - goto lose; - memcpy (new, dots, dotsize); - } - else - { - new = realloc ((PTR) dotlist, dotsize * 2 + 1); - if (new == NULL) - goto lose; - } - memcpy (&new[dotsize], new, dotsize); - dotp = &new[dotsize]; - dotsize *= 2; - new[dotsize] = '\0'; - dotlist = new; - } - - dotp -= 3; - - /* Figure out if this directory is a mount point. */ - if (stat (dotp, &st) < 0) - goto lose; - dotdev = st.st_dev; - dotino = st.st_ino; - mount_point = dotdev != thisdev; - - /* Search for the last directory. */ - dirstream = opendir (dotp); - if (dirstream == NULL) - goto lose; - while ((d = readdir (dirstream)) != NULL) - { - if (d->d_name[0] == '.' && - (d->d_name[1] == '\0' || - (d->d_name[1] == '.' && d->d_name[2] == '\0'))) - continue; - if (mount_point || d->d_fileno == thisino) - { - char *name; - - namlen = D_NAMLEN(d); - name = (char *) - alloca (dotlist + dotsize - dotp + 1 + namlen + 1); - memcpy (name, dotp, dotlist + dotsize - dotp); - name[dotlist + dotsize - dotp] = '/'; - memcpy (&name[dotlist + dotsize - dotp + 1], - d->d_name, namlen + 1); - if (lstat (name, &st) < 0) - { - int save = errno; - (void) closedir (dirstream); - errno = save; - goto lose; - } - if (st.st_dev == thisdev && st.st_ino == thisino) - break; - } - } - if (d == NULL) - { - int save = errno; - (void) closedir (dirstream); - errno = save; - goto lose; - } - else - { - size_t space; - - while ((space = pathp - pathbuf) <= namlen) - { - char *new; - - if (pathbuf == path) - { - new = malloc (pathsize * 2); - if (!new) - goto lose; - } - else - { - new = realloc ((PTR) pathbuf, (pathsize * 2)); - if (!new) - goto lose; - pathp = new + space; - } - (void) memcpy (new + pathsize + space, pathp, pathsize - space); - pathp = new + pathsize + space; - pathbuf = new; - pathsize *= 2; - } - - pathp -= namlen; - (void) memcpy (pathp, d->d_name, namlen); - *--pathp = '/'; - (void) closedir (dirstream); - } - - thisdev = dotdev; - thisino = dotino; - } - - if (pathp == &path[sizeof(path) - 1]) - *--pathp = '/'; - - if (dotlist != dots) - free ((PTR) dotlist); - - { - size_t len = pathbuf + pathsize - pathp; - if (buf == NULL) - { - if (len < (size_t) size) - len = size; - buf = (char *) malloc (len); - if (buf == NULL) - goto lose2; - } - else if ((size_t) size < len) - { - errno = ERANGE; - goto lose2; - } - (void) memcpy((PTR) buf, (PTR) pathp, len); - } - - if (pathbuf != path) - free (pathbuf); - - return (buf); - - lose: - if ((dotlist != dots) && dotlist) - { - int e = errno; - free ((PTR) dotlist); - errno = e; - } - - lose2: - if ((pathbuf != path) && pathbuf) - { - int e = errno; - free ((PTR) pathbuf); - errno = e; - } - return ((char *)NULL); - } - - #if defined (TEST) - # include - main (argc, argv) - int argc; - char **argv; - { - char b[PATH_MAX]; - - if (getcwd(b, sizeof(b))) - { - printf ("%s\n", b); - exit (0); - } - else - { - perror ("cwd: getcwd"); - exit (1); - } - } - #endif /* TEST */ - #endif /* !HAVE_GETCWD */ --- 0 ---- diff -Nrc2 bash-2.01.1/hashcmd.c bash-2.02/hashcmd.c *** bash-2.01.1/hashcmd.c Tue Jun 3 11:19:23 1997 --- bash-2.02/hashcmd.c Mon Oct 6 17:22:24 1997 *************** *** 32,36 **** #include "shell.h" ! #include "execute_cmd.h" #include "hashcmd.h" --- 32,36 ---- #include "shell.h" ! #include "findcmd.h" #include "hashcmd.h" *************** *** 149,155 **** { tail = (pathdata(item)->flags & HASH_RELPATH) ? path : filename; ! dotted_filename = xmalloc (3 + strlen (tail)); ! dotted_filename[0] = '.'; dotted_filename[1] = '/'; ! strcpy (dotted_filename + 2, tail); if (executable_file (dotted_filename)) --- 149,161 ---- { tail = (pathdata(item)->flags & HASH_RELPATH) ? path : filename; ! /* If the pathname does not start with a `./', add a `./' to it. */ ! if (tail[0] != '.' || tail[1] != '/') ! { ! dotted_filename = xmalloc (3 + strlen (tail)); ! dotted_filename[0] = '.'; dotted_filename[1] = '/'; ! strcpy (dotted_filename + 2, tail); ! } ! else ! dotted_filename = savestring (tail); if (executable_file (dotted_filename)) diff -Nrc2 bash-2.01.1/hashcmd.h bash-2.02/hashcmd.h *** bash-2.01.1/hashcmd.h Tue Apr 1 12:22:45 1997 --- bash-2.02/hashcmd.h Mon Jul 28 11:07:16 1997 *************** *** 21,25 **** #include "hashlib.h" ! #define FILENAME_HASH_BUCKETS 631 extern HASH_TABLE *hashed_filenames; --- 21,25 ---- #include "hashlib.h" ! #define FILENAME_HASH_BUCKETS 107 extern HASH_TABLE *hashed_filenames; diff -Nrc2 bash-2.01.1/hashlib.c bash-2.02/hashlib.c *** bash-2.01.1/hashlib.c Mon Apr 14 16:07:02 1997 --- bash-2.02/hashlib.c Tue Nov 18 11:37:08 1997 *************** *** 24,27 **** --- 24,30 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 226,229 **** --- 229,234 ---- } + /* No longer necessary; everything uses the macro */ + #if 0 /* Return the bucket_contents list of bucket BUCKET in TABLE. If TABLE doesn't have BUCKET buckets, return NULL. */ *************** *** 239,244 **** return (BUCKET_CONTENTS *)NULL; } ! /* #ifdef DEBUG */ print_table_stats (table, name) HASH_TABLE *table; --- 244,251 ---- return (BUCKET_CONTENTS *)NULL; } + #endif ! #ifdef DEBUG ! void print_table_stats (table, name) HASH_TABLE *table; *************** *** 266,270 **** } } ! /* #endif */ #ifdef TEST_HASHING --- 273,277 ---- } } ! #endif #ifdef TEST_HASHING diff -Nrc2 bash-2.01.1/input.c bash-2.02/input.c *** bash-2.01.1/input.c Wed Nov 20 11:33:13 1996 --- bash-2.02/input.c Mon Oct 13 12:45:43 1997 *************** *** 22,26 **** #include "bashtypes.h" ! #include #include "filecntl.h" #include "posixstat.h" --- 22,28 ---- #include "bashtypes.h" ! #ifndef _MINIX ! # include ! #endif #include "filecntl.h" #include "posixstat.h" *************** *** 97,102 **** #endif /* !SEEK_CUR */ - void free_buffered_stream (); - extern int return_EOF (); --- 99,102 ---- *************** *** 110,114 **** in constructs like 3<&4. buffers[x]->b_fd == x -- that is how the correspondence is maintained. */ ! BUFFERED_STREAM **buffers = (BUFFERED_STREAM **)NULL; static int nbuffers; --- 110,114 ---- in constructs like 3<&4. buffers[x]->b_fd == x -- that is how the correspondence is maintained. */ ! static BUFFERED_STREAM **buffers = (BUFFERED_STREAM **)NULL; static int nbuffers; *************** *** 141,145 **** int fd; char *buffer; ! int bufsize; { BUFFERED_STREAM *bp; --- 141,145 ---- int fd; char *buffer; ! size_t bufsize; { BUFFERED_STREAM *bp; *************** *** 270,274 **** /* Return 1 if a seek on FD will succeed. */ ! #define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0) /* Take FD, a file descriptor, and create and return a buffered stream --- 270,278 ---- /* Return 1 if a seek on FD will succeed. */ ! #ifndef __CYGWIN32__ ! # define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0) ! #else ! # define fd_is_seekable(fd) 0 ! #endif /* __CYGWIN32__ */ /* Take FD, a file descriptor, and create and return a buffered stream *************** *** 280,284 **** { char *buffer; ! int size; struct stat sb; --- 284,288 ---- { char *buffer; ! size_t size; struct stat sb; *************** *** 292,297 **** size = 1; else ! size = (sb.st_size > MAX_INPUT_BUFFER_SIZE) ? MAX_INPUT_BUFFER_SIZE ! : sb.st_size; buffer = (char *)xmalloc (size); --- 296,302 ---- size = 1; else ! size = (size_t)((sb.st_size > MAX_INPUT_BUFFER_SIZE) ! ? MAX_INPUT_BUFFER_SIZE ! : sb.st_size); buffer = (char *)xmalloc (size); *************** *** 353,356 **** --- 358,375 ---- return (close (fd)); return (close_buffered_stream (buffers[fd])); + } + + /* Make the BUFFERED_STREAM associcated with buffers[FD] be BP, and return + the old BUFFERED_STREAM. */ + BUFFERED_STREAM * + set_buffered_stream (fd, bp) + int fd; + BUFFERED_STREAM *bp; + { + BUFFERED_STREAM *ret; + + ret = buffers[fd]; + buffers[fd] = bp; + return ret; } diff -Nrc2 bash-2.01.1/input.h bash-2.02/input.h *** bash-2.01.1/input.h Wed Feb 12 15:20:09 1997 --- bash-2.02/input.h Mon Oct 6 12:41:08 1997 *************** *** 37,40 **** --- 37,44 ---- /* Possible values for b_flag. */ + #undef B_EOF + #undef B_ERROR /* There are some systems with this define */ + #undef B_UNBUFF + #define B_EOF 0x1 #define B_ERROR 0x2 *************** *** 47,51 **** int b_fd; char *b_buffer; /* The buffer that holds characters read. */ ! int b_size; /* How big the buffer is. */ int b_used; /* How much of the buffer we're using, */ int b_flag; /* Flag values. */ --- 51,55 ---- int b_fd; char *b_buffer; /* The buffer that holds characters read. */ ! size_t b_size; /* How big the buffer is. */ int b_used; /* How much of the buffer we're using, */ int b_flag; /* Flag values. */ *************** *** 53,59 **** } BUFFERED_STREAM; extern BUFFERED_STREAM **buffers; ! ! extern BUFFERED_STREAM *fd_to_buffered_stream (); extern int default_buffered_input; --- 57,63 ---- } BUFFERED_STREAM; + #if 0 extern BUFFERED_STREAM **buffers; ! #endif extern int default_buffered_input; *************** *** 103,106 **** --- 107,111 ---- extern int duplicate_buffered_stream __P((int, int)); extern BUFFERED_STREAM *fd_to_buffered_stream __P((int)); + extern BUFFERED_STREAM *set_buffered_stream __P((int, BUFFERED_STREAM *)); extern BUFFERED_STREAM *open_buffered_stream __P((char *)); extern void free_buffered_stream __P((BUFFERED_STREAM *)); diff -Nrc2 bash-2.01.1/jobs.c bash-2.02/jobs.c *** bash-2.01.1/jobs.c Mon Aug 18 11:54:02 1997 --- bash-2.02/jobs.c Mon Apr 6 16:06:34 1998 *************** *** 38,44 **** #endif ! #if defined (HAVE_SYS_RESOURCE_H) && defined (HAVE_WAIT3) && !defined (_POSIX_VERSION) # include ! #endif /* !_POSIX_VERSION && HAVE_SYS_RESOURCE_H && HAVE_WAIT3 */ #include --- 38,44 ---- #endif ! #if defined (HAVE_SYS_RESOURCE_H) && defined (HAVE_WAIT3) && !defined (_POSIX_VERSION) && !defined (RLIMTYPE) # include ! #endif /* !_POSIX_VERSION && HAVE_SYS_RESOURCE_H && HAVE_WAIT3 && !RLIMTYPE */ #include *************** *** 166,170 **** static int *pstatuses; /* list of pipeline statuses */ static int statsize; - static void set_pipestatus_array (); #endif static void setjstatus (); --- 166,169 ---- *************** *** 230,234 **** static char *current_working_directory (); static char *job_working_directory (); ! static pid_t last_pid (); static int set_new_line_discipline (), map_over_jobs (), last_running_job (); static int most_recent_job_in_state (), last_stopped_job (), find_job (); --- 229,233 ---- static char *current_working_directory (); static char *job_working_directory (); ! static pid_t find_last_pid (), last_pid (); static int set_new_line_discipline (), map_over_jobs (), last_running_job (); static int most_recent_job_in_state (), last_stopped_job (), find_job (); *************** *** 545,550 **** for (i = 0; i < job_slots; i++) if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i)) ! delete_job (i); UNBLOCK_CHILD (oset); --- 544,554 ---- for (i = 0; i < job_slots; i++) + #if 0 + if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i) && + (interactive_shell || (find_last_pid (i) != last_asynchronous_pid))) + #else if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i)) ! #endif ! delete_job (i, 0); UNBLOCK_CHILD (oset); *************** *** 554,565 **** with SIGCHLD blocked. */ void ! delete_job (job_index) ! int job_index; { register JOB *temp; ! if (jobs_list_frozen) return; temp = jobs[job_index]; if (job_index == current_job || job_index == previous_job) --- 558,572 ---- with SIGCHLD blocked. */ void ! delete_job (job_index, warn_stopped) ! int job_index, warn_stopped; { register JOB *temp; ! if (job_slots == 0 || jobs_list_frozen) return; + if (warn_stopped && subshell_environment == 0 && STOPPED (job_index)) + internal_warning ("deleting stopped job %d with process group %d", job_index+1, jobs[job_index]->pgrp); + temp = jobs[job_index]; if (job_index == current_job || job_index == previous_job) *************** *** 584,587 **** --- 591,597 ---- register JOB *temp; + if (job_slots == 0) + return; + if (temp = jobs[job_index]) temp->flags |= J_NOHUP; *************** *** 982,986 **** if (format || (p == last)) ! fprintf (stream, "\r\n"); if (p == last) --- 992,1006 ---- if (format || (p == last)) ! { ! /* We need to add a CR only if this is an interactive shell, and ! we're reporting the status of a completed job asynchronously. ! We can't really check whether this particular job is being ! reported asynchronously, so just add the CR if the shell is ! currently interactive and asynchronous notification is enabled. */ ! if (asynchronous_notification && interactive) ! fprintf (stream, "\r\n"); ! else ! fprintf (stream, "\n"); ! } if (p == last) *************** *** 1029,1038 **** p = jobs[job_index]->pipe; /* We have printed information about this job. When the job's status changes, waitchld () sets the notification flag to 0. */ jobs[job_index]->flags |= J_NOTIFIED; - print_pipeline (p, job_index, format, stream); - UNBLOCK_CHILD (oset); } --- 1049,1058 ---- p = jobs[job_index]->pipe; + print_pipeline (p, job_index, format, stream); + /* We have printed information about this job. When the job's status changes, waitchld () sets the notification flag to 0. */ jobs[job_index]->flags |= J_NOTIFIED; UNBLOCK_CHILD (oset); } *************** *** 1138,1146 **** 0 because that's the file descriptor used when redirecting input, and it's wrong to close the file in that case. */ ! if (default_buffered_input > 0) ! { ! close_buffered_fd (default_buffered_input); ! default_buffered_input = bash_input.location.buffered_fd = -1; ! } #endif /* BUFFERED_INPUT */ --- 1158,1162 ---- 0 because that's the file descriptor used when redirecting input, and it's wrong to close the file in that case. */ ! unset_bash_input (0); #endif /* BUFFERED_INPUT */ *************** *** 1407,1417 **** counts. */ static pid_t ! last_pid (job) int job; { register PROCESS *p; - sigset_t set, oset; - - BLOCK_CHILD (set, oset); p = jobs[job]->pipe; --- 1423,1430 ---- counts. */ static pid_t ! find_last_pid (job) int job; { register PROCESS *p; p = jobs[job]->pipe; *************** *** 1419,1426 **** p = p->next; - UNBLOCK_CHILD (oset); return (p->pid); } /* Wait for a particular child of the shell to finish executing. This low-level function prints an error message if PID is not --- 1432,1452 ---- p = p->next; return (p->pid); } + static pid_t + last_pid (job) + int job; + { + pid_t pid; + sigset_t set, oset; + + BLOCK_CHILD (set, oset); + pid = find_last_pid (job); + UNBLOCK_CHILD (oset); + + return (pid); + } + /* Wait for a particular child of the shell to finish executing. This low-level function prints an error message if PID is not *************** *** 1432,1435 **** --- 1458,1462 ---- register PROCESS *child; sigset_t set, oset; + int r, job; BLOCK_CHILD (set, oset); *************** *** 1443,1447 **** } ! return (wait_for (pid)); } --- 1470,1487 ---- } ! r = wait_for (pid); ! ! /* POSIX.2: if we just waited for $!, we can remove the job from the ! jobs table. */ ! if (pid == last_asynchronous_pid) ! { ! BLOCK_CHILD (set, oset); ! job = find_job (pid); ! if (job != NO_JOB && jobs[job] && DEADJOB (job)) ! jobs[job]->flags |= J_NOTIFIED; ! UNBLOCK_CHILD (oset); ! } ! ! return r; } *************** *** 1760,1766 **** { pid_t pid; pid = last_pid (job); ! return (wait_for (pid)); } --- 1800,1825 ---- { pid_t pid; + int r; + sigset_t set, oset; + + BLOCK_CHILD(set, oset); + if (JOBSTATE (job) == JSTOPPED) + internal_warning ("wait_for_job: job %d is stopped", job+1); + UNBLOCK_CHILD(oset); pid = last_pid (job); ! r = wait_for (pid); ! ! /* POSIX.2: if we just waited for $!, we can remove the job from the ! jobs table. */ ! if (pid == last_asynchronous_pid) ! { ! BLOCK_CHILD (set, oset); ! if (job != NO_JOB && jobs[job] && DEADJOB (job)) ! jobs[job]->flags |= J_NOTIFIED; ! UNBLOCK_CHILD (oset); ! } ! ! return r; } *************** *** 2326,2329 **** --- 2385,2389 ---- the signal to ourselves. */ SigHandler *temp_handler; + temp_handler = old_sigint_handler; /* Bogus. If we've reset the signal handler as the result *************** *** 2437,2441 **** --- 2497,2509 ---- (startup_state == 0 && WIFSIGNALED (s) == 0)) { + #if 0 if (DEADJOB (job)) + #else + /* POSIX.2 compatibility: if the shell is not interactive, + hang onto the job corresponding to the last asynchronous + pid until the user has been notified of its status or does + a `wait'. */ + if (DEADJOB (job) && (interactive_shell || (find_last_pid (job) != last_asynchronous_pid))) + #endif jobs[job]->flags |= J_NOTIFIED; continue; *************** *** 2449,2452 **** --- 2517,2526 ---- case JDEAD: if (interactive_shell == 0 && termsig && WIFSIGNALED (s) && + #if 1 + termsig != SIGINT && + #endif + #if defined (DONT_REPORT_SIGPIPE) + termsig != SIGPIPE && + #endif signal_is_trapped (termsig) == 0) { *************** *** 2819,2825 **** children of the shell, who should not have any job structures as baggage when they start executing (forking subshells for parenthesized execution ! and functions with pipes are the two that spring to mind). */ void ! delete_all_jobs () { register int i; --- 2893,2901 ---- children of the shell, who should not have any job structures as baggage when they start executing (forking subshells for parenthesized execution ! and functions with pipes are the two that spring to mind). If RUNNING_ONLY ! is nonzero, only running jobs are removed from the table. */ void ! delete_all_jobs (running_only) ! int running_only; { register int i; *************** *** 2833,2841 **** for (i = 0; i < job_slots; i++) ! if (jobs[i]) ! delete_job (i); ! free ((char *)jobs); ! job_slots = 0; } --- 2909,2920 ---- for (i = 0; i < job_slots; i++) ! if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i)))) ! delete_job (i, 1); ! if (running_only == 0) ! { ! free ((char *)jobs); ! job_slots = 0; ! } } *************** *** 2844,2850 **** /* Mark all jobs in the job array so that they don't get a SIGHUP when the ! shell gets one. */ void ! nohup_all_jobs () { register int i; --- 2923,2930 ---- /* Mark all jobs in the job array so that they don't get a SIGHUP when the ! shell gets one. If RUNNING_ONLY is nonzero, mark only running jobs. */ void ! nohup_all_jobs (running_only) ! int running_only; { register int i; *************** *** 2856,2860 **** { for (i = 0; i < job_slots; i++) ! if (jobs[i]) nohup_job (i); } --- 2936,2940 ---- { for (i = 0; i < job_slots; i++) ! if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i)))) nohup_job (i); } *************** *** 2876,2880 **** --- 2956,2964 ---- for (i = 0; i < job_slots; i++) + #if 0 if (jobs[i] && DEADJOB (i)) + #else + if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i) != last_asynchronous_pid))) + #endif jobs[i]->flags |= J_NOTIFIED; *************** *** 2911,2915 **** stop_making_children (); start_pipeline (); ! delete_all_jobs (); set_job_control (0); } --- 2995,2999 ---- stop_making_children (); start_pipeline (); ! delete_all_jobs (0); set_job_control (0); } *************** *** 3024,3052 **** #endif } - - #if defined (ARRAY_VARS) - static void - set_pipestatus_array (ps) - int *ps; - { - SHELL_VAR *v; - ARRAY *a; - register int i; - char *t; - - v = find_variable ("PIPESTATUS"); - if (v == 0) - v = make_new_array_variable ("PIPESTATUS"); - if (array_p (v) == 0) - return; /* Do nothing if not an array variable. */ - a = array_cell (v); - if (a) - empty_array (a); - for (i = 0; ps[i] != -1; i++) - { - t = itos (ps[i]); - array_add_element (a, i, t); - free (t); - } - } - #endif --- 3108,3109 ---- diff -Nrc2 bash-2.01.1/jobs.h bash-2.02/jobs.h *** bash-2.01.1/jobs.h Thu May 8 14:55:27 1997 --- bash-2.02/jobs.h Thu Jul 10 10:16:07 1997 *************** *** 111,118 **** extern int stop_pipeline __P((int, COMMAND *)); ! extern void delete_job __P((int)); extern void nohup_job __P((int)); ! extern void delete_all_jobs __P((void)); ! extern void nohup_all_jobs __P((void)); extern void terminate_current_pipeline __P((void)); --- 111,118 ---- extern int stop_pipeline __P((int, COMMAND *)); ! extern void delete_job __P((int, int)); extern void nohup_job __P((int)); ! extern void delete_all_jobs __P((int)); ! extern void nohup_all_jobs __P((int)); extern void terminate_current_pipeline __P((void)); diff -Nrc2 bash-2.01.1/lib/glob/collsyms.h bash-2.02/lib/glob/collsyms.h *** bash-2.01.1/lib/glob/collsyms.h Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/glob/collsyms.h Thu Mar 27 08:48:55 1997 *************** *** 0 **** --- 1,129 ---- + /* collsyms.h -- collating symbol names and their corresponding characters + (in ascii) as given by POSIX.2 in table 2.8. */ + + /* Copyright (C) 1997 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. */ + + #ifndef _COLLSYMS_H_ + # define _COLLSYSMS_H_ + + /* The upper-case letters, lower-case letters, and digits are omitted from + this table. The digits are not included in the table in the POSIX.2 + spec. The upper and lower case letters are translated by the code + in fnmatch.c:collsym(). */ + + typedef struct _collsym { + char *name; + char code; + } COLLSYM; + + static COLLSYM posix_collsyms[] = + { + "NUL", '\0', + "SOH", '\001', + "STX", '\002', + "ETX", '\003', + "EOT", '\004', + "ENQ", '\005', + "ACK", '\006', + #ifdef __STDC__ + "alert", '\a', + #else + "alert", '\007', + #endif + "backspace", '\b', + "tab", '\t', + "newline", '\n', + "vertical-tab", '\v', + "form-feed", '\f', + "carriage-return", '\r', + "SO", '\016', + "SI", '\017', + "DLE", '\020', + "DC1", '\021', + "DC2", '\022', + "DC3", '\023', + "DC4", '\024', + "NAK", '\025', + "SYN", '\026', + "ETB", '\027', + "CAN", '\030', + "EM", '\031', + "SUB", '\032', + "ESC", '\033', + "IS4", '\034', + "IS3", '\035', + "IS2", '\036', + "IS1", '\037', + "space", ' ', + "exclamation-mark", '!', + "quotation-mark", '"', + "number-sign", '#', + "dollar-sign", '$', + "percent-sign", '%', + "ampersand", '&', + "apostrophe", '\'', + "left-parenthesis", '(', + "right-parenthesis", ')', + "asterisk", '*', + "plus-sign", '+', + "comma", ',', + "hyphen", '-', + "minus", '-', /* extension from POSIX.2 */ + "dash", '-', /* extension from POSIX.2 */ + "period", '.', + "slash", '/', + "solidus", '/', /* extension from POSIX.2 */ + "zero", '0', + "one", '1', + "two", '2', + "three", '3', + "four", '4', + "five", '5', + "six", '6', + "seven", '7', + "eight", '8', + "nine", '9', + "colon", ':', + "semicolon", ';', + "less-than-sign", '<', + "equals-sign", '=', + "greater-than-sign", '>', + "question-mark", '?', + "commercial-at", '@', + /* upper-case letters omitted */ + "left-square-bracket",'[', + "backslash", '\\', + "reverse-solidus", '\\', + "right-square-bracket", ']', + "circumflex", '^', + "circumflex-accent", '^', /* extension from POSIX.2 */ + "underscore", '_', + "grave-accent", '`', + /* lower-case letters omitted */ + "left-brace", '{', /* extension from POSIX.2 */ + "left-curly-bracket", '{', + "vertical-line", '|', + "right-brace", '}', /* extension from POSIX.2 */ + "right-curly-bracket", '}', + "tilde", '~', + "DEL", '\177', + 0, 0, + }; + + #endif diff -Nrc2 bash-2.01.1/lib/glob/fnmatch.c bash-2.02/lib/glob/fnmatch.c *** bash-2.01.1/lib/glob/fnmatch.c Thu Mar 27 08:49:03 1997 --- bash-2.02/lib/glob/fnmatch.c Wed Jan 7 15:04:58 1998 *************** *** 1,31 **** ! /* Copyright (C) 1991 Free Software Foundation, Inc. ! This file is part of the GNU C Library. ! The GNU C Library is free software; you can redistribute it and/or ! modify it under the terms of the GNU Library General Public License as ! published by the Free Software Foundation; either version 2 of the ! License, or (at your option) any later version. ! ! The GNU C Library 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 ! Library General Public License for more details. ! ! You should have received a copy of the GNU Library General Public ! License along with the GNU C Library; see the file COPYING.LIB. If ! not, write to the Free Software Foundation, Inc., 675 Mass Ave, ! Cambridge, MA 02139, USA. */ ! #include #include "fnmatch.h" ! #if !defined (__GNU_LIBRARY__) && !defined (STDC_HEADERS) ! # if !defined (errno) ! extern int errno; ! # endif /* !errno */ #endif ! /* Match STRING against the filename pattern PATTERN, returning zero if ! it matches, FNM_NOMATCH if not. */ int fnmatch (pattern, string, flags) --- 1,116 ---- ! /* fnmatch.c -- ksh-like extended pattern matching for the shell and filename ! globbing. */ ! /* Copyright (C) 1991, 1997 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. */ ! ! #include ! #include "fnmatch.h" + #include "collsyms.h" + #include ! static int gmatch (); ! static char *brackmatch (); ! #ifdef EXTENDED_GLOB ! static int extmatch (); ! #endif ! ! #if !defined (isascii) ! # define isascii(c) ((unsigned int)(c) <= 0177) #endif ! /* Note that these evaluate C many times. */ ! ! #define ISUPPER(c) (isascii (c) && isupper (c)) ! #define ISLOWER(c) (isascii (c) && islower (c)) ! ! #ifndef isblank ! # define isblank(c) ((c) == ' ' || (c) == '\t') ! #endif ! ! #ifndef isgraph ! # define isgraph(c) ((c) != ' ' && isprint((c))) ! #endif ! ! #ifndef isxdigit ! # define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) ! #endif ! ! # define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) ! ! #ifndef STREQ ! #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) ! #endif ! ! #if defined (HAVE_STRCOLL) ! static int rangecmp (c1, c2) ! int c1, c2; ! { ! 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); ! ! s1[0] = c1; ! s2[0] = c2; ! ! if ((ret = strcoll (s1, s2)) != 0) ! return ret; ! return (c1 - c2); ! } ! #else /* !HAVE_STRCOLL */ ! # define rangecmp(c1, c2) ((c1) - (c2)) ! #endif /* !HAVE_STRCOLL */ ! ! #if defined (HAVE_STRCOLL) ! static int collequiv (c1, c2) ! int c1, c2; ! { ! return (rangecmp (c1, c2) == 0); ! } ! #else ! # define collequiv(c1, c2) ((c1) == (c2)) ! #endif ! ! static int ! collsym (s, len) ! char *s; ! int len; ! { ! register struct _collsym *csp; ! ! for (csp = posix_collsyms; csp->name; csp++) ! { ! if (STREQN(csp->name, s, len) && csp->name[len] == '\0') ! return (csp->code); ! } ! if (len == 1) ! return s[0]; ! return -1; ! } ! int fnmatch (pattern, string, flags) *************** *** 34,229 **** int flags; { ! register char *p = pattern, *n = string; ! register char c; ! if ((flags & ~__FNM_FLAGS) != 0) ! { ! errno = EINVAL; ! return (-1); ! } ! while ((c = *p++) != '\0') { switch (c) { ! case '?': ! if (*n == '\0') ! return (FNM_NOMATCH); ! else if ((flags & FNM_PATHNAME) && *n == '/') /* If we are matching a pathname, `?' can never match a `/'. */ ! return (FNM_NOMATCH); ! else if ((flags & FNM_PERIOD) && *n == '.' && (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) /* `?' 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 '\\': ! if (!(flags & FNM_NOESCAPE)) { c = *p++; ! if (c == '\0') ! return (FNM_NOMATCH); } ! if (*n != c) ! return (FNM_NOMATCH); break; ! case '*': ! if ((flags & FNM_PERIOD) && *n == '.' && (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) /* `*' 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 == '?' || c == '*'; c = *p++) { ! if ((flags & FNM_PATHNAME) && *n == '/') /* A slash does not match a wildcard under FNM_PATHNAME. */ ! return (FNM_NOMATCH); else if (c == '?') { ! if (*n == '\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++; } } ! if (c == '\0') return (0); /* General case, use recursion. */ { ! char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; ! for (--p; *n != '\0'; ++n) /* Only call fnmatch if the first character indicates a possible match. */ ! if ((c == '[' || *n == c1) && ! fnmatch (p, n, flags & ~FNM_PERIOD) == 0) return (0); ! return (FNM_NOMATCH); } case '[': { ! /* Nonzero if the sense of the character class is inverted. */ ! register int not; ! ! if (*n == '\0') ! 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) && *n == '.' && (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) return (FNM_NOMATCH); ! /* 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 `]'. This code will have to be changed when ! POSIX.2 character classes are implemented. */ ! { ! register char *np; ! ! for (np = p; np && *np && *np != ']'; np++) ! ; ! ! if (np && !*np) ! { ! if (*n != '[') ! return (FNM_NOMATCH); ! break; ! } ! } ! ! not = (*p == '!' || *p == '^'); ! if (not) ! ++p; ! ! c = *p++; ! for (;;) ! { ! register char cstart, cend; ! ! /* Initialize cstart and cend in case `-' is the last ! character of the pattern. */ ! cstart = cend = c; ! ! if (!(flags & FNM_NOESCAPE) && c == '\\') ! { ! if (*p == '\0') ! return FNM_NOMATCH; ! cstart = cend = *p++; ! } ! ! if (c == '\0') ! /* [ (unterminated) loses. */ ! return (FNM_NOMATCH); ! ! c = *p++; ! ! if ((flags & FNM_PATHNAME) && c == '/') ! /* [/] can never match. */ ! return (FNM_NOMATCH); ! ! /* 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 == '-' && *p != ']') ! { ! cend = *p++; ! if (!(flags & FNM_NOESCAPE) && cend == '\\') ! cend = *p++; ! if (cend == '\0') ! return (FNM_NOMATCH); ! ! c = *p++; ! } ! ! if (*n >= cstart && *n <= cend) ! goto matched; ! ! if (c == ']') ! break; ! } ! if (!not) ! return (FNM_NOMATCH); ! break; ! ! matched: ! /* Skip the rest of the [...] that already matched. */ ! while (c != ']') ! { ! if (c == '\0') ! /* [... (unterminated) loses. */ ! return (FNM_NOMATCH); ! ! c = *p++; ! if (!(flags & FNM_NOESCAPE) && c == '\\') ! { ! if (*p == '\0') ! return FNM_NOMATCH; ! /* XXX 1003.2d11 is unclear if this is right. */ ! ++p; ! } ! } ! if (not) ! return (FNM_NOMATCH); } break; default: ! if (c != *n) return (FNM_NOMATCH); } --- 119,277 ---- int flags; { ! char *se, *pe; ! if (string == 0 || pattern == 0) ! return FNM_NOMATCH; ! ! se = string + strlen (string); ! pe = pattern + strlen (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; ! { ! register char *p, *n; /* pattern, string */ ! register char c; /* current pattern character */ ! register char sc; /* current string character */ ! ! p = pattern; ! n = string; ! ! if (string == 0 || pattern == 0) ! return FNM_NOMATCH; ! ! while (p < pe) { + c = *p++; + c = FOLD (c); + + sc = n < se ? *n : '\0'; + + #ifdef EXTENDED_GLOB + if ((flags & FNM_EXTMATCH) && *p == '(' && + (c == '+' || c == '*' || c == '?' || c == '@' || c == '!')) /* ) */ + /* extmatch () will handle recursively calling gmatch, so we can + just return what extmatch() returns. */ + return (extmatch (c, n, se, p, pe, flags)); + #endif + switch (c) { ! case '?': /* Match single character */ ! if (sc == '\0') ! return FNM_NOMATCH; ! else if ((flags & FNM_PATHNAME) && sc == '/') /* If we are matching a pathname, `?' can never match a `/'. */ ! return FNM_NOMATCH; ! else if ((flags & FNM_PERIOD) && sc == '.' && (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) /* `?' 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 '\\': /* 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) != c) ! return FNM_NOMATCH; break; ! case '*': /* Match zero or more characters */ ! if (p == pe) ! return 0; ! ! if ((flags & FNM_PERIOD) && sc == '.' && (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) /* `*' 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 == '?' || c == '*'); c = *p++) { ! if ((flags & FNM_PATHNAME) && sc == '/') /* A slash does not match a wildcard under FNM_PATHNAME. */ ! return FNM_NOMATCH; else if (c == '?') { ! if (sc == '\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 == '*' && *p == '(') /*)*/ + return (extmatch (c, n, se, p, pe, flags)); + #endif + if (p == pe) + break; } ! /* 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 == '?' || c == '*')) return (0); /* General case, use recursion. */ { ! char c1; ! ! c1 = ((flags & FNM_NOESCAPE) == 0 && c == '\\') ? *p : c; ! c1 = FOLD (c1); ! for (--p; n < se; ++n) /* Only call fnmatch if the first character indicates a possible match. */ ! if ((c == '[' || FOLD (*n) == c1) && ! gmatch (n, se, p, pe, flags & ~FNM_PERIOD) == 0) return (0); ! return FNM_NOMATCH; } case '[': { ! if (sc == '\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 == '.' && (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) return (FNM_NOMATCH); ! p = brackmatch (p, sc, flags); ! if (p == 0) ! return FNM_NOMATCH; } break; default: ! if (c != FOLD (sc)) return (FNM_NOMATCH); } *************** *** 232,238 **** } ! if (*n == '\0') return (0); return (FNM_NOMATCH); } --- 280,738 ---- } ! if (n == se) return (0); + if ((flags & FNM_LEADING_DIR) && *n == '/') + /* 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] == '.' && p[pc+1] == ']') + break; + val = collsym (p, pc); + if (vp) + *vp = val; + return (p + pc + 2); + } + + static char * + brackmatch (p, test, flags) + char *p; + unsigned char test; + int flags; + { + register char cstart, cend, c; + register int not; /* Nonzero if the sense of the character class is inverted. */ + int pc, brcnt; + 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 starging with an unquoted circumflex character produces + unspecified results. This implementation treats the two identically. */ + if (not = (*p == '!' || *p == '^')) + ++p; + + c = *p++; + for (;;) + { + /* Initialize cstart and cend in case `-' is the last + character of the pattern. */ + cstart = cend = c; + + /* 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 == '[' && *p == '=' && p[2] == '=' && p[3] == ']') + { + pc = FOLD (p[1]); + p += 4; + if (collequiv (test, pc)) + goto matched; + else + { + c = *p++; + if (c == '\0') + return ((test == '[') ? savep : (char *)0); + c = FOLD (c); + continue; + } + } + + /* POSIX.2 character class expression. See POSIX.2 2.8.3.2. */ + if (c == '[' && *p == ':') + { + pc = 0; /* make sure invalid char classes don't match. */ + if (STREQN (p+1, "alnum:]", 7)) + { pc = isalnum (test); p += 8; } + else if (STREQN (p+1, "alpha:]", 7)) + { pc = isalpha (test); p += 8; } + else if (STREQN (p+1, "blank:]", 7)) + { pc = isblank (test); p += 8; } + else if (STREQN (p+1, "cntrl:]", 7)) + { pc = iscntrl (test); p += 8; } + else if (STREQN (p+1, "digit:]", 7)) + { pc = isdigit (test); p += 8; } + else if (STREQN (p+1, "graph:]", 7)) + { pc = isgraph (test); p += 8; } + else if (STREQN (p+1, "lower:]", 7)) + { pc = ISLOWER (test); p += 8; } + else if (STREQN (p+1, "print:]", 7)) + { pc = isprint (test); p += 8; } + else if (STREQN (p+1, "punct:]", 7)) + { pc = ispunct (test); p += 8; } + else if (STREQN (p+1, "space:]", 7)) + { pc = isspace (test); p += 8; } + else if (STREQN (p+1, "upper:]", 7)) + { pc = ISUPPER (test); p += 8; } + else if (STREQN (p+1, "xdigit:]", 8)) + { pc = isxdigit (test); p += 9; } + else if (STREQN (p+1, "ascii:]", 7)) + { pc = isascii (test); p += 8; } + if (pc) + goto matched; + else + { + /* continue the loop here, since this expression can't be + the first part of a range expression. */ + c = *p++; + if (c == '\0') + return ((test == '[') ? savep : (char *)0); + else if (c == ']') + 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 == '[' && *p == '.') + { + 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 == -1) ? test + 1 : pc; + } + + if (!(flags & FNM_NOESCAPE) && c == '\\') + { + 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 == '\0') + return ((test == '[') ? savep : (char *)0); + + c = *p++; + c = FOLD (c); + + if ((flags & FNM_PATHNAME) && c == '/') + /* [/] 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 == '-' && *p != ']') + { + cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return (char *)0; + if (cend == '[' && *p == '.') + { + 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 == -1) ? test - 1 : pc; + } + 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) > 0) + { + if (c == ']') + break; + c = FOLD (c); + continue; + } + } + + if (rangecmp (test, cstart) >= 0 && rangecmp (test, cend) <= 0) + goto matched; + + if (c == ']') + break; + } + /* No match. */ + return (!not ? (char *)0 : p); + + matched: + /* Skip the rest of the [...] that already matched. */ + brcnt = (c != ']') + (c == '[' && (*p == '=' || *p == ':' || *p == '.')); + while (brcnt > 0) + { + /* A `[' without a matching `]' is just another character to match. */ + if (c == '\0') + return ((test == '[') ? savep : (char *)0); + + c = *p++; + if (c == '[' && (*p == '=' || *p == ':' || *p == '.')) + brcnt++; + else if (c == ']') + brcnt--; + else if (!(flags & FNM_NOESCAPE) && c == '\\') + { + 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. */ + static char * + patscan (string, end, delim) + char *string, *end; + int delim; + { + int pnest, bnest; + char *s, c; + + pnest = bnest = 0; + for (s = string; c = *s; s++) + { + switch (c) + { + case '\0': + return ((char *)0); + case '[': + bnest++; + break; + case ']': + if (bnest) + bnest--; + break; + case '(': + if (bnest == 0) + pnest++; + break; + case ')': + if (bnest == 0) + pnest--; + if (pnest <= 0) + return ++s; + break; + case '|': + if (bnest == 0 && pnest == 0 && delim == '|') + return ++s; + break; + } + } + return (char *)0; + } + + /* 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; + + c1 = *pe; + c2 = *se; + + *pe = *se = '\0'; + #if defined (HAVE_STRCOLL) + ret = strcoll (p, s); + #else + ret = strcmp (p, s); + #endif + + *pe = c1; + *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; + + switch (xc) + { + case '+': /* match one or more occurrences */ + case '*': /* match zero or more occurrences */ + prest = patscan (p, 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)); + + /* 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 == '*' && (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, '|'); + 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) + m2 = (gmatch (srest, se, prest, pe, flags) == 0) || + (s != srest && gmatch (srest, se, p - 1, pe, flags) == 0); + if (m1 && m2) + return (0); + } + if (pnext == prest) + break; + } + return (FNM_NOMATCH); + + case '?': /* match zero or one of the patterns */ + case '@': /* match exactly one of the patterns */ + prest = patscan (p, pe, 0); + if (prest == 0) + return (strcompare (p - 1, pe, s, se)); + + /* 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 == '?' && (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, '|'); + srest = (prest == pe) ? se : s; + for ( ; srest <= se; srest++) + { + if (gmatch (s, srest, psub, pnext - 1, flags) == 0 && + gmatch (srest, se, prest, pe, flags) == 0) + return (0); + } + if (pnext == prest) + break; + } + return (FNM_NOMATCH); + + case '!': /* match anything *except* one of the patterns */ + prest = patscan (p, pe, 0); + if (prest == 0) + return (strcompare (p - 1, pe, s, se)); + + for (srest = s; srest <= se; srest++) + { + m1 = 0; + for (psub = p + 1; ; psub = pnext) + { + pnext = patscan (psub, pe, '|'); + /* 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 (m1 == 0 && gmatch (srest, se, prest, pe, flags) == 0) + return (0); + } + return (FNM_NOMATCH); + } + return (FNM_NOMATCH); } + #endif /* EXTENDED_GLOB */ + + #ifdef TEST + main (c, v) + int c; + char **v; + { + char *string, *pat; + + string = v[1]; + pat = v[2]; + + if (fnmatch (pat, string, 0) == 0) + { + printf ("%s matches %s\n", string, pat); + exit (0); + } + else + { + printf ("%s does not match %s\n", string, pat); + exit (1); + } + } + #endif diff -Nrc2 bash-2.01.1/lib/glob/fnmatch.h bash-2.02/lib/glob/fnmatch.h *** bash-2.01.1/lib/glob/fnmatch.h Thu Mar 27 08:49:03 1997 --- bash-2.02/lib/glob/fnmatch.h Thu Jul 31 15:34:29 1997 *************** *** 18,29 **** #ifndef _FNMATCH_H - #define _FNMATCH_H 1 /* Bits set in the FLAGS argument to `fnmatch'. */ ! #define FNM_PATHNAME (1 << 0)/* No wildcard can ever match `/'. */ ! #define FNM_NOESCAPE (1 << 1)/* Backslashes don't quote special chars. */ ! #define FNM_PERIOD (1 << 2)/* Leading `.' is matched only explicitly. */ ! #define __FNM_FLAGS (FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD) /* Value returned by `fnmatch' if STRING does not match PATTERN. */ --- 18,39 ---- #ifndef _FNMATCH_H #define _FNMATCH_H 1 + /* We #undef these before defining them because some losing systems + (HP-UX A.08.07 for example) define these in . */ + #undef FNM_PATHNAME + #undef FNM_NOESCAPE + #undef FNM_PERIOD + /* Bits set in the FLAGS argument to `fnmatch'. */ ! /* standard flags */ ! #define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ ! #define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ ! #define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ ! ! /* extended flags */ ! #define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ ! #define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ ! #define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */ /* Value returned by `fnmatch' if STRING does not match PATTERN. */ *************** *** 34,36 **** extern int fnmatch(); ! #endif /* fnmatch.h */ --- 44,46 ---- extern int fnmatch(); ! #endif /* _FNMATCH_H */ diff -Nrc2 bash-2.01.1/lib/glob/glob.c bash-2.02/lib/glob/glob.c *** bash-2.01.1/lib/glob/glob.c Thu Feb 13 11:58:09 1997 --- bash-2.02/lib/glob/glob.c Fri Jan 30 13:18:08 1998 *************** *** 26,43 **** #endif /* _AIX && RISC6000 && !__GNUC__ */ #if defined (HAVE_UNISTD_H) # include #endif ! #if defined (HAVE_STDLIB_H) ! # include #else ! # if defined (SHELL) ! # include "ansi_stdlib.h" ! # endif /* SHELL */ #endif - #include - #if defined (HAVE_DIRENT_H) # include --- 26,52 ---- #endif /* _AIX && RISC6000 && !__GNUC__ */ + #if defined (SHELL) + # include "bashtypes.h" + #else + # include + #endif + #if defined (HAVE_UNISTD_H) # include #endif ! #if defined (SHELL) ! # include "bashansi.h" #else ! # if defined (HAVE_STDLIB_H) ! # include ! # endif ! # if defined (HAVE_STRING_H) ! # include ! # else /* !HAVE_STRING_H */ ! # include ! # endif /* !HAVE_STRING_H */ #endif #if defined (HAVE_DIRENT_H) # include *************** *** 67,91 **** #endif /* _POSIX_SOURCE */ - #if defined (HAVE_STRING_H) - # include - #else /* !HAVE_STRING_H */ - # include - #endif /* !HAVE_STRING_H */ - #if !defined (HAVE_BCOPY) # define bcopy(s, d, n) ((void) memcpy ((d), (s), (n))) #endif /* !HAVE_BCOPY */ ! /* If the opendir () on your system lets you open non-directory files, ! then we consider that not robust. */ ! #if defined (OPENDIR_NOT_ROBUST) ! # if defined (SHELL) ! # include "posixstat.h" ! # else /* !SHELL */ ! # include ! # endif /* !SHELL */ ! #endif /* OPENDIR_NOT_ROBUST */ - #include "memalloc.h" #include "fnmatch.h" --- 76,98 ---- #endif /* _POSIX_SOURCE */ #if !defined (HAVE_BCOPY) # define bcopy(s, d, n) ((void) memcpy ((d), (s), (n))) #endif /* !HAVE_BCOPY */ ! #if defined (SHELL) ! # include "posixstat.h" ! #else /* !SHELL */ ! # include ! #endif /* !SHELL */ ! ! #include "filecntl.h" ! #if !defined (F_OK) ! # define F_OK 0 ! #endif ! ! #if defined (SHELL) ! # include "memalloc.h" ! #endif #include "fnmatch.h" *************** *** 105,110 **** --- 112,119 ---- #if defined (SHELL) extern void throw_to_top_level (); + extern int test_eaccess (); extern int interrupt_state; + extern int extended_glob; #endif /* SHELL */ *************** *** 113,116 **** --- 122,129 ---- int noglob_dot_filenames = 1; + /* Global variable which controls whether or not filename globbing + is done without regard to case. */ + int glob_ignore_case = 0; + /* Global variable to return to signify an error in globbing. */ char *glob_error_return; *************** *** 121,127 **** char *pattern; { ! register char *p = pattern; register char c; ! int open = 0; while ((c = *p++) != '\0') --- 134,143 ---- char *pattern; { ! register char *p; register char c; ! int bopen; ! ! p = pattern; ! bopen = 0; while ((c = *p++) != '\0') *************** *** 133,143 **** case '[': /* Only accept an open brace if there is a close */ ! open++; /* brace to match it. Bracket expressions must be */ continue; /* complete, according to Posix.2 */ case ']': ! if (open) return (1); continue; case '\\': if (*p++ == '\0') --- 149,166 ---- case '[': /* Only accept an open brace if there is a close */ ! bopen++; /* brace to match it. Bracket expressions must be */ continue; /* complete, according to Posix.2 */ case ']': ! if (bopen) return (1); continue; + case '+': /* extended matching operators */ + case '@': + case '!': + if (*p == '(') /*) */ + return (1); + continue; + case '\\': if (*p++ == '\0') *************** *** 169,172 **** --- 192,224 ---- + + /* Test whether NAME exists. */ + + #if defined (HAVE_LSTAT) + # define GLOB_TESTNAME(name) (lstat (name, &finfo)) + #else /* !HAVE_LSTAT */ + # if defined (SHELL) && !defined (AFS) + # define GLOB_TESTNAME(name) (test_eaccess (nextname, F_OK)) + # else /* !SHELL || AFS */ + # define GLOB_TESTNAME(name) (access (nextname, F_OK)) + # endif /* !SHELL || AFS */ + #endif /* !HAVE_LSTAT */ + + /* Return 0 if DIR is a directory, -1 otherwise. */ + static int + glob_testdir (dir) + char *dir; + { + struct stat finfo; + + if (stat (dir, &finfo) < 0) + return (-1); + + if (S_ISDIR (finfo.st_mode) == 0) + return (-1); + + return (0); + } + /* Return a vector of names of files in directory DIR whose names match glob pattern PAT. *************** *** 205,234 **** register char **name_vector; register unsigned int i; ! #if defined (OPENDIR_NOT_ROBUST) ! struct stat finfo; ! ! if (stat (dir, &finfo) < 0) ! return ((char **) &glob_error_return); ! ! if (!S_ISDIR (finfo.st_mode)) ! return ((char **) &glob_error_return); ! #endif /* OPENDIR_NOT_ROBUST */ ! ! d = opendir (dir); ! if (d == NULL) ! return ((char **) &glob_error_return); lastlink = 0; ! count = 0; ! lose = 0; ! skip = 0; /* If PAT is empty, skip the loop, but return one (empty) filename. */ ! if (!pat || !*pat) { nextlink = (struct globval *)alloca (sizeof (struct globval)); ! nextlink->next = lastlink; nextname = (char *) malloc (1); ! if (!nextname) lose = 1; else --- 257,275 ---- register char **name_vector; register unsigned int i; ! int flags; /* Flags passed to fnmatch (). */ lastlink = 0; ! count = lose = skip = 0; /* If PAT is empty, skip the loop, but return one (empty) filename. */ ! if (pat == 0 || *pat == '\0') { + if (glob_testdir (dir) < 0) + return ((char **) &glob_error_return); + nextlink = (struct globval *)alloca (sizeof (struct globval)); ! nextlink->next = (struct globval *)0; nextname = (char *) malloc (1); ! if (nextname == 0) lose = 1; else *************** *** 237,296 **** nextlink->name = nextname; nextname[0] = '\0'; ! count++; } skip = 1; } ! /* Scan the directory, finding all names that match. ! For each name that matches, allocate a struct globval ! on the stack and store the name in it. ! Chain those structs together; lastlink is the front of the chain. */ ! while (!skip) { ! int flags; /* Flags passed to fnmatch (). */ ! #if defined (SHELL) ! /* Make globbing interruptible in the bash shell. */ ! if (interrupt_state) { ! closedir (d); ! lose = 1; ! goto lost; } - #endif /* SHELL */ - - dp = readdir (d); - if (dp == NULL) - break; ! /* If this directory entry is not to be used, try again. */ ! if (!REAL_DIR_ENTRY (dp)) ! continue; ! /* If a dot must be explicity matched, check to see if they do. */ ! if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.' && ! (pat[0] != '\\' || pat[1] != '.')) ! continue; flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME; ! if (fnmatch (pat, dp->d_name, flags) != FNM_NOMATCH) { ! nextlink = (struct globval *) alloca (sizeof (struct globval)); ! nextlink->next = lastlink; ! nextname = (char *) malloc (D_NAMLEN (dp) + 1); ! if (nextname == NULL) { lose = 1; break; } ! lastlink = nextlink; ! nextlink->name = nextname; ! bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1); ! ++count; } } - (void) closedir (d); ! if (!lose) { name_vector = (char **) malloc ((count + 1) * sizeof (char *)); --- 278,409 ---- nextlink->name = nextname; nextname[0] = '\0'; ! count = 1; } + skip = 1; } ! /* If the filename pattern (PAT) does not contain any globbing characters, ! we can dispense with reading the directory, and just see if there is ! a filename `DIR/PAT'. If there is, and we can access it, just make the ! vector to return and bail immediately. */ ! if (skip == 0 && glob_pattern_p (pat) == 0) { ! int dirlen; ! struct stat finfo; ! ! if (glob_testdir (dir) < 0) ! return ((char **) &glob_error_return); ! ! dirlen = strlen (dir); ! nextname = (char *)malloc (dirlen + strlen (pat) + 2); ! if (nextname == 0) ! lose = 1; ! else { ! strcpy (nextname, dir); ! nextname[dirlen++] = '/'; ! strcpy (nextname + dirlen, pat); ! ! if (GLOB_TESTNAME (nextname) >= 0) ! { ! free (nextname); ! nextlink = (struct globval *)alloca (sizeof (struct globval)); ! nextlink->next = (struct globval *)0; ! nextname = (char *) malloc (strlen (pat) + 1); ! if (nextname == 0) ! lose = 1; ! else ! { ! lastlink = nextlink; ! nextlink->name = nextname; ! strcpy (nextname, pat); ! count = 1; ! } ! } ! else ! free (nextname); } ! skip = 1; ! } ! if (skip == 0) ! { ! /* Open the directory, punting immediately if we cannot. If opendir ! is not robust (i.e., it opens non-directories successfully), test ! that DIR is a directory and punt if it's not. */ ! #if defined (OPENDIR_NOT_ROBUST) ! if (glob_testdir (dir) < 0) ! return ((char **) &glob_error_return); ! #endif ! ! d = opendir (dir); ! if (d == NULL) ! return ((char **) &glob_error_return); + /* Compute the flags that will be passed to fnmatch(). We don't + need to do this every time through the loop. */ flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME; ! #ifdef FNM_CASEFOLD ! if (glob_ignore_case) ! flags |= FNM_CASEFOLD; ! #endif ! ! #ifdef SHELL ! if (extended_glob) ! flags |= FNM_EXTMATCH; ! #endif ! ! /* Scan the directory, finding all names that match. ! For each name that matches, allocate a struct globval ! on the stack and store the name in it. ! Chain those structs together; lastlink is the front of the chain. */ ! while (1) { ! #if defined (SHELL) ! /* Make globbing interruptible in the shell. */ ! if (interrupt_state) { lose = 1; break; } ! #endif /* SHELL */ ! ! dp = readdir (d); ! if (dp == NULL) ! break; ! ! /* If this directory entry is not to be used, try again. */ ! if (REAL_DIR_ENTRY (dp) == 0) ! continue; ! ! /* If a dot must be explicity matched, check to see if they do. */ ! if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.' && ! (pat[0] != '\\' || pat[1] != '.')) ! continue; ! ! if (fnmatch (pat, dp->d_name, flags) != FNM_NOMATCH) ! { ! nextlink = (struct globval *) alloca (sizeof (struct globval)); ! nextlink->next = lastlink; ! nextname = (char *) malloc (D_NAMLEN (dp) + 1); ! if (nextname == NULL) ! { ! lose = 1; ! break; ! } ! lastlink = nextlink; ! nextlink->name = nextname; ! bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1); ! ++count; ! } } + + (void) closedir (d); } ! if (lose == 0) { name_vector = (char **) malloc ((count + 1) * sizeof (char *)); *************** *** 299,305 **** /* Have we run out of memory? */ - #if defined (SHELL) - lost: - #endif if (lose) { --- 412,415 ---- *************** *** 314,318 **** throw_to_top_level (); #endif /* SHELL */ ! return (NULL); } --- 424,429 ---- throw_to_top_level (); #endif /* SHELL */ ! ! return ((char **)NULL); } diff -Nrc2 bash-2.01.1/lib/glob/glob.h bash-2.02/lib/glob/glob.h *** bash-2.01.1/lib/glob/glob.h Wed Mar 29 16:00:59 1995 --- bash-2.02/lib/glob/glob.h Mon Jul 14 15:00:50 1997 *************** *** 27,30 **** --- 27,31 ---- extern char *glob_error_return; extern int noglob_dot_filenames; + extern int glob_ignore_case; #endif /* _GLOB_H_ */ diff -Nrc2 bash-2.01.1/lib/malloc/getpagesize.h bash-2.02/lib/malloc/getpagesize.h *** bash-2.01.1/lib/malloc/getpagesize.h Thu Apr 17 10:52:22 1997 --- bash-2.02/lib/malloc/getpagesize.h Thu Jul 17 09:49:42 1997 *************** *** 17,20 **** --- 17,23 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include # if defined (_SC_PAGESIZE) *************** *** 28,32 **** #if !defined (getpagesize) ! # include # if defined (PAGESIZE) # define getpagesize() PAGESIZE --- 31,37 ---- #if !defined (getpagesize) ! # ifndef _MINIX ! # include ! # endif # if defined (PAGESIZE) # define getpagesize() PAGESIZE diff -Nrc2 bash-2.01.1/lib/malloc/gmalloc.c bash-2.02/lib/malloc/gmalloc.c *** bash-2.01.1/lib/malloc/gmalloc.c Tue Apr 23 14:06:03 1996 --- bash-2.02/lib/malloc/gmalloc.c Fri Jul 18 17:03:47 1997 *************** *** 1,6 **** - /* DO NOT EDIT THIS FILE -- it is automagically generated. -*- C -*- */ - - #define _MALLOC_INTERNAL - /* The malloc headers and source files from the C library follow here. */ --- 1,2 ---- *************** *** 21,35 **** You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If ! not, write to the Free Software Foundation, Inc., 675 Mass Ave, ! Cambridge, MA 02139, USA. The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ ! #ifndef _MALLOC_H ! ! #define _MALLOC_H 1 ! ! #ifdef _MALLOC_INTERNAL #ifdef HAVE_CONFIG_H --- 17,38 ---- You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If ! ot, write to the Free Software Foundation, Inc., 59 Temple Place - ! Suite 330, Boston, MA 02111-1307, USA. The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ ! /* XXX NOTES: ! 1. Augment the mstats struct so we can see how many blocks for fragments ! and how many blocks for large requests were allocated. ! */ ! ! /* CHANGES: ! 1. Reorganized the source for my benefit. ! 2. Integrated the range-checking code by default. ! 3. free(0) no longer dumps core. ! 4. Extended the statistics. ! 5. Fixed a couple of places where the stats were not kept correctly. ! */ #ifdef HAVE_CONFIG_H *************** *** 37,92 **** #endif ! #if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG) ! #include #else ! #ifndef memset ! #define memset(s, zero, n) bzero ((s), (n)) ! #endif ! #ifndef memcpy ! #define memcpy(d, s, n) bcopy ((s), (d), (n)) ! #endif #endif ! #if defined (__GNU_LIBRARY__) || (defined (__STDC__) && __STDC__) ! #include ! #else ! #ifndef CHAR_BIT ! #define CHAR_BIT 8 #endif #endif ! #ifdef HAVE_UNISTD_H ! #include #endif ! #endif /* _MALLOC_INTERNAL. */ ! #ifdef __cplusplus ! extern "C" ! { #endif ! #if defined (__cplusplus) || (defined (__STDC__) && __STDC__) ! #undef __P ! #define __P(args) args ! #undef __ptr_t ! #define __ptr_t void * ! #else /* Not C++ or ANSI C. */ ! #undef __P ! #define __P(args) () ! #undef const ! #define const ! #undef __ptr_t ! #define __ptr_t char * ! #endif /* C++ or ANSI C. */ ! ! #if defined (__STDC__) && __STDC__ ! #include ! #define __malloc_size_t size_t ! #define __malloc_ptrdiff_t ptrdiff_t #else ! #define __malloc_size_t unsigned int ! #define __malloc_ptrdiff_t int #endif --- 40,96 ---- #endif ! #if defined (HAVE_STRING_H) ! # include #else ! # include #endif ! #if defined (HAVE_LIMITS_H) ! # include #endif + + #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif + # include #endif ! #if defined (HAVE_STDDEF_H) ! # include #endif + #include ! #if defined (RCHECK) && !defined (botch) ! # include ! # define STDIO_H_INCLUDED ! #endif + #include "stdc.h" ! #ifndef errno ! extern int errno; #endif ! /* Need an autoconf test for this. */ ! #if __STDC__ ! # undef genptr_t ! # define genptr_t void * #else ! # undef genptr_t ! # define genptr_t char * ! #endif /* !__STDC__ */ ! ! #if !defined (HAVE_MEMSET) ! # define memset(s, zero, n) bzero ((s), (n)) ! #endif ! #if !defined (HAVE_MEMCPY) ! # define memcpy(d, s, n) bcopy ((s), (d), (n)) ! #endif ! ! /* Cope with systems lacking `memmove'. */ ! #if !defined (HAVE_MEMMOVE) && !defined (memmove) ! static void malloc_safe_bcopy __P ((genptr_t, genptr_t, size_t)); ! # define memmove(to, from, size) malloc_safe_bcopy ((from), (to), (size)) #endif *************** *** 95,122 **** #endif /* Allocate SIZE bytes of memory. */ ! extern __ptr_t malloc __P ((__malloc_size_t __size)); /* Re-allocate the previously allocated block ! in __ptr_t, making the new block SIZE bytes long. */ ! extern __ptr_t realloc __P ((__ptr_t __ptr, __malloc_size_t __size)); /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ ! extern __ptr_t calloc __P ((__malloc_size_t __nmemb, __malloc_size_t __size)); /* Free a block allocated by `malloc', `realloc' or `calloc'. */ ! extern void free __P ((__ptr_t __ptr)); /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ ! #if ! (defined (_MALLOC_INTERNAL) && __DJGPP__ - 0 == 1) /* Avoid conflict. */ ! extern __ptr_t memalign __P ((__malloc_size_t __alignment, ! __malloc_size_t __size)); ! #endif ! /* Allocate SIZE bytes on a page boundary. */ ! #if ! (defined (_MALLOC_INTERNAL) && defined (emacs)) /* Avoid conflict. */ ! extern __ptr_t valloc __P ((__malloc_size_t __size)); ! #endif ! #ifdef _MALLOC_INTERNAL /* The allocator divides the heap into blocks of fixed size; large --- 99,174 ---- #endif + #ifndef min + #define min(A, B) ((A) < (B) ? (A) : (B)) + #endif + + /* Return values for `mprobe': these are the kinds of inconsistencies that + `mcheck' enables detection of. */ + enum mcheck_status + { + MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */ + MCHECK_OK, /* Block is fine. */ + MCHECK_FREE, /* Block freed twice. */ + MCHECK_HEAD, /* Memory before the block was clobbered. */ + MCHECK_TAIL /* Memory after the block was clobbered. */ + }; + + /* Statistics available to the user. */ + struct mstats + { + size_t bytes_total; /* Total size of the heap. */ + size_t chunks_used; /* Chunks allocated by the user. */ + size_t bytes_used; /* Byte total of user-allocated chunks. */ + size_t chunks_free; /* Chunks in the free list. */ + size_t bytes_free; /* Byte total of chunks in the free list. */ + int nmalloc; /* Total number of calls to malloc. */ + int nfree; /* Total number of calls to free. */ + int nrealloc; /* Total number of calls to realloc. */ + int nsbrk; /* Total number of calls to sbrk. */ + size_t tsbrk; /* Total number of bytes allocated via sbrk. */ + int negsbrk; /* Total number of calls to sbrk with a negative arg */ + size_t tnegsbrk; /* Total number of bytes returned to the kernel. */ + }; + #ifdef RCHECK + /* Arbitrary magical numbers. */ + #define MAGICWORD 0xfedabeeb + #define MAGICFREE 0xd8675309 + #define MAGICBYTE ((char) 0xd7) + #define MALLOCFLOOD ((char) 0x93) + #define FREEFLOOD ((char) 0x95) + + struct hdr + { + size_t size; /* Exact size requested by user. */ + u_int32_t magic; /* Magic number to check header integrity. */ + }; + #endif /* RCHECK */ + + /* Functions exported by this library. */ /* Allocate SIZE bytes of memory. */ ! extern genptr_t malloc __P ((size_t __size)); ! /* Re-allocate the previously allocated block ! in genptr_t, making the new block SIZE bytes long. */ ! extern genptr_t realloc __P ((genptr_t __ptr, size_t __size)); ! /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ ! extern genptr_t calloc __P ((size_t __nmemb, size_t __size)); ! /* Free a block allocated by `malloc', `realloc' or `calloc'. */ ! extern void free __P ((genptr_t __ptr)); /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ ! extern genptr_t memalign __P ((size_t __alignment, size_t __size)); ! /* Pick up the current statistics. */ ! extern struct mstats mstats __P ((void)); + #ifdef RCHECK + extern enum mcheck_status mprobe __P((genptr_t ptr)); + #endif ! /* End of exported functions. */ /* The allocator divides the heap into blocks of fixed size; large *************** *** 125,136 **** and all fragments of a block are the same size. When all the fragments in a block have been freed, the block itself is freed. */ ! #define INT_BIT (CHAR_BIT * sizeof(int)) ! #define BLOCKLOG (INT_BIT > 16 ? 12 : 9) ! #define BLOCKSIZE (1 << BLOCKLOG) #define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE) /* Determine the amount of memory spanned by the initial heap table (not an absolute limit). */ ! #define HEAP (INT_BIT > 16 ? 4194304 : 65536) /* Number of contiguous free blocks allowed to build up at the end of --- 177,187 ---- and all fragments of a block are the same size. When all the fragments in a block have been freed, the block itself is freed. */ ! #define BLOCKLOG 12 ! #define BLOCKSIZE 4096 /* 1 << BLOCKLOG */ #define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE) /* Determine the amount of memory spanned by the initial heap table (not an absolute limit). */ ! #define HEAP 4194304 /* 1 << 22 */ /* Number of contiguous free blocks allowed to build up at the end of *************** *** 151,188 **** struct { ! __malloc_size_t nfree; /* Free frags in a fragmented block. */ ! __malloc_size_t first; /* First free fragment of the block. */ } frag; /* For a large object, in its first block, this has the number of blocks in the object. In the other blocks, this has a negative number which says how far back the first block is. */ ! __malloc_ptrdiff_t size; } info; } busy; ! /* Heap information for a free block ! (that may be the first of a free cluster). */ struct { ! __malloc_size_t size; /* Size (in blocks) of a free cluster. */ ! __malloc_size_t next; /* Index of next free cluster. */ ! __malloc_size_t prev; /* Index of previous free cluster. */ } free; } malloc_info; /* Pointer to first block of the heap. */ ! extern char *_heapbase; /* Table indexed by block number giving per-block information. */ ! extern malloc_info *_heapinfo; /* Address to block number and vice versa. */ #define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) ! #define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase)) /* Current search index for the heap table. */ ! extern __malloc_size_t _heapindex; /* Limit of valid info table indices. */ ! extern __malloc_size_t _heaplimit; /* Doubly linked lists of free fragments. */ --- 202,242 ---- struct { ! size_t nfree; /* Free frags in a fragmented block. */ ! size_t first; /* First free fragment of the block. */ } frag; /* For a large object, in its first block, this has the number of blocks in the object. In the other blocks, this has a negative number which says how far back the first block is. */ ! ptrdiff_t size; } info; } busy; ! /* Heap information for a free block (that may be the first of a ! free cluster). */ struct { ! size_t size; /* Size (in blocks) of a free cluster. */ ! size_t next; /* Index of next free cluster. */ ! size_t prev; /* Index of previous free cluster. */ } free; } malloc_info; /* Pointer to first block of the heap. */ ! static char *_heapbase; /* Table indexed by block number giving per-block information. */ ! static malloc_info *_heapinfo; /* Address to block number and vice versa. */ #define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) ! #define ADDRESS(B) ((genptr_t) (((B) - 1) * BLOCKSIZE + _heapbase)) ! ! /* Number of info entries. */ ! static size_t heapsize; /* Current search index for the heap table. */ ! static size_t _heapindex; /* Limit of valid info table indices. */ ! static size_t _heaplimit; /* Doubly linked lists of free fragments. */ *************** *** 194,406 **** /* Free list headers for each fragment size. */ ! extern struct list _fraghead[]; ! /* List of blocks allocated with `memalign' (or `valloc'). */ struct alignlist { struct alignlist *next; ! __ptr_t aligned; /* The address that memaligned returned. */ ! __ptr_t exact; /* The address that malloc returned. */ }; - extern struct alignlist *_aligned_blocks; ! /* Instrumentation. */ ! extern __malloc_size_t _chunks_used; ! extern __malloc_size_t _bytes_used; ! extern __malloc_size_t _chunks_free; ! extern __malloc_size_t _bytes_free; /* Internal versions of `malloc', `realloc', and `free' ! used when these functions need to call each other. ! They are the same but don't call the hooks. */ ! extern __ptr_t _malloc_internal __P ((__malloc_size_t __size)); ! extern __ptr_t _realloc_internal __P ((__ptr_t __ptr, __malloc_size_t __size)); ! extern void _free_internal __P ((__ptr_t __ptr)); ! ! #endif /* _MALLOC_INTERNAL. */ /* Given an address in the middle of a malloc'd object, return the address of the beginning of the object. */ ! extern __ptr_t malloc_find_object_address __P ((__ptr_t __ptr)); /* Underlying allocation function; successive calls should return contiguous pieces of memory. */ ! extern __ptr_t (*__morecore) __P ((__malloc_ptrdiff_t __size)); ! ! /* Default value of `__morecore'. */ ! extern __ptr_t __default_morecore __P ((__malloc_ptrdiff_t __size)); ! ! /* If not NULL, this function is called after each time ! `__morecore' is called to increase the data size. */ ! extern void (*__after_morecore_hook) __P ((void)); /* Number of extra blocks to get each time we ask for more core. ! This reduces the frequency of calling `(*__morecore)'. */ ! extern __malloc_size_t __malloc_extra_blocks; /* Nonzero if `malloc' has been called and done its initialization. */ ! extern int __malloc_initialized; /* Function called to initialize malloc data structures. */ ! extern int __malloc_initialize __P ((void)); ! ! /* Hooks for debugging versions. */ ! extern void (*__malloc_initialize_hook) __P ((void)); ! extern void (*__free_hook) __P ((__ptr_t __ptr)); ! extern __ptr_t (*__malloc_hook) __P ((__malloc_size_t __size)); ! extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size)); ! extern __ptr_t (*__memalign_hook) __P ((__malloc_size_t __size, ! __malloc_size_t __alignment)); ! ! /* Return values for `mprobe': these are the kinds of inconsistencies that ! `mcheck' enables detection of. */ ! enum mcheck_status ! { ! MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */ ! MCHECK_OK, /* Block is fine. */ ! MCHECK_FREE, /* Block freed twice. */ ! MCHECK_HEAD, /* Memory before the block was clobbered. */ ! MCHECK_TAIL /* Memory after the block was clobbered. */ ! }; ! ! /* Activate a standard collection of debugging hooks. This must be called ! before `malloc' is ever called. ABORTFUNC is called with an error code ! (see enum above) when an inconsistency is detected. If ABORTFUNC is ! null, the standard function prints on stderr and then calls `abort'. */ ! extern int mcheck __P ((void (*__abortfunc) __P ((enum mcheck_status)))); ! ! /* Check for aberrations in a particular malloc'd block. You must have ! called `mcheck' already. These are the same checks that `mcheck' does ! when you free or reallocate a block. */ ! extern enum mcheck_status mprobe __P ((__ptr_t __ptr)); ! ! /* Activate a standard collection of tracing hooks. */ ! extern void mtrace __P ((void)); ! extern void muntrace __P ((void)); ! ! /* Statistics available to the user. */ ! struct mstats ! { ! __malloc_size_t bytes_total; /* Total size of the heap. */ ! __malloc_size_t chunks_used; /* Chunks allocated by the user. */ ! __malloc_size_t bytes_used; /* Byte total of user-allocated chunks. */ ! __malloc_size_t chunks_free; /* Chunks in the free list. */ ! __malloc_size_t bytes_free; /* Byte total of chunks in the free list. */ ! }; ! ! /* Pick up the current statistics. */ ! extern struct mstats mstats __P ((void)); ! ! /* Call WARNFUN with a warning message when memory usage is high. */ ! extern void memory_warnings __P ((__ptr_t __start, ! void (*__warnfun) __P ((const char *)))); ! ! ! /* Relocating allocator. */ ! ! /* Allocate SIZE bytes, and store the address in *HANDLEPTR. */ ! extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size)); ! ! /* Free the storage allocated in HANDLEPTR. */ ! extern void r_alloc_free __P ((__ptr_t *__handleptr)); ! ! /* Adjust the block at HANDLEPTR to be SIZE bytes long. */ ! extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size)); ! ! #ifdef __cplusplus ! } #endif - #endif /* malloc.h */ - /* Memory allocator `malloc'. - Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - Written May 1989 by Mike Haertel. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; see the file COPYING.LIB. If - not, write to the Free Software Foundation, Inc., 675 Mass Ave, - Cambridge, MA 02139, USA. - - The author may be reached (Email) at the address mike@ai.mit.edu, - or (US mail) as Mike Haertel c/o Free Software Foundation. */ - - #ifndef _MALLOC_INTERNAL - #define _MALLOC_INTERNAL - #include - #endif - #include - - /* How to really get more memory. */ - __ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore; - - /* Debugging hook for `malloc'. */ - __ptr_t (*__malloc_hook) __P ((__malloc_size_t __size)); - - /* Pointer to the base of the first block. */ - char *_heapbase; - - /* Block information table. Allocated with align/__free (not malloc/free). */ - malloc_info *_heapinfo; - - /* Number of info entries. */ - static __malloc_size_t heapsize; - - /* Search index in the info table. */ - __malloc_size_t _heapindex; - - /* Limit of valid info table indices. */ - __malloc_size_t _heaplimit; - - /* Free lists for each fragment size. */ - struct list _fraghead[BLOCKLOG]; - /* Instrumentation. */ ! __malloc_size_t _chunks_used; ! __malloc_size_t _bytes_used; ! __malloc_size_t _chunks_free; ! __malloc_size_t _bytes_free; ! ! /* Are you experienced? */ ! int __malloc_initialized; ! ! __malloc_size_t __malloc_extra_blocks; ! ! void (*__malloc_initialize_hook) __P ((void)); ! void (*__after_morecore_hook) __P ((void)); ! /* Aligned allocation. */ ! static __ptr_t align __P ((__malloc_size_t)); ! static __ptr_t align (size) ! __malloc_size_t size; { ! __ptr_t result; unsigned long int adj; ! result = (*__morecore) (size); adj = (unsigned long int) ((unsigned long int) ((char *) result - (char *) NULL)) % BLOCKSIZE; if (adj != 0) { ! __ptr_t new; adj = BLOCKSIZE - adj; ! new = (*__morecore) (adj); result = (char *) result + adj; } - if (__after_morecore_hook) - (*__after_morecore_hook) (); - return result; } --- 248,323 ---- /* Free list headers for each fragment size. */ ! static struct list _fraghead[BLOCKLOG]; ! /* List of blocks allocated with `memalign'. */ struct alignlist { struct alignlist *next; ! genptr_t aligned; /* The address that memaligned returned. */ ! genptr_t exact; /* The address that malloc returned. */ }; ! /* List of blocks allocated by memalign. */ ! static struct alignlist *_aligned_blocks = NULL; /* Internal versions of `malloc', `realloc', and `free' ! used when these functions need to call each other. */ ! static genptr_t imalloc __P ((size_t __size)); ! static genptr_t irealloc __P ((genptr_t __ptr, size_t __size)); ! static void ifree __P ((genptr_t __ptr)); /* Given an address in the middle of a malloc'd object, return the address of the beginning of the object. */ ! static genptr_t malloc_find_object_address __P ((genptr_t __ptr)); /* Underlying allocation function; successive calls should return contiguous pieces of memory. */ ! static genptr_t default_morecore __P ((ptrdiff_t __size)); /* Number of extra blocks to get each time we ask for more core. ! This reduces the frequency of calling `default_morecore'. */ ! static size_t malloc_extra_blocks; /* Nonzero if `malloc' has been called and done its initialization. */ ! static int malloc_initialized; /* Function called to initialize malloc data structures. */ ! static int malloc_initialize __P ((void)); ! #ifdef RCHECK ! static void zmemset __P((genptr_t, int, size_t)); ! static enum mcheck_status checkhdr __P((const struct hdr *)); ! static void mabort __P((enum mcheck_status)); #endif /* Instrumentation. */ ! static size_t chunks_used; ! static size_t bytes_used; ! static size_t chunks_free; ! static size_t bytes_free; ! static int nmalloc, nfree, nrealloc; ! static int nsbrk; ! static size_t tsbrk; ! static int negsbrk; ! static size_t tnegsbrk; /* Aligned allocation. */ ! static genptr_t align (size) ! size_t size; { ! genptr_t result; unsigned long int adj; ! result = default_morecore (size); adj = (unsigned long int) ((unsigned long int) ((char *) result - (char *) NULL)) % BLOCKSIZE; if (adj != 0) { ! genptr_t new; adj = BLOCKSIZE - adj; ! new = default_morecore (adj); result = (char *) result + adj; } return result; } *************** *** 409,422 **** Return the address of the space we got. If we cannot get space at END, fail and return -1. */ ! static __ptr_t get_contiguous_space __P ((__malloc_ptrdiff_t, __ptr_t)); ! static __ptr_t get_contiguous_space (size, position) ! __malloc_ptrdiff_t size; ! __ptr_t position; { ! __ptr_t before; ! __ptr_t after; ! before = (*__morecore) (0); /* If we can tell in advance that the break is at the wrong place, fail now. */ --- 326,338 ---- Return the address of the space we got. If we cannot get space at END, fail and return -1. */ ! static genptr_t get_contiguous_space (size, position) ! ptrdiff_t size; ! genptr_t position; { ! genptr_t before; ! genptr_t after; ! before = default_morecore (0); /* If we can tell in advance that the break is at the wrong place, fail now. */ *************** *** 425,429 **** /* Allocate SIZE bytes and get the address of them. */ ! after = (*__morecore) (size); if (!after) return 0; --- 341,345 ---- /* Allocate SIZE bytes and get the address of them. */ ! after = default_morecore (size); if (!after) return 0; *************** *** 432,436 **** if (after != position) { ! (*__morecore) (- size); return 0; } --- 348,352 ---- if (after != position) { ! default_morecore (- size); return 0; } *************** *** 439,454 **** } - /* This is called when `_heapinfo' and `heapsize' have just been set to describe a new info table. Set up the table to describe itself and account for it in the statistics. */ ! static void register_heapinfo __P ((void)); ! #ifdef __GNUC__ ! __inline__ ! #endif ! static void register_heapinfo () { ! __malloc_size_t block, blocks; block = BLOCK (_heapinfo); --- 355,365 ---- } /* This is called when `_heapinfo' and `heapsize' have just been set to describe a new info table. Set up the table to describe itself and account for it in the statistics. */ ! inline static void register_heapinfo () { ! size_t block, blocks; block = BLOCK (_heapinfo); *************** *** 456,461 **** /* Account for the _heapinfo block itself in the statistics. */ ! _bytes_used += blocks * BLOCKSIZE; ! ++_chunks_used; /* Describe the heapinfo block itself in the heapinfo. */ --- 367,372 ---- /* Account for the _heapinfo block itself in the statistics. */ ! bytes_used += blocks * BLOCKSIZE; ! ++chunks_used; /* Describe the heapinfo block itself in the heapinfo. */ *************** *** 468,480 **** /* Set everything up and remember that we have. */ ! int ! __malloc_initialize () { ! if (__malloc_initialized) return 0; - if (__malloc_initialize_hook) - (*__malloc_initialize_hook) (); - heapsize = HEAP / BLOCKSIZE; _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info)); --- 379,388 ---- /* Set everything up and remember that we have. */ ! static int ! malloc_initialize () { ! if (malloc_initialized) return 0; heapsize = HEAP / BLOCKSIZE; _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info)); *************** *** 490,509 **** register_heapinfo (); ! __malloc_initialized = 1; return 1; } static int morecore_recursing; /* Get neatly aligned memory, initializing or growing the heap info table as necessary. */ ! static __ptr_t morecore __P ((__malloc_size_t)); ! static __ptr_t morecore (size) ! __malloc_size_t size; { ! __ptr_t result; malloc_info *newinfo, *oldinfo; ! __malloc_size_t newsize; if (morecore_recursing) --- 398,438 ---- register_heapinfo (); ! malloc_initialized = 1; return 1; } + /* Allocate INCREMENT more bytes of data space, + and return the start of data space, or NULL on errors. + If INCREMENT is negative, shrink data space. */ + static genptr_t + default_morecore (increment) + ptrdiff_t increment; + { + genptr_t result; + + nsbrk++; + tsbrk += increment; + if (increment < 0) + { + negsbrk++; + tnegsbrk += -increment; + } + result = (genptr_t) sbrk (increment); + if ((long)result == -1L) + return NULL; + return result; + } + static int morecore_recursing; /* Get neatly aligned memory, initializing or growing the heap info table as necessary. */ ! static genptr_t morecore (size) ! size_t size; { ! genptr_t result; malloc_info *newinfo, *oldinfo; ! size_t newsize; if (morecore_recursing) *************** *** 516,520 **** /* Check if we need to grow the info table. */ ! if ((__malloc_size_t) BLOCK ((char *) result + size) > heapsize) { /* Calculate the new _heapinfo table size. We do not account for the --- 445,449 ---- /* Check if we need to grow the info table. */ ! if ((size_t) BLOCK ((char *) result + size) > heapsize) { /* Calculate the new _heapinfo table size. We do not account for the *************** *** 524,529 **** newsize = heapsize; do ! newsize *= 2; ! while ((__malloc_size_t) BLOCK ((char *) result + size) > newsize); /* We must not reuse existing core for the new info table when called --- 453,458 ---- newsize = heapsize; do ! newsize <<= 1; ! while ((size_t) BLOCK ((char *) result + size) > newsize); /* We must not reuse existing core for the new info table when called *************** *** 541,546 **** int save = errno; /* Don't want to clobber errno with ENOMEM. */ morecore_recursing = 1; ! newinfo = (malloc_info *) _realloc_internal ! (_heapinfo, newsize * sizeof (malloc_info)); morecore_recursing = 0; if (newinfo == NULL) --- 470,474 ---- int save = errno; /* Don't want to clobber errno with ENOMEM. */ morecore_recursing = 1; ! newinfo = (malloc_info *) irealloc (_heapinfo, newsize * sizeof (malloc_info)); morecore_recursing = 0; if (newinfo == NULL) *************** *** 551,556 **** table's blocks on the free list. Now zero the new part of the table and install the new table location. */ ! memset (&newinfo[heapsize], 0, ! (newsize - heapsize) * sizeof (malloc_info)); _heapinfo = newinfo; heapsize = newsize; --- 479,483 ---- table's blocks on the free list. Now zero the new part of the table and install the new table location. */ ! memset (&newinfo[heapsize], 0, (newsize - heapsize) * sizeof (malloc_info)); _heapinfo = newinfo; heapsize = newsize; *************** *** 567,571 **** if (newinfo == NULL) { ! (*__morecore) (-size); return NULL; } --- 494,498 ---- if (newinfo == NULL) { ! default_morecore (-size); return NULL; } *************** *** 573,583 **** /* Is it big enough to record status for its own space? If so, we win. */ ! if ((__malloc_size_t) BLOCK ((char *) newinfo ! + newsize * sizeof (malloc_info)) ! < newsize) break; /* Must try again. First give back most of what we just got. */ ! (*__morecore) (- newsize * sizeof (malloc_info)); newsize *= 2; } --- 500,508 ---- /* Is it big enough to record status for its own space? If so, we win. */ ! if ((size_t) BLOCK ((char *) newinfo + newsize * sizeof (malloc_info)) < newsize) break; /* Must try again. First give back most of what we just got. */ ! default_morecore (- newsize * sizeof (malloc_info)); newsize *= 2; } *************** *** 586,591 **** and zero the rest of the new table. */ memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info)); ! memset (&newinfo[heapsize], 0, ! (newsize - heapsize) * sizeof (malloc_info)); oldinfo = _heapinfo; _heapinfo = newinfo; --- 511,515 ---- and zero the rest of the new table. */ memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info)); ! memset (&newinfo[heapsize], 0, (newsize - heapsize) * sizeof (malloc_info)); oldinfo = _heapinfo; _heapinfo = newinfo; *************** *** 594,601 **** register_heapinfo (); ! /* Reset _heaplimit so _free_internal never decides it can relocate or resize the info table. */ _heaplimit = 0; ! _free_internal (oldinfo); /* The new heap limit includes the new table just allocated. */ --- 518,525 ---- register_heapinfo (); ! /* Reset _heaplimit so ifree never decides it can relocate or resize the info table. */ _heaplimit = 0; ! ifree (oldinfo); /* The new heap limit includes the new table just allocated. */ *************** *** 610,620 **** /* Allocate memory from the heap. */ ! __ptr_t ! _malloc_internal (size) ! __malloc_size_t size; ! { ! __ptr_t result; ! __malloc_size_t block, blocks, lastblocks, start; ! register __malloc_size_t i; struct list *next; --- 534,544 ---- /* Allocate memory from the heap. */ ! static genptr_t ! imalloc (size) ! size_t size; ! { ! genptr_t result; ! size_t block, blocks, lastblocks, start; ! register size_t i; struct list *next; *************** *** 626,630 **** Be compatible. */ ! #if 0 if (size == 0) return NULL; --- 550,554 ---- Be compatible. */ ! #if 0 if (size == 0) return NULL; *************** *** 644,648 **** /* Small allocation to receive a fragment of a block. Determine the logarithm to base two of the fragment size. */ ! register __malloc_size_t log = 1; --size; while ((size /= 2) != 0) --- 568,572 ---- /* Small allocation to receive a fragment of a block. Determine the logarithm to base two of the fragment size. */ ! register size_t log = 1; --size; while ((size /= 2) != 0) *************** *** 657,661 **** Pop a fragment out of the fragment list and return it. Update the block's nfree and first counters. */ ! result = (__ptr_t) next; next->prev->next = next->next; if (next->next != NULL) --- 581,585 ---- Pop a fragment out of the fragment list and return it. Update the block's nfree and first counters. */ ! result = (genptr_t) next; next->prev->next = next->next; if (next->next != NULL) *************** *** 668,675 **** /* Update the statistics. */ ! ++_chunks_used; ! _bytes_used += 1 << log; ! --_chunks_free; ! _bytes_free -= 1 << log; } else --- 592,599 ---- /* Update the statistics. */ ! ++chunks_used; ! bytes_used += 1 << log; ! --chunks_free; ! bytes_free -= 1 << log; } else *************** *** 677,681 **** /* No free fragments of the desired size, so get a new block and break it into fragments, returning the first. */ ! result = malloc (BLOCKSIZE); if (result == NULL) return NULL; --- 601,605 ---- /* No free fragments of the desired size, so get a new block and break it into fragments, returning the first. */ ! result = imalloc (BLOCKSIZE); if (result == NULL) return NULL; *************** *** 687,691 **** _fraghead[log].next = next; ! for (i = 2; i < (__malloc_size_t) (BLOCKSIZE >> log); ++i) { next = (struct list *) ((char *) result + (i << log)); --- 611,615 ---- _fraghead[log].next = next; ! for (i = 2; i < (size_t) (BLOCKSIZE >> log); ++i) { next = (struct list *) ((char *) result + (i << log)); *************** *** 702,708 **** _heapinfo[block].busy.info.frag.first = i - 1; ! _chunks_free += (BLOCKSIZE >> log) - 1; ! _bytes_free += BLOCKSIZE - (1 << log); ! _bytes_used -= BLOCKSIZE - (1 << log); } } --- 626,632 ---- _heapinfo[block].busy.info.frag.first = i - 1; ! chunks_free += (BLOCKSIZE >> log) - 1; ! bytes_free += BLOCKSIZE - (1 << log); ! bytes_used -= BLOCKSIZE - (1 << log); } } *************** *** 721,725 **** { /* Need to get more from the system. Get a little extra. */ ! __malloc_size_t wantblocks = blocks + __malloc_extra_blocks; block = _heapinfo[0].free.prev; lastblocks = _heapinfo[block].free.size; --- 645,649 ---- { /* Need to get more from the system. Get a little extra. */ ! size_t wantblocks = blocks + malloc_extra_blocks; block = _heapinfo[0].free.prev; lastblocks = _heapinfo[block].free.size; *************** *** 738,742 **** block = _heapinfo[0].free.prev; _heapinfo[block].free.size += (wantblocks - lastblocks); ! _bytes_free += (wantblocks - lastblocks) * BLOCKSIZE; _heaplimit += wantblocks - lastblocks; continue; --- 662,666 ---- block = _heapinfo[0].free.prev; _heapinfo[block].free.size += (wantblocks - lastblocks); ! bytes_free += (wantblocks - lastblocks) * BLOCKSIZE; _heaplimit += wantblocks - lastblocks; continue; *************** *** 752,756 **** _heapinfo[0].free.prev = block; _heapinfo[_heapinfo[block].free.prev].free.next = block; ! ++_chunks_free; /* Now loop to use some of that block for this allocation. */ } --- 676,681 ---- _heapinfo[0].free.prev = block; _heapinfo[_heapinfo[block].free.prev].free.next = block; ! ++chunks_free; ! bytes_free += wantblocks * BLOCKSIZE; /* Now loop to use some of that block for this allocation. */ } *************** *** 782,793 **** _heapinfo[_heapinfo[block].free.prev].free.next = _heapindex = _heapinfo[block].free.next; ! --_chunks_free; } _heapinfo[block].busy.type = 0; _heapinfo[block].busy.info.size = blocks; ! ++_chunks_used; ! _bytes_used += blocks * BLOCKSIZE; ! _bytes_free -= blocks * BLOCKSIZE; /* Mark all the blocks of the object just allocated except for the --- 707,718 ---- _heapinfo[_heapinfo[block].free.prev].free.next = _heapindex = _heapinfo[block].free.next; ! --chunks_free; } _heapinfo[block].busy.type = 0; _heapinfo[block].busy.info.size = blocks; ! ++chunks_used; ! bytes_used += blocks * BLOCKSIZE; ! bytes_free -= blocks * BLOCKSIZE; /* Mark all the blocks of the object just allocated except for the *************** *** 801,906 **** } ! __ptr_t malloc (size) ! __malloc_size_t size; { ! if (!__malloc_initialized && !__malloc_initialize ()) ! return NULL; ! ! return (__malloc_hook != NULL ? *__malloc_hook : _malloc_internal) (size); ! } ! ! #ifndef _LIBC ! ! /* On some ANSI C systems, some libc functions call _malloc, _free ! and _realloc. Make them use the GNU functions. */ ! ! __ptr_t ! _malloc (size) ! __malloc_size_t size; ! { ! return malloc (size); ! } ! ! void ! _free (ptr) ! __ptr_t ptr; ! { ! free (ptr); ! } ! ! __ptr_t ! _realloc (ptr, size) ! __ptr_t ptr; ! __malloc_size_t size; ! { ! return realloc (ptr, size); ! } ! #endif - /* Free a block of memory allocated by `malloc'. - Copyright 1990, 1991, 1992, 1994, 1995 Free Software Foundation, Inc. - Written May 1989 by Mike Haertel. ! This library is free software; you can redistribute it and/or ! modify it under the terms of the GNU Library General Public License as ! published by the Free Software Foundation; either version 2 of the ! License, or (at your option) any later version. ! ! This library 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 ! Library General Public License for more details. ! ! You should have received a copy of the GNU Library General Public ! License along with this library; see the file COPYING.LIB. If ! not, write to the Free Software Foundation, Inc., 675 Mass Ave, ! Cambridge, MA 02139, USA. ! ! The author may be reached (Email) at the address mike@ai.mit.edu, ! or (US mail) as Mike Haertel c/o Free Software Foundation. */ ! #ifndef _MALLOC_INTERNAL ! #define _MALLOC_INTERNAL ! #include ! #endif ! /* Cope with systems lacking `memmove'. */ ! #ifndef memmove ! #if (defined (MEMMOVE_MISSING) || \ ! !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG)) ! #ifdef emacs ! #undef __malloc_safe_bcopy ! #define __malloc_safe_bcopy safe_bcopy ! #endif ! /* This function is defined in realloc.c. */ ! extern void __malloc_safe_bcopy __P ((__ptr_t, __ptr_t, __malloc_size_t)); ! #define memmove(to, from, size) __malloc_safe_bcopy ((from), (to), (size)) ! #endif #endif ! /* Debugging hook for free. */ ! void (*__free_hook) __P ((__ptr_t __ptr)); ! ! /* List of blocks allocated by memalign. */ ! struct alignlist *_aligned_blocks = NULL; ! ! /* Return memory to the heap. ! Like `free' but don't call a __free_hook if there is one. */ ! void ! _free_internal (ptr) ! __ptr_t ptr; { int type; ! __malloc_size_t block, blocks; ! register __malloc_size_t i; struct list *prev, *next; ! __ptr_t curbrk; ! const __malloc_size_t lesscore_threshold ! /* Threshold of free space at which we will return some to the system. */ ! = FINAL_FREE_BLOCKS + 2 * __malloc_extra_blocks; ! register struct alignlist *l; --- 726,770 ---- } ! genptr_t malloc (size) ! size_t size; { ! #ifdef RCHECK ! struct hdr *hdr; #endif ! nmalloc++; ! if (malloc_initialized == 0 && malloc_initialize () == 0) ! return NULL; + #ifdef RCHECK + hdr = (struct hdr *) imalloc (sizeof (struct hdr) + size + 1); + if (hdr == NULL) + return NULL; ! hdr->size = size; ! hdr->magic = MAGICWORD; ! ((char *) &hdr[1])[size] = MAGICBYTE; ! zmemset ((genptr_t) (hdr + 1), MALLOCFLOOD, size); ! return (genptr_t) (hdr + 1); ! #else ! return (imalloc (size)); #endif + } + /* Free a block of memory allocated by `malloc'. */ ! /* Return memory to the heap. */ ! static void ! ifree (ptr) ! genptr_t ptr; { int type; ! size_t block, blocks; ! register size_t i; struct list *prev, *next; ! genptr_t curbrk; ! size_t lesscore_threshold; register struct alignlist *l; *************** *** 908,911 **** --- 772,778 ---- return; + /* Threshold of free space at which we will return some to the system. */ + lesscore_threshold = FINAL_FREE_BLOCKS + 2 * malloc_extra_blocks; + for (l = _aligned_blocks; l != NULL; l = l->next) if (l->aligned == ptr) *************** *** 923,929 **** case 0: /* Get as many statistics as early as we can. */ ! --_chunks_used; ! _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; ! _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE; /* Find the free cluster previous to this one in the free list. --- 790,796 ---- case 0: /* Get as many statistics as early as we can. */ ! --chunks_used; ! bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; ! bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE; /* Find the free cluster previous to this one in the free list. *************** *** 957,961 **** _heapinfo[i].free.next = block; _heapinfo[_heapinfo[block].free.next].free.prev = block; ! ++_chunks_free; } --- 824,828 ---- _heapinfo[i].free.next = block; _heapinfo[_heapinfo[block].free.next].free.prev = block; ! ++chunks_free; } *************** *** 970,974 **** = _heapinfo[_heapinfo[block].free.next].free.next; _heapinfo[_heapinfo[block].free.next].free.prev = block; ! --_chunks_free; } --- 837,841 ---- = _heapinfo[_heapinfo[block].free.next].free.next; _heapinfo[_heapinfo[block].free.next].free.prev = block; ! --chunks_free; } *************** *** 977,981 **** /* Where is the current end of accessible core? */ ! curbrk = (*__morecore) (0); if (_heaplimit != 0 && curbrk == ADDRESS (_heaplimit)) --- 844,848 ---- /* Where is the current end of accessible core? */ ! curbrk = default_morecore (0); if (_heaplimit != 0 && curbrk == ADDRESS (_heaplimit)) *************** *** 985,994 **** return some space to the system. */ ! __malloc_size_t info_block = BLOCK (_heapinfo); ! __malloc_size_t info_blocks = _heapinfo[info_block].busy.info.size; ! __malloc_size_t prev_block = _heapinfo[block].free.prev; ! __malloc_size_t prev_blocks = _heapinfo[prev_block].free.size; ! __malloc_size_t next_block = _heapinfo[block].free.next; ! __malloc_size_t next_blocks = _heapinfo[next_block].free.size; if (/* Win if this block being freed is last in core, the info table --- 852,861 ---- return some space to the system. */ ! size_t info_block = BLOCK (_heapinfo); ! size_t info_blocks = _heapinfo[info_block].busy.info.size; ! size_t prev_block = _heapinfo[block].free.prev; ! size_t prev_blocks = _heapinfo[prev_block].free.size; ! size_t next_block = _heapinfo[block].free.next; ! size_t next_blocks = _heapinfo[next_block].free.size; if (/* Win if this block being freed is last in core, the info table *************** *** 1013,1017 **** { malloc_info *newinfo; ! __malloc_size_t oldlimit = _heaplimit; /* Free the old info table, clearing _heaplimit to avoid --- 880,884 ---- { malloc_info *newinfo; ! size_t oldlimit = _heaplimit; /* Free the old info table, clearing _heaplimit to avoid *************** *** 1020,1024 **** the new location. */ _heaplimit = 0; ! _free_internal (_heapinfo); _heaplimit = oldlimit; --- 887,891 ---- the new location. */ _heaplimit = 0; ! ifree (_heapinfo); _heaplimit = oldlimit; *************** *** 1028,1032 **** /* Allocate new space for the info table and move its data. */ ! newinfo = (malloc_info *) _malloc_internal (info_blocks * BLOCKSIZE); memmove (newinfo, _heapinfo, info_blocks * BLOCKSIZE); --- 895,899 ---- /* Allocate new space for the info table and move its data. */ ! newinfo = (malloc_info *) imalloc (info_blocks * BLOCKSIZE); memmove (newinfo, _heapinfo, info_blocks * BLOCKSIZE); *************** *** 1044,1050 **** if (block + blocks == _heaplimit && blocks >= lesscore_threshold) { ! register __malloc_size_t bytes = blocks * BLOCKSIZE; _heaplimit -= blocks; ! (*__morecore) (-bytes); _heapinfo[_heapinfo[block].free.prev].free.next = _heapinfo[block].free.next; --- 911,917 ---- if (block + blocks == _heaplimit && blocks >= lesscore_threshold) { ! register size_t bytes = blocks * BLOCKSIZE; _heaplimit -= blocks; ! default_morecore (-bytes); _heapinfo[_heapinfo[block].free.prev].free.next = _heapinfo[block].free.next; *************** *** 1052,1057 **** = _heapinfo[block].free.prev; block = _heapinfo[block].free.prev; ! --_chunks_free; ! _bytes_free -= bytes; } } --- 919,924 ---- = _heapinfo[block].free.prev; block = _heapinfo[block].free.prev; ! --chunks_free; ! bytes_free -= bytes; } } *************** *** 1063,1070 **** default: /* Do some of the statistics. */ ! --_chunks_used; ! _bytes_used -= 1 << type; ! ++_chunks_free; ! _bytes_free += 1 << type; /* Get the address of the first free fragment in this block. */ --- 930,937 ---- default: /* Do some of the statistics. */ ! --chunks_used; ! bytes_used -= 1 << type; ! ++chunks_free; ! bytes_free += 1 << type; /* Get the address of the first free fragment in this block. */ *************** *** 1077,1081 **** from the fragment list and free the whole block. */ next = prev; ! for (i = 1; i < (__malloc_size_t) (BLOCKSIZE >> type); ++i) next = next->next; prev->prev->next = next; --- 944,948 ---- from the fragment list and free the whole block. */ next = prev; ! for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i) next = next->next; prev->prev->next = next; *************** *** 1086,1095 **** /* Keep the statistics accurate. */ ! ++_chunks_used; ! _bytes_used += BLOCKSIZE; ! _chunks_free -= BLOCKSIZE >> type; ! _bytes_free -= BLOCKSIZE; ! free (ADDRESS (block)); } else if (_heapinfo[block].busy.info.frag.nfree != 0) --- 953,962 ---- /* Keep the statistics accurate. */ ! ++chunks_used; ! bytes_used += BLOCKSIZE; ! chunks_free -= BLOCKSIZE >> type; ! bytes_free -= BLOCKSIZE; ! ifree (ADDRESS (block)); } else if (_heapinfo[block].busy.info.frag.nfree != 0) *************** *** 1129,1189 **** void free (ptr) ! __ptr_t ptr; { ! if (__free_hook != NULL) ! (*__free_hook) (ptr); ! else ! _free_internal (ptr); ! } ! ! /* Define the `cfree' alias for `free'. */ ! #ifdef weak_alias ! weak_alias (free, cfree) ! #else ! void ! cfree (ptr) ! __ptr_t ptr; ! { ! free (ptr); ! } #endif - /* Change the size of a block allocated by `malloc'. - Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - Written May 1989 by Mike Haertel. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. ! You should have received a copy of the GNU Library General Public ! License along with this library; see the file COPYING.LIB. If ! not, write to the Free Software Foundation, Inc., 675 Mass Ave, ! Cambridge, MA 02139, USA. ! The author may be reached (Email) at the address mike@ai.mit.edu, ! or (US mail) as Mike Haertel c/o Free Software Foundation. */ ! #ifndef _MALLOC_INTERNAL ! #define _MALLOC_INTERNAL ! #include #endif ! ! /* Cope with systems lacking `memmove'. */ ! #if (defined (MEMMOVE_MISSING) || \ ! !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG)) ! ! #ifdef emacs ! #undef __malloc_safe_bcopy ! #define __malloc_safe_bcopy safe_bcopy ! #else ! /* Snarfed directly from Emacs src/dispnew.c: XXX Should use system bcopy if it handles overlap. */ --- 996,1024 ---- void free (ptr) ! genptr_t ptr; { ! #ifdef RCHECK ! struct hdr *hdr; #endif ! nfree++; ! if (ptr == 0) ! return; ! #ifdef RCHECK ! hdr = ((struct hdr *) ptr) - 1; ! checkhdr (hdr); ! hdr->magic = MAGICFREE; ! zmemset (ptr, FREEFLOOD, hdr->size); ! ifree (hdr); ! #else ! ifree (ptr); #endif + } + /* Change the size of a block allocated by `malloc'. */ ! #ifndef HAVE_MEMMOVE /* Snarfed directly from Emacs src/dispnew.c: XXX Should use system bcopy if it handles overlap. */ *************** *** 1191,1202 **** /* Like bcopy except never gets confused by overlap. */ ! void ! __malloc_safe_bcopy (afrom, ato, size) ! __ptr_t afrom; ! __ptr_t ato; ! __malloc_size_t size; { ! char *from = afrom, *to = ato; if (size <= 0 || from == to) return; --- 1026,1039 ---- /* Like bcopy except never gets confused by overlap. */ ! static void ! malloc_safe_bcopy (afrom, ato, size) ! genptr_t afrom; ! genptr_t ato; ! size_t size; { ! char *from, *to; + from = afrom; + to = ato; if (size <= 0 || from == to) return; *************** *** 1246,1263 **** } } ! #endif /* emacs */ ! ! #ifndef memmove ! extern void __malloc_safe_bcopy __P ((__ptr_t, __ptr_t, __malloc_size_t)); ! #define memmove(to, from, size) __malloc_safe_bcopy ((from), (to), (size)) ! #endif ! ! #endif ! ! ! #define min(A, B) ((A) < (B) ? (A) : (B)) ! ! /* Debugging hook for realloc. */ ! __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size)); /* Resize the given region to the new size, returning a pointer --- 1083,1087 ---- } } ! #endif /* !HAVE_MEMMOVE */ /* Resize the given region to the new size, returning a pointer *************** *** 1267,1286 **** new region. This module has incestuous knowledge of the internals of both free and malloc. */ ! __ptr_t ! _realloc_internal (ptr, size) ! __ptr_t ptr; ! __malloc_size_t size; { ! __ptr_t result; int type; ! __malloc_size_t block, blocks, oldlimit; if (size == 0) { ! _free_internal (ptr); ! return _malloc_internal (0); } else if (ptr == NULL) ! return _malloc_internal (size); block = BLOCK (ptr); --- 1091,1110 ---- new region. This module has incestuous knowledge of the internals of both free and malloc. */ ! static genptr_t ! irealloc (ptr, size) ! genptr_t ptr; ! size_t size; { ! genptr_t result; int type; ! size_t block, blocks, oldlimit; if (size == 0) { ! ifree (ptr); ! return imalloc (0); } else if (ptr == NULL) ! return imalloc (size); block = BLOCK (ptr); *************** *** 1293,1301 **** if (size <= BLOCKSIZE / 2) { ! result = _malloc_internal (size); if (result != NULL) { memcpy (result, ptr, size); ! _free_internal (ptr); return result; } --- 1117,1125 ---- if (size <= BLOCKSIZE / 2) { ! result = imalloc (size); if (result != NULL) { memcpy (result, ptr, size); ! ifree (ptr); return result; } *************** *** 1315,1321 **** /* We have just created a new chunk by splitting a chunk in two. Now we will free this chunk; increment the statistics counter ! so it doesn't become wrong when _free_internal decrements it. */ ! ++_chunks_used; ! _free_internal (ADDRESS (block + blocks)); result = ptr; } --- 1139,1145 ---- /* We have just created a new chunk by splitting a chunk in two. Now we will free this chunk; increment the statistics counter ! so it doesn't become wrong when ifree decrements it. */ ! ++chunks_used; ! ifree (ADDRESS (block + blocks)); result = ptr; } *************** *** 1332,1337 **** oldlimit = _heaplimit; _heaplimit = 0; ! _free_internal (ptr); ! result = _malloc_internal (size); if (_heaplimit == 0) _heaplimit = oldlimit; --- 1156,1161 ---- oldlimit = _heaplimit; _heaplimit = 0; ! ifree (ptr); ! result = imalloc (size); if (_heaplimit == 0) _heaplimit = oldlimit; *************** *** 1342,1352 **** have been coalesced with its neighbors. */ if (_heapindex == block) ! (void) _malloc_internal (blocks * BLOCKSIZE); else { ! __ptr_t previous ! = _malloc_internal ((block - _heapindex) * BLOCKSIZE); ! (void) _malloc_internal (blocks * BLOCKSIZE); ! _free_internal (previous); } return NULL; --- 1166,1176 ---- have been coalesced with its neighbors. */ if (_heapindex == block) ! (void) imalloc (blocks * BLOCKSIZE); else { ! genptr_t previous; ! previous = imalloc ((block - _heapindex) * BLOCKSIZE); ! (void) imalloc (blocks * BLOCKSIZE); ! ifree (previous); } return NULL; *************** *** 1360,1365 **** /* Old size is a fragment; type is logarithm to base two of the fragment size. */ ! if (size > (__malloc_size_t) (1 << (type - 1)) && ! size <= (__malloc_size_t) (1 << type)) /* The new size is the same kind of fragment. */ result = ptr; --- 1184,1189 ---- /* Old size is a fragment; type is logarithm to base two of the fragment size. */ ! if (size > (size_t) (1 << (type - 1)) && ! size <= (size_t) (1 << type)) /* The new size is the same kind of fragment. */ result = ptr; *************** *** 1368,1376 **** /* The new size is different; allocate a new space, and copy the lesser of the new size and the old. */ ! result = _malloc_internal (size); if (result == NULL) return NULL; ! memcpy (result, ptr, min (size, (__malloc_size_t) 1 << type)); ! _free_internal (ptr); } break; --- 1192,1200 ---- /* The new size is different; allocate a new space, and copy the lesser of the new size and the old. */ ! result = imalloc (size); if (result == NULL) return NULL; ! memcpy (result, ptr, min (size, (size_t) 1 << type)); ! ifree (ptr); } break; *************** *** 1380,1428 **** } ! __ptr_t realloc (ptr, size) ! __ptr_t ptr; ! __malloc_size_t size; { ! if (!__malloc_initialized && !__malloc_initialize ()) ! return NULL; ! ! return (__realloc_hook != NULL ? *__realloc_hook : _realloc_internal) ! (ptr, size); ! } ! /* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc. ! ! This library is free software; you can redistribute it and/or ! modify it under the terms of the GNU Library General Public License as ! published by the Free Software Foundation; either version 2 of the ! License, or (at your option) any later version. ! This library 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 ! Library General Public License for more details. ! You should have received a copy of the GNU Library General Public ! License along with this library; see the file COPYING.LIB. If ! not, write to the Free Software Foundation, Inc., 675 Mass Ave, ! Cambridge, MA 02139, USA. ! The author may be reached (Email) at the address mike@ai.mit.edu, ! or (US mail) as Mike Haertel c/o Free Software Foundation. */ ! #ifndef _MALLOC_INTERNAL ! #define _MALLOC_INTERNAL ! #include #endif /* Allocate an array of NMEMB elements each SIZE bytes long. The entire array is initialized to zeros. */ ! __ptr_t calloc (nmemb, size) ! register __malloc_size_t nmemb; ! register __malloc_size_t size; { ! register __ptr_t result = malloc (nmemb * size); if (result != NULL) (void) memset (result, 0, nmemb * size); --- 1204,1254 ---- } ! genptr_t realloc (ptr, size) ! genptr_t ptr; ! size_t size; { ! #ifdef RCHECK ! struct hdr *hdr; ! size_t osize; ! #endif ! if (malloc_initialized == 0 && malloc_initialize () == 0) ! return NULL; ! nrealloc++; ! #ifdef RCHECK ! hdr = ((struct hdr *) ptr) - 1; ! osize = hdr->size; ! ! checkhdr (hdr); ! if (size < osize) ! zmemset ((char *) ptr + size, FREEFLOOD, osize - size); ! hdr = (struct hdr *) irealloc ((genptr_t) hdr, sizeof (struct hdr) + size + 1); ! if (hdr == NULL) ! return NULL; ! hdr->size = size; ! hdr->magic = MAGICWORD; ! ((char *) &hdr[1])[size] = MAGICBYTE; ! if (size > osize) ! zmemset ((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize); ! return (genptr_t) (hdr + 1); ! #else ! return (irealloc (ptr, size)); #endif + } /* Allocate an array of NMEMB elements each SIZE bytes long. The entire array is initialized to zeros. */ ! genptr_t calloc (nmemb, size) ! register size_t nmemb; ! register size_t size; { ! register genptr_t result; + result = malloc (nmemb * size); if (result != NULL) (void) memset (result, 0, nmemb * size); *************** *** 1430,1525 **** return result; } - /* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - This file is part of the GNU C Library. ! The GNU C Library 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. ! ! The GNU C Library 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 the GNU C Library; see the file COPYING. If not, write to ! the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! ! #ifndef _MALLOC_INTERNAL ! #define _MALLOC_INTERNAL ! #include ! #endif ! ! #ifndef __GNU_LIBRARY__ ! #define __sbrk sbrk ! #endif ! ! #ifdef __GNU_LIBRARY__ ! /* It is best not to declare this and cast its result on foreign operating ! systems with potentially hostile include files. */ ! ! #include ! extern __ptr_t __sbrk __P ((ptrdiff_t increment)); ! #endif ! ! #ifndef NULL ! #define NULL 0 ! #endif ! ! /* Allocate INCREMENT more bytes of data space, ! and return the start of data space, or NULL on errors. ! If INCREMENT is negative, shrink data space. */ ! __ptr_t ! __default_morecore (increment) ! __malloc_ptrdiff_t increment; { ! __ptr_t result = (__ptr_t) __sbrk (increment); ! if (result == (__ptr_t) -1) ! return NULL; ! return result; } - /* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc. ! This library is free software; you can redistribute it and/or ! modify it under the terms of the GNU Library General Public License as ! published by the Free Software Foundation; either version 2 of the ! License, or (at your option) any later version. ! ! This library 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 ! Library General Public License for more details. ! ! You should have received a copy of the GNU Library General Public ! License along with this library; see the file COPYING.LIB. If ! not, write to the Free Software Foundation, Inc., 675 Mass Ave, ! Cambridge, MA 02139, USA. */ ! ! #ifndef _MALLOC_INTERNAL ! #define _MALLOC_INTERNAL ! #include ! #endif ! ! #if __DJGPP__ - 0 == 1 ! ! /* There is some problem with memalign in DJGPP v1 and we are supposed ! to omit it. Noone told me why, they just told me to do it. */ ! ! #else ! ! __ptr_t (*__memalign_hook) __P ((size_t __size, size_t __alignment)); ! ! __ptr_t memalign (alignment, size) ! __malloc_size_t alignment; ! __malloc_size_t size; { ! __ptr_t result; unsigned long int adj, lastadj; - if (__memalign_hook) - return (*__memalign_hook) (alignment, size); - /* Allocate a block with enough extra space to pad the block with up to (ALIGNMENT - 1) bytes if necessary. */ --- 1256,1276 ---- return result; } ! /* Define the `cfree' alias for `free'. */ ! void ! cfree (ptr) ! genptr_t ptr; { ! free (ptr); } ! genptr_t memalign (alignment, size) ! size_t alignment; ! size_t size; { ! genptr_t result; unsigned long int adj, lastadj; /* Allocate a block with enough extra space to pad the block with up to (ALIGNMENT - 1) bytes if necessary. */ *************** *** 1561,1565 **** if (l == NULL) { ! l = (struct alignlist *) malloc (sizeof (struct alignlist)); if (l == NULL) { --- 1312,1316 ---- if (l == NULL) { ! l = (struct alignlist *) imalloc (sizeof (struct alignlist)); if (l == NULL) { *************** *** 1577,1579 **** } ! #endif /* Not DJGPP v1 */ --- 1328,1486 ---- } ! /* On some ANSI C systems, some libc functions call _malloc, _free ! and _realloc. Make them use the GNU functions. */ ! ! genptr_t ! _malloc (size) ! size_t size; ! { ! return malloc (size); ! } ! ! void ! _free (ptr) ! genptr_t ptr; ! { ! free (ptr); ! } ! ! genptr_t ! _realloc (ptr, size) ! genptr_t ptr; ! size_t size; ! { ! return realloc (ptr, size); ! } ! ! struct mstats ! mstats () ! { ! struct mstats result; ! ! result.bytes_total = (char *) default_morecore (0) - _heapbase; ! result.chunks_used = chunks_used; ! result.bytes_used = bytes_used; ! result.chunks_free = chunks_free; ! result.bytes_free = bytes_free; ! result.nmalloc = nmalloc; ! result.nrealloc = nrealloc; ! result.nfree = nfree; ! result.nsbrk = nsbrk; ! result.tsbrk = tsbrk; ! result.negsbrk = negsbrk; ! result.tnegsbrk = tnegsbrk; ! ! return result; ! } ! ! #ifdef RCHECK ! /* Standard debugging hooks for `malloc'. */ ! ! static void ! zmemset (ptr, val, size) ! genptr_t ptr; ! int val; ! size_t size; ! { ! char *cp = ptr; ! ! while (size--) ! *cp++ = val; ! } ! ! static enum mcheck_status ! checkhdr (hdr) ! const struct hdr *hdr; ! { ! enum mcheck_status status; ! ! switch (hdr->magic) ! { ! default: ! status = MCHECK_HEAD; ! break; ! case MAGICFREE: ! status = MCHECK_FREE; ! break; ! case MAGICWORD: ! if (((char *) &hdr[1])[hdr->size] != MAGICBYTE) ! status = MCHECK_TAIL; ! else ! status = MCHECK_OK; ! break; ! } ! if (status != MCHECK_OK) ! mabort (status); ! return status; ! } ! ! #ifndef botch ! botch (msg) ! char *msg; ! { ! fprintf (stderr, "mcheck: %s\n", msg); ! fflush (stderr); ! abort (); ! } ! #endif ! ! static void ! mabort (status) ! enum mcheck_status status; ! { ! const char *msg; ! ! switch (status) ! { ! case MCHECK_OK: ! msg = "memory is consistent, library is buggy"; ! break; ! case MCHECK_HEAD: ! msg = "memory clobbered before allocated block"; ! break; ! case MCHECK_TAIL: ! msg = "memory clobbered past end of allocated block"; ! break; ! case MCHECK_FREE: ! msg = "block freed twice"; ! break; ! default: ! msg = "bogus mcheck_status, library is buggy"; ! break; ! } ! ! botch (msg); ! } ! ! enum mcheck_status ! mprobe (ptr) ! genptr_t ptr; ! { ! return checkhdr ((struct hdr *)ptr); ! } ! ! #ifndef STDIO_H_INCLUDED ! # include ! #endif ! ! void ! print_malloc_stats (s) ! char *s; ! { ! struct mstats ms; ! ! ms = mstats (); ! fprintf (stderr, "Memory allocation statistics: %s\n", s ? s : ""); ! fprintf (stderr, "\nTotal chunks in use: %d, total chunks free: %d\n", ! ms.chunks_used, ms.chunks_free); ! fprintf (stderr, "Total bytes in use: %u, total bytes free: %u\n", ! ms.bytes_used, ms.bytes_free); ! fprintf (stderr, "Total bytes (from heapbase): %d\n", ms.bytes_total); ! fprintf (stderr, "Total mallocs: %d, total frees: %d, total reallocs: %d\n", ! ms.nmalloc, ms.nfree, ms.nrealloc); ! fprintf (stderr, "Total sbrks: %d, total bytes via sbrk: %d\n", ! ms.nsbrk, ms.tsbrk); ! fprintf (stderr, "Total negative sbrks: %d, total bytes returned to kernel: %d\n", ! ms.negsbrk, ms.tnegsbrk); ! } ! #endif /* RCHECK */ diff -Nrc2 bash-2.01.1/lib/malloc/malloc.c bash-2.02/lib/malloc/malloc.c *** bash-2.01.1/lib/malloc/malloc.c Fri Apr 25 11:47:20 1997 --- bash-2.02/lib/malloc/malloc.c Tue Nov 11 12:06:03 1997 *************** *** 1,5 **** ! /* dynamic memory allocation for GNU. */ ! /* Copyright (C) 1985, 1987 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify --- 1,5 ---- ! /* malloc.c - dynamic memory allocation for bash. */ ! /* Copyright (C) 1985, 1987, 1997 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify *************** *** 42,49 **** * No longer Emacs-specific; can serve as all-purpose malloc for GNU. * You should call malloc_init to reinitialize after loading dumped Emacs. ! * Call malloc_stats to get info on memory stats if MSTATS turned on. * realloc knows how to return same block given, just changing its size, * if the power of 2 is correct. */ /* --- 42,50 ---- * No longer Emacs-specific; can serve as all-purpose malloc for GNU. * You should call malloc_init to reinitialize after loading dumped Emacs. ! * Call malloc_stats to get info on memory stats if MALLOC_STATS turned on. * realloc knows how to return same block given, just changing its size, * if the power of 2 is correct. */ + #define MALLOC_STATS /* for the time being */ /* *************** *** 52,60 **** * go in the first int of the block, and the returned pointer will point * to the second. - * - #ifdef MSTATS - * nmalloc[i] is the difference between the number of mallocs and frees - * for a given block size. - #endif */ --- 53,56 ---- *************** *** 66,72 **** #endif ! #if defined (emacs) || defined (HAVE_CONFIG_H) # include ! #endif /* emacs */ #if defined (HAVE_UNISTD_H) --- 62,74 ---- #endif ! #if defined (HAVE_CONFIG_H) # include ! #endif /* HAVE_CONFIG_H */ ! ! #if defined (SHELL) ! # include "bashtypes.h" ! #else ! # include ! #endif #if defined (HAVE_UNISTD_H) *************** *** 75,84 **** /* Determine which kind of system this is. */ ! #if defined (SHELL) ! # include "bashtypes.h" #else ! # include #endif ! #include /* Define getpagesize () if the system does not. */ --- 77,91 ---- /* Determine which kind of system this is. */ ! #include ! ! #if defined (HAVE_STRING_H) ! # include #else ! # include #endif ! ! #if defined (MALLOC_STATS) || !defined (botch) ! # include ! #endif /* MALLOC_STATS || !botch */ /* Define getpagesize () if the system does not. */ *************** *** 87,101 **** #endif - #if defined (HAVE_RESOURCE) - # include - # include - #endif /* HAVE_RESOURCE */ - - /* Check for the needed symbols. If they aren't present, this - system's isn't very useful to us. */ - #if !defined (RLIMIT_DATA) - # undef HAVE_RESOURCE - #endif - #if __GNUC__ > 1 # define FASTCOPY(s, d, n) __builtin_memcpy (d, s, n) --- 94,97 ---- *************** *** 116,120 **** #endif ! #define start_of_data() &etext #define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */ --- 112,116 ---- #endif ! #define NBUCKETS 30 #define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */ *************** *** 125,129 **** being the distance to the true beginning of the block. */ - extern char etext; #if !defined (SBRK_DECLARED) --- 121,124 ---- *************** *** 131,260 **** #endif /* !SBRK_DECLARED */ ! /* These two are for user programs to look at, when they are interested. */ ! unsigned int malloc_sbrk_used; /* amount of data space used now */ ! unsigned int malloc_sbrk_unused; /* amount more we can have */ ! ! /* start of data space; can be changed by calling init_malloc */ ! static char *data_space_start; ! ! static void get_lim_data (); ! ! #ifdef MSTATS ! static int nmalloc[30]; ! static int nmal, nfre; ! #endif /* MSTATS */ ! ! /* If range checking is not turned on, all we have is a flag indicating ! whether memory is allocated, an index in nextf[], and a size field; to ! realloc() memory we copy either size bytes or 1<<(index+3) bytes depending ! on whether the former can hold the exact size (given the value of ! 'index'). If range checking is on, we always need to know how much space ! is allocated, so the 'size' field is never used. */ ! ! struct mhead { ! char mh_alloc; /* ISALLOC or ISFREE */ ! char mh_index; /* index in nextf[] */ ! /* Remainder are valid only when block is allocated */ ! unsigned short mh_size; /* size, if < 0x10000 */ ! #ifdef RCHECK ! unsigned int mh_nbytes; /* number of bytes allocated */ ! int mh_magic4; /* should be == MAGIC4 */ ! #endif /* RCHECK */ }; /* Access free-list pointer of a block. ! It is stored at block + 4. ! This is not a field in the mhead structure ! because we want sizeof (struct mhead) ! to describe the overhead for when the block is in use, ! and we do not want the free-list pointer to count in that. */ #define CHAIN(a) \ ! (*(struct mhead **) (sizeof (char *) + (char *) (a))) ! #ifdef RCHECK ! # include ! # if !defined (botch) ! # define botch(x) abort () # else ! extern void botch(); ! # endif /* botch */ ! ! # if !defined (__STRING) ! # if defined (__STDC__) ! # define __STRING(x) #x ! # else ! # define __STRING(x) "x" ! # endif # endif ! /* To implement range checking, we write magic values in at the beginning ! and end of each allocated block, and make sure they are undisturbed ! whenever a free or a realloc occurs. */ ! ! /* Written in each of the 4 bytes following the block's real space */ ! # define MAGIC1 0x55 ! /* Written in the 4 bytes before the block's real space */ ! # define MAGIC4 0x55555555 ! # define ASSERT(p) if (!(p)) botch(__STRING(p)); else ! # define EXTRA 4 /* 4 bytes extra for MAGIC1s */ ! #else /* !RCHECK */ ! # define ASSERT(p) ! # define EXTRA 0 ! #endif /* RCHECK */ /* nextf[i] is free list of blocks of size 2**(i + 3) */ ! static struct mhead *nextf[30]; /* busy[i] is nonzero while allocation of block size i is in progress. */ ! static char busy[30]; ! /* Number of bytes of writable memory we can expect to be able to get */ ! static unsigned int lim_data; ! /* Level number of warnings already issued. ! 0 -- no warnings issued. ! 1 -- 75% warning already issued. ! 2 -- 85% warning already issued. ! */ ! static int warnlevel; ! /* Function to call to issue a warning; ! 0 means don't issue them. */ ! static void (*warnfunction) (); ! /* nonzero once initial bunch of free blocks made */ ! static int gotpool; ! char *_malloc_base; ! static void getpool (); ! /* Cause reinitialization based on job parameters; ! also declare where the end of pure storage is. */ ! void ! malloc_init (start, warnfun) ! char *start; ! void (*warnfun) (); ! { ! if (start) ! data_space_start = start; ! lim_data = 0; ! warnlevel = 0; ! warnfunction = warnfun; } ! /* Return the maximum size to which MEM can be realloc'd ! without actually requiring copying. */ ! ! int ! malloc_usable_size (mem) ! char *mem; { ! int blocksize = 8 << (((struct mhead *) mem) - 1) -> mh_index; ! return blocksize - sizeof (struct mhead) - EXTRA; } --- 126,383 ---- #endif /* !SBRK_DECLARED */ ! #ifdef MALLOC_STATS ! /* ! * NMALLOC[i] is the difference between the number of mallocs and frees ! * for a given block size. TMALLOC[i] is the total number of mallocs for ! * a given block size. NMORECORE[i] is the total number of calls to ! * morecore(i). NMAL and NFRE are counts of the number of calls to malloc() ! * and free(), respectively. NREALLOC is the total number of calls to ! * realloc(); NRCOPY is the number of times realloc() had to allocate new ! * memory and copy to it. NRECURSE is a count of the number of recursive ! * calls to malloc() for the same bucket size, which can be caused by calls ! * to malloc() from a signal handler. NSBRK is the number of calls to sbrk() ! * (whether by morecore() or for alignment); TSBRK is the total number of ! * bytes requested from the kernel with sbrk(). BYTESUSED is the total ! * number of bytes consumed by blocks currently in use; BYTESFREE is the ! * total number of bytes currently on all of the free lists. NBSPLIT is ! * the number of times a larger block was split to satisfy a smaller request. ! * NBCOALESCE is the number of times two adjacent smaller blocks off the free ! * list were combined to satisfy a larger request. ! */ ! struct _malstats { ! int nmalloc[NBUCKETS]; ! int tmalloc[NBUCKETS]; ! int nmorecore[NBUCKETS]; ! int nmal; ! int nfre; ! int nrealloc; ! int nrcopy; ! int nrecurse; ! int nsbrk; ! int32_t tsbrk; ! int32_t bytesused; ! int32_t bytesfree; ! int nbsplit; ! int nbcoalesce; ! }; ! ! static struct _malstats _mstats; ! ! /* Return statistics describing allocation of blocks of size BLOCKSIZE. ! NFREE is the number of free blocks for this allocation size. NUSED ! is the number of blocks in use. NMAL is the number of requests for ! blocks of size BLOCKSIZE. NMORECORE is the number of times we had ! to call MORECORE to repopulate the free list for this bucket. */ ! struct bucket_stats { ! u_int32_t blocksize; ! int nfree; ! int nused; ! int nmal; ! int nmorecore; ! }; ! #endif /* MALLOC_STATS */ ! ! /* We have a flag indicating whether memory is allocated, an index in ! nextf[], a size field, and a sentinel value to determine whether or ! not a caller wrote before the start of allocated memory; to realloc() ! memory we either copy mh_nbytes or just change mh_nbytes if there is ! enough room in the block for the new size. Range checking is always ! done. */ ! union mhead { ! union mhead *mh_align; ! struct { ! char mi_alloc; /* ISALLOC or ISFREE */ /* 1 */ ! char mi_index; /* index in nextf[] */ /* 1 */ ! /* Remainder are valid only when block is allocated */ ! u_int32_t mi_nbytes; /* # of bytes allocated */ /* 4 */ ! unsigned short mi_magic2;/* should be == MAGIC2 */ /* 2 */ ! } minfo; }; + #define mh_alloc minfo.mi_alloc + #define mh_index minfo.mi_index + #define mh_nbytes minfo.mi_nbytes + #define mh_magic2 minfo.mi_magic2 /* Access free-list pointer of a block. ! It is stored at block + sizeof (char *). ! This is not a field in the mhead structure ! because we want sizeof (struct mhead) ! to describe the overhead for when the block is in use, ! and we do not want the free-list pointer to count in that. */ #define CHAIN(a) \ ! (*(union mhead **) (sizeof (char *) + (char *) (a))) ! #if defined (botch) ! extern void botch (); ! #else ! static void ! botch (s) ! char *s; ! { ! fprintf (stderr, "\r\nmalloc: assertion botched: %s\r\n", s); ! (void)fflush (stderr); ! abort (); ! } ! #endif /* !botch */ ! ! #if !defined (__STRING) ! # if defined (__STDC__) ! # define __STRING(x) #x # else ! # define __STRING(x) "x" # endif + #endif /* !__STRING */ ! /* To implement range checking, we write magic values in at the beginning ! and end of each allocated block, and make sure they are undisturbed ! whenever a free or a realloc occurs. */ ! ! /* Written in each of the 4 bytes following the block's real space */ ! #define MAGIC1 0x55 ! /* Written in the 2 bytes before the block's real space */ ! #define MAGIC2 0x5555 ! #define ASSERT(p) do { if (!(p)) botch(__STRING(p)); } while (0) ! #define MSLOP 4 /* 4 bytes extra for MAGIC1s */ ! ! /* Minimum and maximum bucket indices for block splitting (and to bound ! the search for a block to split). */ ! #define SPLIT_MIN 3 ! #define SPLIT_MID 9 ! #define SPLIT_MAX 12 ! ! /* Minimum and maximum bucket indices for block coalescing. */ ! #define COMBINE_MIN 6 ! #define COMBINE_MAX (pagebucket - 1) ! ! #define MIN_COMBINE_FREE 4 /* nextf[i] is free list of blocks of size 2**(i + 3) */ ! static union mhead *nextf[NBUCKETS]; /* busy[i] is nonzero while allocation of block size i is in progress. */ ! static char busy[NBUCKETS]; ! static int pagesz; /* system page size. */ ! static int pagebucket; /* bucket for requests a page in size */ ! #if 0 ! /* Coalesce two adjacent free blocks off the free list for size NU - 1, ! as long as there are at least MIN_COMBINE_FREE free blocks and we ! can find two adjacent free blocks. nextf[NU -1] is assumed to not ! be busy; the caller (morecore()) checks for this. */ ! static void ! bcoalesce (nu) ! register int nu; ! { ! register union mhead *mp, *mp1, *mp2; ! register int nfree, nbuck; ! unsigned long siz; ! nbuck = nu - 1; ! if (nextf[nbuck] == 0) ! return; ! nfree = 1; ! mp1 = nextf[nbuck]; ! mp = CHAIN (mp1); ! mp2 = (union mhead *)0; ! while (CHAIN (mp)) ! { ! mp2 = mp1; ! mp1 = mp; ! mp = CHAIN (mp); ! nfree++; ! /* We may not want to run all the way through the free list here; ! if we do not, we need to check a threshold value here and break ! if nfree exceeds it. */ ! } ! if (nfree < MIN_COMBINE_FREE) ! return; ! /* OK, now we have mp1 pointing to the block we want to add to nextf[NU]. ! CHAIN(mp2) must equal mp1. Check that mp1 and mp are adjacent. */ ! if (CHAIN(mp2) != mp1) ! botch ("bcoalesce: CHAIN(mp2) != mp1"); ! siz = 1 << (nbuck + 3); ! if (CHAIN (mp1) != (union mhead *)((char *)mp1 + siz)) ! return; /* not adjacent */ ! #ifdef MALLOC_STATS ! _mstats.nbcoalesce++; ! #endif ! /* Since they are adjacent, remove them from the free list */ ! CHAIN (mp2) = CHAIN (mp); ! /* And add the combined two blocks to nextf[NU]. */ ! mp1->mh_alloc = ISFREE; ! mp1->mh_index = nu; ! CHAIN (mp1) = nextf[nu]; ! nextf[nu] = mp1; } + #endif ! /* Split a block at index > NU (but less than SPLIT_MAX) into a set of ! blocks of the correct size, and attach them to nextf[NU]. nextf[NU] ! is assumed to be empty. Must be called with signals blocked (e.g., ! by morecore()). */ ! static void ! bsplit (nu) ! register int nu; { ! register union mhead *mp; ! int nbuck, nblks; ! unsigned long siz; ! ! if (nu >= SPLIT_MID) ! { ! for (nbuck = SPLIT_MAX; nbuck > nu; nbuck--) ! { ! if (busy[nbuck] || nextf[nbuck] == 0) ! continue; ! break; ! } ! } ! else ! { ! for (nbuck = nu + 1; nbuck <= SPLIT_MAX; nbuck++) ! { ! if (busy[nbuck] || nextf[nbuck] == 0) ! continue; ! break; ! } ! } ! ! if (nbuck > SPLIT_MAX || nbuck <= nu) ! return; ! /* XXX might want to split only if nextf[nbuck] has >= 2 blocks free ! and nbuck is below some threshold. */ ! ! #ifdef MALLOC_STATS ! _mstats.nbsplit++; ! #endif ! ! /* Figure out how many blocks we'll get. */ ! siz = (1 << (nu + 3)); ! nblks = (1 << (nbuck + 3)) / siz; ! ! /* Remove the block from the chain of larger blocks. */ ! mp = nextf[nbuck]; ! nextf[nbuck] = CHAIN (mp); ! ! /* Split the block and put it on the requested chain. */ ! nextf[nu] = mp; ! while (1) ! { ! mp->mh_alloc = ISFREE; ! mp->mh_index = nu; ! if (--nblks <= 0) break; ! CHAIN (mp) = (union mhead *)((char *)mp + siz); ! mp = (union mhead *)((char *)mp + siz); ! } ! CHAIN (mp) = 0; } *************** *** 263,269 **** register int nu; /* size index to get more of */ { ! register char *cp; register int nblks; ! register unsigned int siz; /* Block all signals in case we are executed from a signal handler. */ --- 386,393 ---- register int nu; /* size index to get more of */ { ! register union mhead *mp; register int nblks; ! register long siz; ! long sbrk_amt; /* amount to get via sbrk() */ /* Block all signals in case we are executed from a signal handler. */ *************** *** 280,359 **** #endif /* HAVE_BSD_SIGNALS */ ! if (!data_space_start) { ! data_space_start = start_of_data (); } ! if (lim_data == 0) ! get_lim_data (); ! /* On initial startup, get two blocks of each size up to 1k bytes */ ! if (!gotpool) ! { getpool (); getpool (); gotpool = 1; } ! ! /* Find current end of memory and issue warning if getting near max */ ! ! cp = sbrk (0); ! siz = cp - data_space_start; ! malloc_sbrk_used = siz; ! malloc_sbrk_unused = lim_data - siz; ! ! if (warnfunction) ! switch (warnlevel) ! { ! case 0: ! if (siz > (lim_data / 4) * 3) ! { ! warnlevel++; ! (*warnfunction) ("Warning: past 75% of memory limit"); ! } ! break; ! case 1: ! if (siz > (lim_data / 20) * 17) ! { ! warnlevel++; ! (*warnfunction) ("Warning: past 85% of memory limit"); ! } ! break; ! case 2: ! if (siz > (lim_data / 20) * 19) ! { ! warnlevel++; ! (*warnfunction) ("Warning: past 95% of memory limit"); ! } ! break; ! } ! ! if ((int) cp & 0x3ff) /* land on 1K boundaries */ ! sbrk (1024 - ((int) cp & 0x3ff)); ! ! /* Take at least 2k, and figure out how many blocks of the desired size ! we're about to get */ ! nblks = 1; ! if ((siz = nu) < 8) ! nblks = 1 << ((siz = 8) - nu); ! ! if ((cp = sbrk (1 << (siz + 3))) == (char *) -1) ! return; /* no more room! */ ! ! if ((int) cp & 7) ! { /* shouldn't happen, but just in case */ ! cp = (char *) (((int) cp + 8) & ~7); nblks--; } ! /* save new header and link the nblks blocks together */ ! nextf[nu] = (struct mhead *) cp; ! siz = 1 << (nu + 3); while (1) { ! ((struct mhead *) cp) -> mh_alloc = ISFREE; ! ((struct mhead *) cp) -> mh_index = nu; if (--nblks <= 0) break; ! CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz); ! cp += siz; } ! CHAIN ((struct mhead *) cp) = 0; #if defined (HAVE_BSD_SIGNALS) sigsetmask (oldmask); --- 404,489 ---- #endif /* HAVE_BSD_SIGNALS */ ! siz = 1 << (nu + 3); /* size of desired block for nextf[nu] */ ! ! if (siz < 0) ! return; /* oops */ ! ! #ifdef MALLOC_STATS ! _mstats.nmorecore[nu]++; ! #endif ! ! /* Try to split a larger block here, if we're within the range of sizes ! to split. */ ! if (nu >= SPLIT_MIN && nu < SPLIT_MAX) ! { ! bsplit (nu); ! if (nextf[nu] != 0) ! goto morecore_done; ! } ! ! #if 0 ! /* Try to coalesce two adjacent blocks from the free list on nextf[nu - 1], ! if we can, and we're withing the range of the block coalescing limits. */ ! if (nu >= COMBINE_MIN && nu < COMBINE_MAX && busy[nu - 1] == 0 && nextf[nu - 1]) ! { ! bcoalesce (nu); ! if (nextf[nu] != 0) ! goto morecore_done; ! } ! #endif ! ! /* Take at least a page, and figure out how many blocks of the requested ! size we're getting. */ ! if (siz <= pagesz) { ! sbrk_amt = pagesz; ! nblks = sbrk_amt / siz; } + else + { + /* We always want to request an integral multiple of the page size + from the kernel, so let's compute whether or not `siz' is such + an amount. If it is, we can just request it. If not, we want + the smallest integral multiple of pagesize that is larger than + `siz' and will satisfy the request. */ + sbrk_amt = siz % pagesz; + if (sbrk_amt == 0) + sbrk_amt = siz; + else + sbrk_amt = siz + pagesz - sbrk_amt; + nblks = 1; + } + + #ifdef MALLOC_STATS + _mstats.nsbrk++; + _mstats.tsbrk += sbrk_amt; + #endif ! mp = (union mhead *) sbrk (sbrk_amt); ! /* Totally out of memory. */ ! if ((long)mp == -1) ! return; ! ! /* shouldn't happen, but just in case -- require 8-byte alignment */ ! if ((long)mp & 7) ! { ! mp = (union mhead *) (((long)mp + 8) & ~7); nblks--; } ! /* save new header and link the nblks blocks together */ ! nextf[nu] = mp; while (1) { ! mp->mh_alloc = ISFREE; ! mp->mh_index = nu; if (--nblks <= 0) break; ! CHAIN (mp) = (union mhead *)((char *)mp + siz); ! mp = (union mhead *)((char *)mp + siz); } ! CHAIN (mp) = 0; + morecore_done: #if defined (HAVE_BSD_SIGNALS) sigsetmask (oldmask); *************** *** 365,406 **** } - static void - getpool () - { - register int nu; - register char *cp = sbrk (0); - - if ((int) cp & 0x3ff) /* land on 1K boundaries */ - sbrk (1024 - ((int) cp & 0x3ff)); - - /* Record address of start of space allocated by malloc. */ - if (_malloc_base == 0) - _malloc_base = cp; - - /* Get 2k of storage */ - - cp = sbrk (04000); - if (cp == (char *) -1) - return; - - /* Divide it into an initial 8-word block - plus one block of size 2**nu for nu = 3 ... 10. */ - - CHAIN (cp) = nextf[0]; - nextf[0] = (struct mhead *) cp; - ((struct mhead *) cp) -> mh_alloc = ISFREE; - ((struct mhead *) cp) -> mh_index = 0; - cp += 8; - - for (nu = 0; nu < 7; nu++) - { - CHAIN (cp) = nextf[nu]; - nextf[nu] = (struct mhead *) cp; - ((struct mhead *) cp) -> mh_alloc = ISFREE; - ((struct mhead *) cp) -> mh_index = nu; - cp += 8 << nu; - } - } - #if defined (MEMSCRAMBLE) || !defined (NO_CALLOC) static char * --- 495,498 ---- *************** *** 419,439 **** #endif /* MEMSCRAMBLE || !NO_CALLOC */ char * malloc (n) /* get a block */ ! unsigned int n; { ! register struct mhead *p; ! register unsigned int nbytes; ! register int nunits = 0; /* Figure out how many bytes are required, rounding up to the nearest ! multiple of 4, then figure out which nextf[] area to use */ ! nbytes = (n + sizeof *p + EXTRA + 3) & ~3; ! { ! register unsigned int shiftr = (nbytes - 1) >> 2; ! while (shiftr >>= 1) ! nunits++; ! } /* In case this is reentrant use of malloc from signal handler, --- 511,590 ---- #endif /* MEMSCRAMBLE || !NO_CALLOC */ + static void + malloc_debug_dummy () + { + ; + } + char * malloc (n) /* get a block */ ! size_t n; { ! register union mhead *p; ! register long nbytes; ! register int nunits; + /* Get the system page size and align break pointer so everything will + be page-aligned. The page size must be at least 1K -- anything + smaller is increased. */ + if (pagesz == 0) + { + register long sbrk_needed; + + pagesz = getpagesize (); + if (pagesz < 1024) + pagesz = 1024; + /* OK, how much do we need to allocate to make things page-aligned? + This partial page is wasted space. Once we figure out how much + to advance the break pointer, go ahead and do it. */ + sbrk_needed = pagesz - ((long)sbrk (0) & (pagesz - 1)); /* sbrk(0) % pagesz */ + if (sbrk_needed < 0) + sbrk_needed += pagesz; + /* Now allocate the wasted space. */ + if (sbrk_needed) + { + #ifdef MALLOC_STATS + _mstats.nsbrk++; + _mstats.tsbrk += sbrk_needed; + #endif + if ((long)sbrk (sbrk_needed) == -1) + return (NULL); + } + nunits = 0; + nbytes = 8; + while (pagesz > nbytes) + { + nbytes <<= 1; + nunits++; + } + pagebucket = nunits; + } + /* Figure out how many bytes are required, rounding up to the nearest ! multiple of 4, then figure out which nextf[] area to use. Try to ! be smart about where to start searching -- if the number of bytes ! needed is greater than the page size, we can start at pagebucket. */ ! nbytes = (n + sizeof *p + MSLOP + 3) & ~3; ! nunits = 0; ! if (nbytes <= (pagesz >> 1)) ! { ! register unsigned int shiftr; ! shiftr = (nbytes - 1) >> 2; /* == (nbytes - 1) / 4 */ ! while (shiftr >>= 1) /* == (nbytes - 1) / {8,16,32,...} */ ! nunits++; ! } ! else ! { ! register u_int32_t amt; ! ! nunits = pagebucket; ! amt = pagesz; ! while (nbytes > amt) ! { ! amt <<= 1; ! nunits++; ! } ! } /* In case this is reentrant use of malloc from signal handler, *************** *** 441,457 **** trying to allocate. That's the easiest harmless way not to interfere with the other level of execution. */ while (busy[nunits]) nunits++; busy[nunits] = 1; /* If there are no blocks of the appropriate size, go get some */ - /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */ if (nextf[nunits] == 0) morecore (nunits); /* Get one block off the list, and set the new list head */ ! if ((p = nextf[nunits]) == 0) { busy[nunits] = 0; ! return 0; } nextf[nunits] = CHAIN (p); --- 592,610 ---- trying to allocate. That's the easiest harmless way not to interfere with the other level of execution. */ + #ifdef MALLOC_STATS + if (busy[nunits]) _mstats.nrecurse++; + #endif while (busy[nunits]) nunits++; busy[nunits] = 1; /* If there are no blocks of the appropriate size, go get some */ if (nextf[nunits] == 0) morecore (nunits); /* Get one block off the list, and set the new list head */ ! if ((p = nextf[nunits]) == NULL) { busy[nunits] = 0; ! return NULL; } nextf[nunits] = CHAIN (p); *************** *** 459,476 **** /* Check for free block clobbered */ ! /* If not for this check, we would gobble a clobbered free chain ptr */ ! /* and bomb out on the NEXT allocate of this size block */ ! if (p -> mh_alloc != ISFREE || p -> mh_index != nunits) ! #ifdef RCHECK ! botch ("block on free list clobbered"); ! #else /* not RCHECK */ ! abort (); ! #endif /* not RCHECK */ /* Fill in the info, and if range checking, set up the magic numbers */ ! p -> mh_alloc = ISALLOC; ! #ifdef RCHECK ! p -> mh_nbytes = n; ! p -> mh_magic4 = MAGIC4; { register char *m = (char *) (p + 1) + n; --- 612,624 ---- /* Check for free block clobbered */ ! /* If not for this check, we would gobble a clobbered free chain ptr ! and bomb out on the NEXT allocate of this size block */ ! if (p->mh_alloc != ISFREE || p->mh_index != nunits) ! botch ("malloc: block on free list clobbered"); /* Fill in the info, and if range checking, set up the magic numbers */ ! p->mh_alloc = ISALLOC; ! p->mh_nbytes = n; ! p->mh_magic2 = MAGIC2; { register char *m = (char *) (p + 1) + n; *************** *** 478,491 **** *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1; } ! #else /* not RCHECK */ ! p -> mh_size = n; ! #endif /* not RCHECK */ #ifdef MEMSCRAMBLE zmemset ((char *)(p + 1), 0xdf, n); /* scramble previous contents */ #endif ! #ifdef MSTATS ! nmalloc[nunits]++; ! nmal++; ! #endif /* MSTATS */ return (char *) (p + 1); } --- 626,638 ---- *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1; } ! #ifdef MEMSCRAMBLE zmemset ((char *)(p + 1), 0xdf, n); /* scramble previous contents */ #endif ! #ifdef MALLOC_STATS ! _mstats.nmalloc[nunits]++; ! _mstats.tmalloc[nunits]++; ! _mstats.nmal++; ! #endif /* MALLOC_STATS */ return (char *) (p + 1); } *************** *** 495,566 **** char *mem; { ! register struct mhead *p; ! { ! register char *ap = mem; ! if (ap == 0) ! return; ! p = (struct mhead *) ap - 1; ! if (p -> mh_alloc == ISMEMALIGN) ! { ! #ifdef RCHECK ! ap -= p->mh_nbytes; ! #else ! ap -= p->mh_size; /* XXX */ ! #endif ! p = (struct mhead *) ap - 1; ! } - #ifndef RCHECK - if (p -> mh_alloc != ISALLOC) - abort (); - - #else /* RCHECK */ - if (p -> mh_alloc != ISALLOC) - { - if (p -> mh_alloc == ISFREE) - botch ("free: Called with already freed block argument\n"); - else - botch ("free: Called with unallocated block argument\n"); - } - - ASSERT (p -> mh_magic4 == MAGIC4); - ap += p -> mh_nbytes; - ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); - ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1); - #endif /* RCHECK */ - } #ifdef MEMSCRAMBLE ! { ! register int n; ! ! #ifdef RCHECK ! n = p->mh_nbytes; ! #else /* not RCHECK */ ! n = p->mh_size; ! #endif /* not RCHECK */ ! zmemset (mem, 0xcf, n); ! } #endif - { - register int nunits = p -> mh_index; ! ASSERT (nunits <= 29); ! p -> mh_alloc = ISFREE; ! /* Protect against signal handlers calling malloc. */ ! busy[nunits] = 1; ! /* Put this block on the free list. */ ! CHAIN (p) = nextf[nunits]; ! nextf[nunits] = p; ! busy[nunits] = 0; ! ! #ifdef MSTATS ! nmalloc[nunits]--; ! nfre++; ! #endif /* MSTATS */ ! } } --- 642,693 ---- char *mem; { ! register union mhead *p; ! register char *ap; ! register int nunits; ! if ((ap = mem) == 0) ! return; ! p = (union mhead *) ap - 1; ! if (p->mh_alloc == ISMEMALIGN) ! { ! ap -= p->mh_nbytes; ! p = (union mhead *) ap - 1; ! } ! ! if (p->mh_alloc != ISALLOC) ! { ! if (p->mh_alloc == ISFREE) ! botch ("free: called with already freed block argument"); ! else ! botch ("free: called with unallocated block argument"); ! } ! ! ASSERT (p->mh_magic2 == MAGIC2); ! ap += p->mh_nbytes; ! ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); ! ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1); #ifdef MEMSCRAMBLE ! zmemset (mem, 0xcf, p->mh_nbytes); #endif ! nunits = p->mh_index; ! ASSERT (nunits < NBUCKETS); ! p->mh_alloc = ISFREE; ! ! /* Protect against signal handlers calling malloc. */ ! busy[nunits] = 1; ! /* Put this block on the free list. */ ! CHAIN (p) = nextf[nunits]; ! nextf[nunits] = p; ! busy[nunits] = 0; ! ! #ifdef MALLOC_STATS ! _mstats.nmalloc[nunits]--; ! _mstats.nfre++; ! #endif /* MALLOC_STATS */ } *************** *** 568,635 **** realloc (mem, n) char *mem; ! register unsigned int n; { ! register struct mhead *p; ! register unsigned int tocopy; register unsigned int nbytes; register int nunits; ! if ((p = (struct mhead *) mem) == 0) return malloc (n); p--; ! nunits = p -> mh_index; ! ASSERT (p -> mh_alloc == ISALLOC); ! #ifdef RCHECK ! ASSERT (p -> mh_magic4 == MAGIC4); ! { ! register char *m = mem + (tocopy = p -> mh_nbytes); ! ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); ! ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1); ! } ! #else /* not RCHECK */ ! if (p -> mh_index >= 13) ! tocopy = (1 << (p -> mh_index + 3)) - sizeof *p; ! else ! tocopy = p -> mh_size; ! #endif /* not RCHECK */ /* See if desired size rounds to same power of 2 as actual size. */ ! nbytes = (n + sizeof *p + EXTRA + 7) & ~7; /* If ok, use the same block, just marking its size as changed. */ if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) { ! #ifdef RCHECK ! register char *m = mem + tocopy; *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; ! p-> mh_nbytes = n; m = mem + n; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; - #else /* not RCHECK */ - p -> mh_size = n; - #endif /* not RCHECK */ return mem; } if (n < tocopy) tocopy = n; - { - register char *new; ! if ((new = malloc (n)) == 0) ! return 0; ! FASTCOPY (mem, new, tocopy); ! free (mem); ! return new; ! } } char * memalign (alignment, size) ! unsigned int alignment, size; { register char *ptr; register char *aligned; ! register struct mhead *p; ptr = malloc (size + alignment); --- 695,762 ---- realloc (mem, n) char *mem; ! register size_t n; { ! register union mhead *p; ! register u_int32_t tocopy; register unsigned int nbytes; register int nunits; + register char *m; ! #ifdef MALLOC_STATS ! _mstats.nrealloc++; ! #endif ! ! if (n == 0) ! { ! free (mem); ! return (NULL); ! } ! if ((p = (union mhead *) mem) == 0) return malloc (n); p--; ! nunits = p->mh_index; ! ASSERT (p->mh_alloc == ISALLOC); ! ASSERT (p->mh_magic2 == MAGIC2); ! ! m = mem + (tocopy = p->mh_nbytes); ! ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); ! ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1); /* See if desired size rounds to same power of 2 as actual size. */ ! nbytes = (n + sizeof *p + MSLOP + 7) & ~7; /* If ok, use the same block, just marking its size as changed. */ if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) { ! m = mem + tocopy; *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; ! p->mh_nbytes = n; m = mem + n; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; return mem; } + #ifdef MALLOC_STATS + _mstats.nrcopy++; + #endif + if (n < tocopy) tocopy = n; ! if ((m = malloc (n)) == 0) ! return 0; ! FASTCOPY (mem, m, tocopy); ! free (mem); ! return m; } char * memalign (alignment, size) ! unsigned int alignment; ! size_t size; { register char *ptr; register char *aligned; ! register union mhead *p; ptr = malloc (size + alignment); *************** *** 645,651 **** /* Store a suitable indication of how to free the block, so that free can find the true beginning of it. */ ! p = (struct mhead *) aligned - 1; ! p -> mh_size = aligned - ptr; ! p -> mh_alloc = ISMEMALIGN; return aligned; } --- 772,778 ---- /* Store a suitable indication of how to free the block, so that free can find the true beginning of it. */ ! p = (union mhead *) aligned - 1; ! p->mh_nbytes = aligned - ptr; ! p->mh_alloc = ISMEMALIGN; return aligned; } *************** *** 689,721 **** #endif /* !NO_CALLOC */ ! #ifdef MSTATS ! /* Return statistics describing allocation of blocks of size 2**n. */ ! struct mstats_value ! { ! int blocksize; ! int nfree; ! int nused; ! }; ! ! struct mstats_value ! malloc_stats (size) int size; { ! struct mstats_value v; ! register int i; ! register struct mhead *p; v.nfree = 0; ! if (size < 0 || size >= 30) { v.blocksize = 0; ! v.nused = 0; return v; } v.blocksize = 1 << (size + 3); ! v.nused = nmalloc[size]; for (p = nextf[size]; p; p = CHAIN (p)) --- 816,841 ---- #endif /* !NO_CALLOC */ ! #ifdef MALLOC_STATS ! struct bucket_stats ! malloc_bucket_stats (size) int size; { ! struct bucket_stats v; ! register union mhead *p; v.nfree = 0; ! if (size < 0 || size >= NBUCKETS) { v.blocksize = 0; ! v.nused = v.nmal = 0; return v; } v.blocksize = 1 << (size + 3); ! v.nused = _mstats.nmalloc[size]; ! v.nmal = _mstats.tmalloc[size]; ! v.nmorecore = _mstats.nmorecore[size]; for (p = nextf[size]; p; p = CHAIN (p)) *************** *** 724,759 **** return v; } - #endif /* MSTATS */ - - /* - * This function returns the total number of bytes that the process - * will be allowed to allocate via the sbrk(2) system call. On - * BSD systems this is the total space allocatable to stack and - * data. On USG systems this is the data space only. - */ ! #if !defined (HAVE_RESOURCE) ! extern long ulimit (); ! static void ! get_lim_data () ! { ! lim_data = ulimit (3, 0); ! lim_data -= (long) data_space_start; } ! #else /* HAVE_RESOURCE */ ! static void ! get_lim_data () { ! struct rlimit XXrlimit; ! getrlimit (RLIMIT_DATA, &XXrlimit); ! #ifdef RLIM_INFINITY ! lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */ ! #else ! lim_data = XXrlimit.rlim_cur; /* soft limit */ ! #endif } ! ! #endif /* HAVE_RESOURCE */ --- 844,894 ---- return v; } ! /* Return a copy of _MSTATS, with two additional fields filled in: ! BYTESFREE is the total number of bytes on free lists. BYTESUSED ! is the total number of bytes in use. These two fields are fairly ! expensive to compute, so we do it only when asked to. */ ! struct _malstats ! malloc_stats () ! { ! struct _malstats result; ! struct bucket_stats v; ! register int i; ! result = _mstats; ! result.bytesused = result.bytesfree = 0; ! for (i = 0; i < NBUCKETS; i++) ! { ! v = malloc_bucket_stats (i); ! result.bytesfree += v.nfree * v.blocksize; ! result.bytesused += v.nused * v.blocksize; ! } ! return (result); } ! void ! print_malloc_stats (s) ! char *s; { ! register int i; ! int totused, totfree; ! struct bucket_stats v; ! fprintf (stderr, "Memory allocation statistics: %s\n\tsize\tfree\tin use\ttotal\tmorecore\n", s ? s : ""); ! for (i = totused = totfree = 0; i < NBUCKETS; i++) ! { ! v = malloc_bucket_stats (i); ! fprintf (stderr, "%12lu\t%4d\t%6d\t%5d\t%8d\n", v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore); ! totfree += v.nfree * v.blocksize; ! totused += v.nused * v.blocksize; ! } ! fprintf (stderr, "\nTotal bytes in use: %d, total bytes free: %d\n", ! totused, totfree); ! fprintf (stderr, "Total mallocs: %d, total frees: %d, total reallocs: %d (%d copies)\n", ! _mstats.nmal, _mstats.nfre, _mstats.nrealloc, _mstats.nrcopy); ! fprintf (stderr, "Total sbrks: %d, total bytes via sbrk: %d\n", ! _mstats.nsbrk, _mstats.tsbrk); ! fprintf (stderr, "Total blocks split: %d, total block coalesces: %d\n", ! _mstats.nbsplit, _mstats.nbcoalesce); } ! #endif /* MALLOC_STATS */ diff -Nrc2 bash-2.01.1/lib/malloc/ogmalloc.c bash-2.02/lib/malloc/ogmalloc.c *** bash-2.01.1/lib/malloc/ogmalloc.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/malloc/ogmalloc.c Tue Apr 23 14:06:03 1996 *************** *** 0 **** --- 1,1579 ---- + /* DO NOT EDIT THIS FILE -- it is automagically generated. -*- C -*- */ + + #define _MALLOC_INTERNAL + + /* The malloc headers and source files from the C library follow here. */ + + /* Declarations for `malloc' and friends. + Copyright 1990, 91, 92, 93, 95, 96 Free Software Foundation, Inc. + Written May 1989 by Mike Haertel. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., 675 Mass Ave, + Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + + #ifndef _MALLOC_H + + #define _MALLOC_H 1 + + #ifdef _MALLOC_INTERNAL + + #ifdef HAVE_CONFIG_H + #include + #endif + + #if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG) + #include + #else + #ifndef memset + #define memset(s, zero, n) bzero ((s), (n)) + #endif + #ifndef memcpy + #define memcpy(d, s, n) bcopy ((s), (d), (n)) + #endif + #endif + + #if defined (__GNU_LIBRARY__) || (defined (__STDC__) && __STDC__) + #include + #else + #ifndef CHAR_BIT + #define CHAR_BIT 8 + #endif + #endif + + #ifdef HAVE_UNISTD_H + #include + #endif + + #endif /* _MALLOC_INTERNAL. */ + + + #ifdef __cplusplus + extern "C" + { + #endif + + #if defined (__cplusplus) || (defined (__STDC__) && __STDC__) + #undef __P + #define __P(args) args + #undef __ptr_t + #define __ptr_t void * + #else /* Not C++ or ANSI C. */ + #undef __P + #define __P(args) () + #undef const + #define const + #undef __ptr_t + #define __ptr_t char * + #endif /* C++ or ANSI C. */ + + #if defined (__STDC__) && __STDC__ + #include + #define __malloc_size_t size_t + #define __malloc_ptrdiff_t ptrdiff_t + #else + #define __malloc_size_t unsigned int + #define __malloc_ptrdiff_t int + #endif + + #ifndef NULL + #define NULL 0 + #endif + + + /* Allocate SIZE bytes of memory. */ + extern __ptr_t malloc __P ((__malloc_size_t __size)); + /* Re-allocate the previously allocated block + in __ptr_t, making the new block SIZE bytes long. */ + extern __ptr_t realloc __P ((__ptr_t __ptr, __malloc_size_t __size)); + /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ + extern __ptr_t calloc __P ((__malloc_size_t __nmemb, __malloc_size_t __size)); + /* Free a block allocated by `malloc', `realloc' or `calloc'. */ + extern void free __P ((__ptr_t __ptr)); + + /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ + #if ! (defined (_MALLOC_INTERNAL) && __DJGPP__ - 0 == 1) /* Avoid conflict. */ + extern __ptr_t memalign __P ((__malloc_size_t __alignment, + __malloc_size_t __size)); + #endif + + /* Allocate SIZE bytes on a page boundary. */ + #if ! (defined (_MALLOC_INTERNAL) && defined (emacs)) /* Avoid conflict. */ + extern __ptr_t valloc __P ((__malloc_size_t __size)); + #endif + + + #ifdef _MALLOC_INTERNAL + + /* The allocator divides the heap into blocks of fixed size; large + requests receive one or more whole blocks, and small requests + receive a fragment of a block. Fragment sizes are powers of two, + and all fragments of a block are the same size. When all the + fragments in a block have been freed, the block itself is freed. */ + #define INT_BIT (CHAR_BIT * sizeof(int)) + #define BLOCKLOG (INT_BIT > 16 ? 12 : 9) + #define BLOCKSIZE (1 << BLOCKLOG) + #define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE) + + /* Determine the amount of memory spanned by the initial heap table + (not an absolute limit). */ + #define HEAP (INT_BIT > 16 ? 4194304 : 65536) + + /* Number of contiguous free blocks allowed to build up at the end of + memory before they will be returned to the system. */ + #define FINAL_FREE_BLOCKS 8 + + /* Data structure giving per-block information. */ + typedef union + { + /* Heap information for a busy block. */ + struct + { + /* Zero for a large (multiblock) object, or positive giving the + logarithm to the base two of the fragment size. */ + int type; + union + { + struct + { + __malloc_size_t nfree; /* Free frags in a fragmented block. */ + __malloc_size_t first; /* First free fragment of the block. */ + } frag; + /* For a large object, in its first block, this has the number + of blocks in the object. In the other blocks, this has a + negative number which says how far back the first block is. */ + __malloc_ptrdiff_t size; + } info; + } busy; + /* Heap information for a free block + (that may be the first of a free cluster). */ + struct + { + __malloc_size_t size; /* Size (in blocks) of a free cluster. */ + __malloc_size_t next; /* Index of next free cluster. */ + __malloc_size_t prev; /* Index of previous free cluster. */ + } free; + } malloc_info; + + /* Pointer to first block of the heap. */ + extern char *_heapbase; + + /* Table indexed by block number giving per-block information. */ + extern malloc_info *_heapinfo; + + /* Address to block number and vice versa. */ + #define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) + #define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase)) + + /* Current search index for the heap table. */ + extern __malloc_size_t _heapindex; + + /* Limit of valid info table indices. */ + extern __malloc_size_t _heaplimit; + + /* Doubly linked lists of free fragments. */ + struct list + { + struct list *next; + struct list *prev; + }; + + /* Free list headers for each fragment size. */ + extern struct list _fraghead[]; + + /* List of blocks allocated with `memalign' (or `valloc'). */ + struct alignlist + { + struct alignlist *next; + __ptr_t aligned; /* The address that memaligned returned. */ + __ptr_t exact; /* The address that malloc returned. */ + }; + extern struct alignlist *_aligned_blocks; + + /* Instrumentation. */ + extern __malloc_size_t _chunks_used; + extern __malloc_size_t _bytes_used; + extern __malloc_size_t _chunks_free; + extern __malloc_size_t _bytes_free; + + /* Internal versions of `malloc', `realloc', and `free' + used when these functions need to call each other. + They are the same but don't call the hooks. */ + extern __ptr_t _malloc_internal __P ((__malloc_size_t __size)); + extern __ptr_t _realloc_internal __P ((__ptr_t __ptr, __malloc_size_t __size)); + extern void _free_internal __P ((__ptr_t __ptr)); + + #endif /* _MALLOC_INTERNAL. */ + + /* Given an address in the middle of a malloc'd object, + return the address of the beginning of the object. */ + extern __ptr_t malloc_find_object_address __P ((__ptr_t __ptr)); + + /* Underlying allocation function; successive calls should + return contiguous pieces of memory. */ + extern __ptr_t (*__morecore) __P ((__malloc_ptrdiff_t __size)); + + /* Default value of `__morecore'. */ + extern __ptr_t __default_morecore __P ((__malloc_ptrdiff_t __size)); + + /* If not NULL, this function is called after each time + `__morecore' is called to increase the data size. */ + extern void (*__after_morecore_hook) __P ((void)); + + /* Number of extra blocks to get each time we ask for more core. + This reduces the frequency of calling `(*__morecore)'. */ + extern __malloc_size_t __malloc_extra_blocks; + + /* Nonzero if `malloc' has been called and done its initialization. */ + extern int __malloc_initialized; + /* Function called to initialize malloc data structures. */ + extern int __malloc_initialize __P ((void)); + + /* Hooks for debugging versions. */ + extern void (*__malloc_initialize_hook) __P ((void)); + extern void (*__free_hook) __P ((__ptr_t __ptr)); + extern __ptr_t (*__malloc_hook) __P ((__malloc_size_t __size)); + extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size)); + extern __ptr_t (*__memalign_hook) __P ((__malloc_size_t __size, + __malloc_size_t __alignment)); + + /* Return values for `mprobe': these are the kinds of inconsistencies that + `mcheck' enables detection of. */ + enum mcheck_status + { + MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */ + MCHECK_OK, /* Block is fine. */ + MCHECK_FREE, /* Block freed twice. */ + MCHECK_HEAD, /* Memory before the block was clobbered. */ + MCHECK_TAIL /* Memory after the block was clobbered. */ + }; + + /* Activate a standard collection of debugging hooks. This must be called + before `malloc' is ever called. ABORTFUNC is called with an error code + (see enum above) when an inconsistency is detected. If ABORTFUNC is + null, the standard function prints on stderr and then calls `abort'. */ + extern int mcheck __P ((void (*__abortfunc) __P ((enum mcheck_status)))); + + /* Check for aberrations in a particular malloc'd block. You must have + called `mcheck' already. These are the same checks that `mcheck' does + when you free or reallocate a block. */ + extern enum mcheck_status mprobe __P ((__ptr_t __ptr)); + + /* Activate a standard collection of tracing hooks. */ + extern void mtrace __P ((void)); + extern void muntrace __P ((void)); + + /* Statistics available to the user. */ + struct mstats + { + __malloc_size_t bytes_total; /* Total size of the heap. */ + __malloc_size_t chunks_used; /* Chunks allocated by the user. */ + __malloc_size_t bytes_used; /* Byte total of user-allocated chunks. */ + __malloc_size_t chunks_free; /* Chunks in the free list. */ + __malloc_size_t bytes_free; /* Byte total of chunks in the free list. */ + }; + + /* Pick up the current statistics. */ + extern struct mstats mstats __P ((void)); + + /* Call WARNFUN with a warning message when memory usage is high. */ + extern void memory_warnings __P ((__ptr_t __start, + void (*__warnfun) __P ((const char *)))); + + + /* Relocating allocator. */ + + /* Allocate SIZE bytes, and store the address in *HANDLEPTR. */ + extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size)); + + /* Free the storage allocated in HANDLEPTR. */ + extern void r_alloc_free __P ((__ptr_t *__handleptr)); + + /* Adjust the block at HANDLEPTR to be SIZE bytes long. */ + extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size)); + + + #ifdef __cplusplus + } + #endif + + #endif /* malloc.h */ + /* Memory allocator `malloc'. + Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Written May 1989 by Mike Haertel. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., 675 Mass Ave, + Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + + #ifndef _MALLOC_INTERNAL + #define _MALLOC_INTERNAL + #include + #endif + #include + + /* How to really get more memory. */ + __ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore; + + /* Debugging hook for `malloc'. */ + __ptr_t (*__malloc_hook) __P ((__malloc_size_t __size)); + + /* Pointer to the base of the first block. */ + char *_heapbase; + + /* Block information table. Allocated with align/__free (not malloc/free). */ + malloc_info *_heapinfo; + + /* Number of info entries. */ + static __malloc_size_t heapsize; + + /* Search index in the info table. */ + __malloc_size_t _heapindex; + + /* Limit of valid info table indices. */ + __malloc_size_t _heaplimit; + + /* Free lists for each fragment size. */ + struct list _fraghead[BLOCKLOG]; + + /* Instrumentation. */ + __malloc_size_t _chunks_used; + __malloc_size_t _bytes_used; + __malloc_size_t _chunks_free; + __malloc_size_t _bytes_free; + + /* Are you experienced? */ + int __malloc_initialized; + + __malloc_size_t __malloc_extra_blocks; + + void (*__malloc_initialize_hook) __P ((void)); + void (*__after_morecore_hook) __P ((void)); + + + /* Aligned allocation. */ + static __ptr_t align __P ((__malloc_size_t)); + static __ptr_t + align (size) + __malloc_size_t size; + { + __ptr_t result; + unsigned long int adj; + + result = (*__morecore) (size); + adj = (unsigned long int) ((unsigned long int) ((char *) result - + (char *) NULL)) % BLOCKSIZE; + if (adj != 0) + { + __ptr_t new; + adj = BLOCKSIZE - adj; + new = (*__morecore) (adj); + result = (char *) result + adj; + } + + if (__after_morecore_hook) + (*__after_morecore_hook) (); + + return result; + } + + /* Get SIZE bytes, if we can get them starting at END. + Return the address of the space we got. + If we cannot get space at END, fail and return -1. */ + static __ptr_t get_contiguous_space __P ((__malloc_ptrdiff_t, __ptr_t)); + static __ptr_t + get_contiguous_space (size, position) + __malloc_ptrdiff_t size; + __ptr_t position; + { + __ptr_t before; + __ptr_t after; + + before = (*__morecore) (0); + /* If we can tell in advance that the break is at the wrong place, + fail now. */ + if (before != position) + return 0; + + /* Allocate SIZE bytes and get the address of them. */ + after = (*__morecore) (size); + if (!after) + return 0; + + /* It was not contiguous--reject it. */ + if (after != position) + { + (*__morecore) (- size); + return 0; + } + + return after; + } + + + /* This is called when `_heapinfo' and `heapsize' have just + been set to describe a new info table. Set up the table + to describe itself and account for it in the statistics. */ + static void register_heapinfo __P ((void)); + #ifdef __GNUC__ + __inline__ + #endif + static void + register_heapinfo () + { + __malloc_size_t block, blocks; + + block = BLOCK (_heapinfo); + blocks = BLOCKIFY (heapsize * sizeof (malloc_info)); + + /* Account for the _heapinfo block itself in the statistics. */ + _bytes_used += blocks * BLOCKSIZE; + ++_chunks_used; + + /* Describe the heapinfo block itself in the heapinfo. */ + _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.info.size = blocks; + /* Leave back-pointers for malloc_find_address. */ + while (--blocks > 0) + _heapinfo[block + blocks].busy.info.size = -blocks; + } + + /* Set everything up and remember that we have. */ + int + __malloc_initialize () + { + if (__malloc_initialized) + return 0; + + if (__malloc_initialize_hook) + (*__malloc_initialize_hook) (); + + heapsize = HEAP / BLOCKSIZE; + _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info)); + if (_heapinfo == NULL) + return 0; + memset (_heapinfo, 0, heapsize * sizeof (malloc_info)); + _heapinfo[0].free.size = 0; + _heapinfo[0].free.next = _heapinfo[0].free.prev = 0; + _heapindex = 0; + _heapbase = (char *) _heapinfo; + _heaplimit = BLOCK (_heapbase + heapsize * sizeof (malloc_info)); + + register_heapinfo (); + + __malloc_initialized = 1; + return 1; + } + + static int morecore_recursing; + + /* Get neatly aligned memory, initializing or + growing the heap info table as necessary. */ + static __ptr_t morecore __P ((__malloc_size_t)); + static __ptr_t + morecore (size) + __malloc_size_t size; + { + __ptr_t result; + malloc_info *newinfo, *oldinfo; + __malloc_size_t newsize; + + if (morecore_recursing) + /* Avoid recursion. The caller will know how to handle a null return. */ + return NULL; + + result = align (size); + if (result == NULL) + return NULL; + + /* Check if we need to grow the info table. */ + if ((__malloc_size_t) BLOCK ((char *) result + size) > heapsize) + { + /* Calculate the new _heapinfo table size. We do not account for the + added blocks in the table itself, as we hope to place them in + existing free space, which is already covered by part of the + existing table. */ + newsize = heapsize; + do + newsize *= 2; + while ((__malloc_size_t) BLOCK ((char *) result + size) > newsize); + + /* We must not reuse existing core for the new info table when called + from realloc in the case of growing a large block, because the + block being grown is momentarily marked as free. In this case + _heaplimit is zero so we know not to reuse space for internal + allocation. */ + if (_heaplimit != 0) + { + /* First try to allocate the new info table in core we already + have, in the usual way using realloc. If realloc cannot + extend it in place or relocate it to existing sufficient core, + we will get called again, and the code above will notice the + `morecore_recursing' flag and return null. */ + int save = errno; /* Don't want to clobber errno with ENOMEM. */ + morecore_recursing = 1; + newinfo = (malloc_info *) _realloc_internal + (_heapinfo, newsize * sizeof (malloc_info)); + morecore_recursing = 0; + if (newinfo == NULL) + errno = save; + else + { + /* We found some space in core, and realloc has put the old + table's blocks on the free list. Now zero the new part + of the table and install the new table location. */ + memset (&newinfo[heapsize], 0, + (newsize - heapsize) * sizeof (malloc_info)); + _heapinfo = newinfo; + heapsize = newsize; + goto got_heap; + } + } + + /* Allocate new space for the malloc info table. */ + while (1) + { + newinfo = (malloc_info *) align (newsize * sizeof (malloc_info)); + + /* Did it fail? */ + if (newinfo == NULL) + { + (*__morecore) (-size); + return NULL; + } + + /* Is it big enough to record status for its own space? + If so, we win. */ + if ((__malloc_size_t) BLOCK ((char *) newinfo + + newsize * sizeof (malloc_info)) + < newsize) + break; + + /* Must try again. First give back most of what we just got. */ + (*__morecore) (- newsize * sizeof (malloc_info)); + newsize *= 2; + } + + /* Copy the old table to the beginning of the new, + and zero the rest of the new table. */ + memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info)); + memset (&newinfo[heapsize], 0, + (newsize - heapsize) * sizeof (malloc_info)); + oldinfo = _heapinfo; + _heapinfo = newinfo; + heapsize = newsize; + + register_heapinfo (); + + /* Reset _heaplimit so _free_internal never decides + it can relocate or resize the info table. */ + _heaplimit = 0; + _free_internal (oldinfo); + + /* The new heap limit includes the new table just allocated. */ + _heaplimit = BLOCK ((char *) newinfo + heapsize * sizeof (malloc_info)); + return result; + } + + got_heap: + _heaplimit = BLOCK ((char *) result + size); + return result; + } + + /* Allocate memory from the heap. */ + __ptr_t + _malloc_internal (size) + __malloc_size_t size; + { + __ptr_t result; + __malloc_size_t block, blocks, lastblocks, start; + register __malloc_size_t i; + struct list *next; + + /* ANSI C allows `malloc (0)' to either return NULL, or to return a + valid address you can realloc and free (though not dereference). + + It turns out that some extant code (sunrpc, at least Ultrix's version) + expects `malloc (0)' to return non-NULL and breaks otherwise. + Be compatible. */ + + #if 0 + if (size == 0) + return NULL; + #endif + + if (size < sizeof (struct list)) + size = sizeof (struct list); + + #ifdef SUNOS_LOCALTIME_BUG + if (size < 16) + size = 16; + #endif + + /* Determine the allocation policy based on the request size. */ + if (size <= BLOCKSIZE / 2) + { + /* Small allocation to receive a fragment of a block. + Determine the logarithm to base two of the fragment size. */ + register __malloc_size_t log = 1; + --size; + while ((size /= 2) != 0) + ++log; + + /* Look in the fragment lists for a + free fragment of the desired size. */ + next = _fraghead[log].next; + if (next != NULL) + { + /* There are free fragments of this size. + Pop a fragment out of the fragment list and return it. + Update the block's nfree and first counters. */ + result = (__ptr_t) next; + next->prev->next = next->next; + if (next->next != NULL) + next->next->prev = next->prev; + block = BLOCK (result); + if (--_heapinfo[block].busy.info.frag.nfree != 0) + _heapinfo[block].busy.info.frag.first = (unsigned long int) + ((unsigned long int) ((char *) next->next - (char *) NULL) + % BLOCKSIZE) >> log; + + /* Update the statistics. */ + ++_chunks_used; + _bytes_used += 1 << log; + --_chunks_free; + _bytes_free -= 1 << log; + } + else + { + /* No free fragments of the desired size, so get a new block + and break it into fragments, returning the first. */ + result = malloc (BLOCKSIZE); + if (result == NULL) + return NULL; + + /* Link all fragments but the first into the free list. */ + next = (struct list *) ((char *) result + (1 << log)); + next->next = NULL; + next->prev = &_fraghead[log]; + _fraghead[log].next = next; + + for (i = 2; i < (__malloc_size_t) (BLOCKSIZE >> log); ++i) + { + next = (struct list *) ((char *) result + (i << log)); + next->next = _fraghead[log].next; + next->prev = &_fraghead[log]; + next->prev->next = next; + next->next->prev = next; + } + + /* Initialize the nfree and first counters for this block. */ + block = BLOCK (result); + _heapinfo[block].busy.type = log; + _heapinfo[block].busy.info.frag.nfree = i - 1; + _heapinfo[block].busy.info.frag.first = i - 1; + + _chunks_free += (BLOCKSIZE >> log) - 1; + _bytes_free += BLOCKSIZE - (1 << log); + _bytes_used -= BLOCKSIZE - (1 << log); + } + } + else + { + /* Large allocation to receive one or more blocks. + Search the free list in a circle starting at the last place visited. + If we loop completely around without finding a large enough + space we will have to get more memory from the system. */ + blocks = BLOCKIFY (size); + start = block = _heapindex; + while (_heapinfo[block].free.size < blocks) + { + block = _heapinfo[block].free.next; + if (block == start) + { + /* Need to get more from the system. Get a little extra. */ + __malloc_size_t wantblocks = blocks + __malloc_extra_blocks; + block = _heapinfo[0].free.prev; + lastblocks = _heapinfo[block].free.size; + /* Check to see if the new core will be contiguous with the + final free block; if so we don't need to get as much. */ + if (_heaplimit != 0 && block + lastblocks == _heaplimit && + /* We can't do this if we will have to make the heap info + table bigger to accomodate the new space. */ + block + wantblocks <= heapsize && + get_contiguous_space ((wantblocks - lastblocks) * BLOCKSIZE, + ADDRESS (block + lastblocks))) + { + /* We got it contiguously. Which block we are extending + (the `final free block' referred to above) might have + changed, if it got combined with a freed info table. */ + block = _heapinfo[0].free.prev; + _heapinfo[block].free.size += (wantblocks - lastblocks); + _bytes_free += (wantblocks - lastblocks) * BLOCKSIZE; + _heaplimit += wantblocks - lastblocks; + continue; + } + result = morecore (wantblocks * BLOCKSIZE); + if (result == NULL) + return NULL; + block = BLOCK (result); + /* Put the new block at the end of the free list. */ + _heapinfo[block].free.size = wantblocks; + _heapinfo[block].free.prev = _heapinfo[0].free.prev; + _heapinfo[block].free.next = 0; + _heapinfo[0].free.prev = block; + _heapinfo[_heapinfo[block].free.prev].free.next = block; + ++_chunks_free; + /* Now loop to use some of that block for this allocation. */ + } + } + + /* At this point we have found a suitable free list entry. + Figure out how to remove what we need from the list. */ + result = ADDRESS (block); + if (_heapinfo[block].free.size > blocks) + { + /* The block we found has a bit left over, + so relink the tail end back into the free list. */ + _heapinfo[block + blocks].free.size + = _heapinfo[block].free.size - blocks; + _heapinfo[block + blocks].free.next + = _heapinfo[block].free.next; + _heapinfo[block + blocks].free.prev + = _heapinfo[block].free.prev; + _heapinfo[_heapinfo[block].free.prev].free.next + = _heapinfo[_heapinfo[block].free.next].free.prev + = _heapindex = block + blocks; + } + else + { + /* The block exactly matches our requirements, + so just remove it from the list. */ + _heapinfo[_heapinfo[block].free.next].free.prev + = _heapinfo[block].free.prev; + _heapinfo[_heapinfo[block].free.prev].free.next + = _heapindex = _heapinfo[block].free.next; + --_chunks_free; + } + + _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.info.size = blocks; + ++_chunks_used; + _bytes_used += blocks * BLOCKSIZE; + _bytes_free -= blocks * BLOCKSIZE; + + /* Mark all the blocks of the object just allocated except for the + first with a negative number so you can find the first block by + adding that adjustment. */ + while (--blocks > 0) + _heapinfo[block + blocks].busy.info.size = -blocks; + } + + return result; + } + + __ptr_t + malloc (size) + __malloc_size_t size; + { + if (!__malloc_initialized && !__malloc_initialize ()) + return NULL; + + return (__malloc_hook != NULL ? *__malloc_hook : _malloc_internal) (size); + } + + #ifndef _LIBC + + /* On some ANSI C systems, some libc functions call _malloc, _free + and _realloc. Make them use the GNU functions. */ + + __ptr_t + _malloc (size) + __malloc_size_t size; + { + return malloc (size); + } + + void + _free (ptr) + __ptr_t ptr; + { + free (ptr); + } + + __ptr_t + _realloc (ptr, size) + __ptr_t ptr; + __malloc_size_t size; + { + return realloc (ptr, size); + } + + #endif + /* Free a block of memory allocated by `malloc'. + Copyright 1990, 1991, 1992, 1994, 1995 Free Software Foundation, Inc. + Written May 1989 by Mike Haertel. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., 675 Mass Ave, + Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + + #ifndef _MALLOC_INTERNAL + #define _MALLOC_INTERNAL + #include + #endif + + + /* Cope with systems lacking `memmove'. */ + #ifndef memmove + #if (defined (MEMMOVE_MISSING) || \ + !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG)) + #ifdef emacs + #undef __malloc_safe_bcopy + #define __malloc_safe_bcopy safe_bcopy + #endif + /* This function is defined in realloc.c. */ + extern void __malloc_safe_bcopy __P ((__ptr_t, __ptr_t, __malloc_size_t)); + #define memmove(to, from, size) __malloc_safe_bcopy ((from), (to), (size)) + #endif + #endif + + + /* Debugging hook for free. */ + void (*__free_hook) __P ((__ptr_t __ptr)); + + /* List of blocks allocated by memalign. */ + struct alignlist *_aligned_blocks = NULL; + + /* Return memory to the heap. + Like `free' but don't call a __free_hook if there is one. */ + void + _free_internal (ptr) + __ptr_t ptr; + { + int type; + __malloc_size_t block, blocks; + register __malloc_size_t i; + struct list *prev, *next; + __ptr_t curbrk; + const __malloc_size_t lesscore_threshold + /* Threshold of free space at which we will return some to the system. */ + = FINAL_FREE_BLOCKS + 2 * __malloc_extra_blocks; + + register struct alignlist *l; + + if (ptr == NULL) + return; + + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == ptr) + { + l->aligned = NULL; /* Mark the slot in the list as free. */ + ptr = l->exact; + break; + } + + block = BLOCK (ptr); + + type = _heapinfo[block].busy.type; + switch (type) + { + case 0: + /* Get as many statistics as early as we can. */ + --_chunks_used; + _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; + _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE; + + /* Find the free cluster previous to this one in the free list. + Start searching at the last block referenced; this may benefit + programs with locality of allocation. */ + i = _heapindex; + if (i > block) + while (i > block) + i = _heapinfo[i].free.prev; + else + { + do + i = _heapinfo[i].free.next; + while (i > 0 && i < block); + i = _heapinfo[i].free.prev; + } + + /* Determine how to link this block into the free list. */ + if (block == i + _heapinfo[i].free.size) + { + /* Coalesce this block with its predecessor. */ + _heapinfo[i].free.size += _heapinfo[block].busy.info.size; + block = i; + } + else + { + /* Really link this block back into the free list. */ + _heapinfo[block].free.size = _heapinfo[block].busy.info.size; + _heapinfo[block].free.next = _heapinfo[i].free.next; + _heapinfo[block].free.prev = i; + _heapinfo[i].free.next = block; + _heapinfo[_heapinfo[block].free.next].free.prev = block; + ++_chunks_free; + } + + /* Now that the block is linked in, see if we can coalesce it + with its successor (by deleting its successor from the list + and adding in its size). */ + if (block + _heapinfo[block].free.size == _heapinfo[block].free.next) + { + _heapinfo[block].free.size + += _heapinfo[_heapinfo[block].free.next].free.size; + _heapinfo[block].free.next + = _heapinfo[_heapinfo[block].free.next].free.next; + _heapinfo[_heapinfo[block].free.next].free.prev = block; + --_chunks_free; + } + + /* How many trailing free blocks are there now? */ + blocks = _heapinfo[block].free.size; + + /* Where is the current end of accessible core? */ + curbrk = (*__morecore) (0); + + if (_heaplimit != 0 && curbrk == ADDRESS (_heaplimit)) + { + /* The end of the malloc heap is at the end of accessible core. + It's possible that moving _heapinfo will allow us to + return some space to the system. */ + + __malloc_size_t info_block = BLOCK (_heapinfo); + __malloc_size_t info_blocks = _heapinfo[info_block].busy.info.size; + __malloc_size_t prev_block = _heapinfo[block].free.prev; + __malloc_size_t prev_blocks = _heapinfo[prev_block].free.size; + __malloc_size_t next_block = _heapinfo[block].free.next; + __malloc_size_t next_blocks = _heapinfo[next_block].free.size; + + if (/* Win if this block being freed is last in core, the info table + is just before it, the previous free block is just before the + info table, and the two free blocks together form a useful + amount to return to the system. */ + (block + blocks == _heaplimit && + info_block + info_blocks == block && + prev_block != 0 && prev_block + prev_blocks == info_block && + blocks + prev_blocks >= lesscore_threshold) || + /* Nope, not the case. We can also win if this block being + freed is just before the info table, and the table extends + to the end of core or is followed only by a free block, + and the total free space is worth returning to the system. */ + (block + blocks == info_block && + ((info_block + info_blocks == _heaplimit && + blocks >= lesscore_threshold) || + (info_block + info_blocks == next_block && + next_block + next_blocks == _heaplimit && + blocks + next_blocks >= lesscore_threshold))) + ) + { + malloc_info *newinfo; + __malloc_size_t oldlimit = _heaplimit; + + /* Free the old info table, clearing _heaplimit to avoid + recursion into this code. We don't want to return the + table's blocks to the system before we have copied them to + the new location. */ + _heaplimit = 0; + _free_internal (_heapinfo); + _heaplimit = oldlimit; + + /* Tell malloc to search from the beginning of the heap for + free blocks, so it doesn't reuse the ones just freed. */ + _heapindex = 0; + + /* Allocate new space for the info table and move its data. */ + newinfo = (malloc_info *) _malloc_internal (info_blocks + * BLOCKSIZE); + memmove (newinfo, _heapinfo, info_blocks * BLOCKSIZE); + _heapinfo = newinfo; + + /* We should now have coalesced the free block with the + blocks freed from the old info table. Examine the entire + trailing free block to decide below whether to return some + to the system. */ + block = _heapinfo[0].free.prev; + blocks = _heapinfo[block].free.size; + } + + /* Now see if we can return stuff to the system. */ + if (block + blocks == _heaplimit && blocks >= lesscore_threshold) + { + register __malloc_size_t bytes = blocks * BLOCKSIZE; + _heaplimit -= blocks; + (*__morecore) (-bytes); + _heapinfo[_heapinfo[block].free.prev].free.next + = _heapinfo[block].free.next; + _heapinfo[_heapinfo[block].free.next].free.prev + = _heapinfo[block].free.prev; + block = _heapinfo[block].free.prev; + --_chunks_free; + _bytes_free -= bytes; + } + } + + /* Set the next search to begin at this block. */ + _heapindex = block; + break; + + default: + /* Do some of the statistics. */ + --_chunks_used; + _bytes_used -= 1 << type; + ++_chunks_free; + _bytes_free += 1 << type; + + /* Get the address of the first free fragment in this block. */ + prev = (struct list *) ((char *) ADDRESS (block) + + (_heapinfo[block].busy.info.frag.first << type)); + + if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1) + { + /* If all fragments of this block are free, remove them + from the fragment list and free the whole block. */ + next = prev; + for (i = 1; i < (__malloc_size_t) (BLOCKSIZE >> type); ++i) + next = next->next; + prev->prev->next = next; + if (next != NULL) + next->prev = prev->prev; + _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.info.size = 1; + + /* Keep the statistics accurate. */ + ++_chunks_used; + _bytes_used += BLOCKSIZE; + _chunks_free -= BLOCKSIZE >> type; + _bytes_free -= BLOCKSIZE; + + free (ADDRESS (block)); + } + else if (_heapinfo[block].busy.info.frag.nfree != 0) + { + /* If some fragments of this block are free, link this + fragment into the fragment list after the first free + fragment of this block. */ + next = (struct list *) ptr; + next->next = prev->next; + next->prev = prev; + prev->next = next; + if (next->next != NULL) + next->next->prev = next; + ++_heapinfo[block].busy.info.frag.nfree; + } + else + { + /* No fragments of this block are free, so link this + fragment into the fragment list and announce that + it is the first free fragment of this block. */ + prev = (struct list *) ptr; + _heapinfo[block].busy.info.frag.nfree = 1; + _heapinfo[block].busy.info.frag.first = (unsigned long int) + ((unsigned long int) ((char *) ptr - (char *) NULL) + % BLOCKSIZE >> type); + prev->next = _fraghead[type].next; + prev->prev = &_fraghead[type]; + prev->prev->next = prev; + if (prev->next != NULL) + prev->next->prev = prev; + } + break; + } + } + + /* Return memory to the heap. */ + void + free (ptr) + __ptr_t ptr; + { + if (__free_hook != NULL) + (*__free_hook) (ptr); + else + _free_internal (ptr); + } + + /* Define the `cfree' alias for `free'. */ + #ifdef weak_alias + weak_alias (free, cfree) + #else + void + cfree (ptr) + __ptr_t ptr; + { + free (ptr); + } + #endif + /* Change the size of a block allocated by `malloc'. + Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Written May 1989 by Mike Haertel. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., 675 Mass Ave, + Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + + #ifndef _MALLOC_INTERNAL + #define _MALLOC_INTERNAL + #include + #endif + + + + /* Cope with systems lacking `memmove'. */ + #if (defined (MEMMOVE_MISSING) || \ + !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG)) + + #ifdef emacs + #undef __malloc_safe_bcopy + #define __malloc_safe_bcopy safe_bcopy + #else + + /* Snarfed directly from Emacs src/dispnew.c: + XXX Should use system bcopy if it handles overlap. */ + + /* Like bcopy except never gets confused by overlap. */ + + void + __malloc_safe_bcopy (afrom, ato, size) + __ptr_t afrom; + __ptr_t ato; + __malloc_size_t size; + { + char *from = afrom, *to = ato; + + if (size <= 0 || from == to) + return; + + /* If the source and destination don't overlap, then bcopy can + handle it. If they do overlap, but the destination is lower in + memory than the source, we'll assume bcopy can handle that. */ + if (to < from || from + size <= to) + bcopy (from, to, size); + + /* Otherwise, we'll copy from the end. */ + else + { + register char *endf = from + size; + register char *endt = to + size; + + /* If TO - FROM is large, then we should break the copy into + nonoverlapping chunks of TO - FROM bytes each. However, if + TO - FROM is small, then the bcopy function call overhead + makes this not worth it. The crossover point could be about + anywhere. Since I don't think the obvious copy loop is too + bad, I'm trying to err in its favor. */ + if (to - from < 64) + { + do + *--endt = *--endf; + while (endf != from); + } + else + { + for (;;) + { + endt -= (to - from); + endf -= (to - from); + + if (endt < to) + break; + + bcopy (endf, endt, to - from); + } + + /* If SIZE wasn't a multiple of TO - FROM, there will be a + little left over. The amount left over is + (endt + (to - from)) - to, which is endt - from. */ + bcopy (from, to, endt - from); + } + } + } + #endif /* emacs */ + + #ifndef memmove + extern void __malloc_safe_bcopy __P ((__ptr_t, __ptr_t, __malloc_size_t)); + #define memmove(to, from, size) __malloc_safe_bcopy ((from), (to), (size)) + #endif + + #endif + + + #define min(A, B) ((A) < (B) ? (A) : (B)) + + /* Debugging hook for realloc. */ + __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size)); + + /* Resize the given region to the new size, returning a pointer + to the (possibly moved) region. This is optimized for speed; + some benchmarks seem to indicate that greater compactness is + achieved by unconditionally allocating and copying to a + new region. This module has incestuous knowledge of the + internals of both free and malloc. */ + __ptr_t + _realloc_internal (ptr, size) + __ptr_t ptr; + __malloc_size_t size; + { + __ptr_t result; + int type; + __malloc_size_t block, blocks, oldlimit; + + if (size == 0) + { + _free_internal (ptr); + return _malloc_internal (0); + } + else if (ptr == NULL) + return _malloc_internal (size); + + block = BLOCK (ptr); + + type = _heapinfo[block].busy.type; + switch (type) + { + case 0: + /* Maybe reallocate a large block to a small fragment. */ + if (size <= BLOCKSIZE / 2) + { + result = _malloc_internal (size); + if (result != NULL) + { + memcpy (result, ptr, size); + _free_internal (ptr); + return result; + } + } + + /* The new size is a large allocation as well; + see if we can hold it in place. */ + blocks = BLOCKIFY (size); + if (blocks < _heapinfo[block].busy.info.size) + { + /* The new size is smaller; return + excess memory to the free list. */ + _heapinfo[block + blocks].busy.type = 0; + _heapinfo[block + blocks].busy.info.size + = _heapinfo[block].busy.info.size - blocks; + _heapinfo[block].busy.info.size = blocks; + /* We have just created a new chunk by splitting a chunk in two. + Now we will free this chunk; increment the statistics counter + so it doesn't become wrong when _free_internal decrements it. */ + ++_chunks_used; + _free_internal (ADDRESS (block + blocks)); + result = ptr; + } + else if (blocks == _heapinfo[block].busy.info.size) + /* No size change necessary. */ + result = ptr; + else + { + /* Won't fit, so allocate a new region that will. + Free the old region first in case there is sufficient + adjacent free space to grow without moving. */ + blocks = _heapinfo[block].busy.info.size; + /* Prevent free from actually returning memory to the system. */ + oldlimit = _heaplimit; + _heaplimit = 0; + _free_internal (ptr); + result = _malloc_internal (size); + if (_heaplimit == 0) + _heaplimit = oldlimit; + if (result == NULL) + { + /* Now we're really in trouble. We have to unfree + the thing we just freed. Unfortunately it might + have been coalesced with its neighbors. */ + if (_heapindex == block) + (void) _malloc_internal (blocks * BLOCKSIZE); + else + { + __ptr_t previous + = _malloc_internal ((block - _heapindex) * BLOCKSIZE); + (void) _malloc_internal (blocks * BLOCKSIZE); + _free_internal (previous); + } + return NULL; + } + if (ptr != result) + memmove (result, ptr, blocks * BLOCKSIZE); + } + break; + + default: + /* Old size is a fragment; type is logarithm + to base two of the fragment size. */ + if (size > (__malloc_size_t) (1 << (type - 1)) && + size <= (__malloc_size_t) (1 << type)) + /* The new size is the same kind of fragment. */ + result = ptr; + else + { + /* The new size is different; allocate a new space, + and copy the lesser of the new size and the old. */ + result = _malloc_internal (size); + if (result == NULL) + return NULL; + memcpy (result, ptr, min (size, (__malloc_size_t) 1 << type)); + _free_internal (ptr); + } + break; + } + + return result; + } + + __ptr_t + realloc (ptr, size) + __ptr_t ptr; + __malloc_size_t size; + { + if (!__malloc_initialized && !__malloc_initialize ()) + return NULL; + + return (__realloc_hook != NULL ? *__realloc_hook : _realloc_internal) + (ptr, size); + } + /* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., 675 Mass Ave, + Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + + #ifndef _MALLOC_INTERNAL + #define _MALLOC_INTERNAL + #include + #endif + + /* Allocate an array of NMEMB elements each SIZE bytes long. + The entire array is initialized to zeros. */ + __ptr_t + calloc (nmemb, size) + register __malloc_size_t nmemb; + register __malloc_size_t size; + { + register __ptr_t result = malloc (nmemb * size); + + if (result != NULL) + (void) memset (result, 0, nmemb * size); + + return result; + } + /* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library 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. + + The GNU C Library 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 the GNU C Library; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + #ifndef _MALLOC_INTERNAL + #define _MALLOC_INTERNAL + #include + #endif + + #ifndef __GNU_LIBRARY__ + #define __sbrk sbrk + #endif + + #ifdef __GNU_LIBRARY__ + /* It is best not to declare this and cast its result on foreign operating + systems with potentially hostile include files. */ + + #include + extern __ptr_t __sbrk __P ((ptrdiff_t increment)); + #endif + + #ifndef NULL + #define NULL 0 + #endif + + /* Allocate INCREMENT more bytes of data space, + and return the start of data space, or NULL on errors. + If INCREMENT is negative, shrink data space. */ + __ptr_t + __default_morecore (increment) + __malloc_ptrdiff_t increment; + { + __ptr_t result = (__ptr_t) __sbrk (increment); + if (result == (__ptr_t) -1) + return NULL; + return result; + } + /* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., 675 Mass Ave, + Cambridge, MA 02139, USA. */ + + #ifndef _MALLOC_INTERNAL + #define _MALLOC_INTERNAL + #include + #endif + + #if __DJGPP__ - 0 == 1 + + /* There is some problem with memalign in DJGPP v1 and we are supposed + to omit it. Noone told me why, they just told me to do it. */ + + #else + + __ptr_t (*__memalign_hook) __P ((size_t __size, size_t __alignment)); + + __ptr_t + memalign (alignment, size) + __malloc_size_t alignment; + __malloc_size_t size; + { + __ptr_t result; + unsigned long int adj, lastadj; + + if (__memalign_hook) + return (*__memalign_hook) (alignment, size); + + /* Allocate a block with enough extra space to pad the block with up to + (ALIGNMENT - 1) bytes if necessary. */ + result = malloc (size + alignment - 1); + if (result == NULL) + return NULL; + + /* Figure out how much we will need to pad this particular block + to achieve the required alignment. */ + adj = (unsigned long int) ((char *) result - (char *) NULL) % alignment; + + do + { + /* Reallocate the block with only as much excess as it needs. */ + free (result); + result = malloc (adj + size); + if (result == NULL) /* Impossible unless interrupted. */ + return NULL; + + lastadj = adj; + adj = (unsigned long int) ((char *) result - (char *) NULL) % alignment; + /* It's conceivable we might have been so unlucky as to get a + different block with weaker alignment. If so, this block is too + short to contain SIZE after alignment correction. So we must + try again and get another block, slightly larger. */ + } while (adj > lastadj); + + if (adj != 0) + { + /* Record this block in the list of aligned blocks, so that `free' + can identify the pointer it is passed, which will be in the middle + of an allocated block. */ + + struct alignlist *l; + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == NULL) + /* This slot is free. Use it. */ + break; + if (l == NULL) + { + l = (struct alignlist *) malloc (sizeof (struct alignlist)); + if (l == NULL) + { + free (result); + return NULL; + } + l->next = _aligned_blocks; + _aligned_blocks = l; + } + l->exact = result; + result = l->aligned = (char *) result + alignment - adj; + } + + return result; + } + + #endif /* Not DJGPP v1 */ diff -Nrc2 bash-2.01.1/lib/malloc/omalloc.c bash-2.02/lib/malloc/omalloc.c *** bash-2.01.1/lib/malloc/omalloc.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/malloc/omalloc.c Fri Apr 25 11:47:20 1997 *************** *** 0 **** --- 1,759 ---- + /* dynamic memory allocation for GNU. */ + + /* Copyright (C) 1985, 1987 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! */ + + /* + * @(#)nmalloc.c 1 (Caltech) 2/21/82 + * + * U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs + * + * Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD. + * + * This is a very fast storage allocator. It allocates blocks of a small + * number of different sizes, and keeps free lists of each size. Blocks + * that don't exactly fit are passed up to the next larger size. In this + * implementation, the available sizes are (2^n)-4 (or -16) bytes long. + * This is designed for use in a program that uses vast quantities of + * memory, but bombs when it runs out. To make it a little better, it + * warns the user when he starts to get near the end. + * + * June 84, ACT: modified rcheck code to check the range given to malloc, + * rather than the range determined by the 2-power used. + * + * Jan 85, RMS: calls malloc_warning to issue warning on nearly full. + * No longer Emacs-specific; can serve as all-purpose malloc for GNU. + * You should call malloc_init to reinitialize after loading dumped Emacs. + * Call malloc_stats to get info on memory stats if MSTATS turned on. + * realloc knows how to return same block given, just changing its size, + * if the power of 2 is correct. + */ + + /* + * nextf[i] is the pointer to the next free block of size 2^(i+3). The + * smallest allocatable block is 8 bytes. The overhead information will + * go in the first int of the block, and the returned pointer will point + * to the second. + * + #ifdef MSTATS + * nmalloc[i] is the difference between the number of mallocs and frees + * for a given block size. + #endif + */ + + /* Define this to have free() write 0xcf into memory as it's freed, to + uncover callers that refer to freed memory. */ + /* SCO 3.2v4 getcwd and possibly other libc routines fail with MEMSCRAMBLE */ + #if !defined (NO_MEMSCRAMBLE) + # define MEMSCRAMBLE + #endif + + #if defined (emacs) || defined (HAVE_CONFIG_H) + # include + #endif /* emacs */ + + #if defined (HAVE_UNISTD_H) + # include + #endif + + /* Determine which kind of system this is. */ + #if defined (SHELL) + # include "bashtypes.h" + #else + # include + #endif + #include + + /* Define getpagesize () if the system does not. */ + #ifndef HAVE_GETPAGESIZE + # include "getpagesize.h" + #endif + + #if defined (HAVE_RESOURCE) + # include + # include + #endif /* HAVE_RESOURCE */ + + /* Check for the needed symbols. If they aren't present, this + system's isn't very useful to us. */ + #if !defined (RLIMIT_DATA) + # undef HAVE_RESOURCE + #endif + + #if __GNUC__ > 1 + # define FASTCOPY(s, d, n) __builtin_memcpy (d, s, n) + #else /* !__GNUC__ */ + # if !defined (HAVE_BCOPY) + # if !defined (HAVE_MEMMOVE) + # define FASTCOPY(s, d, n) memcpy (d, s, n) + # else + # define FASTCOPY(s, d, n) memmove (d, s, n) + # endif /* !HAVE_MEMMOVE */ + # else /* HAVE_BCOPY */ + # define FASTCOPY(s, d, n) bcopy (s, d, n) + # endif /* HAVE_BCOPY */ + #endif /* !__GNUC__ */ + + #if !defined (NULL) + # define NULL 0 + #endif + + #define start_of_data() &etext + + #define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */ + #define ISFREE ((char) 0x54) /* magic byte that implies free block */ + /* this is for error checking only */ + #define ISMEMALIGN ((char) 0xd6) /* Stored before the value returned by + memalign, with the rest of the word + being the distance to the true + beginning of the block. */ + extern char etext; + + #if !defined (SBRK_DECLARED) + extern char *sbrk (); + #endif /* !SBRK_DECLARED */ + + /* These two are for user programs to look at, when they are interested. */ + unsigned int malloc_sbrk_used; /* amount of data space used now */ + unsigned int malloc_sbrk_unused; /* amount more we can have */ + + /* start of data space; can be changed by calling init_malloc */ + static char *data_space_start; + + static void get_lim_data (); + + #ifdef MSTATS + static int nmalloc[30]; + static int nmal, nfre; + #endif /* MSTATS */ + + /* If range checking is not turned on, all we have is a flag indicating + whether memory is allocated, an index in nextf[], and a size field; to + realloc() memory we copy either size bytes or 1<<(index+3) bytes depending + on whether the former can hold the exact size (given the value of + 'index'). If range checking is on, we always need to know how much space + is allocated, so the 'size' field is never used. */ + + struct mhead { + char mh_alloc; /* ISALLOC or ISFREE */ + char mh_index; /* index in nextf[] */ + /* Remainder are valid only when block is allocated */ + unsigned short mh_size; /* size, if < 0x10000 */ + #ifdef RCHECK + unsigned int mh_nbytes; /* number of bytes allocated */ + int mh_magic4; /* should be == MAGIC4 */ + #endif /* RCHECK */ + }; + + /* Access free-list pointer of a block. + It is stored at block + 4. + This is not a field in the mhead structure + because we want sizeof (struct mhead) + to describe the overhead for when the block is in use, + and we do not want the free-list pointer to count in that. */ + + #define CHAIN(a) \ + (*(struct mhead **) (sizeof (char *) + (char *) (a))) + + #ifdef RCHECK + # include + # if !defined (botch) + # define botch(x) abort () + # else + extern void botch(); + # endif /* botch */ + + # if !defined (__STRING) + # if defined (__STDC__) + # define __STRING(x) #x + # else + # define __STRING(x) "x" + # endif + # endif + + /* To implement range checking, we write magic values in at the beginning + and end of each allocated block, and make sure they are undisturbed + whenever a free or a realloc occurs. */ + + /* Written in each of the 4 bytes following the block's real space */ + # define MAGIC1 0x55 + /* Written in the 4 bytes before the block's real space */ + # define MAGIC4 0x55555555 + # define ASSERT(p) if (!(p)) botch(__STRING(p)); else + # define EXTRA 4 /* 4 bytes extra for MAGIC1s */ + #else /* !RCHECK */ + # define ASSERT(p) + # define EXTRA 0 + #endif /* RCHECK */ + + /* nextf[i] is free list of blocks of size 2**(i + 3) */ + + static struct mhead *nextf[30]; + + /* busy[i] is nonzero while allocation of block size i is in progress. */ + + static char busy[30]; + + /* Number of bytes of writable memory we can expect to be able to get */ + static unsigned int lim_data; + + /* Level number of warnings already issued. + 0 -- no warnings issued. + 1 -- 75% warning already issued. + 2 -- 85% warning already issued. + */ + static int warnlevel; + + /* Function to call to issue a warning; + 0 means don't issue them. */ + static void (*warnfunction) (); + + /* nonzero once initial bunch of free blocks made */ + static int gotpool; + + char *_malloc_base; + + static void getpool (); + + /* Cause reinitialization based on job parameters; + also declare where the end of pure storage is. */ + void + malloc_init (start, warnfun) + char *start; + void (*warnfun) (); + { + if (start) + data_space_start = start; + lim_data = 0; + warnlevel = 0; + warnfunction = warnfun; + } + + /* Return the maximum size to which MEM can be realloc'd + without actually requiring copying. */ + + int + malloc_usable_size (mem) + char *mem; + { + int blocksize = 8 << (((struct mhead *) mem) - 1) -> mh_index; + + return blocksize - sizeof (struct mhead) - EXTRA; + } + + static void + morecore (nu) /* ask system for more memory */ + register int nu; /* size index to get more of */ + { + register char *cp; + register int nblks; + register unsigned int siz; + + /* Block all signals in case we are executed from a signal handler. */ + #if defined (HAVE_BSD_SIGNALS) + int oldmask; + oldmask = sigsetmask (-1); + #else + # if defined (HAVE_POSIX_SIGNALS) + sigset_t set, oset; + sigfillset (&set); + sigemptyset (&oset); + sigprocmask (SIG_BLOCK, &set, &oset); + # endif /* HAVE_POSIX_SIGNALS */ + #endif /* HAVE_BSD_SIGNALS */ + + if (!data_space_start) + { + data_space_start = start_of_data (); + } + + if (lim_data == 0) + get_lim_data (); + + /* On initial startup, get two blocks of each size up to 1k bytes */ + if (!gotpool) + { getpool (); getpool (); gotpool = 1; } + + /* Find current end of memory and issue warning if getting near max */ + + cp = sbrk (0); + siz = cp - data_space_start; + malloc_sbrk_used = siz; + malloc_sbrk_unused = lim_data - siz; + + if (warnfunction) + switch (warnlevel) + { + case 0: + if (siz > (lim_data / 4) * 3) + { + warnlevel++; + (*warnfunction) ("Warning: past 75% of memory limit"); + } + break; + case 1: + if (siz > (lim_data / 20) * 17) + { + warnlevel++; + (*warnfunction) ("Warning: past 85% of memory limit"); + } + break; + case 2: + if (siz > (lim_data / 20) * 19) + { + warnlevel++; + (*warnfunction) ("Warning: past 95% of memory limit"); + } + break; + } + + if ((int) cp & 0x3ff) /* land on 1K boundaries */ + sbrk (1024 - ((int) cp & 0x3ff)); + + /* Take at least 2k, and figure out how many blocks of the desired size + we're about to get */ + nblks = 1; + if ((siz = nu) < 8) + nblks = 1 << ((siz = 8) - nu); + + if ((cp = sbrk (1 << (siz + 3))) == (char *) -1) + return; /* no more room! */ + + if ((int) cp & 7) + { /* shouldn't happen, but just in case */ + cp = (char *) (((int) cp + 8) & ~7); + nblks--; + } + + /* save new header and link the nblks blocks together */ + nextf[nu] = (struct mhead *) cp; + siz = 1 << (nu + 3); + while (1) + { + ((struct mhead *) cp) -> mh_alloc = ISFREE; + ((struct mhead *) cp) -> mh_index = nu; + if (--nblks <= 0) break; + CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz); + cp += siz; + } + CHAIN ((struct mhead *) cp) = 0; + + #if defined (HAVE_BSD_SIGNALS) + sigsetmask (oldmask); + #else + # if defined (HAVE_POSIX_SIGNALS) + sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); + # endif + #endif /* HAVE_BSD_SIGNALS */ + } + + static void + getpool () + { + register int nu; + register char *cp = sbrk (0); + + if ((int) cp & 0x3ff) /* land on 1K boundaries */ + sbrk (1024 - ((int) cp & 0x3ff)); + + /* Record address of start of space allocated by malloc. */ + if (_malloc_base == 0) + _malloc_base = cp; + + /* Get 2k of storage */ + + cp = sbrk (04000); + if (cp == (char *) -1) + return; + + /* Divide it into an initial 8-word block + plus one block of size 2**nu for nu = 3 ... 10. */ + + CHAIN (cp) = nextf[0]; + nextf[0] = (struct mhead *) cp; + ((struct mhead *) cp) -> mh_alloc = ISFREE; + ((struct mhead *) cp) -> mh_index = 0; + cp += 8; + + for (nu = 0; nu < 7; nu++) + { + CHAIN (cp) = nextf[nu]; + nextf[nu] = (struct mhead *) cp; + ((struct mhead *) cp) -> mh_alloc = ISFREE; + ((struct mhead *) cp) -> mh_index = nu; + cp += 8 << nu; + } + } + + #if defined (MEMSCRAMBLE) || !defined (NO_CALLOC) + static char * + zmemset (s, c, n) + char *s; + int c; + register int n; + { + register char *sp; + + sp = s; + while (--n >= 0) + *sp++ = c; + return (s); + } + #endif /* MEMSCRAMBLE || !NO_CALLOC */ + + char * + malloc (n) /* get a block */ + unsigned int n; + { + register struct mhead *p; + register unsigned int nbytes; + register int nunits = 0; + + /* Figure out how many bytes are required, rounding up to the nearest + multiple of 4, then figure out which nextf[] area to use */ + nbytes = (n + sizeof *p + EXTRA + 3) & ~3; + { + register unsigned int shiftr = (nbytes - 1) >> 2; + + while (shiftr >>= 1) + nunits++; + } + + /* In case this is reentrant use of malloc from signal handler, + pick a block size that no other malloc level is currently + trying to allocate. That's the easiest harmless way not to + interfere with the other level of execution. */ + while (busy[nunits]) nunits++; + busy[nunits] = 1; + + /* If there are no blocks of the appropriate size, go get some */ + /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */ + if (nextf[nunits] == 0) + morecore (nunits); + + /* Get one block off the list, and set the new list head */ + if ((p = nextf[nunits]) == 0) + { + busy[nunits] = 0; + return 0; + } + nextf[nunits] = CHAIN (p); + busy[nunits] = 0; + + /* Check for free block clobbered */ + /* If not for this check, we would gobble a clobbered free chain ptr */ + /* and bomb out on the NEXT allocate of this size block */ + if (p -> mh_alloc != ISFREE || p -> mh_index != nunits) + #ifdef RCHECK + botch ("block on free list clobbered"); + #else /* not RCHECK */ + abort (); + #endif /* not RCHECK */ + + /* Fill in the info, and if range checking, set up the magic numbers */ + p -> mh_alloc = ISALLOC; + #ifdef RCHECK + p -> mh_nbytes = n; + p -> mh_magic4 = MAGIC4; + { + register char *m = (char *) (p + 1) + n; + + *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1; + } + #else /* not RCHECK */ + p -> mh_size = n; + #endif /* not RCHECK */ + #ifdef MEMSCRAMBLE + zmemset ((char *)(p + 1), 0xdf, n); /* scramble previous contents */ + #endif + #ifdef MSTATS + nmalloc[nunits]++; + nmal++; + #endif /* MSTATS */ + return (char *) (p + 1); + } + + void + free (mem) + char *mem; + { + register struct mhead *p; + { + register char *ap = mem; + + if (ap == 0) + return; + + p = (struct mhead *) ap - 1; + + if (p -> mh_alloc == ISMEMALIGN) + { + #ifdef RCHECK + ap -= p->mh_nbytes; + #else + ap -= p->mh_size; /* XXX */ + #endif + p = (struct mhead *) ap - 1; + } + + #ifndef RCHECK + if (p -> mh_alloc != ISALLOC) + abort (); + + #else /* RCHECK */ + if (p -> mh_alloc != ISALLOC) + { + if (p -> mh_alloc == ISFREE) + botch ("free: Called with already freed block argument\n"); + else + botch ("free: Called with unallocated block argument\n"); + } + + ASSERT (p -> mh_magic4 == MAGIC4); + ap += p -> mh_nbytes; + ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); + ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1); + #endif /* RCHECK */ + } + #ifdef MEMSCRAMBLE + { + register int n; + + #ifdef RCHECK + n = p->mh_nbytes; + #else /* not RCHECK */ + n = p->mh_size; + #endif /* not RCHECK */ + zmemset (mem, 0xcf, n); + } + #endif + { + register int nunits = p -> mh_index; + + ASSERT (nunits <= 29); + p -> mh_alloc = ISFREE; + + /* Protect against signal handlers calling malloc. */ + busy[nunits] = 1; + /* Put this block on the free list. */ + CHAIN (p) = nextf[nunits]; + nextf[nunits] = p; + busy[nunits] = 0; + + #ifdef MSTATS + nmalloc[nunits]--; + nfre++; + #endif /* MSTATS */ + } + } + + char * + realloc (mem, n) + char *mem; + register unsigned int n; + { + register struct mhead *p; + register unsigned int tocopy; + register unsigned int nbytes; + register int nunits; + + if ((p = (struct mhead *) mem) == 0) + return malloc (n); + p--; + nunits = p -> mh_index; + ASSERT (p -> mh_alloc == ISALLOC); + #ifdef RCHECK + ASSERT (p -> mh_magic4 == MAGIC4); + { + register char *m = mem + (tocopy = p -> mh_nbytes); + ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); + ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1); + } + #else /* not RCHECK */ + if (p -> mh_index >= 13) + tocopy = (1 << (p -> mh_index + 3)) - sizeof *p; + else + tocopy = p -> mh_size; + #endif /* not RCHECK */ + + /* See if desired size rounds to same power of 2 as actual size. */ + nbytes = (n + sizeof *p + EXTRA + 7) & ~7; + + /* If ok, use the same block, just marking its size as changed. */ + if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) + { + #ifdef RCHECK + register char *m = mem + tocopy; + *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; + p-> mh_nbytes = n; + m = mem + n; + *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; + #else /* not RCHECK */ + p -> mh_size = n; + #endif /* not RCHECK */ + return mem; + } + + if (n < tocopy) + tocopy = n; + { + register char *new; + + if ((new = malloc (n)) == 0) + return 0; + FASTCOPY (mem, new, tocopy); + free (mem); + return new; + } + } + + char * + memalign (alignment, size) + unsigned int alignment, size; + { + register char *ptr; + register char *aligned; + register struct mhead *p; + + ptr = malloc (size + alignment); + + if (ptr == 0) + return 0; + /* If entire block has the desired alignment, just accept it. */ + if (((int) ptr & (alignment - 1)) == 0) + return ptr; + /* Otherwise, get address of byte in the block that has that alignment. */ + aligned = (char *) (((int) ptr + alignment - 1) & -alignment); + + /* Store a suitable indication of how to free the block, + so that free can find the true beginning of it. */ + p = (struct mhead *) aligned - 1; + p -> mh_size = aligned - ptr; + p -> mh_alloc = ISMEMALIGN; + return aligned; + } + + #if !defined (HPUX) + /* This runs into trouble with getpagesize on HPUX, and Multimax machines. + Patching out seems cleaner than the ugly fix needed. */ + #if defined (__STDC__) + void * + #else + char * + #endif + valloc (size) + size_t size; + { + return memalign (getpagesize (), size); + } + #endif /* !HPUX */ + + #ifndef NO_CALLOC + char * + calloc (n, s) + size_t n, s; + { + size_t total; + char *result; + + total = n * s; + result = malloc (total); + if (result) + zmemset (result, 0, total); + return result; + } + + void + cfree (p) + char *p; + { + free (p); + } + #endif /* !NO_CALLOC */ + + #ifdef MSTATS + /* Return statistics describing allocation of blocks of size 2**n. */ + + struct mstats_value + { + int blocksize; + int nfree; + int nused; + }; + + struct mstats_value + malloc_stats (size) + int size; + { + struct mstats_value v; + register int i; + register struct mhead *p; + + v.nfree = 0; + + if (size < 0 || size >= 30) + { + v.blocksize = 0; + v.nused = 0; + return v; + } + + v.blocksize = 1 << (size + 3); + v.nused = nmalloc[size]; + + for (p = nextf[size]; p; p = CHAIN (p)) + v.nfree++; + + return v; + } + #endif /* MSTATS */ + + /* + * This function returns the total number of bytes that the process + * will be allowed to allocate via the sbrk(2) system call. On + * BSD systems this is the total space allocatable to stack and + * data. On USG systems this is the data space only. + */ + + #if !defined (HAVE_RESOURCE) + extern long ulimit (); + + static void + get_lim_data () + { + lim_data = ulimit (3, 0); + lim_data -= (long) data_space_start; + } + + #else /* HAVE_RESOURCE */ + static void + get_lim_data () + { + struct rlimit XXrlimit; + + getrlimit (RLIMIT_DATA, &XXrlimit); + #ifdef RLIM_INFINITY + lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */ + #else + lim_data = XXrlimit.rlim_cur; /* soft limit */ + #endif + } + + #endif /* HAVE_RESOURCE */ diff -Nrc2 bash-2.01.1/lib/readline/Makefile.in bash-2.02/lib/readline/Makefile.in *** bash-2.01.1/lib/readline/Makefile.in Tue Sep 16 13:10:21 1997 --- bash-2.02/lib/readline/Makefile.in Tue Sep 16 13:11:36 1997 *************** *** 191,195 **** search.o: readline.h keymaps.h chardefs.h tilde.h search.o: ansi_stdlib.h history.h ! shell.o: ${BUILD_DIR}/config.h signals.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h signals.o: readline.h keymaps.h chardefs.h tilde.h --- 191,195 ---- search.o: readline.h keymaps.h chardefs.h tilde.h search.o: ansi_stdlib.h history.h ! shell.o: ${BUILD_DIR}/config.h ansi_stdlib.h signals.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h signals.o: readline.h keymaps.h chardefs.h tilde.h diff -Nrc2 bash-2.01.1/lib/readline/bind.c bash-2.02/lib/readline/bind.c *** bash-2.01.1/lib/readline/bind.c Wed Apr 2 12:11:45 1997 --- bash-2.02/lib/readline/bind.c Mon Oct 6 13:45:33 1997 *************** *** 71,74 **** --- 71,76 ---- extern int _rl_complete_show_all; extern int _rl_complete_mark_directories; + extern int _rl_print_completions_horizontally; + extern int _rl_completion_case_fold; extern int _rl_enable_keypad; #if defined (PAREN_MATCHING) *************** *** 106,109 **** --- 108,112 ---- void rl_set_keymap_from_edit_mode (); + static int _rl_read_init_file (); static int glean_key_from_name (); static int substring_member_of_array (); *************** *** 199,202 **** --- 202,234 ---- } + /* Unbind all keys bound to FUNCTION in MAP. */ + int + rl_unbind_function_in_map (func, map) + Function *func; + Keymap map; + { + register int i; + + for (i = 0; i < KEYMAP_SIZE; i++) + { + if (map[i].type == ISFUNC && map[i].function == func) + map[i].function = (Function *)NULL; + } + } + + int + rl_unbind_command_in_map (command, map) + char *command; + Keymap map; + { + Function *func; + register int i; + + func = rl_named_function (command); + if (func == 0) + return 0; + return (rl_unbind_function_in_map (func, map)); + } + /* Bind the key sequence represented by the string KEYSEQ to FUNCTION. This makes new keymaps as necessary. The initial *************** *** 314,318 **** int *len; { ! register int i, c, l; for (i = l = 0; c = seq[i]; i++) --- 346,350 ---- int *len; { ! register int i, c, l, temp; for (i = l = 0; c = seq[i]; i++) *************** *** 325,329 **** break; ! if (((c == 'C' || c == 'M') && seq[i + 1] == '-') || (c == 'e')) { /* Handle special case of backwards define. */ --- 357,362 ---- break; ! /* Handle \C- and \M- prefixes. */ ! if ((c == 'C' || c == 'M') && seq[i + 1] == '-') { /* Handle special case of backwards define. */ *************** *** 333,361 **** i += 5; array[l++] = CTRL (_rl_to_upper (seq[i])); ! if (!seq[i]) i--; - continue; } ! ! switch (c) { - case 'M': i++; array[l++] = ESC; /* XXX */ ! break; ! ! case 'C': i += 2; /* Special hack for C-?... */ array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i])); - break; - - case 'e': - array[l++] = ESC; } - continue; } } array[l++] = c; } --- 366,446 ---- i += 5; array[l++] = CTRL (_rl_to_upper (seq[i])); ! if (seq[i] == '\0') i--; } ! else if (c == 'M') { i++; array[l++] = ESC; /* XXX */ ! } ! else if (c == 'C') ! { i += 2; /* Special hack for C-?... */ array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i])); } continue; + } + + /* Translate other backslash-escaped characters. These are the + same escape sequences that bash's `echo' and `printf' builtins + handle, with the addition of \d -> RUBOUT. A backslash + preceding a character that is not special is stripped. */ + switch (c) + { + case 'a': + array[l++] = '\007'; + break; + case 'b': + array[l++] = '\b'; + break; + case 'd': + array[l++] = RUBOUT; /* readline-specific */ + break; + case 'e': + array[l++] = ESC; + break; + case 'f': + array[l++] = '\f'; + break; + case 'n': + array[l++] = NEWLINE; + break; + case 'r': + array[l++] = RETURN; + break; + case 't': + array[l++] = TAB; + break; + case 'v': + array[l++] = 0x0B; + break; + case '\\': + array[l++] = '\\'; + break; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + i++; + for (temp = 2, c -= '0'; ISOCTAL (seq[i]) && temp--; i++) + c = (c * 8) + OCTVALUE (seq[i]); + i--; /* auto-increment in for loop */ + array[l++] = c % (largest_char + 1); + break; + case 'x': + i++; + for (temp = 3, c = 0; isxdigit (seq[i]) && temp--; i++) + c = (c * 16) + HEXVALUE (seq[i]); + if (temp == 3) + c = 'x'; + i--; /* auto-increment in for loop */ + array[l++] = c % (largest_char + 1); + break; + default: /* backslashes before non-special chars just add the char */ + array[l++] = c; + break; /* the backslash is stripped */ } + continue; } + array[l++] = c; } *************** *** 542,547 **** --- 627,679 ---- /* The file we're currently reading key bindings from. */ static char *current_readline_init_file; + static int current_readline_init_include_level; static int current_readline_init_lineno; + /* Read FILENAME into a locally-allocated buffer and return the buffer. + The size of the buffer is returned in *SIZEP. Returns NULL if any + errors were encountered. */ + static char * + _rl_read_file (filename, sizep) + char *filename; + size_t *sizep; + { + struct stat finfo; + size_t file_size; + char *buffer; + int i, file; + + if ((stat (filename, &finfo) < 0) || (file = open (filename, O_RDONLY, 0666)) < 0) + return ((char *)NULL); + + 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) + { + if (file >= 0) + close (file); + #if defined (EFBIG) + errno = EFBIG; + #endif + return ((char *)NULL); + } + + /* Read the file into BUFFER. */ + buffer = (char *)xmalloc (file_size + 1); + i = read (file, buffer, file_size); + close (file); + + if (i < file_size) + { + free (buffer); + return ((char *)NULL); + } + + buffer[file_size] = '\0'; + if (sizep) + *sizep = file_size; + return (buffer); + } + /* Re-read the current keybindings file. */ int *************** *** 566,574 **** char *filename; { - register int i; - char *buffer, *openname, *line, *end; - struct stat finfo; - int file; - /* Default the filename. */ if (filename == 0) --- 698,701 ---- *************** *** 584,620 **** filename = DEFAULT_INPUTRC; ! current_readline_init_file = filename; ! openname = tilde_expand (filename); ! if ((stat (openname, &finfo) < 0) || ! (file = open (openname, O_RDONLY, 0666)) < 0) ! { ! free (openname); ! return (errno); ! } ! else ! free (openname); ! if (filename != last_readline_init_file) ! { ! if (last_readline_init_file) ! free (last_readline_init_file); last_readline_init_file = savestring (filename); } - /* Read the file into BUFFER. */ - buffer = (char *)xmalloc ((int)finfo.st_size + 1); - i = read (file, buffer, finfo.st_size); - close (file); - - if (i != finfo.st_size) - return (errno); - /* Loop over the lines in the file. Lines that start with `#' are comments; all other lines are commands for readline initialization. */ current_readline_init_lineno = 1; line = buffer; ! end = buffer + finfo.st_size; while (line < end) { --- 711,745 ---- filename = DEFAULT_INPUTRC; ! return (_rl_read_init_file (filename, 0)); ! } ! static int ! _rl_read_init_file (filename, include_level) ! char *filename; ! int include_level; ! { ! register int i; ! char *buffer, *openname, *line, *end; ! size_t file_size; ! current_readline_init_file = filename; ! current_readline_init_include_level = include_level; + openname = tilde_expand (filename); + buffer = _rl_read_file (openname, &file_size); + if (buffer == 0) + return (errno); + + if (include_level == 0 && filename != last_readline_init_file) + { + FREE (last_readline_init_file); last_readline_init_file = savestring (filename); } /* Loop over the lines in the file. Lines that start with `#' are comments; all other lines are commands for readline initialization. */ current_readline_init_lineno = 1; line = buffer; ! end = buffer + file_size; while (line < end) { *************** *** 640,643 **** --- 765,769 ---- current_readline_init_lineno++; } + free (buffer); return (0); *************** *** 698,702 **** args[i++] = '\0'; ! /* Handle "if term=foo" and "if mode=emacs" constructs. If this isn't term=foo, or mode=emacs, then check to see if the first word in ARGS is the same as the value stored in rl_readline_name. */ --- 824,828 ---- args[i++] = '\0'; ! /* Handle "$if term=foo" and "$if mode=emacs" constructs. If this isn't term=foo, or mode=emacs, then check to see if the first word in ARGS is the same as the value stored in rl_readline_name. */ *************** *** 750,756 **** register int i; ! if (!if_stack_depth) { ! /* Error message? */ return 0; } --- 876,882 ---- register int i; ! if (if_stack_depth == 0) { ! _rl_init_file_error ("$else found without matching $if"); return 0; } *************** *** 776,785 **** _rl_parsing_conditionalized_out = if_stack[--if_stack_depth]; else ! { ! /* *** What, no error message? *** */ ! } return 0; } /* Associate textual names with actual functions. */ static struct { --- 902,935 ---- _rl_parsing_conditionalized_out = if_stack[--if_stack_depth]; else ! _rl_init_file_error ("$endif without matching $if"); return 0; } + static int + parser_include (args) + char *args; + { + char *old_init_file, *e; + int old_line_number, old_include_level, r; + + if (_rl_parsing_conditionalized_out) + return (0); + + old_init_file = current_readline_init_file; + old_line_number = current_readline_init_lineno; + old_include_level = current_readline_init_include_level; + + e = strchr (args, '\n'); + if (e) + *e = '\0'; + r = _rl_read_init_file (args, old_include_level + 1); + + current_readline_init_file = old_init_file; + current_readline_init_lineno = old_line_number; + current_readline_init_include_level = old_include_level; + + return r; + } + /* Associate textual names with actual functions. */ static struct { *************** *** 790,793 **** --- 940,944 ---- { "endif", parser_endif }, { "else", parser_else }, + { "include", parser_include }, { (char *)0x0, (Function *)0x0 } }; *************** *** 826,830 **** } ! /* *** Should an error message be output? */ return (1); } --- 977,982 ---- } ! /* display an error message about the unknown parser directive */ ! _rl_init_file_error ("unknown parser directive"); return (1); } *************** *** 941,948 **** if (*funname == '\'' || *funname == '"') { ! int delimiter = string[i++]; ! int passc = 0; ! for (; c = string[i]; i++) { if (passc) --- 1093,1099 ---- if (*funname == '\'' || *funname == '"') { ! int delimiter = string[i++], passc; ! for (passc = 0; c = string[i]; i++) { if (passc) *************** *** 982,990 **** if (*string == '"') { ! char *seq = xmalloc (1 + strlen (string)); ! register int j, k = 0; ! int passc = 0; ! for (j = 1; string[j]; j++) { /* Allow backslash to quote characters, but leave them in place. --- 1133,1141 ---- if (*string == '"') { ! char *seq; ! register int j, k, passc; ! seq = xmalloc (1 + strlen (string)); ! for (j = 1, k = passc = 0; string[j]; j++) { /* Allow backslash to quote characters, but leave them in place. *************** *** 1079,1082 **** --- 1230,1234 ---- { "blink-matching-paren", &rl_blink_matching_paren }, #endif + { "completion-ignore-case", &_rl_completion_case_fold }, { "convert-meta", &_rl_convert_meta_chars_to_ascii }, { "disable-completion", &rl_inhibit_completion }, *************** *** 1089,1092 **** --- 1241,1245 ---- { "meta-flag", &_rl_meta_flag }, { "output-meta", &_rl_output_meta_chars }, + { "print-completions-horizontally", &_rl_print_completions_horizontally }, { "show-all-if-ambiguous", &_rl_complete_show_all }, #if defined (VISIBLE_STATS) *************** *** 1187,1190 **** --- 1340,1344 ---- } + /* For the time being, unknown variable names are simply ignored. */ return 0; } *************** *** 1339,1343 **** { char *keyname; ! int i, c; keyname = (char *)xmalloc (8); --- 1493,1497 ---- { char *keyname; ! int i, c, v; keyname = (char *)xmalloc (8); *************** *** 1384,1387 **** --- 1538,1553 ---- } + /* XXX experimental code. Turn the characters that are not ASCII or + ISO Latin 1 (128 - 159) into octal escape sequences (\200 - \237). + This changes C. */ + if (c >= 128 && c <= 159) + { + keyname[i++] = '\\'; + keyname[i++] = '2'; + c -= 128; + keyname[i++] = (c / 8) + '0'; + c = (c % 8) + '0'; + } + /* Now, if the character needs to be quoted with a backslash, do that. */ if (c == '\\' || c == '"') *************** *** 1693,1700 **** switch (_rl_bell_preference) { ! case NO_BELL: kname = "none"; break; ! case VISIBLE_BELL: kname = "visible"; break; case AUDIBLE_BELL: ! default: kname = "audible"; break; } if (print_readably) --- 1859,1869 ---- switch (_rl_bell_preference) { ! case NO_BELL: ! kname = "none"; break; ! case VISIBLE_BELL: ! kname = "visible"; break; case AUDIBLE_BELL: ! default: ! kname = "audible"; break; } if (print_readably) diff -Nrc2 bash-2.01.1/lib/readline/callback.c bash-2.02/lib/readline/callback.c *** bash-2.01.1/lib/readline/callback.c Mon Mar 3 16:04:40 1997 --- bash-2.02/lib/readline/callback.c Thu Feb 5 13:40:46 1998 *************** *** 56,63 **** rl_callback_handler_install() with the prompt and a function to call whenever a complete line of input is ready. The user must then ! call readline_char() every time some input is available, and ! readline_char() will call the user's function with the complete text ! read in at each end of line. The terminal is kept prepped and signals ! handled all the time, except during calls to the user's function. */ VFunction *rl_linefunc; /* user callback function */ --- 56,63 ---- rl_callback_handler_install() with the prompt and a function to call whenever a complete line of input is ready. The user must then ! call rl_callback_read_char() every time some input is available, and ! rl_callback_read_char() will call the user's function with the complete ! text read in at each end of line. The terminal is kept prepped and ! signals handled all the time, except during calls to the user's function. */ VFunction *rl_linefunc; /* user callback function */ diff -Nrc2 bash-2.01.1/lib/readline/chardefs.h bash-2.02/lib/readline/chardefs.h *** bash-2.01.1/lib/readline/chardefs.h Tue Sep 10 11:05:16 1996 --- bash-2.02/lib/readline/chardefs.h Thu Sep 25 10:59:00 1997 *************** *** 122,127 **** #undef ESC #endif - #define ESC CTRL('[') #endif /* _CHARDEFS_H_ */ --- 122,140 ---- #undef ESC #endif #define ESC CTRL('[') + + #ifndef ISOCTAL + #define ISOCTAL(c) ((c) >= '0' && (c) <= '7') + #endif + #define OCTVALUE(c) ((c) - '0') + + #ifndef isxdigit + # define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) + #endif + + #define HEXVALUE(c) \ + (((c) >= 'a' && (c) <= 'f') \ + ? (c)-'a'+10 \ + : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0') #endif /* _CHARDEFS_H_ */ diff -Nrc2 bash-2.01.1/lib/readline/complete.c bash-2.02/lib/readline/complete.c *** bash-2.01.1/lib/readline/complete.c Mon Aug 25 14:20:27 1997 --- bash-2.02/lib/readline/complete.c Thu Jan 29 15:19:46 1998 *************** *** 76,79 **** --- 76,80 ---- extern void _rl_abort_internal (); extern int _rl_qsort_string_compare (); + extern void _rl_replace_text (); extern Function *rl_last_func; *************** *** 89,99 **** char **completion_matches (); static char *rl_quote_filename (); static char *rl_strpbrk (); static char **remove_duplicate_matches (); - static void insert_text (); static void insert_match (); ! static void append_to_match (); static void insert_all_matches (); static void display_matches (); --- 90,106 ---- char **completion_matches (); + #if defined (VISIBLE_STATS) + # if !defined (X_OK) + # define X_OK 1 + # endif + static int stat_char (); + #endif + static char *rl_quote_filename (); static char *rl_strpbrk (); static char **remove_duplicate_matches (); static void insert_match (); ! static int append_to_match (); static void insert_all_matches (); static void display_matches (); *************** *** 102,112 **** extern char *xmalloc (), *xrealloc (); ! /* If non-zero, then this is the address of a function to call when ! completing on a directory name. The function is called with ! the address of a string (the current directory name) as an arg. */ ! Function *rl_directory_completion_hook = (Function *)NULL; ! /* Non-zero means readline completion functions perform tilde expansion. */ ! int rl_complete_with_tilde_expansion = 0; /* If non-zero, non-unique completions always show the list of matches. */ --- 109,119 ---- extern char *xmalloc (), *xrealloc (); ! /* **************************************************************** */ ! /* */ ! /* Completion matching, from readline's point of view. */ ! /* */ ! /* **************************************************************** */ ! /* Variables known only to the readline library. */ /* If non-zero, non-unique completions always show the list of matches. */ *************** *** 116,126 **** int _rl_complete_mark_directories = 1; ! #if defined (VISIBLE_STATS) ! # if !defined (X_OK) ! # define X_OK 1 ! # endif ! static int stat_char (); /* Non-zero means add an additional character to each filename displayed during listing completion iff rl_filename_completion_desired which helps --- 123,136 ---- int _rl_complete_mark_directories = 1; ! /* If non-zero, completions are printed horizontally in alphabetical order, ! like `ls -x'. */ ! int _rl_print_completions_horizontally; ! /* Non-zero means that case is not significant in filename completion. */ ! int _rl_completion_case_fold; ! ! /* Global variables available to applications using readline. */ + #if defined (VISIBLE_STATS) /* Non-zero means add an additional character to each filename displayed during listing completion iff rl_filename_completion_desired which helps *************** *** 129,140 **** #endif /* VISIBLE_STATS */ ! /* **************************************************************** */ ! /* */ ! /* Completion matching, from readline's point of view. */ ! /* */ ! /* **************************************************************** */ ! /* Local variable states what happened during the last completion attempt. */ ! static int completion_changed_buffer; /* Pointer to the generator function for completion_matches (). --- 139,149 ---- #endif /* VISIBLE_STATS */ ! /* If non-zero, then this is the address of a function to call when ! completing on a directory name. The function is called with ! the address of a string (the current directory name) as an arg. */ ! Function *rl_directory_completion_hook = (Function *)NULL; ! /* Non-zero means readline completion functions perform tilde expansion. */ ! int rl_complete_with_tilde_expansion = 0; /* Pointer to the generator function for completion_matches (). *************** *** 243,246 **** --- 252,266 ---- int rl_inhibit_completion; + /* Variables local to this file. */ + + /* Local variable states what happened during the last completion attempt. */ + static int completion_changed_buffer; + + /*************************************/ + /* */ + /* Bindable completion functions */ + /* */ + /*************************************/ + /* Complete the word at or before point. You have supplied the function that does the initial simple matching selection algorithm (see *************** *** 275,278 **** --- 295,325 ---- } + /************************************/ + /* */ + /* Completion utility functions */ + /* */ + /************************************/ + + /* Find the first occurrence in STRING1 of any character from STRING2. + Return a pointer to the character in STRING1. */ + static char * + rl_strpbrk (string1, string2) + char *string1, *string2; + { + register char *scan; + + for (; *string1; string1++) + { + for (scan = string2; *scan; scan++) + { + if (*string1 == *scan) + { + return (string1); + } + } + } + return ((char *)NULL); + } + /* The user must press "y" or "n". Non-zero return means "y" pressed. */ static int *************** *** 294,297 **** --- 341,401 ---- } + #if defined (VISIBLE_STATS) + /* Return the character which best describes FILENAME. + `@' for symbolic links + `/' for directories + `*' for executables + `=' for sockets + `|' for FIFOs + `%' for character special devices + `#' for block special devices */ + static int + stat_char (filename) + char *filename; + { + struct stat finfo; + int character, r; + + #if defined (HAVE_LSTAT) && defined (S_ISLNK) + r = lstat (filename, &finfo); + #else + r = stat (filename, &finfo); + #endif + + if (r == -1) + return (0); + + character = 0; + if (S_ISDIR (finfo.st_mode)) + character = '/'; + #if defined (S_ISCHR) + else if (S_ISCHR (finfo.st_mode)) + character = '%'; + #endif /* S_ISCHR */ + #if defined (S_ISBLK) + else if (S_ISBLK (finfo.st_mode)) + character = '#'; + #endif /* S_ISBLK */ + #if defined (S_ISLNK) + else if (S_ISLNK (finfo.st_mode)) + character = '@'; + #endif /* S_ISLNK */ + #if defined (S_ISSOCK) + else if (S_ISSOCK (finfo.st_mode)) + character = '='; + #endif /* S_ISSOCK */ + #if defined (S_ISFIFO) + else if (S_ISFIFO (finfo.st_mode)) + character = '|'; + #endif + else if (S_ISREG (finfo.st_mode)) + { + if (access (filename, X_OK) == 0) + character = '*'; + } + return (character); + } + #endif /* VISIBLE_STATS */ + /* Return the portion of PATHNAME that should be output when listing possible completions. If we are hacking filename completion, we *************** *** 310,320 **** /* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we are using it, check for and output a single character for `special' ! filenames. Return 1 if we printed an extension character, 0 if not. */ #define PUTX(c) \ if (CTRL_CHAR (c)) \ { \ putc ('^', rl_outstream); \ putc (UNCTRL (c), rl_outstream); \ } \ else if (c == RUBOUT) \ --- 414,426 ---- /* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we are using it, check for and output a single character for `special' ! filenames. Return the number of characters we output. */ #define PUTX(c) \ + do { \ if (CTRL_CHAR (c)) \ { \ putc ('^', rl_outstream); \ putc (UNCTRL (c), rl_outstream); \ + printed_len += 2; \ } \ else if (c == RUBOUT) \ *************** *** 322,328 **** putc ('^', rl_outstream); \ putc ('?', rl_outstream); \ } \ else \ ! putc (c, rl_outstream) static int --- 428,439 ---- putc ('^', rl_outstream); \ putc ('?', rl_outstream); \ + printed_len += 2; \ } \ else \ ! { \ ! putc (c, rl_outstream); \ ! printed_len++; \ ! } \ ! } while (0) static int *************** *** 330,333 **** --- 441,445 ---- char *to_print, *full_pathname; { + int printed_len = 0; #if !defined (VISIBLE_STATS) char *s; *************** *** 337,341 **** PUTX (*s); } - return 0; #else char *s, c, *new_full_pathname; --- 449,452 ---- *************** *** 382,391 **** free (s); if (extension_char) ! putc (extension_char, rl_outstream); ! return (extension_char != 0); } - else - return 0; #endif /* VISIBLE_STATS */ } --- 493,503 ---- free (s); if (extension_char) ! { ! putc (extension_char, rl_outstream); ! printed_len++; ! } } #endif /* VISIBLE_STATS */ + return printed_len; } *************** *** 637,640 **** --- 749,871 ---- } + /* Find the common prefix of the list of matches, and put it into + matches[0]. */ + static int + compute_lcd_of_matches (match_list, matches, text) + char **match_list; + int matches; + char *text; + { + register int i, c1, c2, si; + int low; /* Count of max-matched characters. */ + + /* If only one match, just use that. Otherwise, compare each + member of the list with the next, finding out where they + stop matching. */ + if (matches == 1) + { + match_list[0] = match_list[1]; + match_list[1] = (char *)NULL; + return 1; + } + + for (i = 1, low = 100000; i < matches; i++) + { + if (_rl_completion_case_fold) + { + for (si = 0; + (c1 = _rl_to_lower(match_list[i][si])) && + (c2 = _rl_to_lower(match_list[i + 1][si])); + si++) + if (c1 != c2) + break; + } + else + { + for (si = 0; + (c1 = match_list[i][si]) && + (c2 = match_list[i + 1][si]); + si++) + if (c1 != c2) + break; + } + + if (low > si) + low = si; + } + + /* If there were multiple matches, but none matched up to even the + first character, and the user typed something, use that as the + value of matches[0]. */ + if (low == 0 && text && *text) + { + match_list[0] = xmalloc (strlen (text) + 1); + strcpy (match_list[0], text); + } + else + { + match_list[0] = xmalloc (low + 1); + strncpy (match_list[0], match_list[1], low); + match_list[0][low] = '\0'; + } + + return matches; + } + + static int + postprocess_matches (text, matchesp, matching_filenames) + char *text; + char ***matchesp; + int matching_filenames; + { + char *t, **matches, **temp_matches; + int nmatch, i; + + matches = *matchesp; + + /* It seems to me that in all the cases we handle we would like + to ignore duplicate possiblilities. Scan for the text to + insert being identical to the other completions. */ + if (rl_ignore_completion_duplicates) + { + temp_matches = remove_duplicate_matches (matches); + free (matches); + matches = temp_matches; + } + + /* If we are matching filenames, then here is our chance to + do clever processing by re-examining the list. Call the + ignore function with the array as a parameter. It can + munge the array, deleting matches as it desires. */ + if (rl_ignore_some_completions_function && matching_filenames) + { + for (nmatch = 1; matches[nmatch]; nmatch++) + ; + (void)(*rl_ignore_some_completions_function) (matches); + if (matches == 0 || matches[0] == 0) + { + FREE (matches); + ding (); + *matchesp = (char **)0; + return 0; + } + else + { + /* If we removed some matches, recompute the common prefix. */ + for (i = 1; matches[i]; i++) + ; + if (i > 1 && i < nmatch) + { + t = matches[0]; + compute_lcd_of_matches (matches, i - 1, text); + FREE (t); + } + } + } + + *matchesp = matches; + return (1); + } + static void display_matches (matches) *************** *** 719,741 **** qsort (matches + 1, len, sizeof (char *), _rl_qsort_string_compare); - /* Print the sorted items, up-and-down alphabetically, like ls. */ crlf (); ! for (i = 1; i <= count; i++) { ! for (j = 0, l = i; j < limit; j++) { ! if (l > len || matches[l] == 0) ! break; ! else { ! temp = printable_part (matches[l]); ! printed_len = strlen (temp) + print_filename (temp, matches[l]); ! if (j + 1 < limit) for (k = 0; k < max - printed_len; k++) putc (' ', rl_outstream); } - l += count; } crlf (); --- 950,994 ---- qsort (matches + 1, len, sizeof (char *), _rl_qsort_string_compare); crlf (); ! if (_rl_print_completions_horizontally == 0) { ! /* Print the sorted items, up-and-down alphabetically, like ls. */ ! for (i = 1; i <= count; i++) { ! for (j = 0, l = i; j < limit; j++) { ! if (l > len || matches[l] == 0) ! break; ! else ! { ! temp = printable_part (matches[l]); ! printed_len = print_filename (temp, matches[l]); ! if (j + 1 < limit) ! for (k = 0; k < max - printed_len; k++) ! putc (' ', rl_outstream); ! } ! l += count; ! } ! crlf (); ! } ! } ! else ! { ! /* Print the sorted items, across alphabetically, like ls -x. */ ! for (i = 1; matches[i]; i++) ! { ! temp = printable_part (matches[i]); ! printed_len = print_filename (temp, matches[i]); ! /* Have we reached the end of this line? */ ! if (matches[i+1]) ! { ! if (i && (limit > 1) && (i % limit) == 0) ! crlf (); ! else for (k = 0; k < max - printed_len; k++) putc (' ', rl_outstream); } } crlf (); *************** *** 750,765 **** } - static void - insert_text (text, start, end) - char *text; - int start, end; - { - rl_begin_undo_group (); - rl_delete_text (start, end + 1); - rl_point = start; - rl_insert_text (text); - rl_end_undo_group (); - } - static char * make_quoted_replacement (match, mtype, qc) --- 1003,1006 ---- *************** *** 834,838 **** replacement[0] != oqc) start--; ! insert_text (replacement, start, rl_point - 1); if (replacement != match) free (replacement); --- 1075,1079 ---- replacement[0] != oqc) start--; ! _rl_replace_text (replacement, start, rl_point - 1); if (replacement != match) free (replacement); *************** *** 843,848 **** just-inserted match. If the user has specified that directories should be marked by a trailing `/', append one of those instead. The ! default trailing character */ ! static void append_to_match (text, delimiter, quote_char) char *text; --- 1084,1090 ---- just-inserted match. If the user has specified that directories should be marked by a trailing `/', append one of those instead. The ! default trailing character is a space. Returns the number of characters ! appended. */ ! static int append_to_match (text, delimiter, quote_char) char *text; *************** *** 884,887 **** --- 1126,1131 ---- rl_insert_text (temp_string); } + + return (temp_string_index); } *************** *** 936,960 **** int what_to_do; { ! char **matches, **temp_matches; Function *our_func; ! int start, end, delimiter, found_quote, nmatch, i; ! char *text, *saved_line_buffer, *t; char quote_char; - saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL; - - our_func = rl_completion_entry_function - ? rl_completion_entry_function - : (Function *)filename_completion_function; - /* Only the completion entry function can change these. */ rl_filename_completion_desired = 0; rl_filename_quoting_desired = 1; - rl_completion_type = what_to_do; /* We now look backwards for the start of a filename/variable word. */ end = rl_point; - found_quote = delimiter = 0; quote_char = '\0'; --- 1180,1201 ---- int what_to_do; { ! char **matches; Function *our_func; ! int start, end, delimiter, found_quote, i; ! char *text, *saved_line_buffer; char quote_char; /* Only the completion entry function can change these. */ rl_filename_completion_desired = 0; rl_filename_quoting_desired = 1; rl_completion_type = what_to_do; + saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL; + our_func = rl_completion_entry_function + ? rl_completion_entry_function + : (Function *)filename_completion_function; + /* We now look backwards for the start of a filename/variable word. */ end = rl_point; found_quote = delimiter = 0; quote_char = '\0'; *************** *** 976,1023 **** FREE (saved_line_buffer); free (text); ! return 0; ! } ! ! /* It seems to me that in all the cases we handle we would like ! to ignore duplicate possiblilities. Scan for the text to ! insert being identical to the other completions. */ ! if (rl_ignore_completion_duplicates) ! { ! temp_matches = remove_duplicate_matches (matches); ! free (matches); ! matches = temp_matches; } ! /* If we are matching filenames, then here is our chance to ! do clever processing by re-examining the list. Call the ! ignore function with the array as a parameter. It can ! munge the array, deleting matches as it desires. */ ! if (rl_ignore_some_completions_function && ! our_func == (Function *)filename_completion_function) { ! for (nmatch = 1; matches[nmatch]; nmatch++) ! ; ! (void)(*rl_ignore_some_completions_function) (matches); ! if (matches == 0 || matches[0] == 0) ! { ! FREE (matches); ! ding (); ! FREE (saved_line_buffer); ! FREE (text); ! return 0; ! } ! else ! { ! /* If we removed some matches, recompute the common prefix. */ ! for (i = 1; matches[i]; i++) ! ; ! if (i > 1 && i < nmatch) ! { ! t = matches[0]; ! compute_lcd_of_matches (matches, i - 1, text); ! FREE (t); ! } ! } } free (text); --- 1217,1233 ---- FREE (saved_line_buffer); free (text); ! return (0); } ! /* If we are matching filenames, our_func will have been set to ! filename_completion_function */ ! i = our_func == (Function *)filename_completion_function; ! if (postprocess_matches (text, &matches, i) == 0) { ! FREE (saved_line_buffer); ! free (text); ! return (0); } + free (text); *************** *** 1082,1141 **** } ! #if defined (VISIBLE_STATS) ! /* Return the character which best describes FILENAME. ! `@' for symbolic links ! `/' for directories ! `*' for executables ! `=' for sockets ! `|' for FIFOs ! `%' for character special devices ! `#' for block special devices */ ! static int ! stat_char (filename) ! char *filename; { ! struct stat finfo; ! int character, r; ! #if defined (HAVE_LSTAT) && defined (S_ISLNK) ! r = lstat (filename, &finfo); ! #else ! r = stat (filename, &finfo); ! #endif ! if (r == -1) ! return (0); ! character = 0; ! if (S_ISDIR (finfo.st_mode)) ! character = '/'; ! #if defined (S_ISCHR) ! else if (S_ISCHR (finfo.st_mode)) ! character = '%'; ! #endif /* S_ISCHR */ ! #if defined (S_ISBLK) ! else if (S_ISBLK (finfo.st_mode)) ! character = '#'; ! #endif /* S_ISBLK */ ! #if defined (S_ISLNK) ! else if (S_ISLNK (finfo.st_mode)) ! character = '@'; ! #endif /* S_ISLNK */ ! #if defined (S_ISSOCK) ! else if (S_ISSOCK (finfo.st_mode)) ! character = '='; ! #endif /* S_ISSOCK */ ! #if defined (S_ISFIFO) ! else if (S_ISFIFO (finfo.st_mode)) ! character = '|'; ! #endif ! else if (S_ISREG (finfo.st_mode)) { ! if (access (filename, X_OK) == 0) ! character = '*'; } ! return (character); } - #endif /* VISIBLE_STATS */ /* A completion function for usernames. --- 1292,1356 ---- } ! /***************************************************************/ ! /* */ ! /* Application-callable completion match generator functions */ ! /* */ ! /***************************************************************/ ! ! /* Return an array of (char *) which is a list of completions for TEXT. ! If there are no completions, return a NULL pointer. ! The first entry in the returned array is the substitution for TEXT. ! The remaining entries are the possible completions. ! The array is terminated with a NULL pointer. ! ! ENTRY_FUNCTION is a function of two args, and returns a (char *). ! The first argument is TEXT. ! The second is a state argument; it should be zero on the first call, and ! non-zero on subsequent calls. It returns a NULL pointer to the caller ! when there are no more matches. ! */ ! char ** ! completion_matches (text, entry_function) ! char *text; ! CPFunction *entry_function; { ! /* Number of slots in match_list. */ ! int match_list_size; ! /* The list of matches. */ ! char **match_list; ! /* Number of matches actually found. */ ! int matches; ! /* Temporary string binder. */ ! char *string; ! ! matches = 0; ! match_list_size = 10; ! match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); ! match_list[1] = (char *)NULL; ! ! while (string = (*entry_function) (text, matches)) { ! if (matches + 1 == match_list_size) ! match_list = (char **)xrealloc ! (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); ! ! match_list[++matches] = string; ! match_list[matches + 1] = (char *)NULL; } ! ! /* If there were any matches, then look through them finding out the ! lowest common denominator. That then becomes match_list[0]. */ ! if (matches) ! compute_lcd_of_matches (match_list, matches, text); ! else /* There were no matches. */ ! { ! free (match_list); ! match_list = (char **)NULL; ! } ! return (match_list); } /* A completion function for usernames. *************** *** 1195,1327 **** } - /* **************************************************************** */ - /* */ - /* Completion */ - /* */ - /* **************************************************************** */ - - /* Non-zero means that case is not significant in completion. */ - int completion_case_fold = 0; - - /* Find the common prefix of the list of matches, and put it into - matches[0]. */ - static int - compute_lcd_of_matches (match_list, matches, text) - char **match_list; - int matches; - char *text; - { - register int i, c1, c2, si; - int low; /* Count of max-matched characters. */ - - /* If only one match, just use that. Otherwise, compare each - member of the list with the next, finding out where they - stop matching. */ - if (matches == 1) - { - match_list[0] = match_list[1]; - match_list[1] = (char *)NULL; - return 1; - } - - for (i = 1, low = 100000; i < matches; i++) - { - if (completion_case_fold) - { - for (si = 0; - (c1 = _rl_to_lower(match_list[i][si])) && - (c2 = _rl_to_lower(match_list[i + 1][si])); - si++) - if (c1 != c2) - break; - } - else - { - for (si = 0; - (c1 = match_list[i][si]) && - (c2 = match_list[i + 1][si]); - si++) - if (c1 != c2) - break; - } - - if (low > si) - low = si; - } - - /* If there were multiple matches, but none matched up to even the - first character, and the user typed something, use that as the - value of matches[0]. */ - if (low == 0 && text && *text) - { - match_list[0] = xmalloc (strlen (text) + 1); - strcpy (match_list[0], text); - } - else - { - match_list[0] = xmalloc (low + 1); - strncpy (match_list[0], match_list[1], low); - match_list[0][low] = '\0'; - } - - return matches; - } - - /* Return an array of (char *) which is a list of completions for TEXT. - If there are no completions, return a NULL pointer. - The first entry in the returned array is the substitution for TEXT. - The remaining entries are the possible completions. - The array is terminated with a NULL pointer. - - ENTRY_FUNCTION is a function of two args, and returns a (char *). - The first argument is TEXT. - The second is a state argument; it should be zero on the first call, and - non-zero on subsequent calls. It returns a NULL pointer to the caller - when there are no more matches. - */ - char ** - completion_matches (text, entry_function) - char *text; - CPFunction *entry_function; - { - /* Number of slots in match_list. */ - int match_list_size; - - /* The list of matches. */ - char **match_list; - - /* Number of matches actually found. */ - int matches; - - /* Temporary string binder. */ - char *string; - - matches = 0; - match_list_size = 10; - match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); - match_list[1] = (char *)NULL; - - while (string = (*entry_function) (text, matches)) - { - if (matches + 1 == match_list_size) - match_list = (char **)xrealloc - (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); - - match_list[++matches] = string; - match_list[matches + 1] = (char *)NULL; - } - - /* If there were any matches, then look through them finding out the - lowest common denominator. That then becomes match_list[0]. */ - if (matches) - compute_lcd_of_matches (match_list, matches, text); - else /* There were no matches. */ - { - free (match_list); - match_list = (char **)NULL; - } - return (match_list); - } - /* Okay, now we write the entry_function for filename completion. In the general case. Note that completion in the shell is a little different --- 1410,1413 ---- *************** *** 1422,1429 **** /* Otherwise, if these match up to the length of filename, then it is a match. */ ! if ((entry->d_name[0] == filename[0]) && ! (((int)D_NAMLEN (entry)) >= filename_len) && ! (strncmp (filename, entry->d_name, filename_len) == 0)) ! break; } } --- 1508,1525 ---- /* Otherwise, if these match up to the length of filename, then it is a match. */ ! if (_rl_completion_case_fold) ! { ! if ((_rl_to_lower (entry->d_name[0]) == _rl_to_lower (filename[0])) && ! (((int)D_NAMLEN (entry)) >= filename_len) && ! (_rl_strnicmp (filename, entry->d_name, filename_len) == 0)) ! break; ! } ! else ! { ! if ((entry->d_name[0] == filename[0]) && ! (((int)D_NAMLEN (entry)) >= filename_len) && ! (strncmp (filename, entry->d_name, filename_len) == 0)) ! break; ! } } } *************** *** 1488,1560 **** } ! /* A function for simple tilde expansion. */ int ! rl_tilde_expand (ignore, key) ! int ignore, key; { ! register int start, end; ! char *homedir, *temp; ! int len; ! end = rl_point; ! start = end - 1; ! if (rl_point == rl_end && rl_line_buffer[rl_point] == '~') ! { ! homedir = tilde_expand ("~"); ! insert_text (homedir, start, end); ! return (0); ! } ! else if (rl_line_buffer[start] != '~') ! { ! for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--) ; ! start++; } ! end = start; ! do ! end++; ! while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end); ! ! if (whitespace (rl_line_buffer[end]) || end >= rl_end) ! end--; ! ! /* If the first character of the current word is a tilde, perform ! tilde expansion and insert the result. If not a tilde, do ! nothing. */ ! if (rl_line_buffer[start] == '~') ! { ! len = end - start + 1; ! temp = xmalloc (len + 1); ! strncpy (temp, rl_line_buffer + start, len); ! temp[len] = '\0'; ! homedir = tilde_expand (temp); ! free (temp); ! insert_text (homedir, start, end); } ! return (0); ! } ! ! /* Find the first occurrence in STRING1 of any character from STRING2. ! Return a pointer to the character in STRING1. */ ! static char * ! rl_strpbrk (string1, string2) ! char *string1, *string2; ! { ! register char *scan; ! for (; *string1; string1++) { ! for (scan = string2; *scan; scan++) ! { ! if (*string1 == *scan) ! { ! return (string1); ! } ! } } ! return ((char *)NULL); } --- 1584,1702 ---- } ! /* An initial implementation of a menu completion function a la tcsh. The ! first time (if the last readline command was not rl_menu_complete), we ! generate the list of matches. This code is very similar to the code in ! rl_complete_internal -- there should be a way to combine the two. Then, ! for each item in the list of matches, we insert the match in an undoable ! fashion, with the appropriate character appended (this happens on the ! second and subsequent consecutive calls to rl_menu_complete). When we ! hit the end of the match list, we restore the original unmatched text, ! ring the bell, and reset the counter to zero. */ int ! rl_menu_complete (count, ignore) ! int count, ignore; { ! Function *our_func; ! int matching_filenames, found_quote; ! static char *orig_text; ! static char **matches = (char **)0; ! static int match_list_index = 0; ! static int match_list_size = 0; ! static int orig_start, orig_end; ! static char quote_char; ! static int delimiter; ! ! /* The first time through, we generate the list of matches and set things ! up to insert them. */ ! if (rl_last_func != rl_menu_complete) ! { ! /* Clean up from previous call, if any. */ ! FREE (orig_text); ! if (matches) ! { ! for (match_list_index = 0; matches[match_list_index]; match_list_index++) ! free (matches[match_list_index]); ! free (matches); ! } ! ! match_list_index = match_list_size = 0; ! matches = (char **)NULL; ! ! /* Only the completion entry function can change these. */ ! rl_filename_completion_desired = 0; ! rl_filename_quoting_desired = 1; ! rl_completion_type = '%'; ! ! our_func = rl_completion_entry_function ! ? rl_completion_entry_function ! : (Function *)filename_completion_function; ! ! /* We now look backwards for the start of a filename/variable word. */ ! orig_end = rl_point; ! found_quote = delimiter = 0; ! quote_char = '\0'; ! ! if (rl_point) ! /* This (possibly) changes rl_point. If it returns a non-zero char, ! we know we have an open quote. */ ! quote_char = find_completion_word (&found_quote, &delimiter); ! ! orig_start = rl_point; ! rl_point = orig_end; ! ! orig_text = rl_copy_text (orig_start, orig_end); ! matches = gen_completion_matches (orig_text, orig_start, orig_end, ! our_func, found_quote, quote_char); ! ! /* If we are matching filenames, our_func will have been set to ! filename_completion_function */ ! matching_filenames = our_func == (Function *)filename_completion_function; ! if (matches == 0 || postprocess_matches (orig_text, &matches, matching_filenames) == 0) ! { ! ding (); ! FREE (matches); ! matches = (char **)0; ! FREE (orig_text); ! orig_text = (char *)0; ! completion_changed_buffer = 0; ! return (0); ! } ! for (match_list_size = 0; matches[match_list_size]; match_list_size++) ; ! /* matches[0] is lcd if match_list_size > 1, but the circular buffer ! code below should take care of it. */ } ! /* Now we have the list of matches. Replace the text between ! rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with ! matches[match_list_index], and add any necessary closing char. */ ! if (matches == 0 || match_list_size == 0) ! { ! ding (); ! FREE (matches); ! matches = (char **)0; ! completion_changed_buffer = 0; ! return (0); } ! match_list_index = (match_list_index + count) % match_list_size; ! if (match_list_index < 0) ! match_list_index += match_list_size; ! if (match_list_index == 0) { ! ding (); ! insert_match (orig_text, orig_start, MULT_MATCH, "e_char); } ! else ! { ! insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char); ! append_to_match (matches[match_list_index], delimiter, quote_char); ! } ! ! completion_changed_buffer = 1; ! return (0); } diff -Nrc2 bash-2.01.1/lib/readline/display.c bash-2.02/lib/readline/display.c *** bash-2.01.1/lib/readline/display.c Mon Aug 18 11:49:12 1997 --- bash-2.02/lib/readline/display.c Mon Aug 4 15:54:23 1997 *************** *** 73,77 **** --- 73,81 ---- /* Variables and functions imported from terminal.c */ extern void _rl_output_some_chars (); + #ifdef _MINIX + extern void _rl_output_character_function (); + #else extern int _rl_output_character_function (); + #endif extern int _rl_backspace (); diff -Nrc2 bash-2.01.1/lib/readline/doc/hist.texinfo bash-2.02/lib/readline/doc/hist.texinfo *** bash-2.01.1/lib/readline/doc/hist.texinfo Thu Mar 21 16:07:55 1996 --- bash-2.02/lib/readline/doc/hist.texinfo Thu Apr 2 14:38:53 1998 *************** *** 8,18 **** @ignore ! last change: Thu Mar 21 16:07:29 EST 1996 @end ignore ! @set EDITION 2.1 ! @set VERSION 2.1 ! @set UPDATED 21 March 1996 ! @set UPDATE-MONTH March 1996 @ifinfo --- 8,23 ---- @ignore ! last change: Thu Apr 2 14:38:22 EST 1998 @end ignore ! @set EDITION 2.2 ! @set VERSION 2.2 ! @set UPDATED 2 April 1998 ! @set UPDATE-MONTH April 1998 ! ! @dircategory Libraries ! @direntry ! * History: (history). The GNU history library API ! @end direntry @ifinfo *************** *** 21,25 **** typed input. ! Copyright (C) 1988, 1991, 1993, 1995, 1996 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of --- 26,30 ---- typed input. ! Copyright (C) 1988, 1991, 1993, 1995, 1996, 1998 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of diff -Nrc2 bash-2.01.1/lib/readline/doc/hsuser.texinfo bash-2.02/lib/readline/doc/hsuser.texinfo *** bash-2.01.1/lib/readline/doc/hsuser.texinfo Wed Oct 16 15:13:26 1996 --- bash-2.02/lib/readline/doc/hsuser.texinfo Wed Apr 1 11:40:56 1998 *************** *** 30,34 **** This chapter describes how to use the GNU History Library interactively, from a user's standpoint. It should be considered a user's guide. For ! information on using the GNU History Library in your own programs, see the GNU Readline Library Manual. @end ifset --- 30,34 ---- This chapter describes how to use the GNU History Library interactively, from a user's standpoint. It should be considered a user's guide. For ! information on using the GNU History Library in other programs, see the GNU Readline Library Manual. @end ifset *************** *** 44,47 **** --- 44,49 ---- * Bash History Facilities:: How Bash lets you manipulate your command history. + * Bash History Builtins:: The Bash builtin commands that manipulate + the command history. * History Interaction:: What it feels like using History as a user. @end menu *************** *** 85,93 **** lines. If @code{HISTFILESIZE} is not set, no truncation is performed. ! The builtin command @code{fc} (@pxref{Korn Shell Builtins}) ! may be used to list or edit and re-execute a portion of ! the history list. The @code{history} builtin (@pxref{C Shell Builtins}) ! can be used to display or modify the history list and ! manipulate the history file. When using the command-line editing, search commands are available in each editing mode that provide access to the --- 87,94 ---- lines. If @code{HISTFILESIZE} is not set, no truncation is performed. ! The builtin command @code{fc} may be used to list or edit and re-execute ! a portion of the history list. ! The @code{history} builtin can be used to display or modify the history ! list and manipulate the history file. When using the command-line editing, search commands are available in each editing mode that provide access to the *************** *** 105,113 **** shell option causes the shell to save the command with embedded newlines instead of semicolons. ! @xref{Bash Builtins} for a description of @code{shopt}. @end ifset @node History Interaction ! @section Interactive History Expansion @cindex history expansion --- 106,206 ---- shell option causes the shell to save the command with embedded newlines instead of semicolons. ! @xref{Bash Builtins}, for a description of @code{shopt}. ! ! @node Bash History Builtins ! @section Bash History Builtins ! @cindex history builtins ! ! Bash provides two builtin commands that allow you to manipulate the ! history list and history file. ! ! @table @code ! ! @item fc ! @btindex fc ! @example ! @code{fc [-e @var{ename}] [-nlr] [@var{first}] [@var{last}]} ! @code{fc -s [@var{pat}=@var{rep}] [@var{command}]} ! @end example ! ! Fix Command. In the first form, a range of commands from @var{first} to ! @var{last} is selected from the history list. Both @var{first} and ! @var{last} may be specified as a string (to locate the most recent ! 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 @var{last} is not specified it is set to ! @var{first}. If @var{first} is not specified it is set to the previous ! command for editing and @minus{}16 for listing. If the @samp{-l} flag is ! given, the commands are listed on standard output. The @samp{-n} flag ! suppresses the command numbers when listing. The @samp{-r} flag ! reverses the order of the listing. Otherwise, the editor given by ! @var{ename} is invoked on a file containing those commands. If ! @var{ename} is not given, the value of the following variable expansion ! is used: @code{$@{FCEDIT:-$@{EDITOR:-vi@}@}}. This says to use the ! value of the @code{FCEDIT} variable if set, or the value of the ! @code{EDITOR} variable if that is set, or @code{vi} if neither is set. ! When editing is complete, the edited commands are echoed and executed. ! ! In the second form, @var{command} is re-executed after each instance ! of @var{pat} in the selected command is replaced by @var{rep}. ! ! A useful alias to use with the @code{fc} command is @code{r='fc -s'}, so ! that typing @samp{r cc} runs the last command beginning with @code{cc} ! and typing @samp{r} re-executes the last command (@pxref{Aliases}). ! ! @item history ! @btindex history ! @example ! history [-c] [@var{n}] ! history [-anrw] [@var{filename}] ! history -ps @var{arg} ! @end example ! ! Display the history list with line numbers. Lines prefixed with ! with a @samp{*} have been modified. An argument of @var{n} says ! to list only the last @var{n} lines. Options, if supplied, have ! the following meanings: ! ! @table @code ! @item -w ! Write out the current history to the history file. ! ! @item -r ! Read the current history file and append its contents to ! the history list. ! ! @item -a ! Append the new ! history lines (history lines entered since the beginning of the ! current Bash session) to the history file. ! ! @item -n ! Append the history lines not already read from the history file ! to the current history list. These are lines appended to the history ! file since the beginning of the current Bash session. ! ! @item -c ! Clear the history list. This may be combined ! with the other options to replace the history list completely. ! ! @item -s ! The @var{arg}s are added to the end of ! the history list as a single entry. ! ! @item -p ! Perform history substitution on the @var{arg}s and display the result ! on the standard output, without storing the results in the history list. ! @end table ! ! When the @samp{-w}, @samp{-r}, @samp{-a}, or @samp{-n} option is ! used, if @var{filename} ! is given, then it is used as the history file. If not, then ! the value of the @code{HISTFILE} variable is used. ! ! @end table @end ifset @node History Interaction ! @section History Expansion @cindex history expansion *************** *** 122,133 **** History expansion takes place in two parts. The first is to determine ! which line from the previous history should be used during substitution. The second is to select portions of that line for inclusion into the ! current one. The line selected from the previous history is called the @dfn{event}, and the portions of that line that are acted upon are called @dfn{words}. Various @dfn{modifiers} are available to manipulate the selected words. The line is broken into words in the same fashion ! that Bash does, so that several English (or Unix) words ! surrounded by quotes are considered as one word. History expansions are introduced by the appearance of the history expansion character, which is @samp{!} by default. --- 215,226 ---- History expansion takes place in two parts. The first is to determine ! which line from the history list should be used during substitution. The second is to select portions of that line for inclusion into the ! current one. The line selected from the history is called the @dfn{event}, and the portions of that line that are acted upon are called @dfn{words}. Various @dfn{modifiers} are available to manipulate the selected words. The line is broken into words in the same fashion ! that Bash does, so that several words ! surrounded by quotes are considered one word. History expansions are introduced by the appearance of the history expansion character, which is @samp{!} by default. *************** *** 154,157 **** --- 247,251 ---- add commands to the end of the history list without actually executing them, so that they are available for subsequent recall. + This is most useful in conjunction with Readline. The shell allows control of the various characters used by the *************** *** 177,181 **** @item @code{!} Start a history substitution, except when followed by a space, tab, ! the end of the line, @key{=} or @key{(}. @item @code{!@var{n}} --- 271,275 ---- @item @code{!} Start a history substitution, except when followed by a space, tab, ! the end of the line, @samp{=} or @samp{(}. @item @code{!@var{n}} *************** *** 211,215 **** Word designators are used to select desired words from the event. A @samp{:} separates the event specification from the word designator. It ! can be omitted if the word designator begins with a @samp{^}, @samp{$}, @samp{*}, @samp{-}, or @samp{%}. Words are numbered from the beginning of the line, with the first word being denoted by 0 (zero). Words are --- 305,309 ---- Word designators are used to select desired words from the event. A @samp{:} separates the event specification from the word designator. It ! may be omitted if the word designator begins with a @samp{^}, @samp{$}, @samp{*}, @samp{-}, or @samp{%}. Words are numbered from the beginning of the line, with the first word being denoted by 0 (zero). Words are diff -Nrc2 bash-2.01.1/lib/readline/doc/rlman.texinfo bash-2.02/lib/readline/doc/rlman.texinfo *** bash-2.01.1/lib/readline/doc/rlman.texinfo Thu Mar 21 16:07:03 1996 --- bash-2.02/lib/readline/doc/rlman.texinfo Thu Apr 2 14:39:18 1998 *************** *** 8,18 **** @ignore ! last change: Thu Mar 21 16:06:39 EST 1996 @end ignore ! @set EDITION 2.1 ! @set VERSION 2.1 ! @set UPDATED 21 March 1996 ! @set UPDATE-MONTH March 1996 @ifinfo --- 8,23 ---- @ignore ! last change: Thu Apr 2 14:39:03 EST 1998 @end ignore ! @set EDITION 2.2 ! @set VERSION 2.2 ! @set UPDATED 2 April 1998 ! @set UPDATE-MONTH April 1998 ! ! @dircategory Libraries ! @direntry ! * Readline: (readline). The GNU readline library API ! @end direntry @ifinfo *************** *** 21,25 **** to provide a command line interface. ! Copyright (C) 1988, 1991 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of --- 26,30 ---- to provide a command line interface. ! Copyright (C) 1988, 1991, 1993, 1996, 1998 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of diff -Nrc2 bash-2.01.1/lib/readline/doc/rltech.texinfo bash-2.02/lib/readline/doc/rltech.texinfo *** bash-2.01.1/lib/readline/doc/rltech.texinfo Mon Mar 3 16:23:25 1997 --- bash-2.02/lib/readline/doc/rltech.texinfo Wed Feb 4 14:43:56 1998 *************** *** 455,458 **** --- 455,466 ---- @end deftypefun + @deftypefun int rl_unbind_function_in_map (Function *function, Keymap map) + Unbind all keys that execute @var{function} in @var{map}. + @end deftypefun + + @deftypefun int rl_unbind_command_in_map (char *command, Keymap map) + Unbind all keys that are bound to @var{command} in @var{map}. + @end deftypefun + @deftypefun int rl_generic_bind (int type, char *keyseq, char *data, Keymap map) Bind the key sequence represented by the string @var{keyseq} to the arbitrary *************** *** 1035,1039 **** @deftypevar {char *} rl_filename_quote_characters A list of characters that cause a filename to be quoted by the completer ! when they appear in a completed filename. The default is empty. @end deftypevar --- 1043,1047 ---- @deftypevar {char *} rl_filename_quote_characters A list of characters that cause a filename to be quoted by the completer ! when they appear in a completed filename. The default is the null string. @end deftypevar diff -Nrc2 bash-2.01.1/lib/readline/doc/rluser.texinfo bash-2.02/lib/readline/doc/rluser.texinfo *** bash-2.01.1/lib/readline/doc/rluser.texinfo Mon May 19 12:56:22 1997 --- bash-2.02/lib/readline/doc/rluser.texinfo Wed Apr 1 12:26:01 1998 *************** *** 136,140 **** Insert the character into the line at the cursor. @item @key{C-_} ! Undo the last thing that you did. You can undo all the way back to an empty line. @end table --- 136,140 ---- Insert the character into the line at the cursor. @item @key{C-_} ! Undo the last editing command. You can undo all the way back to an empty line. @end table *************** *** 156,160 **** Move to the end of the line. @item M-f ! Move forward a word. @item M-b Move backward a word. --- 156,160 ---- Move to the end of the line. @item M-f ! Move forward a word, where a word is composed of letters and digits. @item M-b Move backward a word. *************** *** 208,212 **** @end table ! And, here is how to @dfn{yank} the text back into the line. Yanking means to copy the most-recently-killed text from the kill buffer. --- 208,212 ---- @end table ! Here is how to @dfn{yank} the text back into the line. Yanking means to copy the most-recently-killed text from the kill buffer. *************** *** 228,235 **** command which normally acts in a forward direction, that command will act in a backward direction. For example, to kill text back to the ! start of the line, you might type @w{@kbd{M-- C-k}}. The general way to pass numeric arguments to a command is to type meta ! digits before the command. If the first `digit' you type is a minus sign (@key{-}), then the sign of the argument will be negative. Once you have typed one meta digit to get the argument started, you can type --- 228,235 ---- command which normally acts in a forward direction, that command will act in a backward direction. For example, to kill text back to the ! start of the line, you might type @samp{M-- C-k}. The general way to pass numeric arguments to a command is to type meta ! digits before the command. If the first `digit' typed is a minus sign (@key{-}), then the sign of the argument will be negative. Once you have typed one meta digit to get the argument started, you can type *************** *** 249,274 **** 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 Escape character is used to terminate an incremental search. ! Control-J will also terminate the 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. ! 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 @code{newline} will terminate the search and accept the line, thereby executing the command from the history list. 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 part of the contents of the current line. @node Readline Init File --- 249,273 ---- 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 @key{ESC} character is used to terminate an incremental search. ! @key{C-j} will also terminate the search. ! @key{C-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. ! To find other matching entries in the history list, type @key{C-s} or ! @key{C-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 @key{RET} will terminate the search and accept the line, thereby executing the command from the history list. 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. @node Readline Init File *************** *** 277,284 **** Although the Readline library comes with a set of @code{emacs}-like ! keybindings installed by default, ! it is possible that you would like to use a different set ! of keybindings. You can customize programs that use Readline by putting ! commands in an @dfn{inputrc} file in your home directory. The name of this @ifset BashFeatures file is taken from the value of the shell variable @code{INPUTRC}. If --- 276,284 ---- Although the Readline library comes with a set of @code{emacs}-like ! keybindings installed by default, it is possible to use a different set ! of keybindings. ! Any user can customize programs that use Readline by putting ! commands in an @dfn{inputrc} file in his home directory. ! The name of this @ifset BashFeatures file is taken from the value of the shell variable @code{INPUTRC}. If *************** *** 315,321 **** @table @asis @item Variable Settings ! You can change the state of a few variables in Readline by ! using the @code{set} command within the init file. Here is how you ! would specify that you wish to use @code{vi} line editing commands: @example --- 315,323 ---- @table @asis @item Variable Settings ! You can modify the run-time behavior of Readline by ! altering the values of variables in Readline ! using the @code{set} command within the init file. Here is how to ! change from the default Emacs-like key binding to use ! @code{vi} line editing commands: @example *************** *** 323,328 **** @end example ! Right now, there are only a few variables which can be set; ! so few, in fact, that we just list them here: @table @code --- 325,330 ---- @end example ! A great deal of run-time behavior is changeable with the following ! variables. @table @code *************** *** 342,345 **** --- 344,352 ---- is @code{"#"}. + @item completion-ignore-case + If set to @samp{on}, Readline performs filename matching and completion + in a case-insensitive fashion. + The default value is @samp{off}. + @item completion-query-items @vindex completion-query-items *************** *** 354,358 **** @vindex convert-meta If set to @samp{on}, Readline will convert characters with the ! eigth bit set to an ASCII key sequence by stripping the eigth bit and prepending an @key{ESC} character, converting them to a meta-prefixed key sequence. The default value is @samp{on}. --- 361,365 ---- @vindex convert-meta If set to @samp{on}, Readline will convert characters with the ! eighth bit set to an ASCII key sequence by stripping the eighth bit and prepending an @key{ESC} character, converting them to a meta-prefixed key sequence. The default value is @samp{on}. *************** *** 360,364 **** @item disable-completion @vindex disable-completion ! If set to @samp{On}, readline will inhibit word completion. Completion characters will be inserted into the line as if they had been mapped to @code{self-insert}. The default is @samp{off}. --- 367,371 ---- @item disable-completion @vindex disable-completion ! If set to @samp{On}, Readline will inhibit word completion. Completion characters will be inserted into the line as if they had been mapped to @code{self-insert}. The default is @samp{off}. *************** *** 366,377 **** @item editing-mode @vindex editing-mode ! The @code{editing-mode} variable controls which editing mode you are ! using. By default, Readline starts up in Emacs editing mode, where ! the keystrokes are most similar to Emacs. This variable can be set to either @samp{emacs} or @samp{vi}. @item enable-keypad @vindex enable-keypad ! When set to @samp{on}, readline will try to enable the application keypad when it is called. Some systems need this to enable the arrow keys. The default is @samp{off}. --- 373,384 ---- @item editing-mode @vindex editing-mode ! The @code{editing-mode} variable controls which default set of ! key bindings is used. By default, Readline starts up in Emacs editing ! mode, where the keystrokes are most similar to Emacs. This variable can be set to either @samp{emacs} or @samp{vi}. @item enable-keypad @vindex enable-keypad ! When set to @samp{on}, Readline will try to enable the application keypad when it is called. Some systems need this to enable the arrow keys. The default is @samp{off}. *************** *** 385,389 **** @vindex horizontal-scroll-mode This variable can be set to either @samp{on} or @samp{off}. Setting it ! to @samp{on} means that the text of the lines that you edit will scroll horizontally on a single screen line when they are longer than the width of the screen, instead of wrapping onto a new screen line. By default, --- 392,396 ---- @vindex horizontal-scroll-mode This variable can be set to either @samp{on} or @samp{off}. Setting it ! to @samp{on} means that the text of the lines being edited will scroll horizontally on a single screen line when they are longer than the width of the screen, instead of wrapping onto a new screen line. By default, *************** *** 412,417 **** @item mark-modified-lines @vindex mark-modified-lines ! This variable, when set to @samp{on}, says to display an asterisk ! (@samp{*}) at the start of history lines which have been modified. This variable is @samp{off} by default. --- 419,424 ---- @item mark-modified-lines @vindex mark-modified-lines ! This variable, when set to @samp{on}, causes Readline to display an ! asterisk (@samp{*}) at the start of history lines which have been modified. This variable is @samp{off} by default. *************** *** 431,434 **** --- 438,446 ---- sequence. The default is @samp{off}. + @item print-completions-horizontally + If set to @samp{on}, Readline will display completions with matches + sorted horizontally in alphabetical order, rather than down the screen. + The default is @samp{off}. + @item show-all-if-ambiguous @vindex show-all-if-ambiguous *************** *** 450,456 **** The syntax for controlling key bindings in the init file is simple. First you have to know the name of the command that you ! want to change. The following pages contain tables of the command name, ! the default keybinding, and a short description of what the command ! does. Once you know the name of the command, simply place the name of the key --- 462,468 ---- The syntax for controlling key bindings in the init file is simple. First you have to know the name of the command that you ! want to change. The following sections contain tables of the command ! name, the default keybinding, if any, and a short description of what ! the command does. Once you know the name of the command, simply place the name of the key *************** *** 469,474 **** @end example ! In the above example, @samp{C-u} is bound to the function ! @code{universal-argument}, and @samp{C-o} is bound to run the macro expressed on the right hand side (that is, to insert the text @samp{> output} into the line). --- 481,486 ---- @end example ! In the above example, @key{C-u} is bound to the function ! @code{universal-argument}, and @key{C-o} is bound to run the macro expressed on the right hand side (that is, to insert the text @samp{> output} into the line). *************** *** 487,496 **** @end example ! In the above example, @samp{C-u} is bound to the function @code{universal-argument} (just as it was in the first example), ! @samp{C-x C-r} is bound to the function @code{re-read-init-file}, and ! @samp{ESC [ 1 1 ~} is bound to insert the text @samp{Function Key 1}. ! The following escape sequences are available when specifying key ! sequences: @table @code --- 499,512 ---- @end example ! In the above example, @key{C-u} is bound to the function @code{universal-argument} (just as it was in the first example), ! @samp{@key{C-x} @key{C-r}} is bound to the function @code{re-read-init-file}, ! and @samp{@key{ESC} @key{[} @key{1} @key{1} @key{~}} is bound to insert ! the text @samp{Function Key 1}. ! ! @end table ! ! The following GNU Emacs style escape sequences are available when ! specifying key sequences: @table @code *************** *** 509,517 **** @end table ! When entering the text of a macro, single or double quotes should ! be used to indicate a macro definition. Unquoted text ! is assumed to be a function name. Backslash ! will quote any character in the macro text, including @samp{"} ! and @samp{'}. For example, the following binding will make @samp{C-x \} insert a single @samp{\} into the line: --- 525,562 ---- @end table ! In addition to the GNU Emacs style escape sequences, a second ! set of backslash escapes is available: ! ! @table @code ! @item \a ! alert (bell) ! @item \b ! backspace ! @item \d ! delete ! @item \f ! form feed ! @item \n ! newline ! @item \r ! carriage return ! @item \t ! horizontal tab ! @item \v ! vertical tab ! @item \@var{nnn} ! the character whose ASCII code is the octal value @var{nnn} ! (one to three digits) ! @item \x@var{nnn} ! the character whose ASCII code is the hexadecimal value @var{nnn} ! (one to three digits) ! @end table ! ! 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 @samp{"} and @samp{'}. For example, the following binding will make @samp{C-x \} insert a single @samp{\} into the line: *************** *** 521,525 **** @end table - @end table @node Conditional Init Constructs --- 566,569 ---- *************** *** 529,533 **** compilation features of the C preprocessor which allows key bindings and variable settings to be performed as the result ! of tests. There are three parser directives used. @table @code --- 573,577 ---- 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. @table @code *************** *** 551,556 **** key bindings, perhaps to bind the key sequences output by the terminal's function keys. The word on the right side of the ! @samp{=} is tested against the full name of the terminal and the ! portion of the terminal name before the first @samp{-}. This allows @code{sun} to match both @code{sun} and @code{sun-cmd}, for instance. --- 595,600 ---- key bindings, perhaps to bind the key sequences output by the terminal's function keys. The word on the right side of the ! @samp{=} is tested against both the full name of the terminal and ! the portion of the terminal name before the first @samp{-}. This allows @code{sun} to match both @code{sun} and @code{sun-cmd}, for instance. *************** *** 572,576 **** @item $endif ! This command, as you saw in the previous example, terminates an @code{$if} command. --- 616,620 ---- @item $endif ! This command, as seen in the previous example, terminates an @code{$if} command. *************** *** 578,581 **** --- 622,632 ---- Commands in this branch of the @code{$if} directive are executed if the test fails. + + @item $include + This directive takes a single filename as an argument and reads commands + and bindings from that file. + @example + $include /etc/inputrc + @end example @end table *************** *** 595,598 **** --- 646,654 ---- # Lines beginning with '#' are comments. # + # First, include any systemwide bindings and variable assignments from + # /etc/Inputrc + $include /etc/Inputrc + + # # Set various bindings for emacs mode. *************** *** 739,744 **** Accept the line regardless of where the cursor is. If this line is non-empty, add it to the history list according to the setting of ! the @code{HISTCONTROL} variable. If this line was a history ! line, then restore the history line to its original state. @end ifset @ifclear BashFeatures --- 795,801 ---- Accept the line regardless of where the cursor is. If this line is non-empty, add it to the history list according to the setting of ! the @code{HISTCONTROL} and @code{HISTIGNORE} variables. ! If this line was a history line, then restore the history line to its ! original state. @end ifset @ifclear BashFeatures *************** *** 758,762 **** @item end-of-history (M->) ! Move to the end of the input history, i.e., the line you are entering. @item reverse-search-history (C-r) --- 815,820 ---- @item end-of-history (M->) ! Move to the end of the input history, i.e., the line currently ! being entered. @item reverse-search-history (C-r) *************** *** 781,785 **** Search forward through the history for the string of characters between the start of the current line and the current cursor ! position (the `point'). This is a non-incremental search. By default, this command is unbound. --- 839,843 ---- Search forward through the history for the string of characters between the start of the current line and the current cursor ! position (the @var{point}). This is a non-incremental search. By default, this command is unbound. *************** *** 800,803 **** --- 858,863 ---- previous history entry). With an argument, behave exactly like @code{yank-nth-arg}. + Successive calls to @code{yank-last-arg} move back through the history + list, inserting the last argument of each line in turn. @end ftable *************** *** 810,825 **** Delete the character under the cursor. If the cursor is at the beginning of the line, there are no characters in the line, and ! the last character typed was not @kbd{C-d}, then return @code{EOF}. @item backward-delete-char (Rubout) ! Delete the character behind the cursor. A numeric arg says to kill ! the characters instead of deleting them. @item quoted-insert (C-q, C-v) ! Add the next character that you type to the line verbatim. This is how to insert key sequences like @key{C-q}, for example. @item tab-insert (M-TAB) Insert a tab character. @item self-insert (a, b, A, 1, !, ...) --- 870,888 ---- Delete the character under the cursor. If the cursor is at the beginning of the line, there are no characters in the line, and ! the last character typed was not bound to @code{delete-char}, then ! return @code{EOF}. @item backward-delete-char (Rubout) ! Delete the character behind the cursor. A numeric argument means ! to kill the characters instead of deleting them. @item quoted-insert (C-q, C-v) ! Add the next character typed to the line verbatim. This is how to insert key sequences like @key{C-q}, for example. + @ifclear BashFeatures @item tab-insert (M-TAB) Insert a tab character. + @end ifclear @item self-insert (a, b, A, 1, !, ...) *************** *** 832,836 **** is at the end of the line, then this transposes the last two characters of the line. ! Negative argumentss don't work. @item transpose-words (M-t) --- 895,899 ---- is at the end of the line, then this transposes the last two characters of the line. ! Negative arguments don't work. @item transpose-words (M-t) *************** *** 840,852 **** @item upcase-word (M-u) Uppercase the current (or following) word. With a negative argument, ! do the previous word, but do not move the cursor. @item downcase-word (M-l) Lowercase the current (or following) word. With a negative argument, ! do the previous word, but do not move the cursor. @item capitalize-word (M-c) Capitalize the current (or following) word. With a negative argument, ! do the previous word, but do not move the cursor. @end ftable --- 903,915 ---- @item upcase-word (M-u) Uppercase the current (or following) word. With a negative argument, ! uppercase the previous word, but do not move the cursor. @item downcase-word (M-l) Lowercase the current (or following) word. With a negative argument, ! lowercase the previous word, but do not move the cursor. @item capitalize-word (M-c) Capitalize the current (or following) word. With a negative argument, ! capitalize the previous word, but do not move the cursor. @end ftable *************** *** 865,869 **** @item unix-line-discard (C-u) Kill backward from the cursor to the beginning of the current line. ! Save the killed text on the kill-ring. @item kill-whole-line () --- 928,932 ---- @item unix-line-discard (C-u) Kill backward from the cursor to the beginning of the current line. ! The killed text is saved on the kill-ring. @item kill-whole-line () *************** *** 889,905 **** @item kill-region () Kill the text between the point and the @emph{mark} (saved ! cursor position. This text is referred to as the @var{region}. By default, this command is unbound. @item copy-region-as-kill () ! Copy the text in the region to the kill buffer, so you can yank it right away. By default, this command is unbound. @item copy-backward-word () Copy the word before point to the kill buffer. By default, this command is unbound. @item copy-forward-word () Copy the word following point to the kill buffer. By default, this command is unbound. --- 952,970 ---- @item kill-region () Kill the text between the point and the @emph{mark} (saved ! cursor position). This text is referred to as the @var{region}. By default, this command is unbound. @item copy-region-as-kill () ! Copy the text in the region to the kill buffer, so it can be yanked right away. By default, this command is unbound. @item copy-backward-word () Copy the word before point to the kill buffer. + The word boundaries are the same as @code{backward-word}. By default, this command is unbound. @item copy-forward-word () Copy the word following point to the kill buffer. + The word boundaries are the same as @code{forward-word}. By default, this command is unbound. *************** *** 944,949 **** application-specific. Generally, if you are typing a filename argument, you can do filename completion; if you are typing a command, ! you can do command completion, if you are typing in a symbol to GDB, you ! can do symbol name completion, if you are typing in a variable to Bash, you can do variable name completion, and so on. @ifset BashFeatures --- 1009,1014 ---- application-specific. Generally, if you are typing a filename argument, you can do filename completion; if you are typing a command, ! you can do command completion; if you are typing in a symbol to GDB, you ! can do symbol name completion; if you are typing in a variable to Bash, you can do variable name completion, and so on. @ifset BashFeatures *************** *** 962,965 **** --- 1027,1043 ---- been generated by @code{possible-completions}. + @item menu-complete () + Similar to @code{complete}, but replaces the word to be completed + with a single match from the list of possible completions. + Repeated execution of @code{menu-complete} steps through the list + of possible completions, inserting each match in turn. + At the end of the list of completions, the bell is rung and the + original text is restored. + An argument of @var{n} moves @var{n} 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 @code{TAB}, but is unbound + by default. + @ifset BashFeatures @item complete-filename (M-/) *************** *** 998,1002 **** it as a command name. Command completion attempts to match the text against aliases, reserved words, shell ! functions, builtins, and finally executable filenames, in that order. --- 1076,1080 ---- 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. *************** *** 1053,1057 **** @item prefix-meta (ESC) ! Make the next character that you type be metafied. This is for people without a meta key. Typing @samp{ESC f} is equivalent to typing @samp{M-f}. --- 1131,1135 ---- @item prefix-meta (ESC) ! Make the next character typed be metafied. This is for keyboards without a meta key. Typing @samp{ESC f} is equivalent to typing @samp{M-f}. *************** *** 1061,1065 **** @item revert-line (M-r) ! Undo all changes made to this line. This is like typing the @code{undo} command enough times to get back to the beginning. --- 1139,1143 ---- @item revert-line (M-r) ! Undo all changes made to this line. This is like executing the @code{undo} command enough times to get back to the beginning. *************** *** 1094,1098 **** @item 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 @var{inputrc} file. This command is unbound by default. --- 1172,1176 ---- @item 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 @var{inputrc} file. This command is unbound by default. *************** *** 1100,1109 **** @item dump-variables () Print all of the settable 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 @var{inputrc} file. This command is unbound by default. @item dump-macros () ! Print all of the readline key sequences bound to macros and the strings they ouput. If a numeric argument is supplied, the output is formatted in such a way that it can be made part --- 1178,1187 ---- @item dump-variables () Print all of the settable 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 @var{inputrc} file. This command is unbound by default. @item dump-macros () ! Print all of the Readline key sequences bound to macros and the strings they ouput. If a numeric argument is supplied, the output is formatted in such a way that it can be made part *************** *** 1117,1122 **** @item glob-list-expansions (C-x g) The list of expansions that would have been generated by ! @code{glob-expand-word} ! is inserted into the line, replacing the word before point. @item display-shell-version (C-x C-v) --- 1195,1199 ---- @item glob-list-expansions (C-x g) The list of expansions that would have been generated by ! @code{glob-expand-word} is displayed, and the line is redrawn. @item display-shell-version (C-x C-v) *************** *** 1124,1138 **** @item shell-expand-line (M-C-e) ! Expand the line the way the shell does when it reads it. This ! performs alias and history expansion as well as all of the shell ! word expansions. @item history-expand-line (M-^) Perform history expansion on the current line. ! @item alias-expand-line Perform alias expansion on the current line (@pxref{Aliases}). ! @item history-and-alias-expand-line Perform history and alias expansion on the current line. --- 1201,1219 ---- @item 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 (@pxref{Shell Expansions}). @item history-expand-line (M-^) Perform history expansion on the current line. ! @item magic-space () ! Perform history expansion on the current line and insert a space ! (@pxref{History Interaction}). ! ! @item alias-expand-line () Perform alias expansion on the current line (@pxref{Aliases}). ! @item history-and-alias-expand-line () Perform history and alias expansion on the current line. diff -Nrc2 bash-2.01.1/lib/readline/examples/rltest.c bash-2.02/lib/readline/examples/rltest.c *** bash-2.01.1/lib/readline/examples/rltest.c Wed Jan 29 11:54:28 1997 --- bash-2.02/lib/readline/examples/rltest.c Thu Aug 21 14:04:06 1997 *************** *** 20,29 **** #include "history.h" main () { ! HIST_ENTRY **history_list (); ! char *temp = (char *)NULL; ! char *prompt = "readline$ "; ! int done = 0; while (!done) --- 20,33 ---- #include "history.h" + extern HIST_ENTRY **history_list (); + main () { ! char *temp, *prompt; ! int done; ! ! temp = (char *)NULL; ! prompt = "readline$ "; ! done = 0; while (!done) *************** *** 48,64 **** if (strcmp (temp, "list") == 0) { ! HIST_ENTRY **list = history_list (); register int i; if (list) { for (i = 0; list[i]; i++) ! { ! fprintf (stderr, "%d: %s\r\n", i, list[i]->line); ! free (list[i]->line); ! } ! free (list); } } free (temp); } } --- 52,67 ---- if (strcmp (temp, "list") == 0) { ! HIST_ENTRY **list; register int i; + + list = history_list (); if (list) { for (i = 0; list[i]; i++) ! fprintf (stderr, "%d: %s\r\n", i, list[i]->line); } } free (temp); } + exit (0); } diff -Nrc2 bash-2.01.1/lib/readline/funmap.c bash-2.02/lib/readline/funmap.c *** bash-2.01.1/lib/readline/funmap.c Mon Mar 3 15:50:48 1997 --- bash-2.02/lib/readline/funmap.c Mon Sep 8 16:02:33 1997 *************** *** 95,98 **** --- 95,99 ---- { "kill-region", rl_kill_region }, { "kill-word", rl_kill_word }, + { "menu-complete", rl_menu_complete }, { "next-history", rl_get_next_history }, { "non-incremental-forward-search-history", rl_noninc_forward_search }, *************** *** 100,103 **** --- 101,107 ---- { "non-incremental-forward-search-history-again", rl_noninc_forward_search_again }, { "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again }, + #ifdef __CYGWIN32__ + { "paste-from-clipboard", rl_paste_from_clipboard }, + #endif { "possible-completions", rl_possible_completions }, { "previous-history", rl_get_previous_history }, diff -Nrc2 bash-2.01.1/lib/readline/histexpand.c bash-2.02/lib/readline/histexpand.c *** bash-2.01.1/lib/readline/histexpand.c Wed Mar 26 13:17:27 1997 --- bash-2.02/lib/readline/histexpand.c Thu Nov 6 15:44:45 1997 *************** *** 36,39 **** --- 36,42 ---- #if defined (HAVE_UNISTD_H) + # ifndef _MINIX + # include + # endif # include #endif *************** *** 48,51 **** --- 51,57 ---- #include "histlib.h" + #define HISTORY_WORD_DELIMITERS " \t\n;&()|<>" + #define HISTORY_QUOTE_CHARACTERS "\"'`" + static char error_pointer; *************** *** 824,829 **** l = strlen (hstring); ! /* Grovel the string. Only backslash can quote the history escape ! character. We also handle arg specifiers. */ /* Before we grovel forever, see if the history_expansion_char appears --- 830,835 ---- 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 *************** *** 853,857 **** { cc = string[i + 1]; ! if (string[i] == history_expansion_char) { if (!cc || member (cc, history_no_expand_chars)) --- 859,874 ---- { cc = string[i + 1]; ! /* The history_comment_char, if set, appearing that 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 && ! (i == 0 || member (string[i - 1], HISTORY_WORD_DELIMITERS))) ! { ! while (string[i]) ! i++; ! break; ! } ! else if (string[i] == history_expansion_char) { if (!cc || member (cc, history_no_expand_chars)) *************** *** 868,871 **** --- 885,890 ---- break; } + /* XXX - at some point, might want to extend this to handle + double quotes as well. */ else if (history_quotes_inhibit_expansion && string[i] == '\'') { *************** *** 905,908 **** --- 924,929 ---- if (tchar == history_expansion_char) tchar = -3; + else if (tchar == history_comment_char) + tchar = -2; switch (tchar) *************** *** 940,943 **** --- 961,977 ---- } + case -2: /* history_comment_char */ + if (i == 0 || member (string[i - 1], HISTORY_WORD_DELIMITERS)) + { + temp = xmalloc (l - i + 1); + strcpy (temp, string + i); + ADD_STRING (temp); + free (temp); + i = l; + } + else + ADD_CHAR (string[i]); + break; + case -3: /* history_expansion_char */ cc = string[i + 1]; *************** *** 1239,1243 **** /* Get word from string + i; */ ! if (member (string[i], "\"'`")) delimiter = string[i++]; --- 1273,1277 ---- /* Get word from string + i; */ ! if (member (string[i], HISTORY_QUOTE_CHARACTERS)) delimiter = string[i++]; *************** *** 1263,1270 **** } ! if (!delimiter && (member (string[i], " \t\n;&()|<>"))) break; ! if (!delimiter && member (string[i], "\"'`")) delimiter = string[i]; } --- 1297,1304 ---- } ! if (!delimiter && (member (string[i], HISTORY_WORD_DELIMITERS))) break; ! if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS)) delimiter = string[i]; } diff -Nrc2 bash-2.01.1/lib/readline/histfile.c bash-2.02/lib/readline/histfile.c *** bash-2.01.1/lib/readline/histfile.c Fri Jul 18 13:58:33 1997 --- bash-2.02/lib/readline/histfile.c Mon Oct 6 13:45:12 1997 *************** *** 33,37 **** #include ! #include #include #include --- 33,39 ---- #include ! #ifndef _MINIX ! # include ! #endif #include #include *************** *** 130,137 **** { register int line_start, line_end; ! char *input, *buffer = (char *)NULL; int file, current_line; struct stat finfo; input = history_filename (filename); file = open (input, O_RDONLY|O_BINARY, 0666); --- 132,141 ---- { register int line_start, line_end; ! char *input, *buffer; int file, current_line; struct stat finfo; + size_t file_size; + buffer = (char *)NULL; input = history_filename (filename); file = open (input, O_RDONLY|O_BINARY, 0666); *************** *** 140,146 **** goto error_and_exit; ! buffer = xmalloc ((int)finfo.st_size + 1); ! if (read (file, buffer, finfo.st_size) != finfo.st_size) { error_and_exit: --- 144,160 ---- 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) ! { ! #if defined (EFBIG) ! errno = EFBIG; ! #endif ! goto error_and_exit; ! } ! buffer = xmalloc (file_size + 1); ! if (read (file, buffer, file_size) != file_size) { error_and_exit: *************** *** 158,162 **** /* Set TO to larger than end of file if negative. */ if (to < 0) ! to = finfo.st_size; /* Start at beginning of file, work to end. */ --- 172,176 ---- /* Set TO to larger than end of file if negative. */ if (to < 0) ! to = file_size; /* Start at beginning of file, work to end. */ *************** *** 164,170 **** /* Skip lines until we are at FROM. */ ! while (line_start < finfo.st_size && current_line < from) { ! for (line_end = line_start; line_end < finfo.st_size; line_end++) if (buffer[line_end] == '\n') { --- 178,184 ---- /* Skip lines until we are at FROM. */ ! while (line_start < file_size && current_line < from) { ! for (line_end = line_start; line_end < file_size; line_end++) if (buffer[line_end] == '\n') { *************** *** 177,181 **** /* If there are lines left to gobble, then gobble them now. */ ! for (line_end = line_start; line_end < finfo.st_size; line_end++) if (buffer[line_end] == '\n') { --- 191,195 ---- /* If there are lines left to gobble, then gobble them now. */ ! for (line_end = line_start; line_end < file_size; line_end++) if (buffer[line_end] == '\n') { *************** *** 210,213 **** --- 224,228 ---- char *buffer, *filename; struct stat finfo; + size_t file_size; buffer = (char *)NULL; *************** *** 218,223 **** goto truncate_exit; ! buffer = xmalloc ((int)finfo.st_size + 1); ! chars_read = read (file, buffer, finfo.st_size); close (file); --- 233,250 ---- 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) ! errno = EFBIG; ! #endif ! goto truncate_exit; ! } ! ! buffer = xmalloc (file_size + 1); ! chars_read = read (file, buffer, file_size); close (file); *************** *** 249,253 **** if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1)) { ! write (file, buffer + i, finfo.st_size - i); close (file); } --- 276,280 ---- if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1)) { ! write (file, buffer + i, file_size - i); close (file); } diff -Nrc2 bash-2.01.1/lib/readline/history.c bash-2.02/lib/readline/history.c *** bash-2.01.1/lib/readline/history.c Thu Jun 27 17:19:11 1996 --- bash-2.02/lib/readline/history.c Fri Jul 18 17:05:41 1997 *************** *** 39,42 **** --- 39,45 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/lib/readline/histsearch.c bash-2.02/lib/readline/histsearch.c *** bash-2.01.1/lib/readline/histsearch.c Fri Sep 29 10:57:05 1995 --- bash-2.02/lib/readline/histsearch.c Fri Jul 18 17:06:05 1997 *************** *** 34,37 **** --- 34,40 ---- #endif /* HAVE_STDLIB_H */ #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/lib/readline/isearch.c bash-2.02/lib/readline/isearch.c *** bash-2.01.1/lib/readline/isearch.c Mon Aug 18 11:55:27 1997 --- bash-2.02/lib/readline/isearch.c Tue Aug 12 12:55:24 1997 *************** *** 263,267 **** } ! if (c >= 0 && (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT) && c != CTRL ('g')) { rl_execute_next (c); --- 263,267 ---- } ! if (c >= 0 && (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT) && c != CTRL ('G')) { rl_execute_next (c); *************** *** 298,301 **** --- 298,316 ---- free (lines); return 0; + + #if 0 + /* delete character from search string. */ + case -3: + if (search_string_index == 0) + ding (); + else + { + search_string[--search_string_index] = '\0'; + /* This is tricky. To do this right, we need to keep a + stack of search positions for the current search, with + sentinels marking the beginning and end. */ + } + break; + #endif default: diff -Nrc2 bash-2.01.1/lib/readline/keymaps.h bash-2.02/lib/readline/keymaps.h *** bash-2.01.1/lib/readline/keymaps.h Tue Aug 16 12:01:00 1994 --- bash-2.02/lib/readline/keymaps.h Thu Sep 4 13:11:41 1997 *************** *** 40,46 **** /* A keymap contains one entry for each key in the ASCII set. Each entry consists of a type and a pointer. ! POINTER is the address of a function to run, or the address of a keymap to indirect through. ! TYPE says which kind of thing POINTER is. */ typedef struct _keymap_entry { char type; --- 40,46 ---- /* A keymap contains one entry for each key in the ASCII set. Each entry consists of a type and a pointer. ! FUNCTION is the address of a function to run, or the address of a keymap to indirect through. ! TYPE says which kind of thing FUNCTION is. */ typedef struct _keymap_entry { char type; diff -Nrc2 bash-2.01.1/lib/readline/kill.c bash-2.02/lib/readline/kill.c *** bash-2.01.1/lib/readline/kill.c Wed Apr 2 15:20:55 1997 --- bash-2.02/lib/readline/kill.c Wed Jul 9 15:10:26 1997 *************** *** 496,510 **** } ! /* Yank the COUNTth argument from the previous history line. */ ! int ! rl_yank_nth_arg (count, ignore) ! int count, ignore; { register HIST_ENTRY *entry; char *arg; entry = previous_history (); if (entry) ! next_history (); else { --- 496,525 ---- } ! /* Yank the COUNTh argument from the previous history line, skipping ! HISTORY_SKIP lines before looking for the `previous line'. */ ! static int ! rl_yank_nth_arg_internal (count, ignore, history_skip) ! int count, ignore, history_skip; { register HIST_ENTRY *entry; char *arg; + int i; + + if (history_skip) + { + for (i = 0; i < history_skip; i++) + entry = previous_history (); + } entry = previous_history (); if (entry) ! { ! if (history_skip) ! { ! for (i = 0; i < history_skip; i++) ! next_history (); ! } ! next_history (); ! } else { *************** *** 539,542 **** --- 554,565 ---- } + /* Yank the COUNTth argument from the previous history line. */ + int + rl_yank_nth_arg (count, ignore) + int count, ignore; + { + return (rl_yank_nth_arg_internal (count, ignore, 0)); + } + /* Yank the last argument from the previous history line. This `knows' how rl_yank_nth_arg treats a count of `$'. With an argument, this *************** *** 546,552 **** int count, key; { ! if (rl_explicit_arg) ! return (rl_yank_nth_arg (count, key)); else ! return (rl_yank_nth_arg ('$', key)); } --- 569,634 ---- int count, key; { ! static int history_skip = 0; ! static int explicit_arg_p = 0; ! static int count_passed = 1; ! static int direction = 1; ! ! if (rl_last_func != rl_yank_last_arg) ! { ! history_skip = 0; ! explicit_arg_p = rl_explicit_arg; ! count_passed = count; ! direction = 1; ! } ! else ! { ! rl_do_undo (); ! if (count < 1) ! direction = -direction; ! history_skip += direction; ! if (history_skip < 0) ! history_skip = 0; ! count_passed = count; ! } ! ! if (explicit_arg_p) ! return (rl_yank_nth_arg_internal (count, key, history_skip)); else ! return (rl_yank_nth_arg_internal ('$', key, history_skip)); ! } ! ! /* A special paste command for users of Cygnus's cygwin32. */ ! #if defined (__CYGWIN32__) ! #include ! ! int ! rl_paste_from_clipboard (count, key) ! int count, key; ! { ! char *data, *ptr; ! int len; ! ! if (OpenClipboard (NULL) == 0) ! return (0); ! ! data = (char *)GetClipboardData (CF_TEXT); ! if (data) ! { ! ptr = strchr (data, '\r'); ! if (ptr) ! { ! len = ptr - data; ! ptr = xmalloc (len + 1); ! ptr[len] = '\0'; ! strncpy (ptr, data, len); ! } ! else ! ptr = data; ! rl_insert_text (ptr); ! if (ptr != data) ! free (ptr); ! CloseClipboard (); ! } ! return (0); } + #endif /* __CYGWIN32__ */ diff -Nrc2 bash-2.01.1/lib/readline/nls.c bash-2.02/lib/readline/nls.c *** bash-2.01.1/lib/readline/nls.c Fri May 2 12:05:47 1997 --- bash-2.02/lib/readline/nls.c Mon Nov 17 11:05:22 1997 *************** *** 70,74 **** "iso88599", "iso885910", ! "koi8r", 0 }; --- 70,75 ---- "iso88599", "iso885910", ! "koi8r", ! "koi8-r", 0 }; diff -Nrc2 bash-2.01.1/lib/readline/parens.c bash-2.02/lib/readline/parens.c *** bash-2.01.1/lib/readline/parens.c Fri Jul 5 12:59:00 1996 --- bash-2.02/lib/readline/parens.c Fri Feb 20 16:38:30 1998 *************** *** 102,106 **** FD_ZERO (&readfds); FD_SET (fileno (rl_instream), &readfds); ! timer.tv_sec = 1; timer.tv_usec = 500; --- 102,106 ---- FD_ZERO (&readfds); FD_SET (fileno (rl_instream), &readfds); ! timer.tv_sec = 0; timer.tv_usec = 500; diff -Nrc2 bash-2.01.1/lib/readline/readline.c bash-2.02/lib/readline/readline.c *** bash-2.01.1/lib/readline/readline.c Wed Apr 2 15:22:39 1997 --- bash-2.02/lib/readline/readline.c Thu Apr 2 11:16:12 1998 *************** *** 65,69 **** #ifndef RL_LIBRARY_VERSION ! # define RL_LIBRARY_VERSION "2.1-bash" #endif --- 65,69 ---- #ifndef RL_LIBRARY_VERSION ! # define RL_LIBRARY_VERSION "2.2-bash" #endif *************** *** 79,83 **** --- 79,87 ---- extern int _rl_init_terminal_io (); extern void _rl_enable_meta_key (); + #ifdef _MINIX + extern void _rl_output_character_function (); + #else extern int _rl_output_character_function (); + #endif extern void _rl_get_screen_size (); *************** *** 1027,1030 **** --- 1031,1046 ---- } #undef _RL_FIX_POINT + + void + _rl_replace_text (text, start, end) + char *text; + int start, end; + { + rl_begin_undo_group (); + rl_delete_text (start, end + 1); + rl_point = start; + rl_insert_text (text); + rl_end_undo_group (); + } /* **************************************************************** */ diff -Nrc2 bash-2.01.1/lib/readline/readline.h bash-2.02/lib/readline/readline.h *** bash-2.01.1/lib/readline/readline.h Mon Aug 18 12:13:08 1997 --- bash-2.02/lib/readline/readline.h Mon Sep 8 16:00:15 1997 *************** *** 74,77 **** --- 74,78 ---- rl_backward_kill_word (), rl_backward_kill_line (), rl_transpose_words (), rl_complete (), rl_possible_completions (), rl_insert_completions (), + rl_menu_complete (), rl_do_lowercase_version (), rl_kill_full_line (), rl_digit_argument (), rl_universal_argument (), rl_abort (), *************** *** 94,104 **** extern void rl_callback_handler_remove (); /* These are *both* defined even when VI_MODE is not. */ extern int rl_vi_editing_mode (), rl_emacs_editing_mode (); /* Non incremental history searching. */ ! extern int ! rl_noninc_forward_search (), rl_noninc_reverse_search (), ! rl_noninc_forward_search_again (), rl_noninc_reverse_search_again (); /* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */ --- 95,111 ---- extern void rl_callback_handler_remove (); + /* Not available unless __CYGWIN32__ is defined. */ + #ifdef __CYGWIN32__ + extern int rl_paste_from_clipboard (); + #endif + /* These are *both* defined even when VI_MODE is not. */ extern int rl_vi_editing_mode (), rl_emacs_editing_mode (); /* Non incremental history searching. */ ! extern int rl_noninc_forward_search (); ! extern int rl_noninc_reverse_search (); ! extern int rl_noninc_forward_search_again (); ! extern int rl_noninc_reverse_search_again (); /* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */ *************** *** 154,157 **** --- 161,165 ---- extern int rl_bind_key (), rl_bind_key_in_map (); extern int rl_unbind_key (), rl_unbind_key_in_map (); + extern int rl_unbind_function_in_map (), rl_unbind_command_in_map (); extern int rl_set_key (); extern int rl_generic_bind (); diff -Nrc2 bash-2.01.1/lib/readline/rltty.h bash-2.02/lib/readline/rltty.h *** bash-2.01.1/lib/readline/rltty.h Fri Apr 11 13:19:09 1997 --- bash-2.02/lib/readline/rltty.h Wed Jul 9 15:32:09 1997 *************** *** 43,57 **** #endif ! /* Stuff for `struct winsize' on various systems. */ ! #if defined (HAVE_SYS_STREAM_H) ! # include ! #endif /* HAVE_SYS_STREAM_H */ ! #if defined (HAVE_SYS_PTEM_H) ! # include ! # define _IO_PTEM_H /* work around SVR4.2 1.1.4 bug */ ! #endif /* HAVE_SYS_PTEM_H */ ! #if defined (HAVE_SYS_PTE_H) ! # include ! #endif /* HAVE_SYS_PTE_H */ /* Define _POSIX_VDISABLE if we are not using the `new' tty driver and --- 43,47 ---- #endif ! #include "rlwinsize.h" /* Define _POSIX_VDISABLE if we are not using the `new' tty driver and diff -Nrc2 bash-2.01.1/lib/readline/rlwinsize.h bash-2.02/lib/readline/rlwinsize.h *** bash-2.01.1/lib/readline/rlwinsize.h Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/readline/rlwinsize.h Wed Jul 9 15:27:42 1997 *************** *** 0 **** --- 1,58 ---- + /* rlwinsize.h -- an attempt to isolate some of the system-specific defines + for `struct winsize' and TIOCGWINSZ. */ + + /* Copyright (C) 1997 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library 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. + + The Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ + + #if !defined (_RLWINSIZE_H_) + #define _RLWINSIZE_H_ + + #if defined (HAVE_CONFIG_H) + # include "config.h" + #endif + + /* Try to find the definitions of `struct winsize' and TIOGCWINSZ */ + + #if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ) + # include + #endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */ + + #if defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL) + # include + #endif /* STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */ + + /* Not in either of the standard places, look around. */ + #if !defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL) + # if defined (HAVE_SYS_STREAM_H) + # include + # endif /* HAVE_SYS_STREAM_H */ + # if defined (HAVE_SYS_PTEM_H) /* SVR4.2, at least, has it here */ + # include + # define _IO_PTEM_H /* work around SVR4.2 1.1.4 bug */ + # endif /* HAVE_SYS_PTEM_H */ + # if defined (HAVE_SYS_PTE_H) /* ??? */ + # include + # endif /* HAVE_SYS_PTE_H */ + #endif /* !STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */ + + #endif /* _RL_WINSIZE_H */ + + diff -Nrc2 bash-2.01.1/lib/readline/shell.c bash-2.02/lib/readline/shell.c *** bash-2.01.1/lib/readline/shell.c Wed Apr 16 15:35:33 1997 --- bash-2.02/lib/readline/shell.c Tue Feb 3 10:31:56 1998 *************** *** 28,31 **** --- 28,34 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif /* HAVE_UNISTD_H */ *************** *** 36,39 **** --- 39,48 ---- # include "ansi_stdlib.h" #endif /* HAVE_STDLIB_H */ + + #if defined (HAVE_STRING_H) + # include + #else + # include + #endif /* !HAVE_STRING_H */ extern char *xmalloc (), *xrealloc (); diff -Nrc2 bash-2.01.1/lib/readline/terminal.c bash-2.02/lib/readline/terminal.c *** bash-2.01.1/lib/readline/terminal.c Wed Apr 16 16:28:12 1997 --- bash-2.02/lib/readline/terminal.c Fri Jul 18 17:08:00 1997 *************** *** 435,438 **** --- 435,446 ---- /* A function for the use of tputs () */ + #ifdef _MINIX + void + _rl_output_character_function (c) + int c; + { + putc (c, _rl_out_stream); + } + #else /* !_MINIX */ int _rl_output_character_function (c) *************** *** 441,445 **** return putc (c, _rl_out_stream); } ! /* Write COUNT characters from STRING to the output stream. */ void --- 449,453 ---- return putc (c, _rl_out_stream); } ! #endif /* !_MINIX */ /* Write COUNT characters from STRING to the output stream. */ void *************** *** 520,535 **** /* **************************************************************** */ - static int - outchar (c) - int c; - { - return putc (c, rl_outstream); - } - void _rl_enable_meta_key () { if (term_has_meta && term_mm) ! tputs (term_mm, 1, outchar); } --- 528,536 ---- /* **************************************************************** */ void _rl_enable_meta_key () { if (term_has_meta && term_mm) ! tputs (term_mm, 1, _rl_output_character_function); } *************** *** 539,544 **** { if (on && term_ks) ! tputs (term_ks, 1, outchar); else if (!on && term_ke) ! tputs (term_ke, 1, outchar); } --- 540,545 ---- { if (on && term_ks) ! tputs (term_ks, 1, _rl_output_character_function); else if (!on && term_ke) ! tputs (term_ke, 1, _rl_output_character_function); } diff -Nrc2 bash-2.01.1/lib/readline/tilde.c bash-2.02/lib/readline/tilde.c *** bash-2.01.1/lib/readline/tilde.c Tue Jul 1 17:25:52 1997 --- bash-2.02/lib/readline/tilde.c Fri Jul 18 17:08:41 1997 *************** *** 25,28 **** --- 25,31 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/lib/readline/util.c bash-2.02/lib/readline/util.c *** bash-2.01.1/lib/readline/util.c Wed Mar 26 13:16:40 1997 --- bash-2.02/lib/readline/util.c Fri Oct 3 11:12:47 1997 *************** *** 167,170 **** --- 167,222 ---- } + + /* A function for simple tilde expansion. */ + int + rl_tilde_expand (ignore, key) + int ignore, key; + { + register int start, end; + char *homedir, *temp; + int len; + + end = rl_point; + start = end - 1; + + if (rl_point == rl_end && rl_line_buffer[rl_point] == '~') + { + homedir = tilde_expand ("~"); + _rl_replace_text (homedir, start, end); + return (0); + } + else if (rl_line_buffer[start] != '~') + { + for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--) + ; + start++; + } + + end = start; + do + end++; + while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end); + + if (whitespace (rl_line_buffer[end]) || end >= rl_end) + end--; + + /* If the first character of the current word is a tilde, perform + tilde expansion and insert the result. If not a tilde, do + nothing. */ + if (rl_line_buffer[start] == '~') + { + len = end - start + 1; + temp = xmalloc (len + 1); + strncpy (temp, rl_line_buffer + start, len); + temp[len] = '\0'; + homedir = tilde_expand (temp); + free (temp); + + _rl_replace_text (homedir, start, end); + } + + return (0); + } + /* **************************************************************** */ /* */ *************** *** 300,302 **** --- 352,364 ---- { return (isdigit (c) ? c - '0' : c); + } + + /* Backwards compatibility, now that savestring has been removed from + all `public' readline header files. */ + #undef _rl_savestring + char * + _rl_savestring (s) + char *s; + { + return ((char *)strcpy (xmalloc (1 + (int)strlen (s)), (s))); } diff -Nrc2 bash-2.01.1/lib/readline/vi_mode.c bash-2.02/lib/readline/vi_mode.c *** bash-2.01.1/lib/readline/vi_mode.c Fri Nov 15 16:29:26 1996 --- bash-2.02/lib/readline/vi_mode.c Tue Mar 17 10:41:27 1998 *************** *** 616,619 **** --- 616,626 ---- int len, start, end; + if (up == 0) + { + if (vi_insert_buffer_size >= 1) + vi_insert_buffer[0] = '\0'; + return; + } + start = up->start; end = up->end; diff -Nrc2 bash-2.01.1/lib/sh/Makefile.in bash-2.02/lib/sh/Makefile.in *** bash-2.01.1/lib/sh/Makefile.in Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/Makefile.in Tue Feb 24 16:11:48 1998 *************** *** 0 **** --- 1,164 ---- + # + # Makefile for the Bash library + # + + srcdir = @srcdir@ + VPATH = .:@srcdir@ + topdir = @top_srcdir@ + BUILD_DIR = @BUILD_DIR@ + + POSIX_INC = ${topdir}/lib/posixheaders + + INSTALL = @INSTALL@ + INSTALL_PROGRAM = @INSTALL_PROGRAM@ + INSTALL_DATA = @INSTALL_DATA@ + + CC = @CC@ + RANLIB = @RANLIB@ + AR = @AR@ + RM = rm -f + CP = cp + MV = mv + + CFLAGS = @CFLAGS@ + LOCAL_CFLAGS = @LOCAL_CFLAGS@ + CPPFLAGS = @CPPFLAGS@ + LDFLAGS = @LDFLAGS@ @LOCAL_LDFLAGS@ + + PROFILE_FLAGS = @PROFILE_FLAGS@ + + DEFS = @DEFS@ + LOCAL_DEFS = @LOCAL_DEFS@ + + INCLUDES = -I. -I../.. -I$(topdir) -I$(topdir)/lib -I$(POSIX_INC) -I$(srcdir) + + CCFLAGS = ${PROFILE_FLAGS} ${INCLUDES} $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) \ + $(CFLAGS) $(CPPFLAGS) + + .c.o: + $(CC) -c $(CCFLAGS) $< + + # The name of the library target. + LIBRARY_NAME = libsh.a + + # The C code source files for this library. + CSOURCES = clktck.c getcwd.c getenv.c oslib.c setlinebuf.c \ + strcasecmp.c strerror.c strtod.c strtol.c strtoul.c \ + vprint.c itos.c + + # The header files for this library. + HSOURCES = + + # The object files contained in $(LIBRARY_NAME) + OBJECTS = clktck.o getcwd.o getenv.o oslib.o setlinebuf.o \ + strcasecmp.o strerror.o strtod.o strtol.o strtoul.o \ + vprint.o itos.o + + SUPPORT = Makefile + + all: $(LIBRARY_NAME) + + $(LIBRARY_NAME): $(OBJECTS) + $(RM) $@ + $(AR) cr $@ $(OBJECTS) + -test -n "$(RANLIB)" && $(RANLIB) $@ + + force: + + # The rule for 'includes' is written funny so that the if statement + # always returns TRUE unless there really was an error installing the + # include files. + install: + + clean: + $(RM) $(OBJECTS) $(LIBRARY_NAME) + + realclean distclean maintainer-clean: clean + $(RM) Makefile + + mostlyclean: clean + + # Dependencies + + # rules for losing makes, like SunOS + clktck.o: clktck.c + getcwd.o: getcwd.c + getenv.o: getenv.c + itos.o: itos.c + oslib.o: oslib.c + setlinebuf.o: setlinebuf.c + strcasecmp.o: strcasecmp.c + strerror.o: strerror.c + strtod.o: strtod.c + strtol.o: strtol.c + strtoul.o: strtoul.c + vprint.o: vprint.c + + # all files in the library depend on config.h + clktck.o: ${BUILD_DIR}/config.h + getcwd.o: ${BUILD_DIR}/config.h + getenv.o: ${BUILD_DIR}/config.h + itos.o: ${BUILD_DIR}/config.h + oslib.o: ${BUILD_DIR}/config.h + setlinebuf.o: ${BUILD_DIR}/config.h + strcasecmp.o: ${BUILD_DIR}/config.h + strerror.o: ${BUILD_DIR}/config.h + strtod.o: ${BUILD_DIR}/config.h + strtol.o: ${BUILD_DIR}/config.h + strtoul.o: ${BUILD_DIR}/config.h + vprint.o: ${BUILD_DIR}/config.h + + clktck.o: ${topdir}/bashtypes.h + + getcwd.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${topdir}/maxpath.h + getcwd.o: ${POSIX_INC}/posixstat.h ${POSIX_INC}/posixdir.h + getcwd.o: ${POSIX_INC}/memalloc.h ${POSIX_INC}/ansi_stdlib.h + + getenv.o: ${topdir}/bashansi.h ${topdir}/ansi_stdlib.h + getenv.o: ${topdir}/shell.h ${topdir}/bashjmp.h ${topdir}/posixjmp.h + getenv.o: ${topdir}/command.h ${topdir}/stdc.h ${topdir}/error.h + getenv.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h + getenv.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h + getenv.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h + getenv.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h + getenv.o: ${topdir}/pathnames.h ${topdir}/externs.h + + itos.o: ${topdir}/bashansi.h ${topdir}/ansi_stdlib.h + itos.o: ${topdir}/shell.h ${topdir}/bashjmp.h ${topdir}/posixjmp.h + itos.o: ${topdir}/command.h ${topdir}/stdc.h ${topdir}/error.h + itos.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h + itos.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h + itos.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h + itos.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h + itos.o: ${topdir}/pathnames.h ${topdir}/externs.h + + oslib.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${topdir}/maxpath.h + oslib.o: ${topdir}/shell.h ${topdir}/bashjmp.h ${topdir}/posixjmp.h + oslib.o: ${topdir}/command.h ${topdir}/stdc.h ${topdir}/error.h + oslib.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h + oslib.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h + oslib.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h + oslib.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h + oslib.o: ${topdir}/pathnames.h ${topdir}/externs.h + oslib.o: ${POSIX_INC}/posixstat.h ${POSIX_INC}/filecntl.h + oslib.o: ${POSIX_INC}/ansi_stdlib.h + + strcasecmp.o: ${topdir}/stdc.h ${topdir}/bashansi.h ${topdir}/ansi_stdlib.h + + strerror.o: ${topdir}/bashtypes.h + strerror.o: ${topdir}/shell.h ${topdir}/bashjmp.h ${topdir}/posixjmp.h + strerror.o: ${topdir}/command.h ${topdir}/stdc.h ${topdir}/error.h + strerror.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h + strerror.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h + strerror.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h + strerror.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h + strerror.o: ${topdir}/pathnames.h ${topdir}/externs.h + + strtod.o: ${topdir}/bashansi.h + strtod.o: ${POSIX_INC}/ansi_stdlib.h + + strtol.o: ${topdir}/bashansi.h + strtol.o: ${POSIX_INC}/ansi_stdlib.h + + strtoul.o: ${topdir}/bashansi.h + strtoul.o: ${POSIX_INC}/ansi_stdlib.h diff -Nrc2 bash-2.01.1/lib/sh/clktck.c bash-2.02/lib/sh/clktck.c *** bash-2.01.1/lib/sh/clktck.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/clktck.c Fri Oct 10 11:35:23 1997 *************** *** 0 **** --- 1,55 ---- + /* clktck.c - get the value of CLK_TCK. */ + + /* Copyright (C) 1997 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */ + + #include + + #include + #include + + #if defined (HAVE_UNISTD_H) + # include + #endif + + #if !defined (HAVE_SYSCONF) || !defined (_SC_CLK_TCK) + # if !defined (CLK_TCK) + # if defined (HZ) + # define CLK_TCK HZ + # else + # define CLK_TCK 60 + # endif + # endif /* !CLK_TCK */ + #endif /* !HAVE_SYSCONF && !_SC_CLK_TCK */ + + long + get_clk_tck () + { + static long retval = 0; + + if (retval != 0) + return (retval); + + #if defined (HAVE_SYSCONF) && defined (_SC_CLK_TCK) + retval = sysconf (_SC_CLK_TCK); + #else /* !SYSCONF || !_SC_CLK_TCK */ + retval = CLK_TCK; + #endif /* !SYSCONF || !_SC_CLK_TCK */ + + return (retval); + } diff -Nrc2 bash-2.01.1/lib/sh/getcwd.c bash-2.02/lib/sh/getcwd.c *** bash-2.01.1/lib/sh/getcwd.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/getcwd.c Wed Feb 4 14:53:58 1998 *************** *** 0 **** --- 1,319 ---- + /* getcwd.c -- stolen from the GNU C library and modified to work with bash. */ + + /* Copyright (C) 1991 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., 675 Mass Ave, + Cambridge, MA 02139, USA. */ + + #include + + #if !defined (HAVE_GETCWD) + + #include + #include + + #if defined (HAVE_LIMITS_H) + # include + #endif + + #if defined (HAVE_UNISTD_H) + # include + #endif + + #include + #include + #include + #include + + #include + + #if !defined (errno) + extern int errno; + #endif /* !errno */ + + #if defined (__STDC__) + # define CONST const + # define PTR void * + #else /* !__STDC__ */ + # define CONST + # define PTR char * + #endif /* !__STDC__ */ + + #if !defined (PATH_MAX) + # if defined (MAXPATHLEN) + # define PATH_MAX MAXPATHLEN + # else /* !MAXPATHLEN */ + # define PATH_MAX 1024 + # endif /* !MAXPATHLEN */ + #endif /* !PATH_MAX */ + + #if !defined (HAVE_LSTAT) + # define lstat stat + #endif + + /* Get the pathname of the current working directory, + and put it in SIZE bytes of BUF. Returns NULL if the + directory couldn't be determined or SIZE was too small. + If successful, returns BUF. In GNU, if BUF is NULL, + an array is allocated with `malloc'; the array is SIZE + bytes long, unless SIZE <= 0, in which case it is as + big as necessary. */ + #if defined (__STDC__) + char * + getcwd (char *buf, size_t size) + #else /* !__STDC__ */ + char * + getcwd (buf, size) + char *buf; + size_t size; + #endif /* !__STDC__ */ + { + static CONST char dots[] + = "../../../../../../../../../../../../../../../../../../../../../../../\ + ../../../../../../../../../../../../../../../../../../../../../../../../../../\ + ../../../../../../../../../../../../../../../../../../../../../../../../../.."; + CONST char *dotp, *dotlist; + size_t dotsize; + dev_t rootdev, thisdev; + ino_t rootino, thisino; + char path[PATH_MAX + 1]; + register char *pathp; + char *pathbuf; + size_t pathsize; + struct stat st; + int saved_errno; + + if (buf != NULL && size == 0) + { + errno = EINVAL; + return ((char *)NULL); + } + + pathsize = sizeof (path); + pathp = &path[pathsize]; + *--pathp = '\0'; + pathbuf = path; + + if (stat (".", &st) < 0) + return ((char *)NULL); + thisdev = st.st_dev; + thisino = st.st_ino; + + if (stat ("/", &st) < 0) + return ((char *)NULL); + rootdev = st.st_dev; + rootino = st.st_ino; + + saved_errno = 0; + + dotsize = sizeof (dots) - 1; + dotp = &dots[sizeof (dots)]; + dotlist = dots; + while (!(thisdev == rootdev && thisino == rootino)) + { + register DIR *dirstream; + register struct dirent *d; + dev_t dotdev; + ino_t dotino; + char mount_point; + int namlen; + + /* Look at the parent directory. */ + if (dotp == dotlist) + { + /* My, what a deep directory tree you have, Grandma. */ + char *new; + if (dotlist == dots) + { + new = malloc (dotsize * 2 + 1); + if (new == NULL) + goto lose; + memcpy (new, dots, dotsize); + } + else + { + new = realloc ((PTR) dotlist, dotsize * 2 + 1); + if (new == NULL) + goto lose; + } + memcpy (&new[dotsize], new, dotsize); + dotp = &new[dotsize]; + dotsize *= 2; + new[dotsize] = '\0'; + dotlist = new; + } + + dotp -= 3; + + /* Figure out if this directory is a mount point. */ + if (stat (dotp, &st) < 0) + goto lose; + dotdev = st.st_dev; + dotino = st.st_ino; + mount_point = dotdev != thisdev; + + /* Search for the last directory. */ + dirstream = opendir (dotp); + if (dirstream == NULL) + goto lose; + while ((d = readdir (dirstream)) != NULL) + { + if (d->d_name[0] == '.' && + (d->d_name[1] == '\0' || + (d->d_name[1] == '.' && d->d_name[2] == '\0'))) + continue; + if (mount_point || d->d_fileno == thisino) + { + char *name; + + namlen = D_NAMLEN(d); + name = (char *) + alloca (dotlist + dotsize - dotp + 1 + namlen + 1); + memcpy (name, dotp, dotlist + dotsize - dotp); + name[dotlist + dotsize - dotp] = '/'; + memcpy (&name[dotlist + dotsize - dotp + 1], + d->d_name, namlen + 1); + if (lstat (name, &st) < 0) + { + #if 0 + int save = errno; + (void) closedir (dirstream); + errno = save; + goto lose; + #else + saved_errno = errno; + #endif + } + if (st.st_dev == thisdev && st.st_ino == thisino) + break; + } + } + if (d == NULL) + { + #if 0 + int save = errno; + #else + int save = errno ? errno : saved_errno; + #endif + (void) closedir (dirstream); + errno = save; + goto lose; + } + else + { + size_t space; + + while ((space = pathp - pathbuf) <= namlen) + { + char *new; + + if (pathbuf == path) + { + new = malloc (pathsize * 2); + if (!new) + goto lose; + } + else + { + new = realloc ((PTR) pathbuf, (pathsize * 2)); + if (!new) + goto lose; + pathp = new + space; + } + (void) memcpy (new + pathsize + space, pathp, pathsize - space); + pathp = new + pathsize + space; + pathbuf = new; + pathsize *= 2; + } + + pathp -= namlen; + (void) memcpy (pathp, d->d_name, namlen); + *--pathp = '/'; + (void) closedir (dirstream); + } + + thisdev = dotdev; + thisino = dotino; + } + + if (pathp == &path[sizeof(path) - 1]) + *--pathp = '/'; + + if (dotlist != dots) + free ((PTR) dotlist); + + { + size_t len = pathbuf + pathsize - pathp; + if (buf == NULL) + { + if (len < (size_t) size) + len = size; + buf = (char *) malloc (len); + if (buf == NULL) + goto lose2; + } + else if ((size_t) size < len) + { + errno = ERANGE; + goto lose2; + } + (void) memcpy((PTR) buf, (PTR) pathp, len); + } + + if (pathbuf != path) + free (pathbuf); + + return (buf); + + lose: + if ((dotlist != dots) && dotlist) + { + int e = errno; + free ((PTR) dotlist); + errno = e; + } + + lose2: + if ((pathbuf != path) && pathbuf) + { + int e = errno; + free ((PTR) pathbuf); + errno = e; + } + return ((char *)NULL); + } + + #if defined (TEST) + # include + main (argc, argv) + int argc; + char **argv; + { + char b[PATH_MAX]; + + if (getcwd(b, sizeof(b))) + { + printf ("%s\n", b); + exit (0); + } + else + { + perror ("cwd: getcwd"); + exit (1); + } + } + #endif /* TEST */ + #endif /* !HAVE_GETCWD */ diff -Nrc2 bash-2.01.1/lib/sh/getenv.c bash-2.02/lib/sh/getenv.c *** bash-2.01.1/lib/sh/getenv.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/getenv.c Fri Oct 10 11:37:28 1997 *************** *** 0 **** --- 1,99 ---- + /* getenv.c - get environment variable value from the shell's variable + list. */ + + /* Copyright (C) 1997 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */ + + #include + + #if defined (CAN_REDEFINE_GETENV) + + #if defined (HAVE_UNISTD_H) + # include + #endif + + #include + #include + + extern char **environ; + + /* We supply our own version of getenv () because we want library + routines to get the changed values of exported variables. */ + + /* The NeXT C library has getenv () defined and used in the same file. + This screws our scheme. However, Bash will run on the NeXT using + the C library getenv (), since right now the only environment variable + that we care about is HOME, and that is already defined. */ + static char *last_tempenv_value = (char *)NULL; + + char * + getenv (name) + #if defined (__linux__) || defined (__bsdi__) || defined (convex) + const char *name; + #else + char const *name; + #endif /* !__linux__ && !__bsdi__ && !convex */ + { + SHELL_VAR *var; + + var = find_tempenv_variable ((char *)name); + if (var) + { + FREE (last_tempenv_value); + + last_tempenv_value = savestring (value_cell (var)); + dispose_variable (var); + return (last_tempenv_value); + } + else if (shell_variables) + { + var = find_variable ((char *)name); + if (var && exported_p (var)) + return (value_cell (var)); + } + else + { + register int i, len; + + /* In some cases, s5r3 invokes getenv() before main(); BSD systems + using gprof also exhibit this behavior. This means that + shell_variables will be 0 when this is invoked. We look up the + variable in the real environment in that case. */ + + for (i = 0, len = strlen (name); environ[i]; i++) + { + if ((STREQN (environ[i], name, len)) && (environ[i][len] == '=')) + return (environ[i] + len + 1); + } + } + + return ((char *)NULL); + } + + /* Some versions of Unix use _getenv instead. */ + char * + _getenv (name) + #if defined (__linux__) || defined (__bsdi__) || defined (convex) + const char *name; + #else + char const *name; + #endif /* !__linux__ && !__bsdi__ && !convex */ + { + return (getenv (name)); + } + #endif /* CAN_REDEFINE_GETENV */ diff -Nrc2 bash-2.01.1/lib/sh/itos.c bash-2.02/lib/sh/itos.c *** bash-2.01.1/lib/sh/itos.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/itos.c Tue Feb 24 15:46:04 1998 *************** *** 0 **** --- 1,64 ---- + /* itos.c -- Convert integer to string. */ + + /* Copyright (C) 1998, 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. */ + + #include + + #if defined (HAVE_UNISTD_H) + # include + #endif + + #include "bashansi.h" + #include "shell.h" + + /* Number of characters that can appear in a string representation + of an integer. 32 is larger than the string rep of 2^^31 - 1. */ + #define MAX_INT_LEN 32 + + /* Integer to string conversion. This conses the string; the + caller should free it. */ + char * + itos (i) + int i; + { + char buf[MAX_INT_LEN], *p, *ret; + int negative = 0; + unsigned int ui; + + if (i < 0) + { + negative++; + i = -i; + } + + ui = (unsigned int) i; + + p = buf + MAX_INT_LEN - 2; + p[1] = '\0'; + + do + *p-- = (ui % 10) + '0'; + while (ui /= 10); + + if (negative) + *p-- = '-'; + + ret = savestring (p + 1); + return (ret); + } diff -Nrc2 bash-2.01.1/lib/sh/oslib.c bash-2.02/lib/sh/oslib.c *** bash-2.01.1/lib/sh/oslib.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/oslib.c Fri Oct 10 13:07:14 1997 *************** *** 0 **** --- 1,233 ---- + /* oslib.c - functions present only in some unix versions. */ + + /* Copyright (C) 1995 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */ + + #include + + #include + #ifndef _MINIX + # include + #endif + + #if defined (HAVE_UNISTD_H) + # include + #endif + + #include + #include + #include + + #include + #include + #include + + #include + + #if !defined (errno) + extern int errno; + #endif /* !errno */ + + /* Make the functions strchr and strrchr if they do not exist. */ + #if !defined (HAVE_STRCHR) + char * + strchr (string, c) + char *string; + int c; + { + register char *s; + + for (s = string; s && *s; s++) + if (*s == c) + return (s); + + return ((char *) NULL); + } + + char * + strrchr (string, c) + char *string; + int c; + { + register char *s, *t; + + for (s = string, t = (char *)NULL; s && *s; s++) + if (*s == c) + t = s; + return (t); + } + #endif /* !HAVE_STRCHR */ + + #if !defined (HAVE_DUP2) || defined (DUP2_BROKEN) + /* Replacement for dup2 (), for those systems which either don't have it, + or supply one with broken behaviour. */ + int + dup2 (fd1, fd2) + int fd1, fd2; + { + int saved_errno, r; + + /* If FD1 is not a valid file descriptor, then return immediately with + an error. */ + if (fcntl (fd1, F_GETFL, 0) == -1) + return (-1); + + if (fd2 < 0 || fd2 >= getdtablesize ()) + { + errno = EBADF; + return (-1); + } + + if (fd1 == fd2) + return (0); + + saved_errno = errno; + + (void) close (fd2); + r = fcntl (fd1, F_DUPFD, fd2); + + if (r >= 0) + errno = saved_errno; + else + if (errno == EINVAL) + errno = EBADF; + + /* Force the new file descriptor to remain open across exec () calls. */ + SET_OPEN_ON_EXEC (fd2); + return (r); + } + #endif /* !HAVE_DUP2 */ + + /* + * Return the total number of available file descriptors. + * + * On some systems, like 4.2BSD and its descendents, there is a system call + * that returns the size of the descriptor table: getdtablesize(). There are + * lots of ways to emulate this on non-BSD systems. + * + * On System V.3, this can be obtained via a call to ulimit: + * return (ulimit(4, 0L)); + * + * On other System V systems, NOFILE is defined in /usr/include/sys/param.h + * (this is what we assume below), so we can simply use it: + * return (NOFILE); + * + * On POSIX systems, there are specific functions for retrieving various + * configuration parameters: + * return (sysconf(_SC_OPEN_MAX)); + * + */ + + #if !defined (HAVE_GETDTABLESIZE) + int + getdtablesize () + { + # if defined (_POSIX_VERSION) && defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX) + return (sysconf(_SC_OPEN_MAX)); /* Posix systems use sysconf */ + # else /* ! (_POSIX_VERSION && HAVE_SYSCONF && _SC_OPEN_MAX) */ + # if defined (ULIMIT_MAXFDS) + return (ulimit (4, 0L)); /* System V.3 systems use ulimit(4, 0L) */ + # else /* !ULIMIT_MAXFDS */ + # if defined (NOFILE) /* Other systems use NOFILE */ + return (NOFILE); + # else /* !NOFILE */ + return (20); /* XXX - traditional value is 20 */ + # endif /* !NOFILE */ + # endif /* !ULIMIT_MAXFDS */ + # endif /* ! (_POSIX_VERSION && _SC_OPEN_MAX) */ + } + #endif /* !HAVE_GETDTABLESIZE */ + + #if !defined (HAVE_BCOPY) + void + bcopy (s,d,n) + char *d, *s; + int n; + { + FASTCOPY (s, d, n); + } + #endif /* !HAVE_BCOPY */ + + #if !defined (HAVE_BZERO) + void + bzero (s, n) + char *s; + int n; + { + register int i; + register char *r; + + for (i = 0, r = s; i < n; i++) + *r++ = '\0'; + } + #endif + + #if !defined (HAVE_GETHOSTNAME) + # if defined (HAVE_UNAME) + # include + int + gethostname (name, namelen) + char *name; + int namelen; + { + int i; + struct utsname ut; + + --namelen; + + uname (&ut); + i = strlen (ut.nodename) + 1; + strncpy (name, ut.nodename, i < namelen ? i : namelen); + name[namelen] = '\0'; + return (0); + } + # else /* !HAVE_UNAME */ + int + gethostname (name, namelen) + int name, namelen; + { + strncpy (name, "unknown", namelen); + name[namelen] = '\0'; + return 0; + } + # endif /* !HAVE_UNAME */ + #endif /* !HAVE_GETHOSTNAME */ + + #if !defined (HAVE_KILLPG) + int + killpg (pgrp, sig) + pid_t pgrp; + int sig; + { + return (kill (-pgrp, sig)); + } + #endif /* !HAVE_KILLPG */ + + #if !defined (HAVE_MKFIFO) && defined (PROCESS_SUBSTITUTION) + int + mkfifo (path, mode) + char *path; + int mode; + { + #if defined (S_IFIFO) + return (mknod (path, (mode | S_IFIFO), 0)); + #else /* !S_IFIFO */ + return (-1); + #endif /* !S_IFIFO */ + } + #endif /* !HAVE_MKFIFO && PROCESS_SUBSTITUTION */ diff -Nrc2 bash-2.01.1/lib/sh/setlinebuf.c bash-2.02/lib/sh/setlinebuf.c *** bash-2.01.1/lib/sh/setlinebuf.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/setlinebuf.c Fri Oct 10 13:10:03 1997 *************** *** 0 **** --- 1,41 ---- + /* setlinebuf.c - line-buffer a stdio stream. */ + + /* Copyright (C) 1997 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */ + + #include + + #if !defined (HAVE_SETLINEBUF) + + #include + + /* Cause STREAM to buffer lines as opposed to characters or blocks. */ + int + setlinebuf (stream) + FILE *stream; + { + #if defined (_IOLBF) + # if defined (SETVBUF_REVERSED) + setvbuf (stream, _IOLBF, (char *)NULL, BUFSIZ); + # else /* !SETVBUF_REVERSED */ + setvbuf (stream, (char *)NULL, _IOLBF, BUFSIZ); + # endif /* !SETVBUF_REVERSED */ + #endif /* _IOLBF */ + return (0); + } + #endif /* !HAVE_SETLINEBUF */ diff -Nrc2 bash-2.01.1/lib/sh/strcasecmp.c bash-2.02/lib/sh/strcasecmp.c *** bash-2.01.1/lib/sh/strcasecmp.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/strcasecmp.c Fri Oct 10 12:28:08 1997 *************** *** 0 **** --- 1,88 ---- + /* strcasecmp.c - functions for case-insensitive string comparison. */ + + /* Copyright (C) 1995 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */ + + #include + + #if !defined (HAVE_STRCASECMP) + + #include + #include + #include + + #if !defined (to_lower) + # define to_lower(c) (islower(c) ? (c) : tolower(c)) + #endif /* to_lower */ + + /* Compare at most COUNT characters from string1 to string2. Case + doesn't matter. */ + int + strncasecmp (string1, string2, count) + const char *string1; + const char *string2; + int count; + { + register const char *s1; + register const char *s2; + register int r; + + if (count <= 0 || (string1 == string2)) + return 0; + + s1 = string1; + s2 = string2; + do + { + if ((r = to_lower (*s1) - to_lower (*s2)) != 0) + return r; + if (*s1++ == '\0') + break; + s2++; + } + while (--count != 0); + + return (0); + } + + /* strcmp (), but caseless. */ + int + strcasecmp (string1, string2) + const char *string1; + const char *string2; + { + register const char *s1; + register const char *s2; + register int r; + + s1 = string1; + s2 = string2; + + if (s1 == s2) + return (0); + + while ((r = to_lower (*s1) - to_lower (*s2)) == 0) + { + if (*s1++ == '\0') + return 0; + s2++; + } + + return (r); + } + #endif /* !HAVE_STRCASECMP */ diff -Nrc2 bash-2.01.1/lib/sh/strerror.c bash-2.02/lib/sh/strerror.c *** bash-2.01.1/lib/sh/strerror.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/strerror.c Fri Oct 10 12:07:28 1997 *************** *** 0 **** --- 1,74 ---- + /* strerror.c - string corresponding to a particular value of errno. */ + + /* Copyright (C) 1995 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */ + + #include + + #if !defined (HAVE_STRERROR) + + #include + #ifndef _MINIX + # include + #endif + + #if defined (HAVE_UNISTD_H) + # include + #endif + + #include + #include + + #include + + #if !defined (errno) + extern int errno; + #endif /* !errno */ + + /* Return a string corresponding to the error number E. From + the ANSI C spec. */ + #if defined (strerror) + # undef strerror + #endif + + static char *errbase = "Unknown system error "; + + char * + strerror (e) + int e; + { + static char emsg[40]; + #if defined (HAVE_SYS_ERRLIST) + extern int sys_nerr; + extern char *sys_errlist[]; + + if (e > 0 && e < sys_nerr) + return (sys_errlist[e]); + else + #endif /* HAVE_SYS_ERRLIST */ + { + char *z; + + z = itos (e); + strcpy (emsg, errbase); + strcat (emsg, z); + free (z); + return (&emsg[0]); + } + } + #endif /* HAVE_STRERROR */ diff -Nrc2 bash-2.01.1/lib/sh/strtod.c bash-2.02/lib/sh/strtod.c *** bash-2.01.1/lib/sh/strtod.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/strtod.c Thu Oct 9 12:02:20 1997 *************** *** 0 **** --- 1,197 ---- + /* Copyright (C) 1991, 1992 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-1307, USA. */ + + #if HAVE_CONFIG_H + # include + #endif + + #ifndef HAVE_STRTOD + + #include + #ifndef errno + extern int errno; + #endif + + #include + #include + + #if HAVE_FLOAT_H + # include + #else + # define DBL_MAX 1.7976931348623159e+308 + # define DBL_MIN 2.2250738585072010e-308 + #endif + + #include + + #ifndef NULL + # define NULL 0 + #endif + + #ifndef HUGE_VAL + # define HUGE_VAL HUGE + #endif + + /* Convert NPTR to a double. If ENDPTR is not NULL, a pointer to the + character after the last one used in the number is put in *ENDPTR. */ + double + strtod (nptr, endptr) + const char *nptr; + char **endptr; + { + register const char *s; + short sign; + + /* The number so far. */ + double num; + + int got_dot; /* Found a decimal point. */ + int got_digit; /* Seen any digits. */ + + /* The exponent of the number. */ + long int exponent; + + if (nptr == NULL) + { + errno = EINVAL; + goto noconv; + } + + s = nptr; + + /* Eat whitespace. */ + while (isspace (*s)) + ++s; + + /* Get the sign. */ + sign = *s == '-' ? -1 : 1; + if (*s == '-' || *s == '+') + ++s; + + num = 0.0; + got_dot = 0; + got_digit = 0; + exponent = 0; + for (;; ++s) + { + if (isdigit (*s)) + { + got_digit = 1; + + /* Make sure that multiplication by 10 will not overflow. */ + if (num > DBL_MAX * 0.1) + /* The value of the digit doesn't matter, since we have already + gotten as many digits as can be represented in a `double'. + This doesn't necessarily mean the result will overflow. + The exponent may reduce it to within range. + + We just need to record that there was another + digit so that we can multiply by 10 later. */ + ++exponent; + else + num = (num * 10.0) + (*s - '0'); + + /* Keep track of the number of digits after the decimal point. + If we just divided by 10 here, we would lose precision. */ + if (got_dot) + --exponent; + } + else if (!got_dot && *s == '.') + /* Record that we have found the decimal point. */ + got_dot = 1; + else + /* Any other character terminates the number. */ + break; + } + + if (!got_digit) + goto noconv; + + if (tolower (*s) == 'e') + { + /* Get the exponent specified after the `e' or `E'. */ + int save = errno; + char *end; + long int exp; + + errno = 0; + ++s; + exp = strtol (s, &end, 10); + if (errno == ERANGE) + { + /* The exponent overflowed a `long int'. It is probably a safe + assumption that an exponent that cannot be represented by + a `long int' exceeds the limits of a `double'. */ + if (endptr != NULL) + *endptr = end; + if (exp < 0) + goto underflow; + else + goto overflow; + } + else if (end == s) + /* There was no exponent. Reset END to point to + the 'e' or 'E', so *ENDPTR will be set there. */ + end = (char *) s - 1; + errno = save; + s = end; + exponent += exp; + } + + if (endptr != NULL) + *endptr = (char *) s; + + if (num == 0.0) + return 0.0; + + /* Multiply NUM by 10 to the EXPONENT power, + checking for overflow and underflow. */ + + if (exponent < 0) + { + if (num < DBL_MIN * pow (10.0, (double) -exponent)) + goto underflow; + } + else if (exponent > 0) + { + if (num > DBL_MAX * pow (10.0, (double) -exponent)) + goto overflow; + } + + num *= pow (10.0, (double) exponent); + + return num * sign; + + overflow: + /* Return an overflow error. */ + errno = ERANGE; + return HUGE_VAL * sign; + + underflow: + /* Return an underflow error. */ + if (endptr != NULL) + *endptr = (char *) nptr; + errno = ERANGE; + return 0.0; + + noconv: + /* There was no number. */ + if (endptr != NULL) + *endptr = (char *) nptr; + return 0.0; + } + + #endif /* !HAVE_STRTOD */ diff -Nrc2 bash-2.01.1/lib/sh/strtol.c bash-2.02/lib/sh/strtol.c *** bash-2.01.1/lib/sh/strtol.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/strtol.c Thu Oct 9 11:37:20 1997 *************** *** 0 **** --- 1,213 ---- + /* strtol - Convert string representation of a number into an integer value. + Copyright (C) 1997 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-1307, USA. */ + + #include + + #if !defined (HAVE_STRTOL) + + #include + #include + + #ifndef errno + extern int errno; + #endif + + #ifndef __set_errno + # define __set_errno(Val) errno = (Val) + #endif + + #ifdef HAVE_LIMITS_H + # include + #endif + + #include + + #ifndef NULL + # define NULL 0 + #endif + + /* Nonzero if we are defining `strtoul', operating on unsigned integers. */ + #ifndef UNSIGNED + # define UNSIGNED 0 + # define RETTYPE long + #else + # define RETTYPE unsigned long + #endif + + /* Determine the name. */ + #if UNSIGNED + # define strtol strtoul + #endif + + #ifndef CHAR_BIT + # define CHAR_BIT 8 + #endif + + #ifndef ULONG_MAX + # define ULONG_MAX ((unsigned long) ~(unsigned long) 0) + # define ULONG_MIN ((unsigned long) 0 - ULONG_MAX) + #endif + + #ifndef LONG_MAX + # define LONG_MAX ((long) (ULONG_MAX >> 1)) + # define LONG_MIN ((long) (0 - LONG_MAX)) + #endif + + /* Convert NPTR to an `unsigned long int' or `long int' in base BASE. + If BASE is 0 the base is determined by the presence of a leading + zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. + If BASE is < 2 or > 36, it is reset to 10. + If ENDPTR is not NULL, a pointer to the character after the last + one converted is stored in *ENDPTR. */ + + RETTYPE + strtol (nptr, endptr, base) + const char *nptr; + char **endptr; + int base; + { + int negative; + register unsigned long cutoff, i; + register unsigned int cutlim; + register const char *s; + register unsigned char c; + const char *save, *end; + int overflow; + + if (base < 0 || base == 1 || base > 36) + base = 10; + + save = s = nptr; + + /* Skip white space. */ + while (isspace (*s)) + ++s; + if (*s == '\0') + goto noconv; + + /* Check for a sign. */ + if (*s == '-' || *s == '+') + { + negative = (*s == '-'); + ++s; + } + else + negative = 0; + + if (base == 16 && *s == '0' && toupper (s[1]) == 'X') + s += 2; + + /* If BASE is zero, figure it out ourselves. */ + if (base == 0) + if (*s == '0') + { + if (toupper (s[1]) == 'X') + { + s += 2; + base = 16; + } + else + base = 8; + } + else + base = 10; + + /* Save the pointer so we can check later if anything happened. */ + save = s; + + end = NULL; + + cutoff = ULONG_MAX / (unsigned long int) base; + cutlim = ULONG_MAX % (unsigned long int) base; + + overflow = 0; + i = 0; + for (c = *s; c != '\0'; c = *++s) + { + if (s == end) + break; + + if (c >= '0' && c <= '9') + c -= '0'; + else if (isalpha (c)) + c = toupper (c) - 'A' + 10; + else + break; + + if ((int) c >= base) + break; + + /* Check for overflow. */ + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + i *= (unsigned long int) base; + i += c; + } + } + + /* Check if anything actually happened. */ + if (s == save) + goto noconv; + + /* Store in ENDPTR the address of one character + past the last character we converted. */ + if (endptr != NULL) + *endptr = (char *) s; + + #if !UNSIGNED + /* Check for a value that is within the range of + `unsigned long int', but outside the range of `long int'. */ + if (overflow == 0 + && i > (negative + ? -((unsigned long) (LONG_MIN + 1)) + 1 + : (unsigned long) LONG_MAX)) + overflow = 1; + #endif + + if (overflow) + { + __set_errno (ERANGE); + #if UNSIGNED + return ULONG_MAX; + #else + return negative ? LONG_MIN : LONG_MAX; + #endif + } + + /* Return the result with the appropriate sign. */ + return (negative ? -i : i); + + noconv: + /* We must handle a special case here: the base is 0 or 16 and the + first two characters are '0' and 'x', but the rest are no + hexadecimal digits. This is no error case. We return 0 and + ENDPTR points to the `x'. */ + if (endptr != NULL) + { + if (save - nptr >= 2 && toupper (save[-1]) == 'X' && save[-2] == '0') + *endptr = (char *) &save[-1]; + else + /* There was no number to convert. */ + *endptr = (char *) nptr; + } + + return 0L; + } + + #endif /* !HAVE_STRTOL */ diff -Nrc2 bash-2.01.1/lib/sh/strtoul.c bash-2.02/lib/sh/strtoul.c *** bash-2.01.1/lib/sh/strtoul.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/strtoul.c Thu Oct 9 11:38:08 1997 *************** *** 0 **** --- 1,26 ---- + /* Copyright (C) 1997 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-1307, USA. */ + + #include + + #ifndef HAVE_STRTOUL + + #define UNSIGNED 1 + #undef HAVE_STRTOL + + #include + + #endif /* !HAVE_STRTOUL */ diff -Nrc2 bash-2.01.1/lib/sh/vprint.c bash-2.02/lib/sh/vprint.c *** bash-2.01.1/lib/sh/vprint.c Wed Dec 31 19:00:00 1969 --- bash-2.02/lib/sh/vprint.c Tue Oct 14 15:37:34 1997 *************** *** 0 **** --- 1,85 ---- + /* vprint.c -- v[fs]printf() for 4.[23] BSD systems. */ + + /* Copyright (C) 1987,1989 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. */ + + #include + + #if defined (USE_VFPRINTF_EMULATION) + + #include + + #if !defined (NULL) + # if defined (__STDC__) + # define NULL ((void *)0) + # else + # define NULL 0x0 + # endif /* __STDC__ */ + #endif /* !NULL */ + + /* + * Beware! Don't trust the value returned by either of these functions; it + * seems that pre-4.3-tahoe implementations of _doprnt () return the first + * argument, i.e. a char *. + */ + #include + + int + vfprintf (iop, fmt, ap) + FILE *iop; + char *fmt; + va_list ap; + { + int len; + char localbuf[BUFSIZ]; + + if (iop->_flag & _IONBF) + { + iop->_flag &= ~_IONBF; + iop->_ptr = iop->_base = localbuf; + len = _doprnt (fmt, ap, iop); + (void) fflush (iop); + iop->_flag |= _IONBF; + iop->_base = NULL; + iop->_bufsiz = 0; + iop->_cnt = 0; + } + else + len = _doprnt (fmt, ap, iop); + return (ferror (iop) ? EOF : len); + } + + /* + * Ditto for vsprintf + */ + int + vsprintf (str, fmt, ap) + char *str, *fmt; + va_list ap; + { + FILE f; + int len; + + f._flag = _IOWRT|_IOSTRG; + f._ptr = str; + f._cnt = 32767; + len = _doprnt (fmt, ap, &f); + *f._ptr = 0; + return (len); + } + #endif /* USE_VFPRINTF_EMULATION */ diff -Nrc2 bash-2.01.1/lib/termcap/termcap.c bash-2.02/lib/termcap/termcap.c *** bash-2.01.1/lib/termcap/termcap.c Wed Aug 16 20:50:06 1995 --- bash-2.02/lib/termcap/termcap.c Thu Jul 17 09:55:30 1997 *************** *** 22,30 **** /* Get the O_* definitions for open et al. */ #include - #ifdef USG5 - #include #endif #else /* not HAVE_CONFIG_H */ --- 22,31 ---- /* Get the O_* definitions for open et al. */ + #ifndef _MINIX #include #endif + #include + #else /* not HAVE_CONFIG_H */ *************** *** 778,780 **** #endif /* TEST */ - --- 779,780 ---- diff -Nrc2 bash-2.01.1/lib/tilde/tilde.c bash-2.02/lib/tilde/tilde.c *** bash-2.01.1/lib/tilde/tilde.c Tue Jul 1 17:25:52 1997 --- bash-2.02/lib/tilde/tilde.c Fri Jul 18 17:08:41 1997 *************** *** 25,28 **** --- 25,31 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif diff -Nrc2 bash-2.01.1/list.c bash-2.02/list.c *** bash-2.01.1/list.c Thu Feb 27 10:20:13 1997 --- bash-2.02/list.c Fri Nov 21 12:50:50 1997 *************** *** 23,26 **** --- 23,29 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 31,34 **** --- 34,38 ---- GENERIC_LIST global_error_list; + #ifdef INCLUDE_UNUSED /* Call FUNCTION on every member of LIST, a generic list. */ void *************** *** 50,53 **** --- 54,58 ---- (*function) (words->word->word); } + #endif /* INCLUDE_UNUSED */ /* Reverse the chain of structures in LIST. Output the new head diff -Nrc2 bash-2.01.1/mailcheck.c bash-2.02/mailcheck.c *** bash-2.01.1/mailcheck.c Fri Jul 18 13:59:48 1997 --- bash-2.02/mailcheck.c Wed Feb 4 15:30:33 1998 *************** *** 24,28 **** #include "bashtypes.h" #include "posixstat.h" ! #include #if defined (HAVE_UNISTD_H) # include --- 24,30 ---- #include "bashtypes.h" #include "posixstat.h" ! #ifndef _MINIX ! # include ! #endif #if defined (HAVE_UNISTD_H) # include *************** *** 45,49 **** time_t access_time; time_t mod_time; ! long file_size; } FILEINFO; --- 47,51 ---- time_t access_time; time_t mod_time; ! off_t file_size; } FILEINFO; *************** *** 118,122 **** { \ mailfiles[i]->access_time = mailfiles[i]->mod_time = 0; \ ! mailfiles[i]->file_size = 0L; \ } \ while (0) --- 120,124 ---- { \ mailfiles[i]->access_time = mailfiles[i]->mod_time = 0; \ ! mailfiles[i]->file_size = 0; \ } \ while (0) *************** *** 158,162 **** mailfiles[i]->mod_time = finfo.st_mtime; mailfiles[i]->access_time = finfo.st_atime; ! mailfiles[i]->file_size = (long)finfo.st_size; } free (filename); --- 160,164 ---- mailfiles[i]->mod_time = finfo.st_mtime; mailfiles[i]->access_time = finfo.st_atime; ! mailfiles[i]->file_size = finfo.st_size; } free (filename); *************** *** 249,253 **** int i; { ! long size; struct stat finfo; char *file; --- 251,255 ---- int i; { ! off_t size; struct stat finfo; char *file; *************** *** 292,295 **** --- 294,298 ---- char *mp; + get_current_user_info (); mp = xmalloc (2 + sizeof (DEFAULT_MAIL_DIRECTORY) + strlen (current_user.user_name)); strcpy (mp, DEFAULT_MAIL_DIRECTORY); diff -Nrc2 bash-2.01.1/make_cmd.c bash-2.02/make_cmd.c *** bash-2.01.1/make_cmd.c Tue Mar 4 10:58:04 1997 --- bash-2.02/make_cmd.c Fri Sep 12 14:21:01 1997 *************** *** 24,28 **** #include #include "bashtypes.h" ! #include #include "filecntl.h" #include "bashansi.h" --- 24,30 ---- #include #include "bashtypes.h" ! #ifndef _MINIX ! # include ! #endif #include "filecntl.h" #include "bashansi.h" *************** *** 101,105 **** } - #ifdef INCLUDE_UNUSED WORD_DESC * make_word_from_token (token) --- 103,106 ---- *************** *** 113,117 **** return (make_word (tokenizer)); } - #endif WORD_LIST * --- 114,117 ---- *************** *** 289,292 **** --- 289,358 ---- COMMAND * + make_arith_command (exp) + WORD_LIST *exp; + { + #if defined (DPAREN_ARITHMETIC) + COMMAND *command; + ARITH_COM *temp; + + command = (COMMAND *)xmalloc (sizeof (COMMAND)); + command->value.Arith = temp = (ARITH_COM *)xmalloc (sizeof (ARITH_COM)); + + temp->flags = 0; + temp->line = line_number; + temp->exp = exp; + + command->type = cm_arith; + command->redirects = (REDIRECT *)NULL; + command->flags = 0; + + return (command); + #else + return ((COMMAND *)NULL); + #endif + } + + #if defined (COND_COMMAND) + struct cond_com * + make_cond_node (type, op, left, right) + int type; + WORD_DESC *op; + struct cond_com *left, *right; + { + COND_COM *temp; + + temp = (COND_COM *)xmalloc (sizeof (COND_COM)); + temp->flags = 0; + temp->line = line_number; + temp->type = type; + temp->op = op; + temp->left = left; + temp->right = right; + + return (temp); + } + #endif + + COMMAND * + make_cond_command (cond_node) + COND_COM *cond_node; + { + #if defined (COND_COMMAND) + COMMAND *command; + + command = (COMMAND *)xmalloc (sizeof (COMMAND)); + command->value.Cond = cond_node; + + command->type = cm_cond; + command->redirects = (REDIRECT *)NULL; + command->flags = 0; + + return (command); + #else + return ((COMMAND *)NULL); + #endif + } + + COMMAND * make_bare_simple_command () { *************** *** 517,521 **** temp->name = name; temp->line = lineno; ! temp->ignore = 0; command->line = lstart; return (make_command (cm_function_def, (SIMPLE_COM *)temp)); --- 583,587 ---- temp->name = name; temp->line = lineno; ! temp->flags = 0; command->line = lstart; return (make_command (cm_function_def, (SIMPLE_COM *)temp)); diff -Nrc2 bash-2.01.1/make_cmd.h bash-2.02/make_cmd.h *** bash-2.01.1/make_cmd.h Wed Oct 4 14:27:47 1995 --- bash-2.02/make_cmd.h Fri Sep 12 12:38:41 1997 *************** *** 47,51 **** --- 47,58 ---- extern COMMAND *clean_simple_command __P((COMMAND *)); + extern COMMAND *make_arith_command __P((WORD_LIST *)); + extern COMMAND *make_select_command __P((WORD_DESC *, WORD_LIST *, COMMAND *)); + + #if defined (COND_COMMAND) + extern COND_COM *make_cond_node __P((int, WORD_DESC *, COND_COM *, COND_COM *)); + extern COMMAND *make_cond_command __P((COND_COM *)); + #endif extern COMMAND *connect_async_list __P((COMMAND *, COMMAND *, int)); diff -Nrc2 bash-2.01.1/nojobs.c bash-2.02/nojobs.c *** bash-2.01.1/nojobs.c Tue Mar 25 10:53:50 1997 --- bash-2.02/nojobs.c Wed Jul 30 13:44:51 1997 *************** *** 356,361 **** as fd 0, but have not changed the buffered stream corresponding to the old fd 0. We don't want to sync the stream in this case. */ ! if (default_buffered_input != -1 && ! (!async_p || default_buffered_input > 0)) sync_buffered_stream (default_buffered_input); #endif /* BUFFERED_INPUT */ --- 356,360 ---- as fd 0, but have not changed the buffered stream corresponding to the old fd 0. We don't want to sync the stream in this case. */ ! if (default_buffered_input != -1 && (!async_p || default_buffered_input > 0)) sync_buffered_stream (default_buffered_input); #endif /* BUFFERED_INPUT */ *************** *** 387,395 **** { #if defined (BUFFERED_INPUT) ! if (default_buffered_input > 0) ! { ! close_buffered_fd (default_buffered_input); ! default_buffered_input = bash_input.location.buffered_fd = -1; ! } #endif /* BUFFERED_INPUT */ --- 386,390 ---- { #if defined (BUFFERED_INPUT) ! unset_bash_input (0); #endif /* BUFFERED_INPUT */ diff -Nrc2 bash-2.01.1/oslib.c bash-2.02/oslib.c *** bash-2.01.1/oslib.c Fri Jul 18 14:00:51 1997 --- bash-2.02/oslib.c Wed Dec 31 19:00:00 1969 *************** *** 1,430 **** - /* oslib.c - functions present only in some unix versions. */ - - /* Copyright (C) 1995 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. */ - - #include "config.h" - - #include "bashtypes.h" - #include - - #if defined (HAVE_UNISTD_H) - # include - #endif - - #include "posixstat.h" - #include "filecntl.h" - #include "bashansi.h" - - #include - #include - #include - - #include "shell.h" - #include "maxpath.h" - - #if !defined (errno) - extern int errno; - #endif /* !errno */ - - /* A standard error message to use when getcwd() returns NULL. */ - char *bash_getcwd_errstr = "getcwd: cannot access parent directories"; - - #if !defined (HAVE_SYSCONF) || !defined (_SC_CLK_TCK) - # if !defined (CLK_TCK) - # if defined (HZ) - # define CLK_TCK HZ - # else - # define CLK_TCK 60 - # endif - # endif /* !CLK_TCK */ - #endif /* !HAVE_SYSCONF && !_SC_CLK_TCK */ - - long - get_clk_tck () - { - static long retval = 0; - - if (retval != 0) - return (retval); - - #if defined (HAVE_SYSCONF) && defined (_SC_CLK_TCK) - retval = sysconf (_SC_CLK_TCK); - #else /* !SYSCONF || !_SC_CLK_TCK */ - retval = CLK_TCK; - #endif /* !SYSCONF || !_SC_CLK_TCK */ - - return (retval); - } - - /* Make the functions strchr and strrchr if they do not exist. */ - #if !defined (HAVE_STRCHR) - char * - strchr (string, c) - char *string; - int c; - { - register char *s; - - for (s = string; s && *s; s++) - if (*s == c) - return (s); - - return ((char *) NULL); - } - - char * - strrchr (string, c) - char *string; - int c; - { - register char *s, *t; - - for (s = string, t = (char *)NULL; s && *s; s++) - if (*s == c) - t = s; - return (t); - } - #endif /* !HAVE_STRCHR */ - - #if !defined (HAVE_STRCASECMP) - - #if !defined (to_lower) - # define to_lower(c) (islower(c) ? (c) : tolower(c)) - #endif /* to_lower */ - - /* Compare at most COUNT characters from string1 to string2. Case - doesn't matter. */ - int - strncasecmp (string1, string2, count) - const char *string1, *string2; - int count; - { - register char *s1, *s2; - register int r; - - if (count > 0) - { - s1 = (char *)string1; - s2 = (char *)string2; - do - { - if ((r = to_lower (*s1) - to_lower (*s2)) != 0) - return r; - if (*s1++ == '\0') - break; - s2++; - } - while (--count != 0); - } - return (0); - } - - /* strcmp (), but caseless. */ - int - strcasecmp (string1, string2) - const char *string1, *string2; - { - register char *s1, *s2; - register int r; - - s1 = (char *)string1; - s2 = (char *)string2; - - while ((r = to_lower (*s1) - to_lower (*s2)) == 0) - { - if (*s1++ == '\0') - return 0; - s2++; - } - return (r); - } - #endif /* !HAVE_STRCASECMP */ - - /* Return a string corresponding to the error number E. From - the ANSI C spec. */ - #if defined (strerror) - # undef strerror - #endif - - #if !defined (HAVE_STRERROR) - char * - strerror (e) - int e; - { - static char emsg[40]; - #if defined (HAVE_SYS_ERRLIST) - extern int sys_nerr; - extern char *sys_errlist[]; - - if (e > 0 && e < sys_nerr) - return (sys_errlist[e]); - else - #endif /* HAVE_SYS_ERRLIST */ - { - sprintf (emsg, "Unknown error %d", e); - return (&emsg[0]); - } - } - #endif /* HAVE_STRERROR */ - - #if !defined (HAVE_DUP2) || defined (DUP2_BROKEN) - /* Replacement for dup2 (), for those systems which either don't have it, - or supply one with broken behaviour. */ - int - dup2 (fd1, fd2) - int fd1, fd2; - { - int saved_errno, r; - - /* If FD1 is not a valid file descriptor, then return immediately with - an error. */ - if (fcntl (fd1, F_GETFL, 0) == -1) - return (-1); - - if (fd2 < 0 || fd2 >= getdtablesize ()) - { - errno = EBADF; - return (-1); - } - - if (fd1 == fd2) - return (0); - - saved_errno = errno; - - (void) close (fd2); - r = fcntl (fd1, F_DUPFD, fd2); - - if (r >= 0) - errno = saved_errno; - else - if (errno == EINVAL) - errno = EBADF; - - /* Force the new file descriptor to remain open across exec () calls. */ - SET_OPEN_ON_EXEC (fd2); - return (r); - } - #endif /* !HAVE_DUP2 */ - - /* - * Return the total number of available file descriptors. - * - * On some systems, like 4.2BSD and its descendents, there is a system call - * that returns the size of the descriptor table: getdtablesize(). There are - * lots of ways to emulate this on non-BSD systems. - * - * On System V.3, this can be obtained via a call to ulimit: - * return (ulimit(4, 0L)); - * - * On other System V systems, NOFILE is defined in /usr/include/sys/param.h - * (this is what we assume below), so we can simply use it: - * return (NOFILE); - * - * On POSIX systems, there are specific functions for retrieving various - * configuration parameters: - * return (sysconf(_SC_OPEN_MAX)); - * - */ - - #if !defined (HAVE_GETDTABLESIZE) - int - getdtablesize () - { - # if defined (_POSIX_VERSION) && defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX) - return (sysconf(_SC_OPEN_MAX)); /* Posix systems use sysconf */ - # else /* ! (_POSIX_VERSION && HAVE_SYSCONF && _SC_OPEN_MAX) */ - # if defined (ULIMIT_MAXFDS) - return (ulimit (4, 0L)); /* System V.3 systems use ulimit(4, 0L) */ - # else /* !ULIMIT_MAXFDS */ - # if defined (NOFILE) /* Other systems use NOFILE */ - return (NOFILE); - # else /* !NOFILE */ - return (20); /* XXX - traditional value is 20 */ - # endif /* !NOFILE */ - # endif /* !ULIMIT_MAXFDS */ - # endif /* ! (_POSIX_VERSION && _SC_OPEN_MAX) */ - } - #endif /* !HAVE_GETDTABLESIZE */ - - #if !defined (HAVE_BCOPY) - void - bcopy (s,d,n) - char *d, *s; - int n; - { - FASTCOPY (s, d, n); - } - #endif /* !HAVE_BCOPY */ - - #if !defined (HAVE_BZERO) - void - bzero (s, n) - char *s; - int n; - { - register int i; - register char *r; - - for (i = 0, r = s; i < n; i++) - *r++ = '\0'; - } - #endif - - #if !defined (HAVE_GETHOSTNAME) - # if defined (HAVE_UNAME) - # include - int - gethostname (name, namelen) - char *name; - int namelen; - { - int i; - struct utsname ut; - - --namelen; - - uname (&ut); - i = strlen (ut.nodename) + 1; - strncpy (name, ut.nodename, i < namelen ? i : namelen); - name[namelen] = '\0'; - return (0); - } - # else /* !HAVE_UNAME */ - int - gethostname (name, namelen) - int name, namelen; - { - strncpy (name, "unknown", namelen); - name[namelen] = '\0'; - return 0; - } - # endif /* !HAVE_UNAME */ - #endif /* !HAVE_GETHOSTNAME */ - - #if !defined (HAVE_KILLPG) - int - killpg (pgrp, sig) - pid_t pgrp; - int sig; - { - return (kill (-pgrp, sig)); - } - #endif /* !HAVE_KILLPG */ - - - /* We supply our own version of getenv () because we want library - routines to get the changed values of exported variables. */ - - /* The NeXT C library has getenv () defined and used in the same file. - This screws our scheme. However, Bash will run on the NeXT using - the C library getenv (), since right now the only environment variable - that we care about is HOME, and that is already defined. */ - #if defined (CAN_REDEFINE_GETENV) - static char *last_tempenv_value = (char *)NULL; - extern char **environ; - - char * - getenv (name) - #if defined (__linux__) || defined (__bsdi__) || defined (convex) - const char *name; - #else - char const *name; - #endif /* !__linux__ && !__bsdi__ && !convex */ - { - SHELL_VAR *var; - - var = find_tempenv_variable ((char *)name); - if (var) - { - FREE (last_tempenv_value); - - last_tempenv_value = savestring (value_cell (var)); - dispose_variable (var); - return (last_tempenv_value); - } - else if (shell_variables) - { - var = find_variable ((char *)name); - if (var && exported_p (var)) - return (value_cell (var)); - } - else - { - register int i, len; - - /* In some cases, s5r3 invokes getenv() before main(); BSD systems - using gprof also exhibit this behavior. This means that - shell_variables will be 0 when this is invoked. We look up the - variable in the real environment in that case. */ - - for (i = 0, len = strlen (name); environ[i]; i++) - { - if ((STREQN (environ[i], name, len)) && (environ[i][len] == '=')) - return (environ[i] + len + 1); - } - } - - return ((char *)NULL); - } - - /* Some versions of Unix use _getenv instead. */ - char * - _getenv (name) - #if defined (__linux__) || defined (__bsdi__) || defined (convex) - const char *name; - #else - char const *name; - #endif /* !__linux__ && !__bsdi__ && !convex */ - { - return (getenv (name)); - } - - #endif /* CAN_REDEFINE_GETENV */ - - #if !defined (HAVE_MKFIFO) && defined (PROCESS_SUBSTITUTION) - int - mkfifo (path, mode) - char *path; - int mode; - { - #if defined (S_IFIFO) - return (mknod (path, (mode | S_IFIFO), 0)); - #else /* !S_IFIFO */ - return (-1); - #endif /* !S_IFIFO */ - } - #endif - - #if !defined (HAVE_SETLINEBUF) - /* Cause STREAM to buffer lines as opposed to characters or blocks. */ - int - setlinebuf (stream) - FILE *stream; - { - #if defined (_IOLBF) - # if defined (SETVBUF_REVERSED) - setvbuf (stream, _IOLBF, (char *)NULL, BUFSIZ); - # else /* !SETVBUF_REVERSED */ - setvbuf (stream, (char *)NULL, _IOLBF, BUFSIZ); - # endif /* !SETVBUF_REVERSED */ - #endif /* _IOLBF */ - return (0); - } - #endif /* !HAVE_SETLINEBUF */ --- 0 ---- diff -Nrc2 bash-2.01.1/parse.y bash-2.02/parse.y *** bash-2.01.1/parse.y Mon Aug 25 14:15:15 1997 --- bash-2.02/parse.y Wed Mar 25 12:16:23 1998 *************** *** 65,71 **** #if defined (PROMPT_STRING_DECODE) ! #include ! #include ! #include "maxpath.h" #endif /* PROMPT_STRING_DECODE */ --- 65,73 ---- #if defined (PROMPT_STRING_DECODE) ! # ifndef _MINIX ! # include ! # endif ! # include ! # include "maxpath.h" #endif /* PROMPT_STRING_DECODE */ *************** *** 75,78 **** --- 77,87 ---- #define YYDEBUG 0 + #if defined (EXTENDED_GLOB) + #define PATTERN_CHAR(c) \ + ((c) == '@' || (c) == '*' || (c) == '+' || (c) == '?' || (c) == '!') + + extern int extended_glob; + #endif + extern int eof_encountered; extern int no_line_editing, running_under_emacs; *************** *** 86,90 **** extern char *dist_version; extern int patch_level; ! extern int dump_translatable_strings; extern Function *last_shell_builtin, *this_shell_builtin; #if defined (BUFFERED_INPUT) --- 95,99 ---- extern char *dist_version; extern int patch_level; ! extern int dump_translatable_strings, dump_po_strings; extern Function *last_shell_builtin, *this_shell_builtin; #if defined (BUFFERED_INPUT) *************** *** 104,107 **** --- 113,119 ---- static int yylex (); static int parse_arith_cmd (); + #if defined (COND_COMMAND) + static COMMAND *parse_cond_command (); + #endif static int read_token_word (); static void discard_parser_constructs (); *************** *** 181,191 **** /* Reserved words. Members of the first group are only recognized in the case that they are preceded by a list_terminator. Members ! of the second group are recognized only under special circumstances. */ %token IF THEN ELSE ELIF FI CASE ESAC FOR SELECT WHILE UNTIL DO DONE FUNCTION ! %token IN BANG TIME TIMEOPT /* More general tokens. yylex () knows how to make these. */ %token WORD ASSIGNMENT_WORD %token NUMBER %token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND %token GREATER_AND SEMI_SEMI LESS_LESS_MINUS AND_GREATER LESS_GREATER --- 193,207 ---- /* Reserved words. Members of the first group are only recognized in the case that they are preceded by a list_terminator. Members ! of the second group are for [[...]] commands. Members of the ! third group are recognized only under special circumstances. */ %token IF THEN ELSE ELIF FI CASE ESAC FOR SELECT WHILE UNTIL DO DONE FUNCTION ! %token COND_START COND_END COND_ERROR ! %token IN BANG TIME TIMEOPT /* More general tokens. yylex () knows how to make these. */ %token WORD ASSIGNMENT_WORD %token NUMBER + %token ARITH_CMD + %token COND_CMD %token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND %token GREATER_AND SEMI_SEMI LESS_LESS_MINUS AND_GREATER LESS_GREATER *************** *** 198,201 **** --- 214,219 ---- %type simple_command shell_command %type for_command select_command case_command group_command + %type arith_command + %type cond_command %type function_def if_command elif_clause subshell %type redirection redirection_list *************** *** 480,483 **** --- 498,505 ---- | group_command { $$ = $1; } + | arith_command + { $$ = $1; } + | cond_command + { $$ = $1; } | function_def { $$ = $1; } *************** *** 560,563 **** --- 582,593 ---- ; + arith_command: ARITH_CMD + { $$ = make_arith_command ($1); } + ; + + cond_command: COND_START COND_CMD COND_END + { $$ = $2; } + ; + elif_clause: ELIF compound_list THEN compound_list { $$ = make_if_command ($2, $4, (COMMAND *)NULL); } *************** *** 748,751 **** --- 778,783 ---- #define PST_CMDSUBST 0x040 /* $( ... ) command substitution */ #define PST_CASESTMT 0x080 /* parsing a case statement */ + #define PST_CONDCMD 0x100 /* parsing a [[...]] command */ + #define PST_CONDEXPR 0x200 /* parsing the guts of [[...]] */ /* Initial size to allocate for tokens, and the *************** *** 1085,1088 **** --- 1117,1125 ---- int line_number = 0; + #if defined (COND_COMMAND) + static int cond_lineno; + static int cond_token; + #endif + STREAM_SAVER *stream_list = (STREAM_SAVER *)NULL; *************** *** 1099,1106 **** /* If we have a buffered stream, clear out buffers[fd]. */ if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0) ! { ! saver->bstream = buffers[bash_input.location.buffered_fd]; ! buffers[bash_input.location.buffered_fd] = (BUFFERED_STREAM *)NULL; ! } #endif /* BUFFERED_INPUT */ --- 1136,1141 ---- /* If we have a buffered stream, clear out buffers[fd]. */ if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0) ! saver->bstream = set_buffered_stream (bash_input.location.buffered_fd, ! (BUFFERED_STREAM *)NULL); #endif /* BUFFERED_INPUT */ *************** *** 1148,1152 **** } } ! buffers[bash_input.location.buffered_fd] = saver->bstream; } #endif /* BUFFERED_INPUT */ --- 1183,1187 ---- } } ! set_buffered_stream (bash_input.location.buffered_fd, saver->bstream); } #endif /* BUFFERED_INPUT */ *************** *** 1181,1185 **** */ ! #if defined (ALIAS) #define END_OF_ALIAS 0 --- 1216,1224 ---- */ ! #if defined (ALIAS) || defined (DPAREN_ARITHMETIC) ! ! #if !defined (ALIAS) ! typedef void *alias_t; ! #endif #define END_OF_ALIAS 0 *************** *** 1198,1202 **** --- 1237,1243 ---- int expand_alias; /* Value to set expand_alias to when string is popped. */ char *saved_line; + #if defined (ALIAS) alias_t *expander; /* alias that caused this line to be pushed. */ + #endif int saved_line_size, saved_line_index, saved_line_terminator; } STRING_SAVER; *************** *** 1225,1234 **** --- 1266,1279 ---- temp->saved_line_index = shell_input_line_index; temp->saved_line_terminator = shell_input_line_terminator; + #if defined (ALIAS) temp->expander = ap; + #endif temp->next = pushed_string_list; pushed_string_list = temp; + #if defined (ALIAS) if (ap) ap->flags |= AL_BEINGEXPANDED; + #endif shell_input_line = s; *************** *** 1264,1269 **** --- 1309,1316 ---- pushed_string_list = pushed_string_list->next; + #if defined (ALIAS) if (t->expander) t->expander->flags &= ~AL_BEINGEXPANDED; + #endif free ((char *)t); *************** *** 1279,1283 **** t1 = t->next; FREE (t->saved_line); ! t->expander->flags &= ~AL_BEINGEXPANDED; free ((char *)t); t = t1; --- 1326,1333 ---- t1 = t->next; FREE (t->saved_line); ! #if defined (ALIAS) ! if (t->expander) ! t->expander->flags &= ~AL_BEINGEXPANDED; ! #endif free ((char *)t); t = t1; *************** *** 1286,1290 **** } ! #endif /* ALIAS */ /* Return a line of text, taken from wherever yylex () reads input. --- 1336,1340 ---- } ! #endif /* ALIAS || DPAREN_ARITHMETIC */ /* Return a line of text, taken from wherever yylex () reads input. *************** *** 1411,1414 **** --- 1461,1468 ---- { "}", '}' }, { "!", BANG }, + #if defined (COND_COMMAND) + { "[[", COND_START }, + { "]]", COND_END }, + #endif { (char *)NULL, 0} }; *************** *** 1458,1462 **** QUIT; ! #if defined (ALIAS) /* If shell_input_line[shell_input_line_index] == 0, but there is something on the pushed list of strings, then we don't want to go --- 1512,1516 ---- QUIT; ! #if defined (ALIAS) || defined (DPAREN_ARITHMETIC) /* If shell_input_line[shell_input_line_index] == 0, but there is something on the pushed list of strings, then we don't want to go *************** *** 1465,1471 **** if (!shell_input_line || ((!shell_input_line[shell_input_line_index]) && (pushed_string_list == (STRING_SAVER *)NULL))) ! #else /* !ALIAS */ if (!shell_input_line || !shell_input_line[shell_input_line_index]) ! #endif /* !ALIAS */ { line_number++; --- 1519,1525 ---- if (!shell_input_line || ((!shell_input_line[shell_input_line_index]) && (pushed_string_list == (STRING_SAVER *)NULL))) ! #else /* !ALIAS && !DPAREN_ARITHMETIC */ if (!shell_input_line || !shell_input_line[shell_input_line_index]) ! #endif /* !ALIAS && !DPAREN_ARITHMETIC */ { line_number++; *************** *** 1618,1622 **** } ! #if defined (ALIAS) /* If C is NULL, we have reached the end of the current input string. If pushed_string_list is non-empty, it's time to pop to the previous string --- 1672,1676 ---- } ! #if defined (ALIAS) || defined (DPAREN_ARITHMETIC) /* If C is NULL, we have reached the end of the current input string. If pushed_string_list is non-empty, it's time to pop to the previous string *************** *** 1640,1644 **** } } ! #endif /* ALIAS */ if (!c && shell_input_line_terminator == EOF) --- 1694,1698 ---- } } ! #endif /* ALIAS || DPAREN_ARITHMETIC */ if (!c && shell_input_line_terminator == EOF) *************** *** 1791,1798 **** --- 1845,1858 ---- if ((parser_state & PST_CASEPAT) && (word_token_alist[i].token != ESAC)) \ break; \ + if (word_token_alist[i].token == TIME) \ + break; \ if (word_token_alist[i].token == ESAC) \ parser_state &= ~(PST_CASEPAT|PST_CASESTMT); \ else if (word_token_alist[i].token == CASE) \ parser_state |= PST_CASESTMT; \ + else if (word_token_alist[i].token == COND_END) \ + parser_state &= ~(PST_CONDCMD|PST_CONDEXPR); \ + else if (word_token_alist[i].token == COND_START) \ + parser_state |= PST_CONDCMD; \ else if (word_token_alist[i].token == '{') \ open_brace_count++; \ *************** *** 1848,1851 **** --- 1908,1932 ---- #endif /* ALIAS */ + static int + time_command_acceptable () + { + #if defined (COMMAND_TIMING) + switch (last_read_token) + { + case 0: + case ';': + case '\n': + case AND_AND: + case OR_OR: + case '&': + return 1; + default: + return 0; + } + #else + return 0; + #endif /* COMMAND_TIMING */ + } + /* Handle special cases of token recognition: IN is recognized if the last token was WORD and the token *************** *** 1862,1865 **** --- 1943,1954 ---- `}' is recognized if there is an unclosed `{' prsent. + + `-p' is returned as TIMEOPT if the last read token was TIME. + + ']]' is returned as COND_END if the parser is currently parsing + a conditional expression ((parser_state & PST_CONDEXPR) != 0) + + `time' is returned as TIME if and only if it is immediately + preceded by one of `;', `\n', `||', `&&', or `&'. */ *************** *** 1927,1933 **** --- 2016,2034 ---- } + #if defined (COMMAND_TIMING) /* Handle -p after `time'. */ if (last_read_token == TIME && token[0] == '-' && token[1] == 'p' && !token[2]) return (TIMEOPT); + #endif + + #if defined (COMMAND_TIMING) + if (STREQ (token, "time") && time_command_acceptable ()) + return (TIME); + #endif /* COMMAND_TIMING */ + + #if defined (COND_COMMAND) /* [[ */ + if ((parser_state & PST_CONDEXPR) && token[0] == ']' && token[1] == ']' && token[2] == '\0') + return (COND_END); + #endif return (-1); *************** *** 1944,1954 **** parser_state = 0; ! #if defined (ALIAS) if (pushed_string_list) ! { ! free_string_list (); ! pushed_string_list = (STRING_SAVER *)NULL; ! } ! #endif /* ALIAS */ if (shell_input_line) --- 2045,2052 ---- parser_state = 0; ! #if defined (ALIAS) || defined (DPAREN_ARITHMETIC) if (pushed_string_list) ! free_string_list (); ! #endif /* ALIAS || DPAREN_ARITHMETIC */ if (shell_input_line) *************** *** 1994,1997 **** --- 2092,2115 ---- } + #if defined (COND_COMMAND) + if ((parser_state & (PST_CONDCMD|PST_CONDEXPR)) == PST_CONDCMD) + { + cond_lineno = line_number; + parser_state |= PST_CONDEXPR; + yylval.command = parse_cond_command (); + if (cond_token != COND_END) + { + if (EOF_Reached && cond_token != COND_ERROR) /* [[ */ + parser_error (cond_lineno, "unexpected EOF while looking for `]]'"); + else if (cond_token != COND_ERROR) + parser_error (cond_lineno, "syntax error in conditional expression"); + return (-1); + } + token_to_read = COND_END; + parser_state &= ~(PST_CONDEXPR|PST_CONDCMD); + return (COND_CMD); + } + #endif + #if defined (ALIAS) /* This is a place to jump back to once we have successfully expanded a *************** *** 2081,2084 **** --- 2199,2203 ---- int cmdtyp, sline; char *wval; + WORD_DESC *wd; sline = line_number; *************** *** 2086,2095 **** if (cmdtyp == 1) /* arithmetic command */ { ! word_desc_to_read = make_word (wval); ! word_desc_to_read->flags = W_QUOTED; ! token_to_read = WORD; ! free (wval); ! yylval.word = make_word ("let"); ! return (WORD); } else if (cmdtyp == 0) /* nested subshell */ --- 2205,2213 ---- if (cmdtyp == 1) /* arithmetic command */ { ! wd = make_word (wval); ! wd->flags = W_QUOTED; ! yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL); ! free (wval); /* make_word copies it */ ! return (ARITH_CMD); } else if (cmdtyp == 0) /* nested subshell */ *************** *** 2363,2366 **** --- 2481,2653 ---- #endif /* DPAREN_ARITHMETIC */ + #if defined (COND_COMMAND) + static COND_COM *cond_term (); + static COND_COM *cond_and (); + static COND_COM *cond_or (); + static COND_COM *cond_expr (); + + static COND_COM * + cond_expr () + { + return (cond_or ()); + } + + static COND_COM * + cond_or () + { + COND_COM *l, *r; + + l = cond_and (); + if (cond_token == OR_OR) + { + r = cond_or (); + l = make_cond_node (COND_OR, (WORD_DESC *)NULL, l, r); + } + return l; + } + + static COND_COM * + cond_and () + { + COND_COM *l, *r; + + l = cond_term (); + if (cond_token == AND_AND) + { + r = cond_and (); + l = make_cond_node (COND_AND, (WORD_DESC *)NULL, l, r); + } + return l; + } + + static int + cond_skip_newlines () + { + while ((cond_token = read_token (READ)) == '\n') + { + if (interactive && (bash_input.type == st_stdin || bash_input.type == st_stream)) + prompt_again (); + } + return (cond_token); + } + + #define COND_RETURN_ERROR() \ + do { cond_token = COND_ERROR; return ((COND_COM *)NULL); } while (0) + + static COND_COM * + cond_term () + { + WORD_DESC *op; + COND_COM *term, *tleft, *tright; + int tok, lineno; + + /* Read a token. It can be a left paren, a `!', a unary operator, or a + word that should be the first argument of a binary operator. Start by + skipping newlines, since this is a compound command. */ + tok = cond_skip_newlines (); + lineno = line_number; + if (tok == COND_END) + { + COND_RETURN_ERROR (); + } + else if (tok == '(') + { + term = cond_expr (); + if (cond_token != ')') + { + if (term) + dispose_cond_node (term); /* ( */ + parser_error (lineno, "expected `)'"); + COND_RETURN_ERROR (); + } + term = make_cond_node (COND_EXPR, (WORD_DESC *)NULL, term, (COND_COM *)NULL); + (void)cond_skip_newlines (); + } + else if (tok == BANG || (tok == WORD && (yylval.word->word[0] == '!' && yylval.word->word[1] == '\0'))) + { + if (tok == WORD) + dispose_word (yylval.word); /* not needed */ + term = cond_term (); + if (term) + term->flags |= CMD_INVERT_RETURN; + } + else if (tok == WORD && test_unop (yylval.word->word)) + { + op = yylval.word; + tok = read_token (READ); + if (tok == WORD) + { + tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL); + term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL); + } + else + { + dispose_word (op); + parser_error (line_number, "unexpected argument to conditional unary operator"); + COND_RETURN_ERROR (); + } + + (void)cond_skip_newlines (); + } + else /* left argument to binary operator */ + { + /* lhs */ + tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL); + + /* binop */ + tok = read_token (READ); + if (tok == WORD && test_binop (yylval.word->word)) + op = yylval.word; + else if (tok == '<' || tok == '>') + op = make_word_from_token (tok); + else if (tok == COND_END || tok == AND_AND || tok == OR_OR) + { + /* Special case. [[ x ]] is equivalent to [[ -n x ]], just like + the test command. Similarly for [[ x && expr ]] or + [[ x || expr ]] */ + op = make_word ("-n"); + term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL); + cond_token = tok; + return (term); + } + else + { + parser_error (line_number, "conditional binary operator expected"); + dispose_cond_node (tleft); + COND_RETURN_ERROR (); + } + + /* rhs */ + tok = read_token (READ); + if (tok == WORD) + { + tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL); + term = make_cond_node (COND_BINARY, op, tleft, tright); + } + else + { + parser_error (line_number, "unexpected argument to conditional binary operator"); + dispose_cond_node (tleft); + dispose_word (op); + COND_RETURN_ERROR (); + } + + (void)cond_skip_newlines (); + } + return (term); + } + + /* This is kind of bogus -- we slip a mini recursive-descent parser in + here to handle the conditional statement syntax. */ + static COMMAND * + parse_cond_command () + { + COND_COM *cexp; + + cexp = cond_expr (); + return (make_cond_command (cexp)); + } + #endif + static int read_token_word (character) *************** *** 2459,2462 **** --- 2746,2777 ---- } + #ifdef EXTENDED_GLOB + /* Parse a ksh-style extended pattern matching specification. */ + if (extended_glob && PATTERN_CHAR(character)) + { + peek_char = shell_getc (1); + if (peek_char == '(') /* ) */ + { + push_delimiter (dstack, peek_char); + ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0); + pop_delimiter (dstack); + if (ttok == &matched_pair_error) + return -1; /* Bail immediately. */ + RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2, + token_buffer_size, + TOKEN_DEFAULT_GROW_SIZE); + token[token_index++] = character; + token[token_index++] = peek_char; + strcpy (token + token_index, ttok); + token_index += ttoklen; + FREE (ttok); + dollar_present = all_digits = 0; + goto next_character; + } + else + shell_ungetc (peek_char); + } + #endif /* EXTENDED_GLOB */ + /* If the delimiter character is not single quote, parse some of the shell expansions that must be read as a single word. */ *************** *** 2504,2507 **** --- 2819,2825 ---- else if (character == '$' && (peek_char == '\'' || peek_char == '"')) { + int first_line; + + first_line = line_number; ttok = parse_matched_pair (peek_char, peek_char, peek_char, &ttoklen, 0); if (ttok == &matched_pair_error) *************** *** 2510,2514 **** ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen); else ! ttrans = localeexpand (ttok, 0, ttoklen - 1, &ttranslen); free (ttok); RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 2, --- 2828,2832 ---- ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen); else ! ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen); free (ttok); RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 2, *************** *** 2702,2708 **** if non-null. */ static char * ! localeexpand (string, start, end, lenp) char *string; ! int start, end, *lenp; { int len, tlen; --- 3020,3026 ---- if non-null. */ static char * ! localeexpand (string, start, end, lineno, lenp) char *string; ! int start, end, lineno, *lenp; { int len, tlen; *************** *** 2717,2721 **** if (dump_translatable_strings) { ! printf ("\"%s\"\n", temp); if (lenp) *lenp = tlen; --- 3035,3043 ---- if (dump_translatable_strings) { ! if (dump_po_strings) ! printf ("#: %s:%d\nmsgid \"%s\"\nmsgstr \"\"\n", ! (bash_input.name ? bash_input.name : "stdin"), lineno, temp); ! else ! printf ("\"%s\"\n", temp); if (lenp) *lenp = tlen; *************** *** 2850,2853 **** --- 3172,3177 ---- return "; "; /* (...) subshell */ } + else if (token_before_that == WORD && two_tokens_ago == FUNCTION) + return " "; /* function def using `function name' without `()' */ for (i = 0; no_semi_successors[i]; i++) *************** *** 3050,3053 **** --- 3374,3383 ---- temp[5] = 'p'; } + goto add_string; + + case 'r': + temp = xmalloc (2); + temp[0] = '\r'; + temp[1] = '\0'; goto add_string; diff -Nrc2 bash-2.01.1/parser-built bash-2.02/parser-built *** bash-2.01.1/parser-built Tue Jul 16 15:53:19 1996 --- bash-2.02/parser-built Fri Dec 12 12:55:50 1997 *************** *** 22,44 **** #define DONE 270 #define FUNCTION 271 ! #define IN 272 ! #define BANG 273 ! #define TIME 274 ! #define TIMEOPT 275 ! #define WORD 276 ! #define ASSIGNMENT_WORD 277 ! #define NUMBER 278 ! #define AND_AND 279 ! #define OR_OR 280 ! #define GREATER_GREATER 281 ! #define LESS_LESS 282 ! #define LESS_AND 283 ! #define GREATER_AND 284 ! #define SEMI_SEMI 285 ! #define LESS_LESS_MINUS 286 ! #define AND_GREATER 287 ! #define LESS_GREATER 288 ! #define GREATER_BAR 289 ! #define yacc_EOF 290 --- 22,49 ---- #define DONE 270 #define FUNCTION 271 ! #define COND_START 272 ! #define COND_END 273 ! #define COND_ERROR 274 ! #define IN 275 ! #define BANG 276 ! #define TIME 277 ! #define TIMEOPT 278 ! #define WORD 279 ! #define ASSIGNMENT_WORD 280 ! #define NUMBER 281 ! #define ARITH_CMD 282 ! #define COND_CMD 283 ! #define AND_AND 284 ! #define OR_OR 285 ! #define GREATER_GREATER 286 ! #define LESS_LESS 287 ! #define LESS_AND 288 ! #define GREATER_AND 289 ! #define SEMI_SEMI 290 ! #define LESS_LESS_MINUS 291 ! #define AND_GREATER 292 ! #define LESS_GREATER 293 ! #define GREATER_BAR 294 ! #define yacc_EOF 295 diff -Nrc2 bash-2.01.1/pathexp.c bash-2.02/pathexp.c *** bash-2.01.1/pathexp.c Mon Apr 14 16:15:21 1997 --- bash-2.02/pathexp.c Fri Jan 30 13:15:21 1998 *************** *** 40,43 **** --- 40,46 ---- int glob_dot_filenames; + /* Control whether the extended globbing features are enabled. */ + int extended_glob = 0; + /* Return nonzero if STRING has any unquoted special globbing chars in it. */ int *************** *** 66,69 **** --- 69,79 ---- continue; + case '+': + case '@': + case '!': + if (*string == '(') /*)*/ + return (1); + continue; + case CTLESC: case '\\': *************** *** 77,98 **** /* 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 CONVERT_QUOTED_NULLS is non-zero, we change quoted null strings (pathname[0] == CTLNUL) into empty strings (pathname[0] == 0). If this is called after quote removal ! is performed, CONVERT_QUOTED_NULLS 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), CONVERT_QUOTED_NULLS should ! be 1. */ char * ! quote_string_for_globbing (pathname, convert_quoted_nulls) char *pathname; ! int convert_quoted_nulls; { char *temp; ! register int i; ! temp = savestring (pathname); ! if (convert_quoted_nulls && QUOTED_NULL (pathname)) { temp[0] = '\0'; --- 87,109 ---- /* 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. */ char * ! quote_string_for_globbing (pathname, qflags) char *pathname; ! int qflags; { char *temp; ! register int i, j; ! temp = xmalloc (strlen (pathname) + 1); ! if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname)) { temp[0] = '\0'; *************** *** 100,108 **** } ! for (i = 0; temp[i]; i++) { ! if (temp[i] == CTLESC) ! temp[i++] = '\\'; } return (temp); --- 111,126 ---- } ! for (i = j = 0; pathname[i]; i++) { ! if (pathname[i] == CTLESC) ! { ! if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/') ! continue; ! temp[j++] = '\\'; ! } ! else ! temp[j++] = pathname[i]; } + temp[j] = '\0'; return (temp); *************** *** 127,130 **** --- 145,154 ---- *t++ = '\\'; break; + case '+': + case '@': + case '!': + if (s[1] == '(') /*(*/ + *t++ = '\\'; + break; } *t++ = *s++; *************** *** 145,149 **** int glob_flags; ! temp = quote_string_for_globbing (pathname, 0); filenames.gl_offs = 0; --- 169,173 ---- int glob_flags; ! temp = quote_string_for_globbing (pathname, QGLOB_FILENAME); filenames.gl_offs = 0; *************** *** 160,164 **** if (i == GLOB_NOMATCH) ! filenames.gl_pathv[0] = (char *)NULL; return (filenames.gl_pathv); --- 184,188 ---- if (i == GLOB_NOMATCH) ! filenames.gl_pathv = (char **)NULL; return (filenames.gl_pathv); *************** *** 170,174 **** noglob_dot_filenames = glob_dot_filenames == 0; ! temp = quote_string_for_globbing (pathname, 0); results = glob_filename (temp); --- 194,198 ---- noglob_dot_filenames = glob_dot_filenames == 0; ! temp = quote_string_for_globbing (pathname, QGLOB_FILENAME); results = glob_filename (temp); *************** *** 233,236 **** --- 257,261 ---- { struct ign *p; + int flags; /* . and .. are never matched */ *************** *** 238,244 **** return (0); for (p = globignore.ignores; p->val; p++) { ! if (fnmatch (p->val, name, FNM_PATHNAME) != FNM_NOMATCH) return (0); } --- 263,270 ---- return (0); + flags = FNM_PATHNAME | FNMATCH_EXTFLAG; for (p = globignore.ignores; p->val; p++) { ! if (fnmatch (p->val, name, flags) != FNM_NOMATCH) return (0); } diff -Nrc2 bash-2.01.1/pathexp.h bash-2.02/pathexp.h *** bash-2.01.1/pathexp.h Mon Nov 13 14:23:21 1995 --- bash-2.02/pathexp.h Fri Aug 8 13:32:09 1997 *************** *** 30,46 **** #endif /* !USE_POSIX_GLOB_LIBRARY */ extern int glob_dot_filenames; extern int unquoted_glob_pattern_p __P((char *)); ! /* 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 CONVERT_QUOTED_NULLS is non-zero, we change quoted null strings (pathname[0] == CTLNUL) into empty strings (pathname[0] == 0). If this is called after quote removal ! is performed, CONVERT_QUOTED_NULLS 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), CONVERT_QUOTED_NULLS should ! be 1. */ extern char *quote_string_for_globbing __P((char *, int)); --- 30,60 ---- #endif /* !USE_POSIX_GLOB_LIBRARY */ + /* Flag values for quote_string_for_globbing */ + #define QGLOB_CVTNULL 0x01 /* convert QUOTED_NULL strings to '\0' */ + #define QGLOB_FILENAME 0x02 /* do correct quoting for matching filenames */ + + #if defined (EXTENDED_GLOB) + /* Flags to OR with other flag args to fnmatch() to enabled the extended + pattern matching. */ + # define FNMATCH_EXTFLAG (extended_glob ? FNM_EXTMATCH : 0) + #else + # define FNMATCH_EXTFLAG 0 + #endif /* !EXTENDED_GLOB */ + extern int glob_dot_filenames; + extern int extended_glob; extern int unquoted_glob_pattern_p __P((char *)); ! /* 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. */ extern char *quote_string_for_globbing __P((char *, int)); diff -Nrc2 bash-2.01.1/print_cmd.c bash-2.02/print_cmd.c *** bash-2.01.1/print_cmd.c Mon Jul 14 12:32:56 1997 --- bash-2.02/print_cmd.c Mon Nov 10 14:39:01 1997 *************** *** 23,26 **** --- 23,29 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 75,78 **** --- 78,88 ---- static void print_if_command (); static void print_function_def (); + #if defined (DPAREN_ARITHMETIC) + static void print_arith_command (); + #endif + #if defined (COND_COMMAND) + static void print_cond_node (); + static void print_cond_command (); + #endif #define PRINTED_COMMAND_INITIAL_SIZE 64 *************** *** 169,172 **** --- 179,194 ---- break; + #if defined (DPAREN_ARITHMETIC) + case cm_arith: + print_arith_command (command->value.Arith); + break; + #endif + + #if defined (COND_COMMAND) + case cm_cond: + print_cond_command (command->value.Cond); + break; + #endif + case cm_simple: print_simple_command (command->value.Simple); *************** *** 458,461 **** --- 480,601 ---- newline ("fi"); } + + #if defined (DPAREN_ARITHMETIC) + static void + print_arith_command (arith_command) + ARITH_COM *arith_command; + { + cprintf ("(( "); + command_print_word_list (arith_command->exp, " "); + cprintf (" ))"); + } + + #if defined (COND_COMMAND) + static void + print_cond_node (cond) + COND_COM *cond; + { + if (cond->flags & CMD_INVERT_RETURN) + cprintf ("! "); + + if (cond->type == COND_EXPR) + { + cprintf ("( "); + print_cond_node (cond->left); + cprintf (" )"); + } + else if (cond->type == COND_AND) + { + print_cond_node (cond->left); + cprintf (" && "); + print_cond_node (cond->right); + } + else if (cond->type == COND_OR) + { + print_cond_node (cond->left); + cprintf (" || "); + print_cond_node (cond->right); + } + else if (cond->type == COND_UNARY) + { + cprintf (cond->op->word); + cprintf (" "); + print_cond_node (cond->left); + } + else if (cond->type == COND_BINARY) + { + print_cond_node (cond->left); + cprintf (" "); + cprintf (cond->op->word); + cprintf (" "); + print_cond_node (cond->right); + } + else if (cond->type == COND_TERM) + { + cprintf (cond->op->word); /* need to add quoting here */ + } + } + + static void + print_cond_command (cond) + COND_COM *cond; + { + cprintf ("[[ "); + print_cond_node (cond); + cprintf (" ]]"); + } + + void + debug_print_cond_command (cond) + COND_COM *cond; + { + fprintf (stderr, "DEBUG: "); + command_string_index = 0; + print_cond_command (cond); + fprintf (stderr, "%s\n", the_printed_command); + } + + void + xtrace_print_cond_term (type, invert, op, arg1, arg2) + int type, invert; + WORD_DESC *op; + char *arg1, *arg2; + { + command_string_index = 0; + fprintf (stderr, "%s", indirection_level_string ()); + fprintf (stderr, "[[ "); + if (invert) + fprintf (stderr, "! "); + + if (type == COND_UNARY) + { + fprintf (stderr, "%s ", op->word); + fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''"); + } + else if (type == COND_BINARY) + { + fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''"); + fprintf (stderr, " %s ", op->word); + fprintf (stderr, "%s", (arg2 && *arg2) ? arg2 : "''"); + } + + fprintf (stderr, " ]]\n"); + } + #endif /* COND_COMMAND */ + + /* A function to print the words of an arithmetic command when set -x is on. */ + void + xtrace_print_arith_cmd (list) + WORD_LIST *list; + { + WORD_LIST *w; + + fprintf (stderr, "%s", indirection_level_string ()); + fprintf (stderr, "(( "); + for (w = list; w; w = w->next) + fprintf (stderr, "%s%s", w->word->word, w->next ? " " : ""); + fprintf (stderr, " ))\n"); + } + #endif void diff -Nrc2 bash-2.01.1/redir.c bash-2.02/redir.c *** bash-2.01.1/redir.c Wed Dec 31 19:00:00 1969 --- bash-2.02/redir.c Thu Jan 29 15:09:17 1998 *************** *** 0 **** --- 1,828 ---- + /* redir.c -- Functions to perform input and output redirection. */ + + /* Copyright (C) 1997 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. */ + #include "config.h" + + #if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX) + #pragma alloca + #endif /* _AIX && RISC6000 && !__GNUC__ */ + + #include + #include "bashtypes.h" + #ifndef _MINIX + # include + #endif + #include "filecntl.h" + #include "posixstat.h" + + #if defined (HAVE_UNISTD_H) + # include + #endif + + #include + + #if !defined (errno) + extern int errno; + #endif + + #include "bashansi.h" + + #include "memalloc.h" + #include "shell.h" + #include "flags.h" + #include "execute_cmd.h" + #include "redir.h" + + #if defined (BUFFERED_INPUT) + # include "input.h" + #endif + + extern int posixly_correct; + extern int interactive, interactive_shell; + extern REDIRECT *redirection_undo_list; + extern REDIRECT *exec_redirection_undo_list; + + /* Static functions defined and used in this file. */ + static void add_undo_close_redirect (); + static void add_exec_redirect (); + static int add_undo_redirect (); + static int do_redirection_internal (); + static int expandable_redirection_filename (); + + /* Spare redirector used when translating [N]>&WORD or [N]<&WORD to a new + redirection and when creating the redirection undo list. */ + static REDIRECTEE rd; + + /* Set to errno when a here document cannot be created for some reason. + Used to print a reasonable error message. */ + static int heredoc_errno; + + void + redirection_error (temp, error) + REDIRECT *temp; + int error; + { + char *filename; + + if (expandable_redirection_filename (temp)) + { + if (posixly_correct && !interactive_shell) + disallow_filename_globbing++; + filename = redirection_expand (temp->redirectee.filename); + if (posixly_correct && !interactive_shell) + disallow_filename_globbing--; + if (filename == 0) + filename = savestring (temp->redirectee.filename->word); + if (filename == 0) + { + filename = xmalloc (1); + filename[0] = '\0'; + } + } + else + filename = itos (temp->redirectee.dest); + + switch (error) + { + case AMBIGUOUS_REDIRECT: + internal_error ("%s: ambiguous redirect", filename); + break; + + case NOCLOBBER_REDIRECT: + internal_error ("%s: cannot overwrite existing file", filename); + break; + + #if defined (RESTRICTED_SHELL) + case RESTRICTED_REDIRECT: + internal_error ("%s: restricted: cannot redirect output", filename); + break; + #endif /* RESTRICTED_SHELL */ + + case HEREDOC_REDIRECT: + internal_error ("cannot create temp file for here document: %s", strerror (heredoc_errno)); + break; + + default: + internal_error ("%s: %s", filename, strerror (error)); + break; + } + + FREE (filename); + } + + /* Perform the redirections on LIST. If FOR_REAL, then actually make + input and output file descriptors, otherwise just do whatever is + neccessary for side effecting. INTERNAL says to remember how to + undo the redirections later, if non-zero. If SET_CLEXEC is non-zero, + file descriptors opened in do_redirection () have their close-on-exec + flag set. */ + int + do_redirections (list, for_real, internal, set_clexec) + REDIRECT *list; + int for_real, internal, set_clexec; + { + int error; + REDIRECT *temp; + + if (internal) + { + if (redirection_undo_list) + { + dispose_redirects (redirection_undo_list); + redirection_undo_list = (REDIRECT *)NULL; + } + if (exec_redirection_undo_list) + dispose_exec_redirects (); + } + + for (temp = list; temp; temp = temp->next) + { + error = do_redirection_internal (temp, for_real, internal, set_clexec); + if (error) + { + redirection_error (temp, error); + return (error); + } + } + return (0); + } + + /* Return non-zero if the redirection pointed to by REDIRECT has a + redirectee.filename that can be expanded. */ + static int + expandable_redirection_filename (redirect) + REDIRECT *redirect; + { + switch (redirect->instruction) + { + case r_output_direction: + case r_appending_to: + case r_input_direction: + case r_inputa_direction: + case r_err_and_out: + case r_input_output: + case r_output_force: + case r_duplicating_input_word: + case r_duplicating_output_word: + return 1; + + default: + return 0; + } + } + + /* Expand the word in WORD returning a string. If WORD expands to + multiple words (or no words), then return NULL. */ + char * + redirection_expand (word) + WORD_DESC *word; + { + char *result; + WORD_LIST *tlist1, *tlist2; + + tlist1 = make_word_list (copy_word (word), (WORD_LIST *)NULL); + tlist2 = expand_words_no_vars (tlist1); + dispose_words (tlist1); + + if (!tlist2 || tlist2->next) + { + /* We expanded to no words, or to more than a single word. + Dispose of the word list and return NULL. */ + if (tlist2) + dispose_words (tlist2); + return ((char *)NULL); + } + result = string_list (tlist2); /* XXX savestring (tlist2->word->word)? */ + dispose_words (tlist2); + return (result); + } + + /* Write the text of the here document pointed to by REDIRECTEE to the file + descriptor FD, which is already open to a temp file. Return 0 if the + write is successful, otherwise return errno. */ + static int + write_here_document (fd, redirectee) + int fd; + WORD_DESC *redirectee; + { + char *document; + int document_len, fd2; + FILE *fp; + register WORD_LIST *t, *tlist; + + /* Expand the text if the word that was specified had + no quoting. The text that we expand is treated + exactly as if it were surrounded by double quotes. */ + + if (redirectee->flags & W_QUOTED) + { + document = redirectee->word; + document_len = strlen (document); + /* Set errno to something reasonable if the write fails. */ + if (write (fd, document, document_len) < document_len) + { + if (errno == 0) + errno = ENOSPC; + return (errno); + } + else + return 0; + } + + tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT); + if (tlist) + { + /* Try using buffered I/O (stdio) and writing a word + at a time, letting stdio do the work of buffering + for us rather than managing our own strings. Most + stdios are not particularly fast, however -- this + may need to be reconsidered later. */ + if ((fd2 = dup (fd)) < 0 || (fp = fdopen (fd2, "w")) == NULL) + { + if (fd2 >= 0) + close (fd2); + return (errno); + } + errno = 0; + for (t = tlist; t; t = t->next) + { + /* This is essentially the body of + string_list_internal expanded inline. */ + document = t->word->word; + document_len = strlen (document); + if (t != tlist) + putc (' ', fp); /* separator */ + fwrite (document, document_len, 1, fp); + if (ferror (fp)) + { + if (errno == 0) + errno = ENOSPC; + fd2 = errno; + fclose(fp); + dispose_words (tlist); + return (fd2); + } + } + fclose (fp); + dispose_words (tlist); + } + return 0; + } + + /* Create a temporary file holding the text of the here document pointed to + by REDIRECTEE, and return a file descriptor open for reading to the temp + file. Return -1 on any error, and make sure errno is set appropriately. */ + static int + here_document_to_fd (redirectee) + WORD_DESC *redirectee; + { + char filename[24]; + int r, fd; + static int fnum = 0; + + do + { + /* Make the filename for the temp file. */ + sprintf (filename, "/tmp/t%d-%d-sh", (int)getpid (), fnum++); + + /* Make sure we open it exclusively. */ + fd = open (filename, O_TRUNC | O_WRONLY | O_CREAT | O_EXCL, 0600); + } + while (fd < 0 && errno == EEXIST); + + /* If we failed for some reason other than the file existing, abort */ + if (fd < 0) + return (fd); + + errno = r = 0; /* XXX */ + /* write_here_document returns 0 on success, errno on failure. */ + if (redirectee->word) + r = write_here_document (fd, redirectee); + + close (fd); + if (r) + { + unlink (filename); + errno = r; + return (-1); + } + + /* XXX - this is raceable */ + /* Make the document really temporary. Also make it the input. */ + fd = open (filename, O_RDONLY, 0600); + + if (fd < 0) + { + r = errno; + unlink (filename); + errno = r; + return -1; + } + + if (unlink (filename) < 0) + { + r = errno; + close (fd); + errno = r; + return (-1); + } + + return (fd); + } + + /* Open FILENAME with FLAGS in noclobber mode, hopefully avoiding most + race conditions and avoiding the problem where the file is replaced + between the stat(2) and open(2). */ + static int + noclobber_open (filename, flags, ri) + char *filename; + int flags; + enum r_instruction ri; + { + int r, fd; + struct stat finfo, finfo2; + + /* If the file exists and is a regular file, return an error + immediately. */ + r = stat (filename, &finfo); + if (r == 0 && (S_ISREG (finfo.st_mode))) + return (NOCLOBBER_REDIRECT); + + /* If the file was not present (r != 0), make sure we open it + exclusively so that if it is created before we open it, our open + will fail. Make sure that we do not truncate an existing file. + Note that we don't turn on O_EXCL unless the stat failed -- if + the file was not a regular file, we leave O_EXCL off. */ + flags &= ~O_TRUNC; + if (r != 0) + { + fd = open (filename, flags|O_EXCL, 0666); + return ((fd < 0 && errno == EEXIST) ? NOCLOBBER_REDIRECT : fd); + } + fd = open (filename, flags, 0666); + + /* If the open failed, return the file descriptor right away. */ + if (fd < 0) + return (errno == EEXIST ? NOCLOBBER_REDIRECT : fd); + + /* OK, the open succeeded, but the file may have been changed from a + non-regular file to a regular file between the stat and the open. + We are assuming that the O_EXCL open handles the case where FILENAME + did not exist and is symlinked to an existing file between the stat + and open. */ + + /* If we can open it and fstat the file descriptor, and neither check + revealed that it was a regular file, and the file has not been replaced, + return the file descriptor. */ + if ((fstat (fd, &finfo2) == 0) && (S_ISREG (finfo2.st_mode) == 0) && + r == 0 && (S_ISREG (finfo.st_mode) == 0) && + same_file (filename, filename, &finfo, &finfo2)) + return fd; + + /* The file has been replaced. badness. */ + close (fd); + errno = EEXIST; + return (NOCLOBBER_REDIRECT); + } + + /* Do the specific redirection requested. Returns errno or one of the + special redirection errors (*_REDIRECT) in case of error, 0 on success. + If FOR_REAL is zero, then just do whatever is neccessary to produce the + appropriate side effects. REMEMBERING, if non-zero, says to remember + how to undo each redirection. If SET_CLEXEC is non-zero, then + we set all file descriptors > 2 that we open to be close-on-exec. */ + static int + do_redirection_internal (redirect, for_real, remembering, set_clexec) + REDIRECT *redirect; + int for_real, remembering, set_clexec; + { + WORD_DESC *redirectee; + int redir_fd, fd, redirector, r; + char *redirectee_word; + enum r_instruction ri; + REDIRECT *new_redirect; + + redirectee = redirect->redirectee.filename; + redir_fd = redirect->redirectee.dest; + redirector = redirect->redirector; + ri = redirect->instruction; + + if (ri == r_duplicating_input_word || ri == r_duplicating_output_word) + { + /* We have [N]>&WORD or [N]<&WORD. Expand WORD, then translate + the redirection into a new one and continue. */ + redirectee_word = redirection_expand (redirectee); + + if (redirectee_word == 0) + return (AMBIGUOUS_REDIRECT); + else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0') + { + rd.dest = 0L; + new_redirect = make_redirection (redirector, r_close_this, rd); + } + else if (all_digits (redirectee_word)) + { + if (ri == r_duplicating_input_word) + { + rd.dest = atol (redirectee_word); + new_redirect = make_redirection (redirector, r_duplicating_input, rd); + } + else + { + rd.dest = atol (redirectee_word); + new_redirect = make_redirection (redirector, r_duplicating_output, rd); + } + } + else if (ri == r_duplicating_output_word && redirector == 1) + { + if (posixly_correct == 0) + { + rd.filename = make_bare_word (redirectee_word); + new_redirect = make_redirection (1, r_err_and_out, rd); + } + else + new_redirect = copy_redirect (redirect); + } + else + { + free (redirectee_word); + return (AMBIGUOUS_REDIRECT); + } + + free (redirectee_word); + + /* Set up the variables needed by the rest of the function from the + new redirection. */ + if (new_redirect->instruction == r_err_and_out) + { + char *alloca_hack; + + /* Copy the word without allocating any memory that must be + explicitly freed. */ + redirectee = (WORD_DESC *)alloca (sizeof (WORD_DESC)); + xbcopy ((char *)new_redirect->redirectee.filename, + (char *)redirectee, sizeof (WORD_DESC)); + + alloca_hack = (char *) + alloca (1 + strlen (new_redirect->redirectee.filename->word)); + redirectee->word = alloca_hack; + strcpy (redirectee->word, new_redirect->redirectee.filename->word); + } + else + /* It's guaranteed to be an integer, and shouldn't be freed. */ + redirectee = new_redirect->redirectee.filename; + + redir_fd = new_redirect->redirectee.dest; + redirector = new_redirect->redirector; + ri = new_redirect->instruction; + + /* Overwrite the flags element of the old redirect with the new value. */ + redirect->flags = new_redirect->flags; + dispose_redirects (new_redirect); + } + + switch (ri) + { + case r_output_direction: + case r_appending_to: + case r_input_direction: + case r_inputa_direction: + case r_err_and_out: /* command &>filename */ + case r_input_output: + case r_output_force: + if (posixly_correct && !interactive_shell) + disallow_filename_globbing++; + redirectee_word = redirection_expand (redirectee); + if (posixly_correct && !interactive_shell) + disallow_filename_globbing--; + + if (redirectee_word == 0) + return (AMBIGUOUS_REDIRECT); + + #if defined (RESTRICTED_SHELL) + if (restricted && (WRITE_REDIRECT (ri))) + { + free (redirectee_word); + return (RESTRICTED_REDIRECT); + } + #endif /* RESTRICTED_SHELL */ + + /* If we are in noclobber mode, you are not allowed to overwrite + existing files. Check before opening. */ + if (noclobber && OUTPUT_REDIRECT (ri)) + { + fd = noclobber_open (redirectee_word, redirect->flags, ri); + if (fd == NOCLOBBER_REDIRECT) + { + free (redirectee_word); + return (NOCLOBBER_REDIRECT); + } + } + else + { + fd = open (redirectee_word, redirect->flags, 0666); + #if defined (AFS) + if ((fd < 0) && (errno == EACCES)) + fd = open (redirectee_word, redirect->flags & ~O_CREAT, 0666); + #endif /* AFS */ + } + free (redirectee_word); + + if (fd < 0) + return (errno); + + if (for_real) + { + if (remembering) + /* Only setup to undo it if the thing to undo is active. */ + if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1)) + add_undo_redirect (redirector); + else + add_undo_close_redirect (redirector); + + #if defined (BUFFERED_INPUT) + check_bash_input (redirector); + #endif + + if ((fd != redirector) && (dup2 (fd, redirector) < 0)) + return (errno); + + #if defined (BUFFERED_INPUT) + /* Do not change the buffered stream for an implicit redirection + of /dev/null to fd 0 for asynchronous commands without job + control (r_inputa_direction). */ + if (ri == r_input_direction || ri == r_input_output) + duplicate_buffered_stream (fd, redirector); + #endif /* BUFFERED_INPUT */ + + /* + * If we're remembering, then this is the result of a while, for + * or until loop with a loop redirection, or a function/builtin + * executing in the parent shell with a redirection. In the + * function/builtin case, we want to set all file descriptors > 2 + * to be close-on-exec to duplicate the effect of the old + * for i = 3 to NOFILE close(i) loop. In the case of the loops, + * both sh and ksh leave the file descriptors open across execs. + * The Posix standard mentions only the exec builtin. + */ + if (set_clexec && (redirector > 2)) + SET_CLOSE_ON_EXEC (redirector); + } + + if (fd != redirector) + { + #if defined (BUFFERED_INPUT) + if (INPUT_REDIRECT (ri)) + close_buffered_fd (fd); + else + #endif /* !BUFFERED_INPUT */ + close (fd); /* Don't close what we just opened! */ + } + + /* If we are hacking both stdout and stderr, do the stderr + redirection here. */ + if (ri == r_err_and_out) + { + if (for_real) + { + if (remembering) + add_undo_redirect (2); + if (dup2 (1, 2) < 0) + return (errno); + } + } + break; + + case r_reading_until: + case r_deblank_reading_until: + /* REDIRECTEE is a pointer to a WORD_DESC containing the text of + the new input. Place it in a temporary file. */ + if (redirectee) + { + fd = here_document_to_fd (redirectee); + + if (fd < 0) + { + heredoc_errno = errno; + return (HEREDOC_REDIRECT); + } + + if (for_real) + { + if (remembering) + /* Only setup to undo it if the thing to undo is active. */ + if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1)) + add_undo_redirect (redirector); + else + add_undo_close_redirect (redirector); + + #if defined (BUFFERED_INPUT) + check_bash_input (redirector); + #endif + if (fd != redirector && dup2 (fd, redirector) < 0) + { + r = errno; + close (fd); + return (r); + } + + #if defined (BUFFERED_INPUT) + duplicate_buffered_stream (fd, redirector); + #endif + + if (set_clexec && (redirector > 2)) + SET_CLOSE_ON_EXEC (redirector); + } + + #if defined (BUFFERED_INPUT) + close_buffered_fd (fd); + #else + close (fd); + #endif + } + break; + + case r_duplicating_input: + case r_duplicating_output: + if (for_real && (redir_fd != redirector)) + { + if (remembering) + /* Only setup to undo it if the thing to undo is active. */ + if (fcntl (redirector, F_GETFD, 0) != -1) + add_undo_redirect (redirector); + else + add_undo_close_redirect (redirector); + + #if defined (BUFFERED_INPUT) + check_bash_input (redirector); + #endif + /* This is correct. 2>&1 means dup2 (1, 2); */ + if (dup2 (redir_fd, redirector) < 0) + return (errno); + + #if defined (BUFFERED_INPUT) + if (ri == r_duplicating_input) + duplicate_buffered_stream (redir_fd, redirector); + #endif /* BUFFERED_INPUT */ + + /* First duplicate the close-on-exec state of redirectee. dup2 + leaves the flag unset on the new descriptor, which means it + stays open. Only set the close-on-exec bit for file descriptors + greater than 2 in any case, since 0-2 should always be open + unless closed by something like `exec 2<&-'. */ + /* if ((already_set || set_unconditionally) && (ok_to_set)) + set_it () */ + if (((fcntl (redir_fd, F_GETFD, 0) == 1) || set_clexec) && + (redirector > 2)) + SET_CLOSE_ON_EXEC (redirector); + } + break; + + case r_close_this: + if (for_real) + { + if (remembering && (fcntl (redirector, F_GETFD, 0) != -1)) + add_undo_redirect (redirector); + + #if defined (BUFFERED_INPUT) + check_bash_input (redirector); + close_buffered_fd (redirector); + #else /* !BUFFERED_INPUT */ + close (redirector); + #endif /* !BUFFERED_INPUT */ + } + break; + + case r_duplicating_input_word: + case r_duplicating_output_word: + break; + } + return (0); + } + + #define SHELL_FD_BASE 10 + + /* Remember the file descriptor associated with the slot FD, + on REDIRECTION_UNDO_LIST. Note that the list will be reversed + before it is executed. Any redirections that need to be undone + even if REDIRECTION_UNDO_LIST is discarded by the exec builtin + are also saved on EXEC_REDIRECTION_UNDO_LIST. */ + static int + add_undo_redirect (fd) + int fd; + { + int new_fd, clexec_flag; + REDIRECT *new_redirect, *closer, *dummy_redirect; + + new_fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE); + + if (new_fd < 0) + { + sys_error ("redirection error"); + return (-1); + } + + clexec_flag = fcntl (fd, F_GETFD, 0); + + rd.dest = 0L; + closer = make_redirection (new_fd, r_close_this, rd); + dummy_redirect = copy_redirects (closer); + + rd.dest = (long)new_fd; + new_redirect = make_redirection (fd, r_duplicating_output, rd); + new_redirect->next = closer; + + closer->next = redirection_undo_list; + redirection_undo_list = new_redirect; + + /* Save redirections that need to be undone even if the undo list + is thrown away by the `exec' builtin. */ + add_exec_redirect (dummy_redirect); + + /* File descriptors used only for saving others should always be + marked close-on-exec. Unfortunately, we have to preserve the + close-on-exec state of the file descriptor we are saving, since + fcntl (F_DUPFD) sets the new file descriptor to remain open + across execs. If, however, the file descriptor whose state we + are saving is <= 2, we can just set the close-on-exec flag, + because file descriptors 0-2 should always be open-on-exec, + and the restore above in do_redirection() will take care of it. */ + if (clexec_flag || fd < 3) + SET_CLOSE_ON_EXEC (new_fd); + + return (0); + } + + /* Set up to close FD when we are finished with the current command + and its redirections. */ + static void + add_undo_close_redirect (fd) + int fd; + { + REDIRECT *closer; + + rd.dest = 0L; + closer = make_redirection (fd, r_close_this, rd); + closer->next = redirection_undo_list; + redirection_undo_list = closer; + } + + static void + add_exec_redirect (dummy_redirect) + REDIRECT *dummy_redirect; + { + dummy_redirect->next = exec_redirection_undo_list; + exec_redirection_undo_list = dummy_redirect; + } + + /* Return non-zero if any of the redirections in REDIRS alter the standard + input. */ + int + stdin_redirects (redirs) + REDIRECT *redirs; + { + REDIRECT *rp; + int n; + + for (n = 0, rp = redirs; rp; rp = rp->next) + switch (rp->instruction) + { + case r_input_direction: + case r_inputa_direction: + case r_input_output: + case r_reading_until: + case r_deblank_reading_until: + n++; + break; + case r_duplicating_input: + case r_duplicating_input_word: + case r_close_this: + n += (rp->redirector == 0); + break; + case r_output_direction: + case r_appending_to: + case r_duplicating_output: + case r_err_and_out: + case r_output_force: + case r_duplicating_output_word: + break; + } + + return n; + } diff -Nrc2 bash-2.01.1/redir.h bash-2.02/redir.h *** bash-2.01.1/redir.h Wed Dec 31 19:00:00 1969 --- bash-2.02/redir.h Thu Sep 4 12:39:05 1997 *************** *** 0 **** --- 1,31 ---- + /* findcmd.h - functions from findcmd.c. */ + + /* Copyright (C) 1997 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 (_REDIR_H_) + #define _REDIR_H_ + + #include "stdc.h" + + extern void redirection_error __P((REDIRECT *, int)); + extern int do_redirections __P((REDIRECT *, int, int, int)); + extern char *redirection_expand __P((WORD_DESC *)); + extern int stdin_redirs __P((REDIRECT *)); + + #endif /* _REDIR_H_ */ diff -Nrc2 bash-2.01.1/shell.c bash-2.02/shell.c *** bash-2.01.1/shell.c Mon Aug 18 12:04:08 1997 --- bash-2.02/shell.c Mon Feb 23 10:43:36 1998 *************** *** 36,40 **** #include "bashtypes.h" ! #include #include "posixstat.h" #include "bashansi.h" --- 36,42 ---- #include "bashtypes.h" ! #ifndef _MINIX ! # include ! #endif #include "posixstat.h" #include "bashansi.h" *************** *** 62,65 **** --- 64,68 ---- #include "input.h" #include "execute_cmd.h" + #include "findcmd.h" #if defined (HISTORY) *************** *** 87,90 **** --- 90,94 ---- extern int expand_aliases; extern char *this_command_name; + extern int array_needs_making; /* Non-zero means that this shell has already been run; i.e. you should *************** *** 120,123 **** --- 124,131 ---- int interactive_shell = 0; + /* Non-zero means to send a SIGHUP to all jobs when an interactive login + shell exits. */ + int hup_on_exit = 0; + /* Tells what state the shell was in when it started: 0 = non-interactive shell script *************** *** 178,181 **** --- 186,191 ---- int posixly_correct = 0; /* Non-zero means posix.2 superset. */ int dump_translatable_strings; /* Dump strings in $"...", don't execute. */ + int dump_po_strings; /* Dump strings in $"..." in po format */ + int wordexp_only = 0; /* Do word expansion only */ /* Some long-winded argument names. These are obviously new. */ *************** *** 189,192 **** --- 199,203 ---- } long_args[] = { { "debug", Int, &debugging, (char **)0x0 }, + { "dump-po-strings", Int, &dump_po_strings, (char **)0x0 }, { "dump-strings", Int, &dump_translatable_strings, (char **)0x0 }, { "help", Int, &want_initial_help, (char **)0x0 }, *************** *** 202,205 **** --- 213,217 ---- { "verbose", Int, &echo_input_at_read, (char **)0x0 }, { "version", Int, &do_version, (char **)0x0 }, + { "wordexp", Int, &wordexp_only, (char **)0x0 }, { (char *)0x0, Int, (int *)0x0, (char **)0x0 } }; *************** *** 232,235 **** --- 244,248 ---- static void set_bash_input (); static int run_one_command (); + static int run_wordexp (); static int uidget (); *************** *** 243,246 **** --- 256,275 ---- static void show_shell_usage (); + #ifdef __CYGWIN32__ + static void + _cygwin32_check_tmp () + { + struct stat sb; + + if (stat ("/tmp", &sb) < 0) + internal_warning ("could not find /tmp, please create!"); + else + { + if (S_ISDIR (sb.st_mode) == 0) + internal_warning ("/tmp must be a valid directory name"); + } + } + #endif /* __CYGWIN32__ */ + int main (argc, argv, env) *************** *** 260,263 **** --- 289,296 ---- check_dev_tty (); + #ifdef __CYGWIN32__ + _cygwin32_check_tmp (); + #endif + /* Wait forever if we are debugging a login shell. */ while (debugging_login_shell); *************** *** 340,343 **** --- 373,379 ---- arg_index = parse_shell_options (argv, arg_index, argc); + if (dump_po_strings) + dump_translatable_strings = 1; + if (dump_translatable_strings) read_but_dont_execute = 1; *************** *** 372,375 **** --- 408,412 ---- if (forced_interactive || /* -i flag */ (!local_pending_command && /* No -c command and ... */ + wordexp_only == 0 && /* No --wordexp and ... */ ((arg_index == argc) || /* no remaining args or... */ read_from_stdin) && /* -s flag with args, and */ *************** *** 481,485 **** #if defined (RESTRICTED_SHELL) ! /* Turn on the restrictions after parsing the startup files. This means that `bash -r' or `set -r' invoked from a startup file will turn on the restrictions after the startup files are executed. */ --- 518,522 ---- #if defined (RESTRICTED_SHELL) ! /* Turn on the restrictions after executing the startup files. This means that `bash -r' or `set -r' invoked from a startup file will turn on the restrictions after the startup files are executed. */ *************** *** 488,491 **** --- 525,535 ---- #endif /* RESTRICTED_SHELL */ + if (wordexp_only) + { + startup_state = 3; + last_command_exit_value = run_wordexp (argv[arg_index]); + exit_shell (last_command_exit_value); + } + if (local_pending_command) { *************** *** 651,655 **** if (o_option == 0) { ! list_minus_o_opts (-1); break; } --- 695,699 ---- if (o_option == 0) { ! list_minus_o_opts (-1, (on_or_off == '-') ? 0 : 1); break; } *************** *** 681,685 **** /* Exit the shell with status S. */ ! int exit_shell (s) int s; --- 725,729 ---- /* Exit the shell with status S. */ ! void exit_shell (s) int s; *************** *** 700,703 **** --- 744,752 ---- #if defined (JOB_CONTROL) + /* If the user has run `shopt -s huponexit', hangup all jobs when we exit + an interactive login shell. ksh does this unconditionally. */ + if (interactive_shell && login_shell && hup_on_exit) + hangup_all_jobs (); + /* If this shell is interactive, terminate all stopped jobs and restore the original terminal process group. */ *************** *** 764,779 **** int old_job_control; #endif ! /* get the rshd case out of the way first. */ if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 && ! act_like_sh == 0 && local_pending_command && isnetconn (fileno (stdin))) { #ifdef SYS_BASHRC ! maybe_execute_file (SYS_BASHRC, 1); #endif ! maybe_execute_file (bashrc_file, 1); ! return; } /* A non-interactive shell not named `sh' and not in posix mode reads and executes commands from $BASH_ENV. If `su' starts a shell with `-c cmd' --- 813,877 ---- int old_job_control; #endif + int sourced_login, run_by_ssh; + SHELL_VAR *sshvar; ! /* get the rshd/sshd case out of the way first. */ if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 && ! act_like_sh == 0 && local_pending_command) { + /* Find out if we were invoked by ssh. If so, set RUN_BY_SSH to 1. */ + sshvar = find_variable ("SSH_CLIENT"); + if (sshvar) + { + run_by_ssh = 1; + /* Now that we've tested the variable, we need to unexport it. */ + sshvar->attributes &= ~att_exported; + array_needs_making = 1; + } + else + run_by_ssh = 0; + + /* If we were run by sshd or we think we were run by rshd, execute + ~/.bashrc. */ + if (run_by_ssh || isnetconn (fileno (stdin))) + { #ifdef SYS_BASHRC ! maybe_execute_file (SYS_BASHRC, 1); #endif ! maybe_execute_file (bashrc_file, 1); ! return; ! } } + #if defined (JOB_CONTROL) + /* Startup files should be run without job control enabled. */ + old_job_control = interactive_shell ? set_job_control (0) : 0; + #endif + + sourced_login = 0; + + #if defined (NON_INTERACTIVE_LOGIN_SHELLS) + if (login_shell) + { + /* We don't execute .bashrc for login shells. */ + no_rc++; + + /* Execute /etc/profile and one of the personal login shell + initialization files. */ + if (no_profile == 0) + { + maybe_execute_file (SYS_PROFILE, 1); + + if (act_like_sh) /* sh */ + maybe_execute_file ("~/.profile", 1); + else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) && + (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */ + maybe_execute_file ("~/.profile", 1); + } + + sourced_login = 1; + } + #endif /* NON_INTERACTIVE_LOGIN_SHELLS */ + /* A non-interactive shell not named `sh' and not in posix mode reads and executes commands from $BASH_ENV. If `su' starts a shell with `-c cmd' *************** *** 788,815 **** } - #if defined (JOB_CONTROL) - /* Startup files should be run without job control enabled. */ - old_job_control = set_job_control (0); - #endif - /* Interactive shell or `-su' shell. */ if (posixly_correct == 0) /* bash, sh */ { ! /* We don't execute .bashrc for login shells. */ ! if (login_shell) ! no_rc++; ! /* Execute /etc/profile and one of the personal login shell ! initialization files. */ ! if (login_shell && no_profile == 0) ! { ! maybe_execute_file (SYS_PROFILE, 1); ! if (act_like_sh) /* sh */ ! maybe_execute_file ("~/.profile", 1); ! else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) && ! (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */ ! maybe_execute_file ("~/.profile", 1); ! } /* bash */ --- 886,910 ---- } /* Interactive shell or `-su' shell. */ if (posixly_correct == 0) /* bash, sh */ { ! if (login_shell && sourced_login++ == 0) ! { ! /* We don't execute .bashrc for login shells. */ ! no_rc++; ! /* Execute /etc/profile and one of the personal login shell ! initialization files. */ ! if (no_profile == 0) ! { ! maybe_execute_file (SYS_PROFILE, 1); ! if (act_like_sh) /* sh */ ! maybe_execute_file ("~/.profile", 1); ! else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) && ! (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */ ! maybe_execute_file ("~/.profile", 1); ! } ! } /* bash */ *************** *** 895,898 **** --- 990,1062 ---- } + static int + run_wordexp (words) + char *words; + { + int code, nw, nb; + WORD_DESC *w; + WORD_LIST *wl, *result; + + code = setjmp (top_level); + + if (code != NOT_JUMPED) + { + switch (code) + { + /* Some kind of throw to top_level has occured. */ + case FORCE_EOF: + return last_command_exit_value = 127; + case EXITPROG: + return last_command_exit_value; + case DISCARD: + return last_command_exit_value = 1; + default: + programming_error ("run_wordexp: bad jump: code %d", code); + } + } + + /* Run it through the parser to get a list of words and expand them */ + if (words && *words) + { + with_input_from_string (words, "--wordexp"); + if (parse_command () != 0) + return (126); + if (global_command == 0) + { + printf ("0\n0\n"); + return (0); + } + if (global_command->type != cm_simple) + return (126); + wl = global_command->value.Simple->words; + result = wl ? expand_words_no_vars (wl) : (WORD_LIST *)0; + } + else + result = (WORD_LIST *)0; + + last_command_exit_value = 0; + + if (result == 0) + { + printf ("0\n0\n"); + return (0); + } + + /* Count up the number of words and bytes, and print them. Don't count + the trailing NUL byte. */ + for (nw = nb = 0, wl = result; wl; wl = wl->next) + { + nw++; + nb += strlen (wl->word->word); + } + printf ("%u\n%u\n", nw, nb); + /* Print each word on a separate line. This will have to be changed when + the interface to glibc is completed. */ + for (wl = result; wl; wl = wl->next) + printf ("%s\n", wl->word->word); + + return (0); + } + #if defined (ONESHOT) /* Run one command, given as the argument to the -c option. Tell *************** *** 1111,1114 **** --- 1275,1303 ---- } + /* Close the current shell script input source and forget about it. This is + extern so execute_cmd.c:initialize_subshell() can call it. If CHECK_ZERO + is non-zero, we close default_buffered_input even if it's the standard + input (fd 0). */ + void + unset_bash_input (check_zero) + int check_zero; + { + #if defined (BUFFERED_INPUT) + if ((check_zero && default_buffered_input >= 0) || + (check_zero == 0 && default_buffered_input > 0)) + { + close_buffered_fd (default_buffered_input); + default_buffered_input = bash_input.location.buffered_fd = -1; + } + #else /* !BUFFERED_INPUT */ + if (default_input) + { + fclose (default_input); + default_input = (FILE *)NULL; + } + #endif /* !BUFFERED_INPUT */ + } + + #if !defined (PROGRAM) # define PROGRAM "bash" *************** *** 1202,1207 **** /* Line buffer output for stderr and stdout. */ ! setlinebuf (stderr); ! setlinebuf (stdout); /* Sort the array of shell builtins so that the binary search in --- 1391,1401 ---- /* Line buffer output for stderr and stdout. */ ! #if defined (SunOS5) ! if (shell_initialized == 0) ! #endif ! { ! setlinebuf (stderr); ! setlinebuf (stdout); ! } /* Sort the array of shell builtins so that the binary search in *************** *** 1255,1260 **** initialize_bash_input (); ! /* Initialize the shell options. */ ! initialize_shell_options (); } --- 1449,1460 ---- initialize_bash_input (); ! /* Initialize the shell options. Don't import the shell options ! from the environment variable $SHELLOPTS if we are running in ! privileged or restricted mode or if the shell is running setuid. */ ! #if defined (RESTRICTED_SHELL) ! initialize_shell_options (privileged_mode||restricted||running_setuid); ! #else ! initialize_shell_options (privileged_mode||running_setuid); ! #endif } *************** *** 1367,1371 **** l = sizeof(sa); ! rv = getpeername(0, &sa, &l); /* Solaris 2.5 getpeername() returns EINVAL if the fd is not a socket. */ return ((rv < 0 && (errno == ENOTSOCK || errno == EINVAL)) ? 0 : 1); --- 1567,1571 ---- l = sizeof(sa); ! rv = getpeername(fd, &sa, &l); /* Solaris 2.5 getpeername() returns EINVAL if the fd is not a socket. */ return ((rv < 0 && (errno == ENOTSOCK || errno == EINVAL)) ? 0 : 1); diff -Nrc2 bash-2.01.1/sig.c bash-2.02/sig.c *** bash-2.01.1/sig.c Tue Jul 29 10:57:25 1997 --- bash-2.02/sig.c Mon Sep 29 13:00:02 1997 *************** *** 24,27 **** --- 24,30 ---- #if defined (HAVE_UNISTD_H) + # ifdef _MINIX + # include + # endif # include #endif *************** *** 230,237 **** set_signal_ignored (XSIG (i)); } ! #if defined (SIGPROF) if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN) sigaction (XSIG (i), &oact, (struct sigaction *)NULL); ! #endif /* SIGPROF */ } --- 233,240 ---- set_signal_ignored (XSIG (i)); } ! #if defined (SIGPROF) && !defined (_MINIX) if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN) sigaction (XSIG (i), &oact, (struct sigaction *)NULL); ! #endif /* SIGPROF && !_MINIX */ } *************** *** 248,253 **** --- 251,258 ---- set_signal_ignored (XSIG (i)); } + #ifdef SIGPROF if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN) signal (XSIG (i), XHANDLER (i)); + #endif } diff -Nrc2 bash-2.01.1/stringlib.c bash-2.02/stringlib.c *** bash-2.01.1/stringlib.c Thu Apr 3 14:44:10 1997 --- bash-2.02/stringlib.c Wed Feb 4 15:20:57 1998 *************** *** 39,42 **** --- 39,52 ---- #endif + #define ISOCTAL(c) ((c) >= '0' && (c) <= '7') + #define OCTVALUE(c) ((c) - '0') + + #ifndef isxdigit + # define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) + #endif + + #define HEXVALUE(c) \ + ((c) >= 'a' && (c) <= 'f' ? (c)-'a'+10 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0') + /* Convert STRING by expanding the escape sequences specified by the ANSI C standard. If SAWC is non-null, recognize `\c' and use that *************** *** 48,52 **** int len, *sawc, *rlen; { ! int c; char *ret, *r, *s; --- 58,62 ---- int len, *sawc, *rlen; { ! int c, temp; char *ret, *r, *s; *************** *** 72,77 **** #endif case 'b': c = '\b'; break; ! case 'e': c = '\033'; break; /* ESC -- non-ANSI */ ! case 'E': c = '\033'; break; /* ESC -- non-ANSI */ case 'f': c = '\f'; break; case 'n': c = '\n'; break; --- 82,87 ---- #endif case 'b': c = '\b'; break; ! case 'e': case 'E': /* ESC -- non-ANSI */ ! c = '\033'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; *************** *** 80,88 **** case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': ! c -= '0'; ! if (*s >= '0' && *s <= '7') ! c = c * 8 + (*s++ - '0'); ! if (*s >= '0' && *s <= '7') ! c = c * 8 + (*s++ - '0'); break; case '\\': --- 90,105 ---- case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': ! for (temp = 2, c -= '0'; ISOCTAL (*s) && temp--; s++) ! c = (c * 8) + OCTVALUE (*s); ! break; ! case 'x': /* Hex digit -- non-ANSI */ ! for (temp = 3, c = 0; isxdigit (*s) && temp--; s++) ! c = (c * 16) + HEXVALUE (*s); ! /* \x followed by non-hex digits is passed through unchanged */ ! if (temp == 3) ! { ! *r++ = '\\'; ! c = 'x'; ! } break; case '\\': *************** *** 115,118 **** --- 132,136 ---- /* **************************************************************** */ + #ifdef INCLUDE_UNUSED /* Find NAME in ARRAY. Return the index of NAME, or -1 if not present. ARRAY should be NULL terminated. */ *************** *** 129,132 **** --- 147,151 ---- return (-1); } + #endif /* Return the length of ARRAY, a NULL terminated array of char *. */ *************** *** 286,298 **** int global; { ! int patlen, templen, tempsize, repl, i; char *temp, *r; patlen = strlen (pat); for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; ) { if (repl && STREQN (string + i, pat, patlen)) { ! RESIZE_MALLOCED_BUFFER (temp, templen, patlen, tempsize, (patlen * 2)); for (r = rep; *r; ) --- 305,318 ---- int global; { ! int patlen, replen, templen, tempsize, repl, i; char *temp, *r; patlen = strlen (pat); + replen = strlen (rep); for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; ) { if (repl && STREQN (string + i, pat, patlen)) { ! RESIZE_MALLOCED_BUFFER (temp, templen, replen, tempsize, (replen * 2)); for (r = rep; *r; ) diff -Nrc2 bash-2.01.1/subst.c bash-2.02/subst.c *** bash-2.01.1/subst.c Mon Aug 18 11:59:55 1997 --- bash-2.02/subst.c Thu Apr 9 20:48:12 1998 *************** *** 51,66 **** #include "builtins/common.h" ! #if defined (READLINE) ! # include "bashline.h" ! # include ! #else ! # include ! #endif ! ! #if defined (HISTORY) ! # include "bashhist.h" ! # include ! #endif ! #include --- 51,55 ---- #include "builtins/common.h" ! #include #include *************** *** 83,88 **** #define ST_CTLESC 0x02 ! /* How to quote character C. */ ! static char *make_quoted_char (); /* Process ID of the last command executed within command substitution. */ --- 72,80 ---- #define ST_CTLESC 0x02 ! /* These defs make it easier to use the editor. */ ! #define LBRACE '{' ! #define RBRACE '}' ! #define LPAREN '(' ! #define RPAREN ')' /* Process ID of the last command executed within command substitution. */ *************** *** 94,104 **** extern int dollar_dollar_pid; extern int posixly_correct; - extern int eof_encountered, eof_encountered_limit, ignoreeof; extern char *this_command_name; extern struct fd_bitmap *current_fds_to_close; ! #if defined (READLINE) ! extern int no_line_editing; ! extern int hostname_list_initialized; ! #endif extern void getopts_reset (); --- 86,92 ---- extern int 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 void getopts_reset (); *************** *** 117,120 **** --- 105,113 ---- static char expand_param_error, expand_param_fatal; + static char *make_quoted_char (); + static void remove_quoted_nulls (); + static char *param_expand (); + static char *maybe_expand_string (); + static WORD_LIST *call_expand_word_internal (); static WORD_LIST *expand_string_internal (); static WORD_LIST *expand_word_internal (), *expand_word_list_internal (); *************** *** 123,131 **** static WORD_LIST *word_list_split (); static WORD_LIST *quote_list (), *dequote_list (); static int unquoted_substring (), unquoted_member (); static int do_assignment_internal (); static char *string_extract_verbatim (), *string_extract (); static char *string_extract_double_quoted (), *string_extract_single_quoted (); ! static int skip_single_quoted (), skip_double_quoted (); static char *extract_delimited_string (); static char *extract_dollar_brace_string (); --- 116,127 ---- static WORD_LIST *word_list_split (); static WORD_LIST *quote_list (), *dequote_list (); + static char *quote_escapes (); + static WORD_LIST *list_quote_escapes (); static int unquoted_substring (), unquoted_member (); static int do_assignment_internal (); static char *string_extract_verbatim (), *string_extract (); static char *string_extract_double_quoted (), *string_extract_single_quoted (); ! static char *string_list_dollar_at (), *string_list_dollar_star (); ! static inline int skip_single_quoted (), skip_double_quoted (); static char *extract_delimited_string (); static char *extract_dollar_brace_string (); *************** *** 221,305 **** } ! /* Conventions: ! ! A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string. ! The parser passes CTLNUL as CTLESC 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. ! Here we remove doubled CTLESC characters inside quoted strings before ! quoting the entire string, so we do not double the number of CTLESC ! characters. */ ! static char * ! remove_quoted_escapes (string) char *string; { ! register char *s; ! int docopy; ! char *t, *t1; ! ! if (string == NULL) ! return (string); ! t1 = t = xmalloc (strlen (string) + 1); ! for (docopy = 0, s = string; *s; s++, t1++) { ! if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL)) { ! s++; ! docopy = 1; } - *t1 = *s; } ! *t1 = '\0'; ! if (docopy) ! strcpy (string, t); ! free (t); ! return (string); } ! /* 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. */ ! static char * ! quote_escapes (string) ! char *string; { ! register char *s, *t; ! char *result; ! result = xmalloc ((strlen (string) * 2) + 1); ! for (s = string, t = result; *s; ) { ! if (*s == CTLESC || *s == CTLNUL) ! *t++ = CTLESC; ! *t++ = *s++; } ! *t = '\0'; ! return (result); } ! #ifdef INCLUDE_UNUSED ! static char * ! dequote_escapes (string) ! char *string; ! { ! register char *s, *t; ! char *result; ! result = xmalloc (strlen (string) + 1); ! for (s = string, t = result; *s; ) { ! if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL)) { ! s++; ! if (*s == '\0') ! break; } ! *t++ = *s++; } ! *t = '\0'; ! return result; } #endif --- 217,350 ---- } ! /* Return 1 if CHARACTER appears in an unquoted portion of ! STRING. Return 0 otherwise. */ ! static int ! unquoted_member (character, string) ! int character; char *string; { ! int sindex, c; ! for (sindex = 0; c = string[sindex]; ) { ! if (c == character) ! return (1); ! ! switch (c) { ! default: ! sindex++; ! break; ! ! case '\\': ! sindex++; ! if (string[sindex]) ! sindex++; ! break; ! ! case '\'': ! sindex = skip_single_quoted (string, ++sindex); ! break; ! ! case '"': ! sindex = skip_double_quoted (string, ++sindex); ! break; } } ! return (0); } ! /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */ ! static int ! unquoted_substring (substr, string) ! char *substr, *string; { ! int sindex, c, sublen; ! if (substr == 0 || *substr == '\0') ! return (0); ! ! sublen = strlen (substr); ! for (sindex = 0; c = string[sindex]; ) { ! if (STREQN (string + sindex, substr, sublen)) ! return (1); ! ! switch (c) ! { ! case '\\': ! sindex++; ! ! if (string[sindex]) ! sindex++; ! break; ! ! case '\'': ! sindex = skip_single_quoted (string, ++sindex); ! break; ! ! case '"': ! sindex = skip_double_quoted (string, ++sindex); ! break; ! ! default: ! 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 = 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) ! int number, *indx, *size; ! char *target; ! { ! char *temp; ! ! temp = itos (number); ! return (sub_append_string (temp, target, indx, size)); } #endif *************** *** 432,440 **** /* Pass everything between `$(' and the matching `)' or a quoted ${ ... } pair through according to the Posix.2 specification. */ ! if (c == '$' && ((string[i + 1] == '(') || (string[i + 1] == '{'))) { si = i + 2; ! if (string[i + 1] == '(') ! ret = extract_delimited_string (string, &si, "$(", "(", ")"); else ret = extract_dollar_brace_string (string, &si, 1); --- 477,485 ---- /* 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))) { si = i + 2; ! if (string[i + 1] == LPAREN) ! ret = extract_delimited_string (string, &si, "$(", "(", ")"); /*)*/ else ret = extract_dollar_brace_string (string, &si, 1); *************** *** 514,521 **** continue; } ! else if (c == '$' && ((string[i + 1] == '(') || (string[i + 1] == '{'))) { si = i + 2; ! if (string[i + 1] == '(') ret = extract_delimited_string (string, &si, "$(", "(", ")"); else --- 559,566 ---- continue; } ! else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE))) { si = i + 2; ! if (string[i + 1] == LPAREN) ret = extract_delimited_string (string, &si, "$(", "(", ")"); else *************** *** 643,647 **** /* 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) --- 688,692 ---- /* 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) *************** *** 784,800 **** } - si = i - *sindex - len_closer + 1; - result = xmalloc (1 + si); - strncpy (result, string + *sindex, si); - result[si] = '\0'; - *sindex = i; - if (c == 0 && nesting_level) { report_error ("bad substitution: no `%s' in %s", closer, string); - free (result); jump_to_top_level (DISCARD); } return (result); } --- 829,844 ---- } if (c == 0 && nesting_level) { report_error ("bad substitution: no `%s' in %s", closer, string); jump_to_top_level (DISCARD); } + si = i - *sindex - len_closer + 1; + result = xmalloc (1 + si); + strncpy (result, string + *sindex, si); + result[si] = '\0'; + *sindex = i; + return (result); } *************** *** 829,840 **** } ! if (c == CTLESC) ! { ! pass_character++; ! continue; ! } ! ! /* Backslashes quote the next character. */ ! if (c == '\\') { pass_character++; --- 873,878 ---- } ! /* CTLESCs and backslashes quote the next character. */ ! if (c == CTLESC || c == '\\') { pass_character++; *************** *** 842,846 **** } ! if (string[i] == '$' && string[i+1] == '{') { nesting_level++; --- 880,884 ---- } ! if (string[i] == '$' && string[i+1] == LBRACE) { nesting_level++; *************** *** 849,853 **** } ! if (c == '}') { nesting_level--; --- 887,891 ---- } ! if (c == RBRACE) { nesting_level--; *************** *** 868,877 **** } ! /* Pass the contents of new-style command substitutions through ! verbatim. */ ! if (string[i] == '$' && string[i+1] == '(') { si = i + 2; ! t = extract_delimited_string (string, &si, "$(", "(", ")"); i = si; free (t); --- 906,915 ---- } ! /* 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_delimited_string (string, &si, "$(", "(", ")"); /*)*/ i = si; free (t); *************** *** 879,901 **** } ! /* Pass the contents of single-quoted strings through verbatim. */ ! if (c == '\'') { si = i + 1; ! i = skip_single_quoted (string, si); ! /* skip_single_quoted leaves index one past close quote */ i--; continue; } ! /* Pass embedded double-quoted strings through verbatim as well. */ ! if (c == '"') ! { ! si = i + 1; ! /* skip_double_quoted leaves index one past close quote */ ! i = skip_double_quoted (string, si); ! i--; ! continue; ! } } --- 917,937 ---- } ! /* Pass the contents of single-quoted and double-quoted strings ! through verbatim. */ ! if (c == '\'' || c == '"') { si = i + 1; ! i = (c == '\'') ? skip_single_quoted (string, si) ! : skip_double_quoted (string, si); ! /* skip_XXX_quoted leaves index one past close quote */ i--; continue; } + } ! if (c == 0 && nesting_level) ! { ! report_error ("bad substitution: no ending `}' in %s", string); ! jump_to_top_level (DISCARD); } *************** *** 906,916 **** *sindex = i; - if (c == 0 && nesting_level) - { - report_error ("bad substitution: no ending `}' in %s", string); - free (result); - jump_to_top_level (DISCARD); - } - return (result); } --- 942,945 ---- *************** *** 932,935 **** --- 961,965 ---- #if 0 + /*UNUSED*/ /* Replace instances of \! in a string with !. */ void *************** *** 1052,1055 **** --- 1082,1091 ---- #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. */ *************** *** 1115,1119 **** to a single field with the value of each parameter separated by the first character of the IFS variable, or by a if IFS is unset." */ ! char * string_list_dollar_star (list) WORD_LIST *list; --- 1151,1155 ---- to a single field with the value of each parameter separated by the first character of the IFS variable, or by a if IFS is unset." */ ! static char * string_list_dollar_star (list) WORD_LIST *list; *************** *** 1122,1132 **** ifs = get_string_value ("IFS"); - if (ifs == 0) - sep[0] = ' '; - else if (*ifs == '\0') - sep[0] = '\0'; - else - sep[0] = *ifs; sep[1] = '\0'; --- 1158,1163 ---- ifs = get_string_value ("IFS"); + sep[0] = (ifs == 0) ? ' ' : *ifs; sep[1] = '\0'; *************** *** 1134,1137 **** --- 1165,1196 ---- } + /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) + is non-zero, the $@ appears within double quotes, and we should quote + the list before converting it into a string. If IFS is unset, and the + word is not quoted, we just need to quote CTLESC and CTLNUL characters + in the words in the list, because the default value of $IFS is + , IFS characters in the words in the list should + also be split. If IFS is null, and the word is not quoted, we need + to quote the words in the list to preserve the positional parameters + exactly. */ + static char * + string_list_dollar_at (list, quoted) + WORD_LIST *list; + int quoted; + { + char *ifs, sep[2]; + WORD_LIST *tlist; + + ifs = get_string_value ("IFS"); + + sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs; + sep[1] = '\0'; + + tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0)) + ? quote_list (list) + : list_quote_escapes (list); + return (string_list_internal (tlist, sep)); + } + /* Return the list of words present in STRING. Separate the string into words at any of the characters found in SEPARATORS. If QUOTED is *************** *** 1159,1210 **** expect to have "" preserved! */ - /* 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. */ - /* - #define remove_quoted_nulls(string) \ - do { if (QUOTED_NULL (string)) string[0] ='\0'; } while (0) - */ - static void - remove_quoted_nulls (string) - char *string; - { - char *nstr, *s, *p; - - nstr = savestring (string); - nstr[0] = '\0'; - for (p = nstr, s = string; *s; s++) - { - if (*s == CTLESC) - { - *p++ = *s++; /* CTLESC */ - if (*s == 0) - break; - *p++ = *s; /* quoted char */ - continue; - } - if (*s == CTLNUL) - continue; - *p++ = *s; - } - *p = '\0'; - strcpy (string, nstr); - free (nstr); - } - - /* 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); - } - /* This performs word splitting and quoted null character removal on STRING. */ --- 1218,1221 ---- *************** *** 1268,1272 **** --- 1279,1287 ---- perform quoted null character removal on the current word. */ remove_quoted_nulls (current_word); + #if 0 result = make_word_list (make_word (current_word), result); + #else + result = add_string_to_list (current_word, result); + #endif if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) result->word->flags |= W_QUOTED; *************** *** 1382,1386 **** } - #if 0 #if defined (ARRAY_VARS) WORD_LIST * --- 1397,1400 ---- *************** *** 1420,1424 **** --- 1434,1442 ---- strncpy (token, s + tokstart, len); token[len] = '\0'; + #if 0 list = make_word_list (make_word (token), list); + #else + list = add_string_to_list (token, list); + #endif free (token); while (spctabnl (s[i])) *************** *** 1435,1508 **** } #endif /* ARRAY_VARS */ - #endif /* 0 */ - - #if defined (PROCESS_SUBSTITUTION) - #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC) - #else - #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC) - #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 * - maybe_expand_string (string, quoted, func) - char *string; - int quoted; - WORD_LIST *(*func)(); - { - WORD_LIST *list; - int i, saw_quote; - char *ret; - - for (i = saw_quote = 0; string[i]; i++) - { - if (EXP_CHAR (string[i])) - break; - else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"') - saw_quote = 1; - } - - 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 (string, quoted, func) - char *string; - int quoted; - WORD_LIST *(*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); ! } #if defined (ARRAY_VARS) --- 1453,1462 ---- } #endif /* ARRAY_VARS */ ! /********************************************************/ ! /* */ ! /* Functions to perform assignment statements */ ! /* */ ! /********************************************************/ #if defined (ARRAY_VARS) *************** *** 1569,1573 **** #if defined (ARRAY_VARS) ! if (expand && temp[0] == '(' && strchr (temp, ')')) { assign_list = ni = 1; --- 1523,1527 ---- #if defined (ARRAY_VARS) ! if (expand && temp[0] == LPAREN && strchr (temp, RPAREN)) { assign_list = ni = 1; *************** *** 1653,1709 **** } ! /* 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 = 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) ! int number, *indx, *size; ! char *target; ! { ! char *temp; ! ! temp = itos (number); ! return (sub_append_string (temp, target, indx, size)); ! } ! #endif /* Return the word list that corresponds to `$*'. */ --- 1607,1615 ---- } ! /*************************************************** ! * * ! * Functions to manage the positional parameters * ! * * ! ***************************************************/ /* Return the word list that corresponds to `$*'. */ *************** *** 1737,1740 **** --- 1643,1666 ---- } + /* Return the value of a positional parameter. This handles values > 10. */ + char * + get_dollar_var_value (ind) + int 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 *************** *** 1753,1804 **** } ! /*************************************************** ! * * ! * Functions to Expand a String * ! * * ! ***************************************************/ ! /* 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, c, e) ! WORD_DESC *w; ! int q, *c, *e; { ! WORD_LIST *result; ! result = expand_word_internal (w, q, c, e); ! if (result == &expand_word_error) { ! /* By convention, each time this error is returned, w->word has ! already been freed. */ ! w->word = (char *)NULL; ! jump_to_top_level (DISCARD); ! /* NOTREACHED */ } - else if (result == &expand_word_fatal) - jump_to_top_level (FORCE_EOF); - /* NOTREACHED */ - else - return (result); - } - - /* Perform parameter expansion, command substitution, and arithmetic - expansion on STRING, as if it were a word. Leave the result quoted. */ - 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); ! bzero ((char *)&td, sizeof (td)); ! td.word = string; ! tresult = call_expand_word_internal (&td, quoted, (int *)NULL, (int *)NULL); ! return (tresult); } --- 1679,1899 ---- } ! /* 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. */ ! static char * ! pos_params (string, start, end, quoted) ! char *string; ! int start, end, quoted; { ! WORD_LIST *save, *params, *h, *t; ! char *ret; ! int i; ! save = params = list_rest_of_args (); ! if (save == 0) ! return ((char *)NULL); ! ! for (i = 1; params && i < start; i++) ! params = params->next; ! if (params == 0) ! return ((char *)NULL); ! for (h = t = params; params && i < end; i++) { ! t = params; ! params = params->next; } ! t->next = (WORD_LIST *)NULL; ! if (string[0] == '*') ! ret = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (h) : string_list (h); ! else ! ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h); ! 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) ! #else ! #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC) ! #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 * ! maybe_expand_string (string, quoted, func) ! char *string; ! int quoted; ! WORD_LIST *(*func)(); ! { ! WORD_LIST *list; ! int i, saw_quote; ! char *ret; ! ! for (i = saw_quote = 0; string[i]; i++) ! { ! if (EXP_CHAR (string[i])) ! break; ! else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"') ! saw_quote = 1; ! } ! ! 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 (string, quoted, func) ! char *string; ! int quoted; ! WORD_LIST *(*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); ! } ! ! #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 = 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 nonzero, 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. The ! caller is responsible for removing the backslashes if the unquoted ! words is needed later. */ ! char * ! cond_expand_word (w, special) ! WORD_DESC *w; ! int special; ! { ! char *r, *p; ! WORD_LIST *l; ! ! if (w->word == 0 || w->word[0] == '\0') ! return ((char *)NULL); ! ! l = call_expand_word_internal (w, 0, (int *)0, (int *)0); ! if (l) ! { ! if (special == 0) ! { ! dequote_list (l); ! r = string_list (l); ! } ! else ! { ! p = string_list (l); ! r = quote_string_for_globbing (p, QGLOB_CVTNULL); ! 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, c, e) ! WORD_DESC *w; ! int q, *c, *e; ! { ! WORD_LIST *result; ! ! result = expand_word_internal (w, q, c, e); ! if (result == &expand_word_error) ! { ! /* By convention, each time this error is returned, w->word has ! already been freed. */ ! w->word = (char *)NULL; ! jump_to_top_level (DISCARD); ! /* NOTREACHED */ ! } ! else if (result == &expand_word_fatal) ! jump_to_top_level (FORCE_EOF); ! /* NOTREACHED */ ! else ! return (result); ! } ! ! /* Perform parameter expansion, command substitution, and arithmetic ! expansion on STRING, as if it were a word. Leave the result quoted. */ ! 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); ! ! bzero ((char *)&td, sizeof (td)); ! td.word = string; ! tresult = call_expand_word_internal (&td, quoted, (int *)NULL, (int *)NULL); ! return (tresult); } *************** *** 1899,1902 **** --- 1994,2097 ---- ***************************************************/ + /* Conventions: + + A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string. + The parser passes CTLNUL as CTLESC 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. + Here we remove doubled CTLESC characters inside quoted strings before + quoting the entire string, so we do not double the number of CTLESC + characters. */ + static char * + remove_quoted_escapes (string) + char *string; + { + register char *s; + int docopy; + char *t, *t1; + + if (string == NULL) + return (string); + + t1 = t = xmalloc (strlen (string) + 1); + for (docopy = 0, s = string; *s; s++, t1++) + { + if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL)) + { + s++; + docopy = 1; + } + *t1 = *s; + } + *t1 = '\0'; + if (docopy) + strcpy (string, t); + free (t); + return (string); + } + + /* 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. */ + static char * + quote_escapes (string) + char *string; + { + register char *s, *t; + char *result; + + result = xmalloc ((strlen (string) * 2) + 1); + for (s = string, t = result; *s; ) + { + if (*s == CTLESC || *s == CTLNUL) + *t++ = CTLESC; + *t++ = *s++; + } + *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; + } + + #ifdef INCLUDE_UNUSED + static char * + dequote_escapes (string) + char *string; + { + register char *s, *t; + char *result; + + result = xmalloc (strlen (string) + 1); + for (s = string, t = result; *s; ) + { + if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL)) + { + s++; + if (*s == '\0') + break; + } + *t++ = *s++; + } + *t = '\0'; + return result; + } + #endif + static WORD_LIST * dequote_list (list) *************** *** 2023,2035 **** } ! /* **************************************************************** */ ! /* */ ! /* Functions for Removing Patterns */ ! /* */ ! /* **************************************************************** */ ! ! /* 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 --- 2218,2278 ---- } ! /* 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. */ ! /* ! #define remove_quoted_nulls(string) \ ! do { if (QUOTED_NULL (string)) string[0] ='\0'; } while (0) ! */ ! static void ! remove_quoted_nulls (string) ! char *string; ! { ! char *nstr, *s, *p; ! ! nstr = savestring (string); ! nstr[0] = '\0'; ! for (p = nstr, s = string; *s; s++) ! { ! if (*s == CTLESC) ! { ! *p++ = *s++; /* CTLESC */ ! if (*s == 0) ! break; ! *p++ = *s; /* quoted char */ ! continue; ! } ! if (*s == CTLNUL) ! continue; ! *p++ = *s; ! } ! *p = '\0'; ! strcpy (string, nstr); ! free (nstr); ! } ! ! /* 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); ! } ! ! /* **************************************************************** */ ! /* */ ! /* Functions for Matching and Removing Patterns */ ! /* */ ! /* **************************************************************** */ ! ! /* 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 *************** *** 2065,2069 **** { c = *p; *p = '\0'; ! if (fnmatch (pattern, param, 0) != FNM_NOMATCH) { *p = c; --- 2308,2312 ---- { c = *p; *p = '\0'; ! if (fnmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH) { *p = c; *************** *** 2078,2082 **** { c = *p; *p = '\0'; ! if (fnmatch (pattern, param, 0) != FNM_NOMATCH) { *p = c; --- 2321,2325 ---- { c = *p; *p = '\0'; ! if (fnmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH) { *p = c; *************** *** 2090,2094 **** for (p = param; p <= end; p++) { ! if (fnmatch (pattern, p, 0) != FNM_NOMATCH) { c = *p; *p = '\0'; --- 2333,2337 ---- for (p = param; p <= end; p++) { ! if (fnmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH) { c = *p; *p = '\0'; *************** *** 2103,2107 **** for (p = end; p >= param; p--) { ! if (fnmatch (pattern, p, 0) != FNM_NOMATCH) { c = *p; *p = '\0'; --- 2346,2350 ---- for (p = end; p >= param; p--) { ! if (fnmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH) { c = *p; *p = '\0'; *************** *** 2122,2130 **** char *pat, *string; { - #if 0 - register char *np; - int neg; - char c1; - #endif char c; --- 2365,2368 ---- *************** *** 2139,2167 **** return (*string == *pat); case '?': ! return (*string != '\0'); case '*': return (1); case '[': - #if 0 - for (np = pat; *np != ']'; np++); - if (*np == 0) - return (*string == '['); - if (neg = (*pat == '!' || *pat == '^')) - pat++; - for ( ; (c1 = *pat++) != ']'; ) - { - if (c1 == '\\') - c1 = *pat++; - if (c1 == 0) - return (0); - if (*pat != '-' || pat[1] == '\0' || pat[1] == ']') - return (neg ? *string != c1 : *string == c1); - if (c1 <= *string && *string <= pat[1]) - return (1); - pat += 2; - } - #else return (*string != '\0'); - #endif } } --- 2377,2389 ---- return (*string == *pat); case '?': ! return (*string == LPAREN ? 1 : (*string != '\0')); case '*': return (1); + case '+': + case '!': + case '@': + return (*string == LPAREN ? 1 : (*string == c)); case '[': return (*string != '\0'); } } *************** *** 2198,2202 **** { c = *p1; *p1 = '\0'; ! if (fnmatch (pat, p, 0) == 0) { *p1 = c; --- 2420,2424 ---- { c = *p1; *p1 = '\0'; ! if (fnmatch (pat, p, FNMATCH_EXTFLAG) == 0) { *p1 = c; *************** *** 2217,2221 **** { c = *p; *p = '\0'; ! if (fnmatch (pat, string, 0) == 0) { *p = c; --- 2439,2443 ---- { c = *p; *p = '\0'; ! if (fnmatch (pat, string, FNMATCH_EXTFLAG) == 0) { *p = c; *************** *** 2230,2234 **** case MATCH_END: for (p = string; p <= end; p++) ! if (fnmatch (pat, p, 0) == 0) { *sp = p; --- 2452,2456 ---- case MATCH_END: for (p = string; p <= end; p++) ! if (fnmatch (pat, p, FNMATCH_EXTFLAG) == 0) { *sp = p; *************** *** 2242,2245 **** --- 2464,2652 ---- } + 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 fnmatch (). 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; + int i; + + tword = strchr (value, '~') ? bash_tilde_expand (value) : savestring (value); + + /* expand_string_internal () leaves WORD quoted and does not perform + word splitting. */ + if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword) + { + i = 0; + pat = string_extract_double_quoted (tword, &i, 1); + free (tword); + tword = pat; + } + + /* There is a problem here: how to handle single or double quotes in the + pattern string when the whole expression is between double quotes? */ + #if 0 + l = *tword ? expand_string_for_rhs (tword, quoted, (int *)NULL, (int *)NULL) + #else + l = *tword ? expand_string_for_rhs (tword, + (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_NOQUOTE : quoted, + (int *)NULL, (int *)NULL) + #endif + : (WORD_LIST *)0; + free (tword); + pat = string_list (l); + dispose_words (l); + if (pat) + { + tword = quote_string_for_globbing (pat, QGLOB_CVTNULL); + free (pat); + pat = tword; + } + return (pat); + } + + /* Handle removing a pattern from a string as a result of ${name%[%]value} + or ${name#[#]value}. */ + static char * + parameter_brace_remove_pattern (value, temp, c, quoted) + char *value, *temp; + int c, quoted; + { + int patspec; + char *pattern, *tword; + + patspec = getpatspec (c, value); + if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT) + value++; + + pattern = getpattern (value, quoted, 1); + + tword = remove_pattern (temp, pattern, patspec); + + FREE (pattern); + return (tword); + } + + static char * + list_remove_pattern (list, pattern, patspec, type, quoted) + WORD_LIST *list; + char *pattern; + int patspec, type, 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 = make_bare_word (tword); + free (tword); + new = make_word_list (w, new); + } + + l = REVERSE_LIST (new, WORD_LIST *); + if (type == '*') + tword = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l); + else + tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l); + + dispose_words (l); + return (tword); + } + + static char * + parameter_list_remove_pattern (value, type, c, quoted) + char *value; + int type, c, quoted; + { + int patspec; + char *pattern, *ret; + WORD_LIST *list; + + patspec = getpatspec (c, value); + if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT) + value++; + + pattern = getpattern (value, quoted, 1); + + list = list_rest_of_args (); + ret = list_remove_pattern (list, pattern, patspec, type, quoted); + dispose_words (list); + FREE (pattern); + return (ret); + } + + #if defined (ARRAY_VARS) + static char * + array_remove_pattern (value, aspec, aval, c, quoted) + char *value, *aspec, *aval; /* AVAL == evaluated ASPEC */ + int c, quoted; + { + SHELL_VAR *var; + int len, patspec; + char *ret, *t, *pattern; + WORD_LIST *l; + + var = array_variable_part (aspec, &t, &len); + if (var == 0) + return ((char *)NULL); + + patspec = getpatspec (c, value); + if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT) + value++; + + pattern = getpattern (value, quoted, 1); + + if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']') + { + if (array_p (var) == 0) + { + report_error ("%s: bad array subscript", aspec); + FREE (pattern); + return ((char *)NULL); + } + l = array_to_word_list (array_cell (var)); + if (l == 0) + return ((char *)NULL); + ret = list_remove_pattern (l, pattern, patspec, t[0], quoted); + dispose_words (l); + } + else + { + ret = remove_pattern (aval, pattern, patspec); + if (ret) + { + t = quote_escapes (ret); + free (ret); + ret = t; + } + } + + FREE (pattern); + return ret; + } + #endif /* ARRAY_VARS */ + /******************************************* * * *************** *** 2289,2319 **** } ! /* Return the value of a positional parameter. This handles values > 10. */ ! char * ! get_dollar_var_value (ind) ! int 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); ! } ! ! #if defined (PROCESS_SUBSTITUTION) ! ! /* **************************************************************** */ ! /* */ ! /* Hacking Process Substitution */ ! /* */ ! /* **************************************************************** */ #if !defined (HAVE_DEV_FD) --- 2696,2706 ---- } ! #if defined (PROCESS_SUBSTITUTION) ! /*****************************************************************/ ! /* */ ! /* Hacking Process Substitution */ ! /* */ ! /*****************************************************************/ #if !defined (HAVE_DEV_FD) *************** *** 2485,2489 **** #endif ! if (!string || !*string) return ((char *)NULL); --- 2872,2876 ---- #endif ! if (!string || !*string || wordexp_only) return ((char *)NULL); *************** *** 2627,2630 **** --- 3014,3023 ---- #endif /* PROCESS_SUBSTITUTION */ + /***********************************/ + /* */ + /* Command Substitution */ + /* */ + /***********************************/ + static char * read_comsub (fd, quoted) *************** *** 2714,2717 **** --- 3107,3116 ---- return ((char *)NULL); + if (wordexp_only && read_but_dont_execute) + { + last_command_exit_value = 125; + jump_to_top_level (EXITPROG); + } + /* Pipe the output of executing STRING into the current shell. */ if (pipe (fildes) < 0) *************** *** 2826,2831 **** /* wait_for gives the terminal back to shell_pgrp. If some other ! process group should have it, give it away to that group here. */ ! if (interactive && pipeline_pgrp != (pid_t)0) give_terminal_to (pipeline_pgrp); #endif /* JOB_CONTROL */ --- 3225,3238 ---- /* wait_for gives the terminal back to shell_pgrp. If some other ! process group should have it, give it away to that group here. ! pipeline_pgrp is non-zero only while we are constructing a ! pipline, so what we are concerned about is whether or not that ! pipeline was started in the background. A pipeline started in ! the background should never get the tty back here. */ ! #if 0 ! if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid) ! #else ! if (interactive && pipeline_pgrp != (pid_t)0 && subshell_environment != SUBSHELL_ASYNC) ! #endif give_terminal_to (pipeline_pgrp); #endif /* JOB_CONTROL */ *************** *** 2841,3046 **** ********************************************************/ ! 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 fnmatch (). 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; ! int i; ! ! tword = strchr (value, '~') ? bash_tilde_expand (value) : savestring (value); ! ! /* expand_string_internal () leaves WORD quoted and does not perform ! word splitting. */ ! if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword) ! { ! i = 0; ! pat = string_extract_double_quoted (tword, &i, 1); ! free (tword); ! tword = pat; ! } ! ! /* There is a problem here: how to handle single or double quotes in the ! pattern string when the whole expression is between double quotes? */ ! #if 0 ! l = *tword ? expand_string_for_rhs (tword, quoted, (int *)NULL, (int *)NULL) ! #else ! l = *tword ? expand_string_for_rhs (tword, ! (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_NOQUOTE : quoted, ! (int *)NULL, (int *)NULL) ! #endif ! : (WORD_LIST *)0; ! free (tword); ! pat = string_list (l); ! dispose_words (l); ! if (pat) ! { ! tword = quote_string_for_globbing (pat, 1); ! free (pat); ! pat = tword; ! } ! return (pat); ! } ! ! /* Handle removing a pattern from a string as a result of ${name%[%]value} ! or ${name#[#]value}. */ ! static char * ! parameter_brace_remove_pattern (value, temp, c, quoted) ! char *value, *temp; ! int c, quoted; ! { ! int patspec; ! char *pattern, *tword; ! ! patspec = getpatspec (c, value); ! if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT) ! value++; ! ! pattern = getpattern (value, quoted, 1); ! ! tword = remove_pattern (temp, pattern, patspec); ! ! FREE (pattern); ! return (tword); ! } ! ! static char * ! list_remove_pattern (list, pattern, patspec, type, quoted) ! WORD_LIST *list; ! char *pattern; ! int patspec, type, 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 = make_bare_word (tword); ! free (tword); ! new = make_word_list (w, new); ! } ! ! l = REVERSE_LIST (new, WORD_LIST *); ! if (type == '*') ! tword = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l); ! else ! tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l); ! ! dispose_words (l); ! return (tword); ! } ! ! static char * ! parameter_list_remove_pattern (value, type, c, quoted) ! char *value; ! int type, c, quoted; ! { ! int patspec; ! char *pattern, *ret; ! WORD_LIST *list; ! ! patspec = getpatspec (c, value); ! if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT) ! value++; ! ! pattern = getpattern (value, quoted, 1); ! ! list = list_rest_of_args (); ! ret = list_remove_pattern (list, pattern, patspec, type, quoted); ! dispose_words (list); ! FREE (pattern); ! return (ret); ! } #if defined (ARRAY_VARS) - static char * - array_remove_pattern (value, aspec, aval, c, quoted) - char *value, *aspec, *aval; /* AVAL == evaluated ASPEC */ - int c, quoted; - { - SHELL_VAR *var; - int len, patspec; - #if 0 - int ind; - #endif - char *ret, *t, *pattern; - WORD_LIST *l; - - var = array_variable_part (aspec, &t, &len); - if (var == 0) - return ((char *)NULL); - - patspec = getpatspec (c, value); - if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT) - value++; - - pattern = getpattern (value, quoted, 1); - - if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']') - { - if (array_p (var) == 0) - { - report_error ("%s: bad array subscript", aspec); - FREE (pattern); - return ((char *)NULL); - } - l = array_to_word_list (array_cell (var)); - if (l == 0) - return ((char *)NULL); - ret = list_remove_pattern (l, pattern, patspec, t[0], quoted); - dispose_words (l); - } - else - { - #if 0 - ind = array_expand_index (t, len); - if (ind < 0) - { - report_error ("%s: bad array subscript", aspec); - FREE (pattern); - return ((char *)NULL); - } - if (array_p (var) == 0 && ind != 0) - return ((char *)NULL); - - t = array_p (var) ? array_reference (array_cell (var), ind) : value_cell (var); - ret = remove_pattern (t, pattern, patspec); - #else - ret = remove_pattern (aval, pattern, patspec); - #endif - if (ret) - { - t = quote_escapes (ret); - free (ret); - ret = t; - } - } - - FREE (pattern); - return ret; - } - int valid_array_reference (name) --- 3248,3254 ---- ********************************************************/ ! /* Utility functions to manage arrays and their contents for expansion */ #if defined (ARRAY_VARS) int valid_array_reference (name) *************** *** 3130,3135 **** { int len, ind; ! char *retval, *t; ! WORD_LIST *l; SHELL_VAR *var; --- 3338,3343 ---- { int len, ind; ! char *retval, *t, *temp; ! WORD_LIST *l, *list; SHELL_VAR *var; *************** *** 3150,3157 **** --- 3358,3376 ---- return ((char *) NULL); + #if 0 if (t[0] == '*') /* ${name[*]} */ retval = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l); else /* ${name[@]} */ retval = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l); + #else + if (t[0] == '*' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) + { + temp = string_list_dollar_star (l); + retval = quote_string (temp); + free (temp); + } + else /* ${name[@]} or unquoted ${name[*]} */ + retval = string_list_dollar_at (l, quoted); + #endif dispose_words (l); *************** *** 3281,3291 **** else if (var_is_special) /* ${@} */ { tt = xmalloc (2 + strlen (name)); ! tt[0] = '$'; strcpy (tt + 1, name); l = expand_string_leave_quoted (tt, quoted); free (tt); temp = string_list (l); dispose_words (l); } #if defined (ARRAY_VARS) --- 3500,3517 ---- else if (var_is_special) /* ${@} */ { + int sindex; tt = xmalloc (2 + strlen (name)); ! tt[sindex = 0] = '$'; strcpy (tt + 1, name); + #if 0 l = expand_string_leave_quoted (tt, quoted); free (tt); temp = string_list (l); dispose_words (l); + #else + temp = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL, + (int *)NULL, (int *)NULL, 0); + free (tt); + #endif } #if defined (ARRAY_VARS) *************** *** 3307,3310 **** --- 3533,3539 ---- if (temp) temp = quote_escapes (temp); + + if (tempvar_p (var)) + dispose_variable (var); } else *************** *** 3441,3444 **** --- 3670,3674 ---- return (!name[1] || /* ${#} */ ((name[1] == '@' || name[1] == '*') && !name[2]) || /* ${#@}, ${#*} */ + (member (name[1], "-?$!#") && !name[2]) || /* ${#-}, etc. */ (digit (name[1]) && all_digits (name + 1)) || /* ${#11} */ #if defined (ARRAY_VARS) *************** *** 3463,3471 **** if (name[1] == '\0') /* ${#} */ number = number_of_args (); #if defined (ARRAY_VARS) else if (valid_array_reference (name + 1)) number = array_length_reference (name + 1); #endif /* ARRAY_VARS */ ! else if (name[1] != '*' && name[1] != '@') { number = 0; --- 3693,3730 ---- if (name[1] == '\0') /* ${#} */ number = number_of_args (); + else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */ + number = number_of_args (); + else if (member (name[1], "-?$!#") && 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; + else + t = itos ((int)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; *************** *** 3498,3503 **** } } - else /* ${#@} and ${#*} */ - number = number_of_args (); return (number); --- 3757,3760 ---- *************** *** 3506,3510 **** /* 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 paramters 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 --- 3763,3767 ---- /* 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 *************** *** 3577,3619 **** } - /* 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. */ - static char * - pos_params (string, start, end, quoted) - char *string; - int start, end, quoted; - { - WORD_LIST *save, *params, *h, *t; - char *ret; - int i; - - save = params = list_rest_of_args (); - if (save == 0) - return ((char *)NULL); - - for (i = 1; params && i < start; i++) - params = params->next; - if (params == 0) - return ((char *)NULL); - for (h = t = params; params && i < end; i++) - { - t = params; - params = params->next; - } - - t->next = (WORD_LIST *)NULL; - if (string[0] == '*') - ret = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (h) : string_list (h); - else - ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h); - t->next = params; - - dispose_words (save); - return (ret); - } - /* 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). */ static int --- 3834,3839 ---- } /* 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). */ static int *************** *** 3666,3669 **** --- 3886,3895 ---- } + /******************************************************/ + /* */ + /* Functions to extract substrings of variable values */ + /* */ + /******************************************************/ + /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME is `@', use the positional parameters; otherwise, use the value of *************** *** 3715,3718 **** --- 3941,3950 ---- } + /****************************************************************/ + /* */ + /* Functions to perform pattern substitution on variable values */ + /* */ + /****************************************************************/ + char * pat_subst (string, pat, rep, mflags) *************** *** 3795,3798 **** --- 4027,4034 ---- } + /* 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, patsub, quoted) *************** *** 3834,3838 **** --- 4070,4078 ---- and process substitution. Also perform quote removal. Do not perform word splitting or filename generation. */ + #if 0 pat = maybe_expand_string (patsub, quoted, expand_string_unsplit); + #else + pat = maybe_expand_string (patsub, (quoted & ~Q_DOUBLE_QUOTES), expand_string_unsplit); + #endif if (rep) { *************** *** 3857,3863 **** mflags |= MATCH_ANY; ! /* OK, we now want to substitute REP for PAT in VAL. If GLOBAL is 1, ! the substitution is done everywhere, otherwise only the first ! occurrence of PAT is replaced. */ switch (vtype) { --- 4097,4104 ---- 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. */ switch (vtype) { *************** *** 3885,3888 **** --- 4126,4135 ---- } + /****************************************************************/ + /* */ + /* Functions to perform parameter expansion on a string */ + /* */ + /****************************************************************/ + /* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */ static char * *************** *** 3896,3914 **** int t_index, sindex, c, number; - sindex = *indexp; - t_index = ++sindex; - name = string_extract (string, &t_index, "#%:-=?+/}", 1); value = (char *)NULL; var_is_set = var_is_null = var_is_special = check_nullness = 0; want_substring = want_indir = want_patsub = 0; ! /* If the name really consists of a special variable, then ! make sure that we have the entire name. Handle indirect ! references to special variables here, too. */ ! if ((sindex == t_index || ! ((sindex == t_index - 1) && string[sindex] == '!')) && (string[t_index] == '-' || string[t_index] == '?' || ! string[t_index] == '#')) { t_index++; --- 4143,4166 ---- int t_index, sindex, c, number; value = (char *)NULL; var_is_set = var_is_null = var_is_special = check_nullness = 0; want_substring = want_indir = want_patsub = 0; ! sindex = *indexp; ! t_index = ++sindex; ! name = string_extract (string, &t_index, "#%:-=?+/}", 1); ! ! /* 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 && (string[t_index] == '-' || string[t_index] == '?' || ! string[t_index] == '#')) || ! (sindex == t_index - 1 && string[sindex] == '!' && ! (string[t_index] == '#' || ! string[t_index] == '?' || ! string[t_index] == '@' || ! string[t_index] == '*'))) { t_index++; *************** *** 3919,3927 **** if (string[sindex] == '!') { ! /* indirect ref. of special variable */ ! name[1] = string[sindex + 1]; ! strcpy (name + 2, temp1); } ! else strcpy (name + 1, temp1); free (temp1); --- 4171,4179 ---- if (string[sindex] == '!') { ! /* indirect reference of $#, $?, $@, or $* */ ! name[1] = string[sindex + 1]; ! strcpy (name + 2, temp1); } ! else strcpy (name + 1, temp1); free (temp1); *************** *** 3944,4010 **** sindex++; } ! else if (c == ':') want_substring = 1; ! else if (c == '/') want_patsub = 1; ! want_indir = *name == '!'; /* Determine the value of this variable. */ ! /* Check for special variables, directly and indirectly ! referenced. */ if ((digit (*name) && all_digits (name)) || (name[1] == '\0' && member (*name, "#-?$!@*")) || ! (want_indir && name[2] == '\0' && member (name[1], "#-?$!@*"))) var_is_special++; ! /* Check for special expansion things. */ ! if (*name == '#') /* length of a parameter */ { ! /* Take the lengths of some of the shell's special ! parameters. */ ! if (string[sindex] == '}' && name[1] == '\0' && ! check_nullness == 0 && member (c, "-?$!#")) ! { ! free (name); ! switch (c) ! { ! case '-': ! temp1 = which_set_flags (); ! break; ! case '?': ! temp1 = itos (last_command_exit_value); ! break; ! case '$': ! temp1 = itos (dollar_dollar_pid); ! break; ! case '!': ! if (last_asynchronous_pid == NO_PID) ! temp1 = (char *)NULL; ! else ! temp1 = itos ((int)last_asynchronous_pid); ! break; ! case '#': ! temp1 = itos (number_of_args ()); ! break; ! } ! number = STRLEN (temp1); ! FREE (temp1); ! *indexp = ++sindex; /* { string[sindex] == '}' */ ! return (itos (number)); ! } ! ! /* Don't allow things like ${#:-foo} to go by; they are ! errors. 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. Explicitly check for ${#:}, ! which the rules do not catch. Also check NAME for ! validity before trying to go on. */ ! if (string[sindex - 1] != '}' || ! member (c, "?-=+") || ! (name[1] == '\0' && c == '}' && check_nullness) || ! (valid_length_expression (name) == 0)) { temp = (char *)NULL; --- 4196,4248 ---- sindex++; } ! else if (c == ':' && string[sindex] != RBRACE) want_substring = 1; ! else if (c == '/' && string[sindex] != RBRACE) want_patsub = 1; ! /* 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 && ! member (c, "-?#") && string[sindex] == RBRACE) ! { ! name = 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 (name[1]) || digit (name[1]) || member (name[1], "#?@*")); /* Determine the value of this variable. */ ! /* Check for special variables, directly referenced. */ if ((digit (*name) && all_digits (name)) || (name[1] == '\0' && member (*name, "#-?$!@*")) || ! (want_indir && name[2] == '\0' && member (name[1], "#?@*"))) 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; *************** *** 4043,4047 **** --- 4281,4289 ---- #if defined (ARRAY_VARS) + #if 0 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && valid_array_reference (name)) + #else + if (valid_array_reference (name)) + #endif { temp1 = strchr (name, '['); *************** *** 4052,4055 **** --- 4294,4304 ---- if (contains_dollar_at) *contains_dollar_at = 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; } } *************** *** 4060,4070 **** /* Get the rest of the stuff inside the braces. */ ! if (c && c != '}') { /* Extract the contents of the ${ ... } expansion according to the Posix.2 rules. */ value = extract_dollar_brace_string (string, &sindex, quoted); ! /*{*/ ! if (string[sindex] == '}') sindex++; else --- 4309,4318 ---- /* 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); ! if (string[sindex] == RBRACE) sindex++; else *************** *** 4106,4111 **** return &expand_param_error; ! /*{*/ ! case '}': if (var_is_set == 0 && unbound_vars_is_error) { --- 4354,4358 ---- return &expand_param_error; ! case RBRACE: if (var_is_set == 0 && unbound_vars_is_error) { *************** *** 4195,4203 **** } ! /* Make a word list which is the parameter and variable expansion, ! command substitution, arithmetic substitution, and quote removed ! expansion 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. --- 4442,4755 ---- } ! /* 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 char * ! 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; ! int zindex, number, c, t_index, expok; ! SHELL_VAR *var; ! WORD_LIST *list, *tlist; ! ! zindex = *sindex; ! c = string[++zindex]; ! ! temp = (char *)NULL; ! ! /* 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[digit_value (c)]; ! if (unbound_vars_is_error && temp1 == (char *)NULL) ! { ! report_error ("$%c: unbound variable", c); ! last_command_exit_value = EXECUTION_FAILURE; ! return (interactive_shell ? &expand_param_error : &expand_param_fatal); ! } ! temp = temp1 ? savestring (temp1) : (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) ! { ! report_error ("$%c: unbound variable", c); ! last_command_exit_value = EXECUTION_FAILURE; ! return (interactive_shell ? &expand_param_error : &expand_param_fatal); ! } ! } ! else ! temp = itos ((int)last_asynchronous_pid); ! break; ! ! /* The only difference between this and $@ is when the arg is quoted. */ ! case '*': /* `$*' */ ! list = list_rest_of_args (); ! ! /* 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)) ! { ! /* 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 = string_list_dollar_star (list); ! temp1 = quote_string (temp); ! free (temp); ! temp = temp1; ! } ! else ! { ! /* If the $* is not quoted it is identical to $@ */ ! temp = string_list_dollar_at (list, quoted); ! if (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 (); ! ! /* 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. */ ! 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. */ ! temp = string_list_dollar_at (list, quoted); ! ! dispose_words (list); ! break; ! ! case LBRACE: ! temp = parameter_brace_expand (string, &zindex, quoted, ! quoted_dollar_at_p, ! contains_dollar_at); ! if (temp == &expand_param_error || temp == &expand_param_fatal) ! return (temp); ! ! /* 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. */ ! if (temp && QUOTED_NULL (temp)) ! { ! if (had_quoted_null_p) ! *had_quoted_null_p = 1; ! free (temp); ! temp = (char *)NULL; ! } ! ! 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); ! 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'; ! ! /* Expand variables found inside the expression. */ ! temp1 = maybe_expand_string (temp2, Q_DOUBLE_QUOTES, expand_string); ! 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_param_fatal); ! } ! else ! return (&expand_param_error); ! } ! temp = itos (number); ! break; ! } ! ! comsub: ! temp1 = command_substitute (temp, quoted); ! FREE (temp); ! temp = temp1; ! break; ! ! /* Do POSIX.2d9-style arithmetic substitution. This will probably go ! away in a future bash release. */ ! case '[': ! /* We have to extract the contents of this arithmetic substitution. */ ! t_index = zindex + 1; ! temp = extract_arithmetic_subst (string, &t_index); ! zindex = t_index; ! ! /* Do initial variable expansion. */ ! temp1 = maybe_expand_string (temp, Q_DOUBLE_QUOTES, expand_string); ! ! 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 = 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 && value_cell (var)) ! { ! #if defined (ARRAY_VARS) ! if (array_p (var)) ! { ! temp = array_reference (array_cell (var), 0); ! if (temp) ! temp = quote_escapes (temp); ! } ! else ! #endif ! temp = quote_escapes (value_cell (var)); ! free (temp1); ! if (tempvar_p (var)) /* XXX */ ! { ! dispose_variable (var); /* XXX */ ! var = (SHELL_VAR *)NULL; ! } ! goto return0; ! } ! ! temp = (char *)NULL; ! ! if (unbound_vars_is_error) ! report_error ("%s: unbound variable", temp1); ! else ! { ! free (temp1); ! goto return0; ! } ! ! free (temp1); ! last_command_exit_value = EXECUTION_FAILURE; ! return ((unbound_vars_is_error && interactive_shell == 0) ! ? &expand_param_fatal ! : &expand_param_error); ! } ! ! if (string[zindex]) ! zindex++; ! ! return0: ! *sindex = zindex; ! return (temp); ! } ! ! /* 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. *************** *** 4255,4258 **** --- 4807,4811 ---- int had_quoted_null; + int has_dollar_at; int expok; *************** *** 4264,4269 **** istring = xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE); istring[istring_index = 0] = '\0'; ! ! quoted_dollar_at = had_quoted_null = 0; quoted_state = UNQUOTED; --- 4817,4821 ---- istring = xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE); istring[istring_index = 0] = '\0'; ! quoted_dollar_at = had_quoted_null = has_dollar_at = 0; quoted_state = UNQUOTED; *************** *** 4293,4300 **** temp[2] = '\0'; if (string[sindex]) sindex++; ! goto add_string; #if defined (PROCESS_SUBSTITUTION) --- 4845,4860 ---- 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) *************** *** 4303,4307 **** case '>': { ! if (string[++sindex] != '(' || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || posixly_correct) { sindex--; --- 4863,4867 ---- case '>': { ! if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || posixly_correct) { sindex--; *************** *** 4309,4315 **** } else ! t_index = sindex + 1; /* skip past both '<' and '(' */ ! temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); sindex = t_index; --- 4869,4875 ---- } else ! t_index = sindex + 1; /* skip past both '<' and LPAREN */ ! temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/ sindex = t_index; *************** *** 4326,4682 **** #endif /* PROCESS_SUBSTITUTION */ - /* See about breaking this into a separate function: - char * - param_expand (string, sindex, quoted, expanded_something, - contains_dollar_at, quoted_dollar_at) - char *string; - int *sindex, quoted, *expanded_something, *contains_dollar_at; - int *quoted_dollar_at; - */ case '$': - if (expanded_something) *expanded_something = 1; ! c = string[++sindex]; ! /* 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[digit_value (c)]; ! if (unbound_vars_is_error && temp1 == (char *)NULL) ! { ! report_error ("$%c: unbound variable", c); ! free (string); ! free (istring); ! last_command_exit_value = EXECUTION_FAILURE; ! return (interactive_shell ? &expand_word_error : &expand_word_fatal); ! } ! temp = temp1 ? savestring (temp1) : (char *)NULL; ! goto dollar_add_string; ! /* $$ -- pid of the invoking shell. */ ! case '$': ! number = dollar_dollar_pid; ! ! add_number: ! temp = itos (number); ! dollar_add_string: ! if (string[sindex]) sindex++; ! /* Add TEMP to ISTRING. */ ! add_string: ! if (temp) ! { ! istring = sub_append_string ! (temp, istring, &istring_index, &istring_size); ! temp = (char *)0; ! } ! break; ! /* $# -- number of positional parameters. */ ! case '#': ! number = number_of_args (); ! goto add_number; ! ! /* $? -- return value of the last synchronous command. */ ! case '?': ! number = last_command_exit_value; ! goto add_number; ! ! /* $- -- flags supplied to the shell on invocation or ! by `set'. */ ! case '-': ! temp = which_set_flags (); ! goto dollar_add_string; ! /* $! -- Pid of the last asynchronous command. */ ! case '!': ! number = (int)last_asynchronous_pid; ! ! /* If no asynchronous pids have been created, expand ! to nothing. */ ! if (number == (int)NO_PID) ! { ! if (string[sindex]) ! sindex++; ! if (expanded_something) ! *expanded_something = 0; ! break; ! } ! goto add_number; ! /* The only difference between this and $@ is when the ! arg is quoted. */ ! case '*': /* `$*' */ ! temp = string_rest_of_args (quoted); ! ! /* 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)) && temp && *temp == '\0') ! { ! free (temp); ! temp = (char *)NULL; ! } ! /* In the case of a quoted string, quote the entire arg-list. ! "$1 $2 $3". Otherwise quote the special escape characters. */ ! if (temp) ! { ! temp1 = temp; ! temp = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ! ? quote_string (temp) ! : quote_escapes (temp); ! free (temp1); ! } ! goto dollar_add_string; ! /* 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 (); ! ! /* 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. */ ! if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ! quoted_dollar_at = 1; ! if (contains_dollar_at) ! *contains_dollar_at = 1; ! temp = string_list (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list) ? quote_list (list) : list); ! /* If the expansion is not quoted, protect any special escape ! characters in the expansion by quoting them. */ ! if (temp && quoted == 0) ! { ! temp1 = temp; ! temp = quote_escapes (temp); ! free (temp1); ! } ! dispose_words (list); ! goto dollar_add_string; ! ! case '{': /*}*/ ! temp = parameter_brace_expand (string, &sindex, quoted, ! "ed_dollar_at, ! contains_dollar_at); ! if (temp == &expand_param_error || temp == &expand_param_fatal) ! { ! free (string); ! free (istring); ! return (temp == &expand_param_error) ? &expand_word_error ! : &expand_word_fatal; ! } ! /* 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. */ ! if (temp && QUOTED_NULL (temp)) ! { ! had_quoted_null = 1; ! free (temp); ! break; ! } ! ! goto add_string; ! /* break; */ ! ! /* Do command or arithmetic substitution. */ ! case '(': /*)*/ ! /* We have to extract the contents of this paren substitution. */ ! t_index = sindex + 1; ! temp = extract_command_subst (string, &t_index); ! sindex = t_index; ! ! /* For Posix.2-style `$(( ))' arithmetic substitution, ! extract the expression and pass it to the evaluator. */ ! if (temp && *temp == '(') ! { ! char *temp2; ! temp1 = temp + 1; ! temp2 = savestring (temp1); ! t_index = strlen (temp2) - 1; ! ! if (temp2[t_index] != ')') ! { ! free (temp2); ! #if 0 ! report_error ("%s: bad arithmetic substitution", temp); ! free (temp); ! free (string); ! free (istring); ! return (&expand_word_error); ! #else ! goto comsub; ! #endif ! } ! ! /* Cut off ending `)' */ ! temp2[t_index] = '\0'; ! ! /* Expand variables found inside the expression. */ ! temp1 = maybe_expand_string (temp2, Q_DOUBLE_QUOTES, expand_string); ! free (temp2); ! ! /* No error messages. */ ! this_command_name = (char *)NULL; ! number = evalexp (temp1, &expok); ! free (temp); ! free (temp1); ! if (expok == 0) ! { ! free (string); ! free (istring); ! return (&expand_word_error); ! } ! goto add_number; ! } ! ! comsub: ! temp1 = command_substitute (temp, quoted); ! FREE (temp); ! temp = temp1; ! goto dollar_add_string; ! ! /* Do straight arithmetic substitution. */ ! case '[': ! /* We have to extract the contents of this ! arithmetic substitution. */ ! t_index = sindex + 1; ! temp = extract_arithmetic_subst (string, &t_index); ! sindex = t_index; ! ! /* Do initial variable expansion. */ ! temp1 = maybe_expand_string (temp, Q_DOUBLE_QUOTES, expand_string); ! ! /* No error messages. */ ! this_command_name = (char *)NULL; ! number = evalexp (temp1, &expok); ! free (temp1); ! free (temp); ! if (expok == 0) ! { ! free (string); ! free (istring); ! return (&expand_word_error); ! } ! goto add_number; ! ! default: ! /* Find the variable in VARIABLE_LIST. */ ! temp = (char *)NULL; ! ! for (t_index = sindex; ! (c = string[sindex]) && legal_variable_char (c); ! sindex++); ! temp1 = substring (string, t_index, sindex); ! ! /* If this isn't a variable name, then just output the `$'. */ ! if (temp1 == 0 || *temp1 == '\0') ! { ! FREE (temp1); ! temp = xmalloc (2); ! temp[0] = '$'; ! temp[1] = '\0'; ! if (expanded_something) ! *expanded_something = 0; ! goto add_string; ! } ! ! /* If the variable exists, return its value cell. */ ! var = find_variable (temp1); ! ! if (var && invisible_p (var) == 0 && value_cell (var)) ! { ! #if defined (ARRAY_VARS) ! if (array_p (var)) ! { ! temp = array_reference (array_cell (var), 0); ! if (temp) ! temp = quote_escapes (temp); ! } ! else ! #endif ! temp = quote_escapes (value_cell (var)); ! free (temp1); ! goto add_string; ! } ! ! temp = (char *)NULL; ! ! if (unbound_vars_is_error) ! report_error ("%s: unbound variable", temp1); ! else ! { ! free (temp1); ! goto add_string; ! } ! ! free (temp1); ! free (string); ! last_command_exit_value = EXECUTION_FAILURE; ! free (istring); ! return ((unbound_vars_is_error && interactive_shell == 0) ! ? &expand_word_fatal ! : &expand_word_error); ! } ! break; /* End case '$': */ ! ! case '`': /* Backquoted command substitution. */ ! { ! sindex++; ! ! if (expanded_something) ! *expanded_something = 1; ! ! temp = string_extract (string, &sindex, "`", 0); ! de_backslash (temp); ! temp1 = command_substitute (temp, quoted); ! 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) ! temp1 = slashify_in_here_document; ! else if (quoted & Q_DOUBLE_QUOTES) ! temp1 = slashify_in_quotes; ! else ! temp1 = ""; ! ! if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && member (c, temp1) == 0) ! { ! temp = xmalloc (3); ! temp[0] = '\\'; temp[1] = c; temp[2] = '\0'; ! } ! else ! /* This character is quoted, so add it in quoted mode. */ ! temp = make_quoted_char (c); if (c) --- 4886,4949 ---- #endif /* PROCESS_SUBSTITUTION */ case '$': if (expanded_something) *expanded_something = 1; ! has_dollar_at = 0; ! temp = param_expand (string, &sindex, quoted, expanded_something, ! &has_dollar_at, "ed_dollar_at, ! &had_quoted_null, 0); ! if (temp == &expand_param_error || temp == &expand_param_fatal) { ! free (string); ! free (istring); ! return ((temp == &expand_param_error) ? &expand_word_error ! : &expand_word_fatal); ! } ! if (contains_dollar_at && has_dollar_at) ! *contains_dollar_at = 1; ! goto add_string; ! break; ! case '`': /* Backquoted command substitution. */ ! { ! sindex++; ! if (expanded_something) ! *expanded_something = 1; ! temp = string_extract (string, &sindex, "`", 0); ! de_backslash (temp); ! temp1 = command_substitute (temp, quoted); ! 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) ! temp1 = slashify_in_here_document; ! else if (quoted & Q_DOUBLE_QUOTES) ! temp1 = slashify_in_quotes; ! else ! temp1 = ""; ! if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && member (c, temp1) == 0) ! { ! temp = xmalloc (3); ! temp[0] = '\\'; temp[1] = c; temp[2] = '\0'; ! } ! else ! /* This character is quoted, so add it in quoted mode. */ ! temp = make_quoted_char (c); if (c) *************** *** 4699,4709 **** if (temp && *temp) { - int dollar_at_flag; - tword = make_word (temp); /* XXX */ free (temp); temp = (char *)NULL; ! list = expand_word_internal (tword, Q_DOUBLE_QUOTES, &dollar_at_flag, (int *)NULL); if (list == &expand_word_error || list == &expand_word_fatal) --- 4966,4975 ---- if (temp && *temp) { tword = make_word (temp); /* XXX */ free (temp); temp = (char *)NULL; ! has_dollar_at = 0; ! list = expand_word_internal (tword, Q_DOUBLE_QUOTES, &has_dollar_at, (int *)NULL); if (list == &expand_word_error || list == &expand_word_fatal) *************** *** 4723,4727 **** not even a NULL word, when there are no positional parameters. */ ! if (list == 0 && dollar_at_flag) { quoted_dollar_at++; --- 4989,4993 ---- not even a NULL word, when there are no positional parameters. */ ! if (list == 0 && has_dollar_at) { quoted_dollar_at++; *************** *** 4740,4744 **** dequote_list (list); ! if (dollar_at_flag) { quoted_dollar_at++; --- 5006,5010 ---- dequote_list (list); ! if (has_dollar_at) { quoted_dollar_at++; *************** *** 4776,4779 **** --- 5042,5057 ---- temp = savestring (list->word->word); dispose_words (list); + #if 1 + /* 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. */ + if (QUOTED_NULL (temp) == 0) + remove_quoted_nulls (temp); /* XXX */ + #endif } } *************** *** 4784,4791 **** partially quoted; we can throw them away. */ if (temp == 0 && quoted_state == PARTIALLY_QUOTED) ! { ! FREE (temp); ! continue; ! } add_quoted_string: --- 5062,5066 ---- partially quoted; we can throw them away. */ if (temp == 0 && quoted_state == PARTIALLY_QUOTED) ! continue; add_quoted_string: *************** *** 4922,4926 **** char *ifs_chars; ! if (quoted_dollar_at) { var = find_variable ("IFS"); --- 5197,5201 ---- char *ifs_chars; ! if (quoted_dollar_at || has_dollar_at) { var = find_variable ("IFS"); *************** *** 4930,4939 **** ifs_chars = (char *)NULL; ! /* According to Posix.2, "$@" expands to a single word if ! IFS="" and the positional parameters are not empty. */ ! if (quoted_dollar_at && ifs_chars && *ifs_chars) ! { ! list = list_string (istring, " ", 1); ! } else { --- 5205,5216 ---- ifs_chars = (char *)NULL; ! /* If we have $@, we need to split the results no matter what. If ! IFS is unset or NULL, string_list_dollar_at has separated the ! positional parameters with a space, so we split on space (we have ! set ifs_chars to " \t\n" above if ifs is unset). If IFS is set, ! string_list_dollar_at has separated the positional parameters ! with the first character of $IFS, so we split on $IFS. */ ! if (has_dollar_at && ifs_chars) ! list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1); else { *************** *** 5052,5134 **** #endif - /* Return 1 if CHARACTER appears in an unquoted portion of - STRING. Return 0 otherwise. */ - static int - unquoted_member (character, string) - int character; - char *string; - { - int sindex, c; - - for (sindex = 0; c = string[sindex]; ) - { - if (c == character) - return (1); - - switch (c) - { - default: - sindex++; - break; - - case '\\': - sindex++; - if (string[sindex]) - sindex++; - break; - - case '\'': - sindex = skip_single_quoted (string, ++sindex); - break; - - case '"': - sindex = skip_double_quoted (string, ++sindex); - break; - } - } - return (0); - } - - /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */ - static int - unquoted_substring (substr, string) - char *substr, *string; - { - int sindex, c, sublen; - - if (substr == 0 || *substr == '\0') - return (0); - - sublen = strlen (substr); - for (sindex = 0; c = string[sindex]; ) - { - if (STREQN (string + sindex, substr, sublen)) - return (1); - - switch (c) - { - case '\\': - sindex++; - - if (string[sindex]) - sindex++; - break; - - case '\'': - sindex = skip_single_quoted (string, ++sindex); - break; - - case '"': - sindex = skip_double_quoted (string, ++sindex); - break; - - default: - sindex++; - break; - } - } - return (0); - } - /******************************************* * * --- 5329,5332 ---- *************** *** 5158,5161 **** --- 5356,5362 ---- result = list_string (w->word, ifs_chars, w->flags & W_QUOTED); + + if (ifs && tempvar_p (ifs)) /* XXX */ + dispose_variable (ifs); /* XXX */ } else *************** *** 5183,5190 **** /************************************************** * * ! * Functions to expand an entire WORD_LIST * * * **************************************************/ static WORD_LIST *varlist = (WORD_LIST *)NULL; --- 5384,5396 ---- /************************************************** * * ! * Functions to expand an entire WORD_LIST * * * **************************************************/ + /* 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) + static WORD_LIST *varlist = (WORD_LIST *)NULL; *************** *** 5278,5281 **** --- 5484,5506 ---- } + #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 *************** *** 5286,5290 **** WORD_LIST *list; { ! return (expand_word_list_internal (list, 1)); } --- 5511,5515 ---- WORD_LIST *list; { ! return (expand_word_list_internal (list, WEXP_ALL)); } *************** *** 5295,5418 **** WORD_LIST *list; { ! return (expand_word_list_internal (list, 0)); } ! /* The workhorse for expand_words () and expand_words_no_vars (). ! First arg is LIST, a WORD_LIST of words. ! Second arg DO_VARS is non-zero if you want to do environment and ! variable assignments, else zero. - This does all of the substitutions: brace expansion, tilde expansion, - parameter expansion, command substitution, arithmetic expansion, - process substitution, word splitting, and pathname expansion. 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_ASSIGNMENT - bit set do not undergo pathname expansion. */ static WORD_LIST * ! expand_word_list_internal (list, do_vars) ! WORD_LIST *list; ! int do_vars; { ! WORD_LIST *tlist, *new_list, *next, *temp_list, *orig_list, *disposables; ! char *temp_string; ! int tint; ! if (list == 0) ! return ((WORD_LIST *)NULL); ! tlist = copy_word_list (list); ! if (do_vars) ! { ! tlist = separate_out_assignments (tlist); ! if (tlist == 0) ! { ! if (varlist) { ! /* All the words were variable assignments, so they are placed ! into the shell's environment. */ ! for (new_list = varlist; new_list; new_list = new_list->next) ! { ! this_command_name = (char *)NULL; /* no arithmetic errors */ ! tint = do_assignment (new_list->word->word); ! /* Variable assignment errors in non-interactive shells ! running in Posix.2 mode cause the shell to exit. */ ! if (tint == 0 && interactive_shell == 0 && posixly_correct) ! { ! last_command_exit_value = EXECUTION_FAILURE; ! jump_to_top_level (FORCE_EOF); ! } ! } ! dispose_words (varlist); ! 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 (brace_expansion && tlist) { ! register char **expansions; ! WORD_LIST *braces; ! WORD_DESC *w; ! int eindex; ! ! for (braces = disposables = (WORD_LIST *)NULL; tlist; tlist = next) ! { ! next = tlist->next; ! ! /* 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 `strchr', 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 (strchr (tlist->word->word, '{')) ! { ! expansions = brace_expand (tlist->word->word); ! for (eindex = 0; temp_string = expansions[eindex]; eindex++) ! { ! w = make_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; ! braces = make_word_list (w, braces); ! free (expansions[eindex]); ! } ! free (expansions); ! /* Add TLIST to the list of words to be freed after brace ! expansion has been performed. */ ! tlist->next = disposables; ! disposables = tlist; ! } ! else { ! tlist->next = braces; ! braces = tlist; } ! } ! dispose_words (disposables); ! tlist = REVERSE_LIST (braces, WORD_LIST *); } ! #endif /* BRACE_EXPANSION */ /* We do tilde expansion all the time. This is what 1003.2 says. */ ! for (orig_list = tlist, new_list = (WORD_LIST *)NULL; tlist; tlist = next) { - WORD_LIST *expanded; - int expanded_something, has_dollar_at; - temp_string = tlist->word->word; --- 5520,5706 ---- 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_ASSIGNMENT) == 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_FAILED (glob_array)) { ! glob_array = (char **) xmalloc (sizeof (char *)); ! glob_array[0] = (char *)NULL; ! } ! ! /* Dequote the current word in case we have to use it. */ ! if (glob_array[0] == NULL) ! { ! temp_string = dequote_string (tlist->word->word); ! free (tlist->word->word); ! tlist->word->word = temp_string; ! } ! ! /* Make the array into a word list. */ ! glob_list = (WORD_LIST *)NULL; ! for (glob_index = 0; glob_array[glob_index]; glob_index++) ! { ! tword = make_bare_word (glob_array[glob_index]); ! tword->flags |= W_GLOBEXP; /* XXX */ ! glob_list = make_word_list (tword, glob_list); ! } ! ! if (glob_list) ! { ! output_list = (WORD_LIST *)list_append (glob_list, output_list); ! PREPEND_LIST (tlist, disposables); ! } ! else if (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); + } + + free_array (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; ! /* 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 `strchr', 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 (strchr (tlist->word->word, LBRACE)) ! { ! expansions = brace_expand (tlist->word->word); ! for (eindex = 0; temp_string = expansions[eindex]; eindex++) { ! w = make_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; ! output_list = make_word_list (w, output_list); ! free (expansions[eindex]); } ! 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 ! ! 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; *************** *** 5471,5607 **** } - /* In the most common cases, t will be a list containing only one - element, so the call to reverse_list would be wasted. */ expanded = REVERSE_LIST (temp_list, WORD_LIST *); new_list = (WORD_LIST *)list_append (expanded, new_list); } ! new_list = REVERSE_LIST (new_list, WORD_LIST *); - dispose_words (orig_list); - - /* Okay, we're almost done. Now let's just do some filename - globbing. */ if (new_list) ! { ! char **glob_array; ! register int glob_index; ! WORD_LIST *glob_list; ! WORD_DESC *tword; ! ! orig_list = disposables = (WORD_LIST *)NULL; ! tlist = new_list; ! ! /* orig_list == output list, despite the name. */ ! if (disallow_filename_globbing == 0) ! { ! 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 0 ! if ((tlist->word->flags & (W_QUOTED|W_ASSIGNMENT)) == 0 && ! #else ! if ((tlist->word->flags & W_ASSIGNMENT) == 0 && ! #endif ! 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_FAILED (glob_array)) ! { ! glob_array = (char **) xmalloc (sizeof (char *)); ! glob_array[0] = (char *)NULL; ! } ! /* Dequote the current word in case we have to use it. */ ! if (glob_array[0] == NULL) ! { ! temp_string = dequote_string (tlist->word->word); ! free (tlist->word->word); ! tlist->word->word = temp_string; ! } ! /* Make the array into a word list. */ ! glob_list = (WORD_LIST *)NULL; ! for (glob_index = 0; glob_array[glob_index]; glob_index++) ! { ! tword = make_bare_word (glob_array[glob_index]); ! tword->flags |= W_GLOBEXP; /* XXX */ ! glob_list = make_word_list (tword, glob_list); ! } ! if (glob_list) ! { ! orig_list = (WORD_LIST *)list_append (glob_list, orig_list); ! tlist->next = disposables; ! disposables = tlist; ! } ! else if (allow_null_glob_expansion == 0) ! { ! /* Failed glob expressions are left unchanged. */ ! tlist->next = orig_list; ! orig_list = tlist; ! } ! else { ! /* Failed glob expressions are removed. */ ! tlist->next = disposables; ! disposables = tlist; } } ! else ! { ! /* Dequote the string. */ ! temp_string = dequote_string (tlist->word->word); ! free (tlist->word->word); ! tlist->word->word = temp_string; ! tlist->next = orig_list; ! orig_list = tlist; ! } ! free_array (glob_array); ! glob_array = (char **)NULL; ! tlist = next; ! } ! if (disposables) ! dispose_words (disposables); ! new_list = REVERSE_LIST (orig_list, WORD_LIST *); ! } else ! { ! /* Dequote the words, because we're not performing globbing. */ ! for (temp_list = new_list; temp_list; temp_list = temp_list->next) ! { ! temp_string = dequote_string (temp_list->word->word); ! free (temp_list->word->word); ! temp_list->word->word = temp_string; ! } ! } } ! if (do_vars) { Function *assign_func; --- 5759,5855 ---- } 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 DO_VARS is non-zero if you want to do environment and ! variable assignments, else zero. ! 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_ASSIGNMENT bit set do not undergo pathname expansion. */ ! static WORD_LIST * ! expand_word_list_internal (list, eflags) ! WORD_LIST *list; ! int eflags; ! { ! WORD_LIST *new_list, *temp_list; ! int tint; ! if (list == 0) ! return ((WORD_LIST *)NULL); ! new_list = copy_word_list (list); ! if (eflags & WEXP_VARASSIGN) ! { ! new_list = separate_out_assignments (new_list); ! if (new_list == 0) ! { ! if (varlist) ! { ! /* All the words were variable assignments, so they are placed ! into the shell's environment. */ ! for (temp_list = varlist; temp_list; temp_list = temp_list->next) ! { ! this_command_name = (char *)NULL; /* no arithmetic errors */ ! tint = do_assignment (temp_list->word->word); ! /* Variable assignment errors in non-interactive shells ! running in Posix.2 mode cause the shell to exit. */ ! if (tint == 0 && interactive_shell == 0 && posixly_correct) { ! last_command_exit_value = EXECUTION_FAILURE; ! jump_to_top_level (FORCE_EOF); } } ! dispose_words (varlist); ! 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) && varlist) { Function *assign_func; *************** *** 5630,5963 **** } tint = list_length (new_list) + 1; RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16); ! for (tint = 0, tlist = new_list; tlist; tlist = tlist->next) ! glob_argv_flags[tint++] = (tlist->word->flags & W_GLOBEXP) ? '1' : '0'; glob_argv_flags[tint] = '\0'; - - return (new_list); - } - - /************************************************* - * * - * Functions to manage special variables * - * * - *************************************************/ - - /* An alist of name.function for each special variable. Most of the - functions don't do much, and in fact, this would be faster with a - switch statement, but by the end of this file, I am sick of switch - statements. */ - - #define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0 - - struct name_and_function { - char *name; - VFunction *function; - } special_vars[] = { - { "PATH", sv_path }, - { "MAIL", sv_mail }, - { "MAILPATH", sv_mail }, - { "MAILCHECK", sv_mail }, - - { "POSIXLY_CORRECT", sv_strict_posix }, - { "GLOBIGNORE", sv_globignore }, - - /* Variables which only do something special when READLINE is defined. */ - #if defined (READLINE) - { "TERM", sv_terminal }, - { "TERMCAP", sv_terminal }, - { "TERMINFO", sv_terminal }, - { "HOSTFILE", sv_hostfile }, - #endif /* READLINE */ - - /* Variables which only do something special when HISTORY is defined. */ - #if defined (HISTORY) - { "HISTIGNORE", sv_histignore }, - { "HISTSIZE", sv_histsize }, - { "HISTFILESIZE", sv_histsize }, - { "HISTCONTROL", sv_history_control }, - # if defined (BANG_HISTORY) - { "histchars", sv_histchars }, - # endif /* BANG_HISTORY */ - #endif /* HISTORY */ - - { "IGNOREEOF", sv_ignoreeof }, - { "ignoreeof", sv_ignoreeof }, - - { "OPTIND", sv_optind }, - { "OPTERR", sv_opterr }, - - { "TEXTDOMAIN", sv_locale }, - { "TEXTDOMAINDIR", sv_locale }, - { "LC_ALL", sv_locale }, - { "LC_COLLATE", sv_locale }, - { "LC_CTYPE", sv_locale }, - { "LC_MESSAGES", sv_locale }, - { "LANG", sv_locale }, - - #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE) - { "TZ", sv_tz }, - #endif - - { (char *)0, (VFunction *)0 } - }; - - /* The variable in NAME has just had its state changed. Check to see if it - is one of the special ones where something special happens. */ - void - stupidly_hack_special_variables (name) - char *name; - { - int i; - - for (i = 0; special_vars[i].name; i++) - { - if (STREQ (special_vars[i].name, name)) - { - (*(special_vars[i].function)) (name); - return; - } - } - } - - /* What to do just after the PATH variable has changed. */ - void - sv_path (name) - char *name; - { - /* hash -r */ - flush_hashed_filenames (); - } - - /* What to do just after one of the MAILxxxx variables has changed. NAME - is the name of the variable. This is called with NAME set to one of - MAIL, MAILCHECK, or MAILPATH. */ - void - sv_mail (name) - char *name; - { - /* If the time interval for checking the files has changed, then - reset the mail timer. Otherwise, one of the pathname vars - to the users mailbox has changed, so rebuild the array of - filenames. */ - if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */ - reset_mail_timer (); - else - { - free_mail_files (); - remember_mail_dates (); - } - } - - /* What to do when GLOBIGNORE changes. */ - void - sv_globignore (name) - char *name; - { - setup_glob_ignore (name); - } - - #if defined (READLINE) - /* What to do just after one of the TERMxxx variables has changed. - If we are an interactive shell, then try to reset the terminal - information in readline. */ - void - sv_terminal (name) - char *name; - { - if (interactive_shell && no_line_editing == 0) - rl_reset_terminal (get_string_value ("TERM")); - } - - void - sv_hostfile (name) - char *name; - { - hostname_list_initialized = 0; - } - #endif /* READLINE */ - - #if defined (HISTORY) - /* What to do after the HISTSIZE or HISTFILESIZE variables change. - If there is a value for this HISTSIZE (and it is numeric), then stifle - the history. Otherwise, if there is NO value for this variable, - unstifle the history. If name is HISTFILESIZE, and its value is - numeric, truncate the history file to hold no more than that many - lines. */ - void - sv_histsize (name) - char *name; - { - char *temp; - long num; - - temp = get_string_value (name); - - if (temp && *temp) - { - if (legal_number (temp, &num)) - { - if (name[4] == 'S') - { - stifle_history (num); - num = where_history (); - if (history_lines_this_session > num) - history_lines_this_session = num; - } - else - { - history_truncate_file (get_string_value ("HISTFILE"), (int)num); - if (num <= history_lines_in_file) - history_lines_in_file = num; - } - } - } - else if (name[4] == 'S') - unstifle_history (); - } - - /* What to do after the HISTIGNORE variable changes. */ - void - sv_histignore (name) - char *name; - { - setup_history_ignore (name); - } - - /* What to do after the HISTCONTROL variable changes. */ - void - sv_history_control (name) - char *name; - { - char *temp; - - history_control = 0; - temp = get_string_value (name); - - if (temp && *temp && STREQN (temp, "ignore", 6)) - { - if (temp[6] == 's') /* ignorespace */ - history_control = 1; - else if (temp[6] == 'd') /* ignoredups */ - history_control = 2; - else if (temp[6] == 'b') /* ignoreboth */ - history_control = 3; - } - } - - #if defined (BANG_HISTORY) - /* Setting/unsetting of the history expansion character. */ - void - sv_histchars (name) - char *name; - { - char *temp; - - temp = get_string_value (name); - if (temp) - { - history_expansion_char = *temp; - if (temp[0] && temp[1]) - { - history_subst_char = temp[1]; - if (temp[2]) - history_comment_char = temp[2]; - } - } - else - { - history_expansion_char = '!'; - history_subst_char = '^'; - history_comment_char = '#'; - } - } - #endif /* BANG_HISTORY */ - #endif /* HISTORY */ - - #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE) - void - sv_tz (name) - char *name; - { - tzset (); - } #endif ! /* If the variable exists, then the value of it can be the number ! of times we actually ignore the EOF. The default is small, ! (smaller than csh, anyway). */ ! void ! sv_ignoreeof (name) ! char *name; ! { ! SHELL_VAR *tmp_var; ! char *temp; ! ! eof_encountered = 0; ! ! tmp_var = find_variable (name); ! ignoreeof = tmp_var != 0; ! temp = tmp_var ? value_cell (tmp_var) : (char *)NULL; ! if (temp) ! eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10; ! set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */ ! } ! ! void ! sv_optind (name) ! char *name; ! { ! char *tt; ! int s; ! ! tt = get_string_value ("OPTIND"); ! if (tt && *tt) ! { ! s = atoi (tt); ! ! /* According to POSIX, setting OPTIND=1 resets the internal state ! of getopt (). */ ! if (s < 0 || s == 1) ! s = 0; ! } ! else ! s = 0; ! getopts_reset (s); ! } ! ! void ! sv_opterr (name) ! char *name; ! { ! char *tt; ! ! tt = get_string_value ("OPTERR"); ! sh_opterr = (tt && *tt) ? atoi (tt) : 1; ! } ! ! void ! sv_strict_posix (name) ! char *name; ! { ! SET_INT_VAR (name, posixly_correct); ! posix_initialize (posixly_correct); ! #if defined (READLINE) ! if (interactive_shell) ! posix_readline_initialize (posixly_correct); ! #endif /* READLINE */ ! set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */ ! } ! ! void ! sv_locale (name) ! char *name; ! { ! char *v; ! ! v = get_string_value (name); ! if (name[0] == 'L' && name[1] == 'A') /* LANG */ ! set_lang (name, v); ! else ! set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */ } --- 5878,5889 ---- } + #if 0 tint = list_length (new_list) + 1; RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16); ! for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next) ! glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0'; glob_argv_flags[tint] = '\0'; #endif ! return (new_list); } diff -Nrc2 bash-2.01.1/subst.h bash-2.02/subst.h *** bash-2.01.1/subst.h Mon Jul 22 14:43:07 1996 --- bash-2.02/subst.h Fri Sep 12 16:54:32 1997 *************** *** 59,69 **** extern char *string_list __P((WORD_LIST *)); - /* Return a single string of all the words present in LIST, obeying the - quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the - expansion [of $*] appears within a double quoted string, it expands - to a single field with the value of each parameter separated by the - first character of the IFS variable, or by a if IFS is unset." */ - extern char *string_list_dollar_star __P((WORD_LIST *)); - /* Perform quoted null character removal on each element of LIST. This modifies LIST. */ --- 59,62 ---- *************** *** 170,176 **** extern WORD_LIST *expand_words_no_vars __P((WORD_LIST *)); ! /* The variable in NAME has just had its state changed. Check to see if it ! is one of the special ones where something special happens. */ ! extern void stupidly_hack_special_variables __P((char *)); extern char *pat_subst __P((char *, char *, char *, int)); --- 163,170 ---- extern WORD_LIST *expand_words_no_vars __P((WORD_LIST *)); ! /* Perform the `normal shell expansions' on a WORD_LIST. These are ! brace expansion, tilde expansion, parameter and variable substitution, ! command substitution, arithmetic expansion, and word splitting. */ ! extern WORD_LIST *expand_words_shellexp __P((WORD_LIST *)); extern char *pat_subst __P((char *, char *, char *, int)); *************** *** 187,209 **** #endif ! /* The `special variable' functions that get called when a particular ! variable is set. */ ! void sv_path (), sv_mail (), sv_ignoreeof (), sv_strict_posix (); ! void sv_optind (), sv_opterr (), sv_globignore (), sv_locale (); ! ! #if defined (READLINE) ! void sv_terminal (), sv_hostfile (); #endif - - #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE) - void sv_tz (); - #endif - - #if defined (HISTORY) - void sv_histsize (), sv_histignore (), sv_history_control (); - # if defined (BANG_HISTORY) - void sv_histchars (); - # endif - #endif /* HISTORY */ /* How to determine the quoted state of the character C. */ --- 181,188 ---- #endif ! #if defined (COND_COMMAND) ! extern char *remove_backslashes __P((char *)); ! extern char *cond_expand_word __P((WORD_DESC *, int)); #endif /* How to determine the quoted state of the character C. */ diff -Nrc2 bash-2.01.1/support/Makefile.in bash-2.02/support/Makefile.in *** bash-2.01.1/support/Makefile.in Wed Dec 31 19:00:00 1969 --- bash-2.02/support/Makefile.in Thu Feb 26 09:58:10 1998 *************** *** 0 **** --- 1,58 ---- + # + # Simple Makefile for the support programs. + # + # documentation support: man2html + # testing support: printenv recho zecho + # + # bashbug lives here but is created by the top-level makefile + # + # Currently only man2html is built + # + + # + # Boilerplate + # + topdir = @top_srcdir@ + srcdir = @srcdir@ + VPATH = .:@srcdir@ + BUILD_DIR = @BUILD_DIR@ + + RM = rm -f + SHELL = /bin/sh + CC = @CC@ + + # + # Compiler options: + # + PROFILE_FLAGS = @PROFILE_FLAGS@ + CFLAGS = @CFLAGS@ + LOCAL_CFLAGS = @LOCAL_CFLAGS@ + CPPFLAGS = @CPPFLAGS@ + DEFS = @DEFS@ + LOCAL_DEFS = @LOCAL_DEFS@ + LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS) + LOCAL_LDFLAGS = @LOCAL_LDFLAGS@ + LIBS = @LIBS@ + + INCLUDES = -I${BUILD_DIR} -I${topdir} + + # + CCFLAGS = ${PROFILE_FLAGS} $(DEFS) $(LOCAL_DEFS) $(SYSTEM_FLAGS) $(CPPFLAGS) \ + ${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS) + + SRC1 = man2html.c + OBJ1 = man2html.o + + .c.o: + $(RM) $@ + $(CC) -c $(CCFLAGS) $< + + all: man2html + + man2html: $(OBJ1) + $(CC) $(CCFLAGS) $(OBJ1) -o $@ ${LIBS} + + clean: + rm man2html + + man2html.o: man2html.c diff -Nrc2 bash-2.01.1/support/bashbug.sh bash-2.02/support/bashbug.sh *** bash-2.01.1/support/bashbug.sh Mon Mar 17 13:09:22 1997 --- bash-2.02/support/bashbug.sh Tue Mar 17 14:21:00 1998 *************** *** 5,9 **** # The bug address depends on the release status of the shell. Versions # with status `alpha' or `beta' mail bug reports to chet@po.cwru.edu. ! # Other versions send mail to bug-bash@prep.ai.mit.edu. # # configuration section: --- 5,9 ---- # The bug address depends on the release status of the shell. Versions # with status `alpha' or `beta' mail bug reports to chet@po.cwru.edu. ! # Other versions send mail to bug-bash@gnu.org. # # configuration section: *************** *** 35,39 **** case "$RELSTATUS" in alpha*|beta*) BUGBASH=chet@po.cwru.edu ;; ! *) BUGBASH=bug-bash@prep.ai.mit.edu ;; esac --- 35,39 ---- case "$RELSTATUS" in alpha*|beta*) BUGBASH=chet@po.cwru.edu ;; ! *) BUGBASH=bug-bash@gnu.org ;; esac *************** *** 70,73 **** --- 70,76 ---- fi + # this is raceable + rm -f $TEMP + cat > $TEMP <dummy.s ! .globl main ! .ent main ! main: ! .frame \$30,0,\$26,0 ! .prologue 0 ! .long 0x47e03d80 # implver $0 ! lda \$2,259 ! .long 0x47e20c21 # amask $2,$1 ! srl \$1,8,\$2 ! sll \$2,2,\$2 ! sll \$0,3,\$0 ! addl \$1,\$0,\$0 ! addl \$2,\$0,\$0 ! ret \$31,(\$26),1 ! .end main ! EOF ! ${CC-cc} dummy.s -o dummy 2>/dev/null ! if test "$?" = 0 ; then ! ./dummy ! case "$?" in ! 7) ! UNAME_MACHINE="alpha" ! ;; ! 15) ! UNAME_MACHINE="alphaev5" ! ;; ! 14) ! UNAME_MACHINE="alphaev56" ! ;; ! 10) ! UNAME_MACHINE="alphapca56" ! ;; ! 16) ! UNAME_MACHINE="alphaev6" ! ;; ! esac ! fi ! rm -f dummy.s dummy ! echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]` exit 0 ;; 21064:Windows_NT:50:3) *************** *** 172,178 **** --- 214,244 ---- echo m68k-cbm-openbsd${UNAME_RELEASE} exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; + arm32:NetBSD:*:*) + echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + SR2?01:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; Pyramid*:OSx*:*:*|MIS*:OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. *************** *** 210,213 **** --- 276,291 ---- echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} *************** *** 231,234 **** --- 309,324 ---- echo m68k-apple-openbsd${UNAME_RELEASE} exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + Power?Macintosh:Rhapsody:*:*) + echo powerpc-apple-nextstep${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-unknown-nextstep${UNAME_RELEASE} + exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} *************** *** 243,246 **** --- 333,339 ---- echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; + 2020:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) sed 's/^ //' << EOF >dummy.c *************** *** 267,271 **** exit 0 ;; Night_Hawk:Power_UNIX:*:*) ! echo powerpc-harris-powerux exit 0 ;; m88k:CX/UX:7*:*) --- 360,364 ---- exit 0 ;; Night_Hawk:Power_UNIX:*:*) ! echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) *************** *** 502,505 **** --- 595,601 ---- echo i386-pc-cygwin32 exit 0 ;; + i*:MINGW*:*) + echo i386-pc-mingw32 + exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin32 *************** *** 509,513 **** exit 0 ;; *:GNU:*:*) ! echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; *:Linux:*:*) --- 605,609 ---- exit 0 ;; *:GNU:*:*) ! echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; *:Linux:*:*) *************** *** 515,549 **** # first see if it will tell us. ld_help_string=`ld --help 2>&1` ! if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i.86"; then ! echo "${UNAME_MACHINE}-pc-linux-gnu" ; exit 0 ! elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86linux"; then ! echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ! elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86coff"; then ! echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ! elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then ! echo "${UNAME_MACHINE}-unknown-linux-gnu" ; exit 0 ! elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then ! echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ! elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf32ppc"; then ! echo "powerpc-unknown-linux-gnu" ; exit 0 ! elif test "${UNAME_MACHINE}" = "alpha" ; then ! echo alpha-unknown-linux-gnu ; exit 0 ! elif test "${UNAME_MACHINE}" = "sparc" ; then ! echo sparc-unknown-linux-gnu ; exit 0 ! else ! # Either a pre-BFD a.out linker (linux-gnuoldld) or one that does not give us ! # useful --help. Gcc wants to distinguish between linux-gnuoldld and linux-gnuaout. ! test ! -d /usr/lib/ldscripts/. \ ! && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 # Determine whether the default compiler is a.out or elf cat >dummy.c <&1` ! ld_supported_emulations=`echo $ld_help_string \ ! | sed -ne '/supported emulations:/!d ! s/[ ][ ]*/ /g ! s/.*supported emulations: *// ! s/ .*// ! p'` ! case "$ld_supported_emulations" in ! i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;; ! i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;; ! sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; ! m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; ! elf32ppc) echo "powerpc-unknown-linux-gnu" ; exit 0 ;; ! esac ! ! if test "${UNAME_MACHINE}" = "alpha" ; then ! sed 's/^ //' <dummy.s ! .globl main ! .ent main ! main: ! .frame \$30,0,\$26,0 ! .prologue 0 ! .long 0x47e03d80 # implver $0 ! lda \$2,259 ! .long 0x47e20c21 # amask $2,$1 ! srl \$1,8,\$2 ! sll \$2,2,\$2 ! sll \$0,3,\$0 ! addl \$1,\$0,\$0 ! addl \$2,\$0,\$0 ! ret \$31,(\$26),1 ! .end main ! EOF ! LIBC="" ! ${CC-cc} dummy.s -o dummy 2>/dev/null ! if test "$?" = 0 ; then ! ./dummy ! case "$?" in ! 7) ! UNAME_MACHINE="alpha" ! ;; ! 15) ! UNAME_MACHINE="alphaev5" ! ;; ! 14) ! UNAME_MACHINE="alphaev56" ! ;; ! 10) ! UNAME_MACHINE="alphapca56" ! ;; ! 16) ! UNAME_MACHINE="alphaev6" ! ;; ! esac ! ! objdump --private-headers dummy | \ ! grep ld.so.1 > /dev/null ! if test "$?" = 0 ; then ! LIBC="libc1" ! fi ! fi ! rm -f dummy.s dummy ! echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 ! elif test "${UNAME_MACHINE}" = "mips" ; then ! cat >dummy.c </dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 ! rm -f dummy.c dummy ! else ! # Either a pre-BFD a.out linker (linux-gnuoldld) ! # or one that does not give us useful --help. ! # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. ! # If ld does not provide *any* "supported emulations:" ! # that means it is gnuoldld. ! echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" ! test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 ! ! case "${UNAME_MACHINE}" in ! i?86) ! VENDOR=pc; ! ;; ! *) ! VENDOR=unknown; ! ;; ! esac # Determine whether the default compiler is a.out or elf cat >dummy.c < main(argc, argv) ! int argc; ! char *argv[]; { #ifdef __ELF__ ! # ifdef __GLIBC__ ! # if __GLIBC__ >= 2 ! printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); ! # else ! printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); ! # endif ! # else ! printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); ! # endif #else ! printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); #endif return 0; *************** *** 558,562 **** echo i386-sequent-sysv4 exit 0 ;; ! i?86:*:4.*:* | i?86:SYSTEM_V:4.*:* | i[34]86:UNIX_SV:4.*:*) if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} --- 738,750 ---- echo i386-sequent-sysv4 exit 0 ;; ! i?86:UNIX_SV:4.2MP:2.*) ! # Unixware is an offshoot of SVR4, but it has its own version ! # number series starting with 2... ! # I am not positive that other SVR4 systems won't match this, ! # I just have to hope. -- rms. ! # Use sysv4.2uw... so that sysv4* matches it. ! echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} ! exit 0 ;; ! i?86:*:4.*:* | i?86:SYSTEM_V:4.*:* | i?86:UNIX_SV:4.*:*) if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} *************** *** 579,582 **** --- 767,775 ---- fi exit 0 ;; + pc:*:*:*) + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 *************** *** 630,634 **** echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; ! RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; --- 823,827 ---- echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; ! RM*:SINIX-*:*:* | RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *************** *** 641,644 **** --- 834,841 ---- fi exit 0 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . *************** *** 653,656 **** --- 850,856 ---- echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; + news*:NEWS-OS:*:6*) + echo mips-sony-newsos6 + exit 0 ;; R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*) if [ -d /usr/nec ]; then *************** *** 711,715 **** int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; ! printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); exit (0); #endif --- 911,915 ---- int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; ! printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); exit (0); #endif diff -Nrc2 bash-2.01.1/support/config.sub bash-2.02/support/config.sub *** bash-2.01.1/support/config.sub Wed Feb 5 10:59:26 1997 --- bash-2.02/support/config.sub Wed Oct 8 11:03:43 1997 *************** *** 153,157 **** | arme[lb] | pyramid \ | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \ ! | alpha | we32k | ns16k | clipper | i370 | sh \ | powerpc | powerpcle | 1750a | dsp16xx | mips64 | mipsel \ | pdp11 | mips64el | mips64orion | mips64orionel \ --- 153,157 ---- | arme[lb] | pyramid \ | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \ ! | hppa2.0 | alpha | we32k | ns16k | clipper | i370 | sh \ | powerpc | powerpcle | 1750a | dsp16xx | mips64 | mipsel \ | pdp11 | mips64el | mips64orion | mips64orionel \ *************** *** 175,179 **** | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \ | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \ ! | hppa-* | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \ | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \ | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \ --- 175,180 ---- | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \ | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \ ! | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* \ ! | alpha-* | we32k-* | cydra-* | ns16k-* \ | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \ | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \ diff -Nrc2 bash-2.01.1/support/man2html.c bash-2.02/support/man2html.c *** bash-2.01.1/support/man2html.c Wed Dec 31 19:00:00 1969 --- bash-2.02/support/man2html.c Fri Feb 27 13:15:57 1998 *************** *** 0 **** --- 1,4018 ---- + /* + * This program was written by Richard Verhoeven (NL:5482ZX35) + * at the Eindhoven University of Technology. Email: rcb5@win.tue.nl + * + * Permission is granted to distribute, modify and use this program as long + * as this comment is not removed or changed. + * + * THIS IS A MODIFIED VERSION. IT WAS MODIFIED BY chet@po.cwru.edu FOR + * USE BY BASH. + */ + + /* + * man2html will add links to the converted manpages. The function add_links + * is used for that. At the moment it will add links as follows, where + * indicates what should match to start with: + * ^^^ + * Recognition Item Link + * ---------------------------------------------------------- + * name(*) Manpage ../man?/name.* + * ^ + * name@hostname Email address mailto:name@hostname + * ^ + * method://string URL method://string + * ^^^ + * www.host.name WWW server http://www.host.name + * ^^^^ + * ftp.host.name FTP server ftp://ftp.host.name + * ^^^^ + * Include file file:/usr/include/file.h + * ^^^ + * + * Since man2html does not check if manpages, hosts or email addresses exist, + * some links might not work. For manpages, some extra checks are performed + * to make sure not every () pair creates a link. Also out of date pages + * might point to incorrect places. + * + * The program will not allow users to get system specific files, such as + * /etc/passwd. It will check that "man" is part of the specified file and + * that "/../" isn't. Even if someone manages to get such file, man2html will + * handle it like a manpage and will usually not produce any output (or crash). + * + * If you find any bugs when normal manpages are converted, please report + * them to me (rcb5@win.tue.nl) after you have checked that man(1) can handle + * the manpage correct. + * + * Known bugs and missing features: + * + * * Equations are not converted at all. + * * Tables are converted but some features are not possible in html. + * * The tabbing environment is converted by counting characters and adding + * spaces. This might go wrong (outside
)
+  *  * Some pages look beter if man2html works in troff mode, especially pages
+  *    with tables. You can deside at compile time which made you want to use.
+  *
+  *    -DNROFF=0     troff mode
+  *    -DNROFF=1     nroff mode   (default)
+  *
+  *    if you install both modes, you should compile with the correct CGIBASE.
+  *  * Some manpages rely on the fact that troff/nroff is used to convert
+  *    them and use features which are not descripted in the man manpages.
+  *    (definitions, calculations, conditionals, requests). I can't guarantee
+  *    that all these features work on all manpages. (I didn't have the
+  *    time to look through all the available manpages.)
+  */
+ #ifdef HAVE_CONFIG_H
+ #include 
+ #endif
+ 
+ #define NROFF 0
+ 
+ #include 
+ #include 
+ #include 
+ #include 
+ #include 
+ #include 
+ #include 
+ #include 
+ #include 
+ 
+ #define NULL_TERMINATED(n) ((n) + 1)
+ 
+ #define HUGE_STR_MAX  10000
+ #define LARGE_STR_MAX 2000
+ #define MED_STR_MAX   500
+ #define SMALL_STR_MAX 100
+ #define TINY_STR_MAX  10
+ 
+ #define MAX_MAN_PATHS 100	/* Max number of directories */
+ #define MAX_ZCATS     10	/* Max number of zcat style programs */
+ #define MAX_WORDLIST  100
+ 
+ #ifndef EXIT_SUCCESS
+ #define EXIT_SUCCESS 0
+ #endif
+ #ifndef EXIT_FAILURE
+ #define EXIT_FAILURE 1
+ #endif
+ #ifndef EXIT_USAGE
+ #define EXIT_USAGE 2
+ #endif
+ 
+ static char location_base[NULL_TERMINATED(MED_STR_MAX)] = "";
+ 
+ char   *signature = "
\n" + "This document was created by man2html\n" + "using the manual pages.
\n" + "Time: %s\n"; + + /* timeformat for signature */ + #define TIMEFORMAT "%T GMT, %B %d, %Y" + + /* BSD mandoc Bl/El lists to HTML list types */ + #define BL_DESC_LIST 1 + #define BL_BULLET_LIST 2 + #define BL_ENUM_LIST 4 + + /* BSD mandoc Bd/Ed example(?) blocks */ + #define BD_LITERAL 1 + #define BD_INDENT 2 + + #ifndef HAVE_STRERROR + static char * + strerror(int e) + { + static char emsg[40]; + + #if defined (HAVE_SYS_ERRLIST) + extern int sys_nerr; + extern char *sys_errlist[]; + + if (e > 0 && e < sys_nerr) + return (sys_errlist[e]); + else + #endif /* HAVE_SYS_ERRLIST */ + { + sprintf(emsg, "Unknown system error %d", e); + return (&emsg[0]); + } + } + #endif /* !HAVE_STRERROR */ + + static char * + strgrow(char *old, int len) + { + char *new = realloc(old, (strlen(old) + len + 1) * sizeof(char)); + + if (!new) { + fprintf(stderr, "man2html: out of memory"); + exit(EXIT_FAILURE); + } + return new; + } + + static char * + stralloc(int len) + { + /* allocate enough for len + NULL */ + char *new = malloc((len + 1) * sizeof(char)); + + if (!new) { + fprintf(stderr, "man2html: out of memory"); + exit(EXIT_FAILURE); + } + return new; + } + + /* + * Some systems don't have strdup so lets use our own - which can also + * check for out of memory. + */ + static char * + strduplicate(char *from) + { + char *new = stralloc(strlen(from)); + + strcpy(new, from); + return new; + } + + /* Assumes space for n plus a null */ + static char * + strmaxcpy(char *to, char *from, int n) + { + int len = strlen(from); + + strncpy(to, from, n); + to[(len <= n) ? len : n] = '\0'; + return to; + } + + static char * + strmaxcat(char *to, char *from, int n) + { + int to_len = strlen(to); + + if (to_len < n) { + int from_len = strlen(from); + int cp = (to_len + from_len <= n) ? from_len : n - to_len; + + strncpy(to + to_len, from, cp); + to[to_len + cp] = '\0'; + } + return to; + } + + /* Assumes space for limit plus a null */ + static char * + strlimitcpy(char *to, char *from, int n, int limit) + { + int len = n > limit ? limit : n; + + strmaxcpy(to, from, len); + to[len] = '\0'; + return to; + } + + /* + * takes string and escapes all metacharacters. should be used before + * including string in system() or similar call. + */ + static char * + escape_input(char *str) + { + int i, j = 0; + static char new[NULL_TERMINATED(MED_STR_MAX)]; + + if (strlen(str) * 2 + 1 > MED_STR_MAX) { + fprintf(stderr, + "man2html: escape_input - str too long:\n%-80s...\n", + str); + exit(EXIT_FAILURE); + } + for (i = 0; i < strlen(str); i++) { + if (!(((str[i] >= 'A') && (str[i] <= 'Z')) || + ((str[i] >= 'a') && (str[i] <= 'z')) || + ((str[i] >= '0') && (str[i] <= '9')))) { + new[j] = '\\'; + j++; + } + new[j] = str[i]; + j++; + } + new[j] = '\0'; + return new; + } + + static void + usage(void) + { + fprintf(stderr, "man2html: usage: man2html filename\n"); + } + + + + /* + * below this you should not change anything unless you know a lot + * about this program or about troff. + */ + + typedef struct STRDEF STRDEF; + struct STRDEF { + int nr, slen; + char *st; + STRDEF *next; + }; + + typedef struct INTDEF INTDEF; + struct INTDEF { + int nr; + int val; + int incr; + INTDEF *next; + }; + + static char NEWLINE[2] = "\n"; + static char idxlabel[6] = "ixAAA"; + + #define INDEXFILE "/tmp/manindex.list" + + static char *fname; + static FILE *idxfile; + + static STRDEF *chardef, *strdef, *defdef; + static INTDEF *intdef; + + #define V(A,B) ((A)*256+(B)) + + static INTDEF standardint[] = { + {V('n', ' '), NROFF, 0, NULL}, + {V('t', ' '), 1 - NROFF, 0, NULL}, + {V('o', ' '), 1, 0, NULL}, + {V('e', ' '), 0, 0, NULL}, + {V('.', 'l'), 70, 0, NULL}, + {V('.', '$'), 0, 0, NULL}, + {V('.', 'A'), NROFF, 0, NULL}, + {V('.', 'T'), 1 - NROFF, 0, NULL}, + {V('.', 'V'), 1, 0, NULL}, /* the me package tests for this */ + {0, 0, 0, NULL}}; + + static STRDEF standardstring[] = { + {V('R', ' '), 1, "®", NULL}, + {V('l', 'q'), 2, "``", NULL}, + {V('r', 'q'), 2, "''", NULL}, + {0, 0, NULL, NULL} + }; + + + static STRDEF standardchar[] = { + {V('*', '*'), 1, "*", NULL}, + {V('*', 'A'), 1, "A", NULL}, + {V('*', 'B'), 1, "B", NULL}, + {V('*', 'C'), 2, "Xi", NULL}, + {V('*', 'D'), 5, "Delta", NULL}, + {V('*', 'E'), 1, "E", NULL}, + {V('*', 'F'), 3, "Phi", NULL}, + {V('*', 'G'), 5, "Gamma", NULL}, + {V('*', 'H'), 5, "Theta", NULL}, + {V('*', 'I'), 1, "I", NULL}, + {V('*', 'K'), 1, "K", NULL}, + {V('*', 'L'), 6, "Lambda", NULL}, + {V('*', 'M'), 1, "M", NULL}, + {V('*', 'N'), 1, "N", NULL}, + {V('*', 'O'), 1, "O", NULL}, + {V('*', 'P'), 2, "Pi", NULL}, + {V('*', 'Q'), 3, "Psi", NULL}, + {V('*', 'R'), 1, "P", NULL}, + {V('*', 'S'), 5, "Sigma", NULL}, + {V('*', 'T'), 1, "T", NULL}, + {V('*', 'U'), 1, "Y", NULL}, + {V('*', 'W'), 5, "Omega", NULL}, + {V('*', 'X'), 1, "X", NULL}, + {V('*', 'Y'), 1, "H", NULL}, + {V('*', 'Z'), 1, "Z", NULL}, + {V('*', 'a'), 5, "alpha", NULL}, + {V('*', 'b'), 4, "beta", NULL}, + {V('*', 'c'), 2, "xi", NULL}, + {V('*', 'd'), 5, "delta", NULL}, + {V('*', 'e'), 7, "epsilon", NULL}, + {V('*', 'f'), 3, "phi", NULL}, + {V('*', 'g'), 5, "gamma", NULL}, + {V('*', 'h'), 5, "theta", NULL}, + {V('*', 'i'), 4, "iota", NULL}, + {V('*', 'k'), 5, "kappa", NULL}, + {V('*', 'l'), 6, "lambda", NULL}, + {V('*', 'm'), 1, "µ", NULL}, + {V('*', 'n'), 2, "nu", NULL}, + {V('*', 'o'), 1, "o", NULL}, + {V('*', 'p'), 2, "pi", NULL}, + {V('*', 'q'), 3, "psi", NULL}, + {V('*', 'r'), 3, "rho", NULL}, + {V('*', 's'), 5, "sigma", NULL}, + {V('*', 't'), 3, "tau", NULL}, + {V('*', 'u'), 7, "upsilon", NULL}, + {V('*', 'w'), 5, "omega", NULL}, + {V('*', 'x'), 3, "chi", NULL}, + {V('*', 'y'), 3, "eta", NULL}, + {V('*', 'z'), 4, "zeta", NULL}, + {V('t', 's'), 5, "sigma", NULL}, + {V('+', '-'), 1, "±", NULL}, + {V('1', '2'), 1, "½", NULL}, + {V('1', '4'), 1, "¼", NULL}, + {V('3', '4'), 1, "¾", NULL}, + {V('F', 'i'), 3, "ffi", NULL}, + {V('F', 'l'), 3, "ffl", NULL}, + {V('a', 'a'), 1, "´", NULL}, + {V('a', 'p'), 1, "~", NULL}, + {V('b', 'r'), 1, "|", NULL}, + {V('b', 'u'), 1, "*", NULL}, + {V('b', 'v'), 1, "|", NULL}, + {V('c', 'i'), 1, "o", NULL}, + {V('c', 'o'), 1, "©", NULL}, + {V('c', 't'), 1, "¢", NULL}, + {V('d', 'e'), 1, "°", NULL}, + {V('d', 'g'), 1, "+", NULL}, + {V('d', 'i'), 1, "÷", NULL}, + {V('e', 'm'), 1, "-", NULL}, + {V('e', 'm'), 3, "---", NULL}, + {V('e', 'q'), 1, "=", NULL}, + {V('e', 's'), 1, "Ø", NULL}, + {V('f', 'f'), 2, "ff", NULL}, + {V('f', 'i'), 2, "fi", NULL}, + {V('f', 'l'), 2, "fl", NULL}, + {V('f', 'm'), 1, "´", NULL}, + {V('g', 'a'), 1, "`", NULL}, + {V('h', 'y'), 1, "-", NULL}, + {V('l', 'c'), 2, "|¯", NULL}, + {V('l', 'f'), 2, "|_", NULL}, + {V('l', 'k'), 1, "{", NULL}, + {V('m', 'i'), 1, "-", NULL}, + {V('m', 'u'), 1, "×", NULL}, + {V('n', 'o'), 1, "¬", NULL}, + {V('o', 'r'), 1, "|", NULL}, + {V('p', 'l'), 1, "+", NULL}, + {V('r', 'c'), 2, "¯|", NULL}, + {V('r', 'f'), 2, "_|", NULL}, + {V('r', 'g'), 1, "®", NULL}, + {V('r', 'k'), 1, "}", NULL}, + {V('r', 'n'), 1, "¯", NULL}, + {V('r', 'u'), 1, "_", NULL}, + {V('s', 'c'), 1, "§", NULL}, + {V('s', 'l'), 1, "/", NULL}, + {V('s', 'q'), 2, "[]", NULL}, + {V('u', 'l'), 1, "_", NULL}, + {0, 0, NULL, NULL} + }; + + /* default: print code */ + + + static char eqndelimopen = 0, eqndelimclose = 0; + static char escapesym = '\\', nobreaksym = '\'', controlsym = '.', fieldsym = 0, padsym = 0; + + static char *buffer = NULL; + static int buffpos = 0, buffmax = 0; + static int scaninbuff = 0; + static int itemdepth = 0; + static int dl_set[20] = {0}; + static int still_dd = 0; + static int tabstops[20] = {8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96}; + static int maxtstop = 12; + static int curpos = 0; + + static char *scan_troff(char *c, int san, char **result); + static char *scan_troff_mandoc(char *c, int san, char **result); + + static char **argument = NULL; + + static char charb[TINY_STR_MAX]; + + static void + print_sig(void) + { + char datbuf[NULL_TERMINATED(MED_STR_MAX)]; + struct tm *timetm; + time_t clock; + + datbuf[0] = '\0'; + clock = time(NULL); + timetm = gmtime(&clock); + strftime(datbuf, MED_STR_MAX, TIMEFORMAT, timetm); + printf(signature, datbuf); + } + + static char * + expand_char(int nr) + { + STRDEF *h; + + h = chardef; + if (!nr) + return NULL; + while (h) + if (h->nr == nr) { + curpos += h->slen; + return h->st; + } else + h = h->next; + charb[0] = nr / 256; + charb[1] = nr % 256; + charb[2] = '\0'; + if (charb[0] == '<') { /* Fix up <= */ + charb[4] = charb[1]; + strncpy(charb, "<", 4); + charb[5] = '\0'; + } + curpos += 2; + return charb; + } + + static char * + expand_string(int nr) + { + STRDEF *h = strdef; + + if (!nr) + return NULL; + while (h) + if (h->nr == nr) { + curpos += h->slen; + return h->st; + } else + h = h->next; + return NULL; + } + + static char * + read_man_page(char *filename) + { + char *man_buf = NULL; + int i; + FILE *man_stream = NULL; + struct stat stbuf; + int buf_size; + + if (stat(filename, &stbuf) == -1) + return NULL; + + buf_size = stbuf.st_size; + man_buf = stralloc(buf_size + 5); + man_stream = fopen(filename, "r"); + if (man_stream) { + man_buf[0] = '\n'; + if (fread(man_buf + 1, 1, buf_size, man_stream) == buf_size) { + man_buf[buf_size] = '\n'; + man_buf[buf_size + 1] = man_buf[buf_size + 2] = '\0'; + } else { + man_buf = NULL; + } + fclose(man_stream); + } + return man_buf; + } + + + static char outbuffer[NULL_TERMINATED(HUGE_STR_MAX)]; + static int obp = 0; + static int no_newline_output = 0; + static int newline_for_fun = 0; + static int output_possible = 0; + static int out_length = 0; + + /* + * Add the links to the output. At the moment the following are + * recognized: + * + #if 0 + * name(*) -> ../man?/name.* + #endif + * method://string -> method://string + * www.host.name -> http://www.host.name + * ftp.host.name -> ftp://ftp.host.name + * name@host -> mailto:name@host + * -> file:/usr/include/name.h (guess) + * + * Other possible links to add in the future: + * + * /dir/dir/file -> file:/dir/dir/file + */ + static void + add_links(char *c) + { + int i, j, nr; + char *f, *g, *h; + char *idtest[6]; /* url, mailto, www, ftp, manpage */ + + out_length += strlen(c); + /* search for (section) */ + nr = 0; + idtest[0] = strstr(c + 1, "://"); + idtest[1] = strchr(c + 1, '@'); + idtest[2] = strstr(c, "www."); + idtest[3] = strstr(c, "ftp."); + #if 0 + idtest[4] = strchr(c + 1, '('); + #else + idtest[4] = 0; + #endif + idtest[5] = strstr(c + 1, ".h>"); + for (i = 0; i < 6; i++) + nr += (idtest[i] != NULL); + while (nr) { + j = -1; + for (i = 0; i < 6; i++) + if (idtest[i] && (j < 0 || idtest[i] < idtest[j])) + j = i; + switch (j) { + case 5: /* */ + f = idtest[5]; + h = f + 2; + g = f; + while (g > c && g[-1] != ';') + g--; + if (g != c) { + char t; + + t = *g; + *g = '\0'; + fputs(c, stdout); + *g = t; + *h = '\0'; + printf("%s>", g, g); + c = f + 6; + } else { + f[5] = '\0'; + fputs(c, stdout); + f[5] = ';'; + c = f + 5; + } + break; + case 4: /* manpage */ + #if 0 + f = idtest[j]; + /* check section */ + g = strchr(f, ')'); + if (g && f - g < 6 && (isalnum(f[-1]) || f[-1] == '>') && + ((isdigit(f[1]) && f[1] != '0' && + (f[2] == ')' || (isalpha(f[2]) && f[3] == ')') || f[2] == 'X')) || + (f[2] == ')' && (f[1] == 'n' || f[1] == 'l')))) { + /* this might be a link */ + h = f - 1; + /* skip html makeup */ + while (h > c && *h == '>') { + while (h != c && *h != '<') + h--; + if (h != c) + h--; + } + if (isalnum(*h)) { + char t, sec, subsec, *e; + + e = h + 1; + sec = f[1]; + subsec = f[2]; + if ((subsec == 'X' && f[3] != ')') || subsec == ')') + subsec = '\0'; + while (h > c && (isalnum(h[-1]) || h[-1] == '_' || + h[-1] == '-' || h[-1] == '.')) + h--; + t = *h; + *h = '\0'; + fputs(c, stdout); + *h = t; + t = *e; + *e = '\0'; + if (subsec) + printf("%s", + sec, h, sec, tolower(subsec), h); + else + printf("%s", + sec, h, sec, h); + *e = t; + c = e; + } + } + *f = '\0'; + fputs(c, stdout); + *f = '('; + idtest[4] = f - 1; + c = f; + #endif + break; /* manpage */ + case 3: /* ftp */ + case 2: /* www */ + g = f = idtest[j]; + while (*g && (isalnum(*g) || *g == '_' || *g == '-' || *g == '+' || + *g == '.')) + g++; + if (g[-1] == '.') + g--; + if (g - f > 4) { + char t; + + t = *f; + *f = '\0'; + fputs(c, stdout); + *f = t; + t = *g; + *g = '\0'; + printf("%s", (j == 3 ? "ftp" : "http"), + f, f); + *g = t; + c = g; + } else { + f[3] = '\0'; + fputs(c, stdout); + c = f + 3; + f[3] = '.'; + } + break; + case 1: /* mailto */ + g = f = idtest[1]; + while (g > c && (isalnum(g[-1]) || g[-1] == '_' || g[-1] == '-' || + g[-1] == '+' || g[-1] == '.' || g[-1] == '%')) + g--; + h = f + 1; + while (*h && (isalnum(*h) || *h == '_' || *h == '-' || *h == '+' || + *h == '.')) + h++; + if (*h == '.') + h--; + if (h - f > 4 && f - g > 1) { + char t; + + t = *g; + *g = '\0'; + fputs(c, stdout); + *g = t; + t = *h; + *h = '\0'; + printf("%s", g, g); + *h = t; + c = h; + } else { + *f = '\0'; + fputs(c, stdout); + *f = '@'; + idtest[1] = c; + c = f; + } + break; + case 0: /* url */ + g = f = idtest[0]; + while (g > c && isalpha(g[-1]) && islower(g[-1])) + g--; + h = f + 3; + while (*h && !isspace(*h) && *h != '<' && *h != '>' && *h != '"' && + *h != '&') + h++; + if (f - g > 2 && f - g < 7 && h - f > 3) { + char t; + + t = *g; + *g = '\0'; + fputs(c, stdout); + *g = t; + t = *h; + *h = '\0'; + printf("%s", g, g); + *h = t; + c = h; + } else { + f[1] = '\0'; + fputs(c, stdout); + f[1] = '/'; + c = f + 1; + } + break; + default: + break; + } + nr = 0; + if (idtest[0] && idtest[0] < c) + idtest[0] = strstr(c + 1, "://"); + if (idtest[1] && idtest[1] < c) + idtest[1] = strchr(c + 1, '@'); + if (idtest[2] && idtest[2] < c) + idtest[2] = strstr(c, "www."); + if (idtest[3] && idtest[3] < c) + idtest[3] = strstr(c, "ftp."); + if (idtest[4] && idtest[4] < c) + idtest[4] = strchr(c + 1, '('); + if (idtest[5] && idtest[5] < c) + idtest[5] = strstr(c + 1, ".h>"); + for (i = 0; i < 6; i++) + nr += (idtest[i] != NULL); + } + fputs(c, stdout); + } + + static int current_font = 0; + static int current_size = 0; + static int fillout = 1; + + static void + out_html(char *c) + { + if (!c) + return; + if (no_newline_output) { + int i = 0; + + no_newline_output = 1; + while (c[i]) { + if (!no_newline_output) + c[i - 1] = c[i]; + if (c[i] == '\n') + no_newline_output = 1; + i++; + } + if (!no_newline_output) + c[i - 1] = 0; + } + if (scaninbuff) { + while (*c) { + if (buffpos >= buffmax) { + char *h; + + h = realloc(buffer, buffmax * 2); + if (!h) + return; + buffer = h; + buffmax *= 2; + } + buffer[buffpos++] = *c++; + } + } else if (output_possible) { + while (*c) { + outbuffer[obp++] = *c; + if (*c == '\n' || obp > HUGE_STR_MAX) { + outbuffer[obp] = '\0'; + add_links(outbuffer); + obp = 0; + } + c++; + } + } + } + + #define FO0 "" + #define FC0 "" + #define FO1 "" + #define FC1 "" + #define FO2 "" + #define FC2 "" + #define FO3 "" + #define FC3 "" + + static char *switchfont[16] = { + "", FC0 FO1, FC0 FO2, FC0 FO3, + FC1 FO0, "", FC1 FO2, FC1 FO3, + FC2 FO0, FC2 FO1, "", FC2 FO3, + FC3 FO0, FC3 FO1, FC3 FO2, "" + }; + + static char * + change_to_font(int nr) + { + int i; + + switch (nr) { + case '0': + nr++; + case '1': + case '2': + case '3': + case '4': + nr = nr - '1'; + break; + case V('C', 'W'): + nr = 3; + break; + case 'L': + nr = 3; + break; + case 'B': + nr = 2; + break; + case 'I': + nr = 1; + break; + case 'P': + case 'R': + nr = 0; + break; + case 0: + case 1: + case 2: + case 3: + break; + default: + nr = 0; + break; + } + i = current_font * 4 + nr % 4; + current_font = nr % 4; + return switchfont[i]; + } + + static char sizebuf[200]; + + static char * + change_to_size(int nr) + { + int i; + + switch (nr) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + nr = nr - '0'; + break; + case '\0': + break; + default: + nr = current_size + nr; + if (nr > 9) + nr = 9; + if (nr < -9) + nr = -9; + break; + } + if (nr == current_size) + return ""; + i = current_font; + sizebuf[0] = '\0'; + strcat(sizebuf, change_to_font(0)); + if (current_size) + strcat(sizebuf, ""); + current_size = nr; + if (nr) { + int l; + + strcat(sizebuf, "nr != i) + intd = intd->next; + if (intd) { + intd->val = intd->val + j * intd->incr; + intresult = intd->val; + } else { + switch (i) { + case V('.', 's'): + intresult = current_size; + break; + case V('.', 'f'): + intresult = current_font; + break; + default: + intresult = 0; + break; + } + } + h = ""; + break; + case 'w': + c++; + i = *c; + c++; + exoutputp = output_possible; + exskipescape = skip_escape; + output_possible = 0; + skip_escape = 1; + j = 0; + while (*c != i) { + j++; + if (*c == escapesym) + c = scan_escape(c + 1); + else + c++; + } + output_possible = exoutputp; + skip_escape = exskipescape; + intresult = j; + break; + case 'l': + h = "
"; + curpos = 0; + case 'b': + case 'v': + case 'x': + case 'o': + case 'L': + case 'h': + c++; + i = *c; + c++; + exoutputp = output_possible; + exskipescape = skip_escape; + output_possible = 0; + skip_escape = 1; + while (*c != i) + if (*c == escapesym) + c = scan_escape(c + 1); + else + c++; + output_possible = exoutputp; + skip_escape = exskipescape; + break; + case 'c': + no_newline_output = 1; + break; + case '{': + newline_for_fun++; + h = ""; + break; + case '}': + if (newline_for_fun) + newline_for_fun--; + h = ""; + break; + case 'p': + h = "
\n"; + curpos = 0; + break; + case 't': + h = "\t"; + curpos = (curpos + 8) & 0xfff8; + break; + case '<': + h = "<"; + curpos++; + break; + case '>': + h = ">"; + curpos++; + break; + case '\\': + if (single_escape) { + c--; + break; + } + default: + b[0] = *c; + b[1] = 0; + h = b; + curpos++; + break; + } + c++; + if (!skip_escape) + out_html(h); + return c; + } + + typedef struct TABLEITEM TABLEITEM; + + struct TABLEITEM { + char *contents; + int size, align, valign, colspan, rowspan, font, vleft, vright, space, + width; + TABLEITEM *next; + }; + + static TABLEITEM emptyfield = {NULL, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, NULL}; + + typedef struct TABLEROW TABLEROW; + + struct TABLEROW { + TABLEITEM *first; + TABLEROW *prev, *next; + }; + + static char *tableopt[] = { + "center", "expand", "box", "allbox", "doublebox", + "tab", "linesize", "delim", NULL + }; + static int tableoptl[] = {6, 6, 3, 6, 9, 3, 8, 5, 0}; + + static void + clear_table(TABLEROW * table) + { + TABLEROW *tr1, *tr2; + TABLEITEM *ti1, *ti2; + + tr1 = table; + while (tr1->prev) + tr1 = tr1->prev; + while (tr1) { + ti1 = tr1->first; + while (ti1) { + ti2 = ti1->next; + if (ti1->contents) + free(ti1->contents); + free(ti1); + ti1 = ti2; + } + tr2 = tr1; + tr1 = tr1->next; + free(tr2); + } + } + + static char *scan_expression(char *c, int *result); + + static char * + scan_format(char *c, TABLEROW ** result, int *maxcol) + { + TABLEROW *layout, *currow; + TABLEITEM *curfield; + int i, j; + + if (*result) { + clear_table(*result); + } + layout = currow = (TABLEROW *) malloc(sizeof(TABLEROW)); + currow->next = currow->prev = NULL; + currow->first = curfield = (TABLEITEM *) malloc(sizeof(TABLEITEM)); + *curfield = emptyfield; + while (*c && *c != '.') { + switch (*c) { + case 'C': + case 'c': + case 'N': + case 'n': + case 'R': + case 'r': + case 'A': + case 'a': + case 'L': + case 'l': + case 'S': + case 's': + case '^': + case '_': + if (curfield->align) { + curfield->next = (TABLEITEM *) malloc(sizeof(TABLEITEM)); + curfield = curfield->next; + *curfield = emptyfield; + } + curfield->align = toupper(*c); + c++; + break; + case 'i': + case 'I': + case 'B': + case 'b': + curfield->font = toupper(*c); + c++; + break; + case 'f': + case 'F': + c++; + curfield->font = toupper(*c); + c++; + if (!isspace(*c)) + c++; + break; + case 't': + case 'T': + curfield->valign = 't'; + c++; + break; + case 'p': + case 'P': + c++; + i = j = 0; + if (*c == '+') { + j = 1; + c++; + } + if (*c == '-') { + j = -1; + c++; + } + while (isdigit(*c)) + i = i * 10 + (*c++) - '0'; + if (j) + curfield->size = i * j; + else + curfield->size = j - 10; + break; + case 'v': + case 'V': + case 'w': + case 'W': + c = scan_expression(c + 2, &curfield->width); + break; + case '|': + if (curfield->align) + curfield->vleft++; + else + curfield->vright++; + c++; + break; + case 'e': + case 'E': + c++; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + i = 0; + while (isdigit(*c)) + i = i * 10 + (*c++) - '0'; + curfield->space = i; + break; + case ',': + case '\n': + currow->next = (TABLEROW *) malloc(sizeof(TABLEROW)); + currow->next->prev = currow; + currow = currow->next; + currow->next = NULL; + curfield = currow->first = (TABLEITEM *) malloc(sizeof(TABLEITEM)); + *curfield = emptyfield; + c++; + break; + default: + c++; + break; + } + } + if (*c == '.') + while (*c++ != '\n'); + *maxcol = 0; + currow = layout; + while (currow) { + curfield = layout->first; + i = 0; + while (curfield) { + i++; + curfield = curfield->next; + } + if (i > *maxcol) + *maxcol = i; + currow = currow->next; + } + *result = layout; + return c; + } + + static TABLEROW * + next_row(TABLEROW * tr) + { + if (tr->next) { + tr = tr->next; + if (!tr->next) + next_row(tr); + return tr; + } else { + TABLEITEM *ti, *ti2; + + tr->next = (TABLEROW *) malloc(sizeof(TABLEROW)); + tr->next->prev = tr; + ti = tr->first; + tr = tr->next; + tr->next = NULL; + if (ti) + tr->first = ti2 = (TABLEITEM *) malloc(sizeof(TABLEITEM)); + else + tr->first = ti2 = NULL; + while (ti != ti2) { + *ti2 = *ti; + ti2->contents = NULL; + if ((ti = ti->next)) { + ti2->next = (TABLEITEM *) malloc(sizeof(TABLEITEM)); + } + ti2 = ti2->next; + } + return tr; + } + } + + static char itemreset[20] = "\\fR\\s0"; + + static char * + scan_table(char *c) + { + char *t, *h, *g; + int center = 0, expand = 0, box = 0, border = 0, linesize = 1; + int i, j, maxcol = 0, finished = 0; + int oldfont, oldsize, oldfillout; + char itemsep = '\t'; + TABLEROW *layout = NULL, *currow, *ftable; + TABLEITEM *curfield; + + while (*c++ != '\n'); + h = c; + if (*h == '.') + return c - 1; + oldfont = current_font; + oldsize = current_size; + oldfillout = fillout; + out_html(change_to_font(0)); + out_html(change_to_size(0)); + if (!fillout) { + fillout = 1; + out_html("
"); + } + while (*h && *h != '\n') + h++; + if (h[-1] == ';') { + /* scan table options */ + while (c < h) { + while (isspace(*c)) + c++; + for (i = 0; tableopt[i] && strncmp(tableopt[i], c, tableoptl[i]); i++); + c = c + tableoptl[i]; + switch (i) { + case 0: + center = 1; + break; + case 1: + expand = 1; + break; + case 2: + box = 1; + break; + case 3: + border = 1; + break; + case 4: + box = 2; + break; + case 5: + while (*c++ != '('); + itemsep = *c++; + break; + case 6: + while (*c++ != '('); + linesize = 0; + while (isdigit(*c)) + linesize = linesize * 10 + (*c++) - '0'; + break; + case 7: + while (*c != ')') + c++; + default: + break; + } + c++; + } + c = h + 1; + } + /* scan layout */ + c = scan_format(c, &layout, &maxcol); + currow = layout; + next_row(currow); + curfield = layout->first; + i = 0; + while (!finished) { + /* search item */ + h = c; + if ((*c == '_' || *c == '=') && (c[1] == itemsep || c[1] == '\n')) { + if (c[-1] == '\n' && c[1] == '\n') { + if (currow->prev) { + currow->prev->next = (TABLEROW *) malloc(sizeof(TABLEROW)); + currow->prev->next->next = currow; + currow->prev->next->prev = currow->prev; + currow->prev = currow->prev->next; + } else { + currow->prev = layout = (TABLEROW *) malloc(sizeof(TABLEROW)); + currow->prev->prev = NULL; + currow->prev->next = currow; + } + curfield = currow->prev->first = + (TABLEITEM *) malloc(sizeof(TABLEITEM)); + *curfield = emptyfield; + curfield->align = *c; + curfield->colspan = maxcol; + curfield = currow->first; + c = c + 2; + } else { + if (curfield) { + curfield->align = *c; + do { + curfield = curfield->next; + } while (curfield && curfield->align == 'S'); + } + if (c[1] == '\n') { + currow = next_row(currow); + curfield = currow->first; + } + c = c + 2; + } + } else if (*c == 'T' && c[1] == '{') { + h = c + 2; + c = strstr(h, "\nT}"); + c++; + *c = '\0'; + g = NULL; + scan_troff(h, 0, &g); + scan_troff(itemreset, 0, &g); + *c = 'T'; + c += 3; + if (curfield) { + curfield->contents = g; + do { + curfield = curfield->next; + } while (curfield && curfield->align == 'S'); + } else if (g) + free(g); + if (c[-1] == '\n') { + currow = next_row(currow); + curfield = currow->first; + } + } else if (*c == '.' && c[1] == 'T' && c[2] == '&' && c[-1] == '\n') { + TABLEROW *hr; + + while (*c++ != '\n'); + hr = currow; + currow = currow->prev; + hr->prev = NULL; + c = scan_format(c, &hr, &i); + hr->prev = currow; + currow->next = hr; + currow = hr; + next_row(currow); + curfield = currow->first; + } else if (*c == '.' && c[1] == 'T' && c[2] == 'E' && c[-1] == '\n') { + finished = 1; + while (*c++ != '\n'); + if (currow->prev) + currow->prev->next = NULL; + currow->prev = NULL; + clear_table(currow); + } else if (*c == '.' && c[-1] == '\n' && !isdigit(c[1])) { + /* + * skip troff request inside table (usually only .sp + * ) + */ + while (*c++ != '\n'); + } else { + h = c; + while (*c && (*c != itemsep || c[-1] == '\\') && + (*c != '\n' || c[-1] == '\\')) + c++; + i = 0; + if (*c == itemsep) { + i = 1; + *c = '\n'; + } + if (h[0] == '\\' && h[2] == '\n' && + (h[1] == '_' || h[1] == '^')) { + if (curfield) { + curfield->align = h[1]; + do { + curfield = curfield->next; + } while (curfield && curfield->align == 'S'); + } + h = h + 3; + } else { + g = NULL; + h = scan_troff(h, 1, &g); + scan_troff(itemreset, 0, &g); + if (curfield) { + curfield->contents = g; + do { + curfield = curfield->next; + } while (curfield && curfield->align == 'S'); + } else if (g) + free(g); + } + if (i) + *c = itemsep; + c = h; + if (c[-1] == '\n') { + currow = next_row(currow); + curfield = currow->first; + } + } + } + /* calculate colspan and rowspan */ + currow = layout; + while (currow->next) + currow = currow->next; + while (currow) { + TABLEITEM *ti, *ti1 = NULL, *ti2 = NULL; + + ti = currow->first; + if (currow->prev) + ti1 = currow->prev->first; + while (ti) { + switch (ti->align) { + case 'S': + if (ti2) { + ti2->colspan++; + if (ti2->rowspan < ti->rowspan) + ti2->rowspan = ti->rowspan; + } + break; + case '^': + if (ti1) + ti1->rowspan++; + default: + if (!ti2) + ti2 = ti; + else { + do { + ti2 = ti2->next; + } while (ti2 && curfield->align == 'S'); + } + break; + } + ti = ti->next; + if (ti1) + ti1 = ti1->next; + } + currow = currow->prev; + } + /* produce html output */ + if (center) + out_html("
"); + if (box == 2) + out_html(""); + curfield = currow->first; + while (curfield) { + if (curfield->align != 'S' && curfield->align != '^') { + out_html("align) { + case 'N': + curfield->space += 4; + case 'R': + out_html(" ALIGN=right"); + break; + case 'C': + out_html(" ALIGN=center"); + default: + break; + } + if (!curfield->valign && curfield->rowspan > 1) + out_html(" VALIGN=center"); + if (curfield->colspan > 1) { + char buf[5]; + + out_html(" COLSPAN="); + sprintf(buf, "%i", curfield->colspan); + out_html(buf); + } + if (curfield->rowspan > 1) { + char buf[5]; + + out_html(" ROWSPAN="); + sprintf(buf, "%i", curfield->rowspan); + out_html(buf); + } + j = j + curfield->colspan; + out_html(">"); + if (curfield->size) + out_html(change_to_size(curfield->size)); + if (curfield->font) + out_html(change_to_font(curfield->font)); + switch (curfield->align) { + case '=': + out_html("

"); + break; + case '_': + out_html("
"); + break; + default: + if (curfield->contents) + out_html(curfield->contents); + break; + } + if (curfield->space) + for (i = 0; i < curfield->space; i++) + out_html(" "); + if (curfield->font) + out_html(change_to_font(0)); + if (curfield->size) + out_html(change_to_size(0)); + if (j >= maxcol && curfield->align > '@' && curfield->align != '_') + out_html("
"); + out_html(""); + } + curfield = curfield->next; + } + out_html("
\n"); + currow = currow->next; + } + if (box && !border) + out_html("
"); + out_html("
\n"); + currow = layout; + while (currow) { + j = 0; + out_html("
"); + out_html(""); + if (box == 2) + out_html(""); + if (center) + out_html("
\n"); + else + out_html("\n"); + if (!oldfillout) + out_html("
");
+ 	fillout = oldfillout;
+ 	out_html(change_to_size(oldsize));
+ 	out_html(change_to_font(oldfont));
+ 	return c;
+ }
+ 
+ static char *
+ scan_expression(char *c, int *result)
+ {
+ 	int     value = 0, value2, j = 0, sign = 1, opex = 0;
+ 	char    oper = 'c';
+ 
+ 	if (*c == '!') {
+ 		c = scan_expression(c + 1, &value);
+ 		value = (!value);
+ 	} else if (*c == 'n') {
+ 		c++;
+ 		value = NROFF;
+ 	} else if (*c == 't') {
+ 		c++;
+ 		value = 1 - NROFF;
+ 	} else if (*c == '\'' || *c == '"' || *c < ' ' || (*c == '\\' && c[1] == '(')) {
+ 		/*
+ 		 * ?string1?string2? test if string1 equals string2.
+ 		 */
+ 		char   *st1 = NULL, *st2 = NULL, *h;
+ 		char   *tcmp = NULL;
+ 		char    sep;
+ 
+ 		sep = *c;
+ 		if (sep == '\\') {
+ 			tcmp = c;
+ 			c = c + 3;
+ 		}
+ 		c++;
+ 		h = c;
+ 		while (*c != sep && (!tcmp || strncmp(c, tcmp, 4)))
+ 			c++;
+ 		*c = '\n';
+ 		scan_troff(h, 1, &st1);
+ 		*c = sep;
+ 		if (tcmp)
+ 			c = c + 3;
+ 		c++;
+ 		h = c;
+ 		while (*c != sep && (!tcmp || strncmp(c, tcmp, 4)))
+ 			c++;
+ 		*c = '\n';
+ 		scan_troff(h, 1, &st2);
+ 		*c = sep;
+ 		if (!st1 && !st2)
+ 			value = 1;
+ 		else if (!st1 || !st2)
+ 			value = 0;
+ 		else
+ 			value = (!strcmp(st1, st2));
+ 		if (st1)
+ 			free(st1);
+ 		if (st2)
+ 			free(st2);
+ 		if (tcmp)
+ 			c = c + 3;
+ 		c++;
+ 	} else {
+ 		while (*c && !isspace(*c) && *c != ')') {
+ 			opex = 0;
+ 			switch (*c) {
+ 			case '(':
+ 				c = scan_expression(c + 1, &value2);
+ 				value2 = sign * value2;
+ 				opex = 1;
+ 				break;
+ 			case '.':
+ 			case '0':
+ 			case '1':
+ 			case '2':
+ 			case '3':
+ 			case '4':
+ 			case '5':
+ 			case '6':
+ 			case '7':
+ 			case '8':
+ 			case '9':{
+ 					int     num = 0, denum = 1;
+ 
+ 					value2 = 0;
+ 					while (isdigit(*c))
+ 						value2 = value2 * 10 + ((*c++) - '0');
+ 					if (*c == '.') {
+ 						c++;
+ 						while (isdigit(*c)) {
+ 							num = num * 10 + ((*c++) - '0');
+ 							denum = denum * 10;
+ 						}
+ 					}
+ 					if (isalpha(*c)) {
+ 						/* scale indicator */
+ 						switch (*c) {
+ 						case 'i':	/* inch -> 10pt */
+ 							value2 = value2 * 10 + (num * 10 + denum / 2) / denum;
+ 							num = 0;
+ 							break;
+ 						default:
+ 							break;
+ 						}
+ 						c++;
+ 					}
+ 					value2 = value2 + (num + denum / 2) / denum;
+ 					value2 = sign * value2;
+ 					opex = 1;
+ 					break;
+ 				}
+ 			case '\\':
+ 				c = scan_escape(c + 1);
+ 				value2 = intresult * sign;
+ 				if (isalpha(*c))
+ 					c++;	/* scale indicator */
+ 				opex = 1;
+ 				break;
+ 			case '-':
+ 				if (oper) {
+ 					sign = -1;
+ 					c++;
+ 					break;
+ 				}
+ 			case '>':
+ 			case '<':
+ 			case '+':
+ 			case '/':
+ 			case '*':
+ 			case '%':
+ 			case '&':
+ 			case '=':
+ 			case ':':
+ 				if (c[1] == '=')
+ 					oper = (*c++) + 16;
+ 				else
+ 					oper = *c;
+ 				c++;
+ 				break;
+ 			default:
+ 				c++;
+ 				break;
+ 			}
+ 			if (opex) {
+ 				sign = 1;
+ 				switch (oper) {
+ 				case 'c':
+ 					value = value2;
+ 					break;
+ 				case '-':
+ 					value = value - value2;
+ 					break;
+ 				case '+':
+ 					value = value + value2;
+ 					break;
+ 				case '*':
+ 					value = value * value2;
+ 					break;
+ 				case '/':
+ 					if (value2)
+ 						value = value / value2;
+ 					break;
+ 				case '%':
+ 					if (value2)
+ 						value = value % value2;
+ 					break;
+ 				case '<':
+ 					value = (value < value2);
+ 					break;
+ 				case '>':
+ 					value = (value > value2);
+ 					break;
+ 				case '>' + 16:
+ 					value = (value >= value2);
+ 					break;
+ 				case '<' + 16:
+ 					value = (value <= value2);
+ 					break;
+ 				case '=':
+ 				case '=' + 16:
+ 					value = (value == value2);
+ 					break;
+ 				case '&':
+ 					value = (value && value2);
+ 					break;
+ 				case ':':
+ 					value = (value || value2);
+ 					break;
+ 				default:
+ 					fprintf(stderr, "man2html: unknown operator %c.\n", oper);
+ 				}
+ 				oper = 0;
+ 			}
+ 		}
+ 		if (*c == ')')
+ 			c++;
+ 	}
+ 	*result = value;
+ 	return c;
+ }
+ 
+ static void
+ trans_char(char *c, char s, char t)
+ {
+ 	char   *sl = c;
+ 	int     slash = 0;
+ 
+ 	while (*sl != '\n' || slash) {
+ 		if (!slash) {
+ 			if (*sl == escapesym)
+ 				slash = 1;
+ 			else if (*sl == s)
+ 				*sl = t;
+ 		} else
+ 			slash = 0;
+ 		sl++;
+ 	}
+ }
+ 
+ static char *
+ fill_words(char *c, char *words[], int *n)
+ {
+ 	char   *sl = c;
+ 	int     slash = 0;
+ 	int     skipspace = 0;
+ 
+ 	*n = 0;
+ 	words[*n] = sl;
+ 	while (*sl && (*sl != '\n' || slash)) {
+ 		if (!slash) {
+ 			if (*sl == '"') {
+ 				*sl = '\a';
+ 				skipspace = !skipspace;
+ 			} else if (*sl == escapesym)
+ 				slash = 1;
+ 			else if ((*sl == ' ' || *sl == '\t') && !skipspace) {
+ 				*sl = '\n';
+ 				if (words[*n] != sl)
+ 					(*n)++;
+ 				words[*n] = sl + 1;
+ 			}
+ 		} else {
+ 			if (*sl == '"') {
+ 				sl--;
+ 				*sl = '\n';
+ 				if (words[*n] != sl)
+ 					(*n)++;
+ 				sl++;
+ 				while (*sl && *sl != '\n')
+ 					sl++;
+ 				words[*n] = sl;
+ 				sl--;
+ 			}
+ 			slash = 0;
+ 		}
+ 		sl++;
+ 	}
+ 	if (sl != words[*n])
+ 		(*n)++;
+ 	return sl;
+ }
+ 
+ static char *abbrev_list[] = {
+ 	"GSBG", "Getting Started ",
+ 	"SUBG", "Customizing SunOS",
+ 	"SHBG", "Basic Troubleshooting",
+ 	"SVBG", "SunView User's Guide",
+ 	"MMBG", "Mail and Messages",
+ 	"DMBG", "Doing More with SunOS",
+ 	"UNBG", "Using the Network",
+ 	"GDBG", "Games, Demos & Other Pursuits",
+ 	"CHANGE", "SunOS 4.1 Release Manual",
+ 	"INSTALL", "Installing SunOS 4.1",
+ 	"ADMIN", "System and Network Administration",
+ 	"SECUR", "Security Features Guide",
+ 	"PROM", "PROM User's Manual",
+ 	"DIAG", "Sun System Diagnostics",
+ 	"SUNDIAG", "Sundiag User's Guide",
+ 	"MANPAGES", "SunOS Reference Manual",
+ 	"REFMAN", "SunOS Reference Manual",
+ 	"SSI", "Sun System Introduction",
+ 	"SSO", "System Services Overview",
+ 	"TEXT", "Editing Text Files",
+ 	"DOCS", "Formatting Documents",
+ 	"TROFF", "Using nroff and troff",
+ 	"INDEX", "Global Index",
+ 	"CPG", "C Programmer's Guide",
+ 	"CREF", "C Reference Manual",
+ 	"ASSY", "Assembly Language Reference",
+ 	"PUL", "Programming Utilities and Libraries",
+ 	"DEBUG", "Debugging Tools",
+ 	"NETP", "Network Programming",
+ 	"DRIVER", "Writing Device Drivers",
+ 	"STREAMS", "STREAMS Programming",
+ 	"SBDK", "SBus Developer's Kit",
+ 	"WDDS", "Writing Device Drivers for the SBus",
+ 	"FPOINT", "Floating-Point Programmer's Guide",
+ 	"SVPG", "SunView 1 Programmer's Guide",
+ 	"SVSPG", "SunView 1 System Programmer's Guide",
+ 	"PIXRCT", "Pixrect Reference Manual",
+ 	"CGI", "SunCGI Reference Manual",
+ 	"CORE", "SunCore Reference Manual",
+ 	"4ASSY", "Sun-4 Assembly Language Reference",
+ 	"SARCH", "SPARC Architecture Manual",
+ 	"KR", "The C Programming Language",
+ NULL, NULL};
+ 
+ static char *
+ lookup_abbrev(char *c)
+ {
+ 	int     i = 0;
+ 
+ 	if (!c)
+ 		return "";
+ 	while (abbrev_list[i] && strcmp(c, abbrev_list[i]))
+ 		i = i + 2;
+ 	if (abbrev_list[i])
+ 		return abbrev_list[i + 1];
+ 	else
+ 		return c;
+ }
+ 
+ static char manidx[NULL_TERMINATED(HUGE_STR_MAX)];
+ static int subs = 0;
+ static int mip = 0;
+ static char label[5] = "lbAA";
+ 
+ static void
+ add_to_index(int level, char *item)
+ {
+ 	char   *c = NULL;
+ 
+ 	label[3]++;
+ 	if (label[3] > 'Z') {
+ 		label[3] = 'A';
+ 		label[2]++;
+ 	}
+ 	if (level != subs) {
+ 		if (subs) {
+ 			strmaxcpy(manidx + mip, "\n", HUGE_STR_MAX - mip);
+ 			mip += 6;
+ 		} else {
+ 			strmaxcpy(manidx + mip, "
\n", HUGE_STR_MAX - mip); + mip += 5; + } + } + subs = level; + scan_troff(item, 1, &c); + sprintf(manidx + mip, "
%s
\n", label, c); + if (c) + free(c); + while (manidx[mip]) + mip++; + } + + static char * + skip_till_newline(char *c) + { + int lvl = 0; + + while (*c && *c != '\n' || lvl > 0) { + if (*c == '\\') { + c++; + if (*c == '}') + lvl--; + else if (*c == '{') + lvl++; + } + c++; + } + c++; + if (lvl < 0 && newline_for_fun) { + newline_for_fun = newline_for_fun + lvl; + if (newline_for_fun < 0) + newline_for_fun = 0; + } + return c; + } + + static int ifelseval = 0; + + static char * + scan_request(char *c) + { + /* BSD Mandoc stuff */ + static int mandoc_synopsis = 0; /* True if we are in the synopsis + * section */ + static int mandoc_command = 0; /* True if this is mandoc page */ + static int mandoc_bd_options; /* Only copes with non-nested Bd's */ + + int i, j, mode = 0; + char *h; + char *wordlist[MAX_WORDLIST]; + int words; + char *sl; + STRDEF *owndef; + + while (*c == ' ' || *c == '\t') + c++; + if (c[0] == '\n') + return c + 1; + if (c[1] == '\n') + j = 1; + else + j = 2; + while (c[j] == ' ' || c[j] == '\t') + j++; + if (c[0] == escapesym) { + /* some pages use .\" .\$1 .\} */ + /* .\$1 is too difficult/stuppid */ + if (c[1] == '$') + c = skip_till_newline(c); + else + c = scan_escape(c + 1); + } else { + i = V(c[0], c[1]); + switch (i) { + case V('a', 'b'): + h = c + j; + while (*h && *h != '\n') + h++; + *h = '\0'; + if (scaninbuff && buffpos) { + buffer[buffpos] = '\0'; + puts(buffer); + } + /* fprintf(stderr, "%s\n", c+2); */ + exit(0); + break; + case V('d', 'i'): + { + STRDEF *de; + int oldcurpos = curpos; + + c = c + j; + i = V(c[0], c[1]); + if (*c == '\n') { + c++; + break; + } + while (*c && *c != '\n') + c++; + c++; + h = c; + while (*c && strncmp(c, ".di", 3)) + while (*c && *c++ != '\n'); + *c = '\0'; + de = strdef; + while (de && de->nr != i) + de = de->next; + if (!de) { + de = (STRDEF *) malloc(sizeof(STRDEF)); + de->nr = i; + de->slen = 0; + de->next = strdef; + de->st = NULL; + strdef = de; + } else { + if (de->st) + free(de->st); + de->slen = 0; + de->st = NULL; + } + scan_troff(h, 0, &de->st); + *c = '.'; + while (*c && *c++ != '\n'); + break; + } + case V('d', 's'): + mode = 1; + case V('a', 's'): + { + STRDEF *de; + int oldcurpos = curpos; + + c = c + j; + i = V(c[0], c[1]); + j = 0; + while (c[j] && c[j] != '\n') + j++; + if (j < 3) { + c = c + j; + break; + } + if (c[1] == ' ') + c = c + 1; + else + c = c + 2; + while (isspace(*c)) + c++; + if (*c == '"') + c++; + de = strdef; + while (de && de->nr != i) + de = de->next; + single_escape = 1; + curpos = 0; + if (!de) { + char *h; + + de = (STRDEF *) malloc(sizeof(STRDEF)); + de->nr = i; + de->slen = 0; + de->next = strdef; + de->st = NULL; + strdef = de; + h = NULL; + c = scan_troff(c, 1, &h); + de->st = h; + de->slen = curpos; + } else { + if (mode) { + char *h = NULL; + + c = scan_troff(c, 1, &h); + free(de->st); + de->slen = 0; + de->st = h; + } else + c = scan_troff(c, 1, &de->st); + de->slen += curpos; + } + single_escape = 0; + curpos = oldcurpos; + } + break; + case V('b', 'r'): + if (still_dd) + out_html("
"); + else + out_html("
\n"); + curpos = 0; + c = c + j; + if (c[0] == escapesym) { + c = scan_escape(c + 1); + } + c = skip_till_newline(c); + break; + case V('c', '2'): + c = c + j; + if (*c != '\n') { + nobreaksym = *c; + } else + nobreaksym = '\''; + c = skip_till_newline(c); + break; + case V('c', 'c'): + c = c + j; + if (*c != '\n') { + controlsym = *c; + } else + controlsym = '.'; + c = skip_till_newline(c); + break; + case V('c', 'e'): + c = c + j; + if (*c == '\n') { + i = 1; + } else { + i = 0; + while ('0' <= *c && *c <= '9') { + i = i * 10 + *c - '0'; + c++; + } + } + c = skip_till_newline(c); + /* center next i lines */ + if (i > 0) { + out_html("
\n"); + while (i && *c) { + char *line = NULL; + + c = scan_troff(c, 1, &line); + if (line && strncmp(line, "
", 4)) { + out_html(line); + out_html("
\n"); + i--; + } + } + out_html("
\n"); + curpos = 0; + } + break; + case V('e', 'c'): + c = c + j; + if (*c != '\n') { + escapesym = *c; + } else + escapesym = '\\'; + break; + c = skip_till_newline(c); + case V('e', 'o'): + escapesym = '\0'; + c = skip_till_newline(c); + break; + case V('e', 'x'): + exit(0); + break; + case V('f', 'c'): + c = c + j; + if (*c == '\n') { + fieldsym = padsym = '\0'; + } else { + fieldsym = c[0]; + padsym = c[1]; + } + c = skip_till_newline(c); + break; + case V('f', 'i'): + if (!fillout) { + out_html(change_to_font(0)); + out_html(change_to_size('0')); + out_html("
\n"); + } + curpos = 0; + fillout = 1; + c = skip_till_newline(c); + break; + case V('f', 't'): + c = c + j; + if (*c == '\n') { + out_html(change_to_font(0)); + } else { + if (*c == escapesym) { + int fn; + + c = scan_expression(c, &fn); + c--; + out_html(change_to_font(fn)); + } else { + out_html(change_to_font(*c)); + c++; + } + } + c = skip_till_newline(c); + break; + case V('e', 'l'): + /* .el anything : else part of if else */ + if (ifelseval) { + c = c + j; + c[-1] = '\n'; + c = scan_troff(c, 1, NULL); + } else + c = skip_till_newline(c + j); + break; + case V('i', 'e'): + /* .ie c anything : then part of if else */ + case V('i', 'f'): + /* + * .if c anything .if !c anything .if N anything .if + * !N anything .if 'string1'string2' anything .if + * !'string1'string2' anything + */ + c = c + j; + c = scan_expression(c, &i); + ifelseval = !i; + if (i) { + *c = '\n'; + c++; + c = scan_troff(c, 1, NULL); + } else + c = skip_till_newline(c); + break; + case V('i', 'g'): + { + char *endwith = "..\n"; + + i = 3; + c = c + j; + if (*c != '\n') { + endwith = c - 1; + i = 1; + c[-1] = '.'; + while (*c && *c != '\n') + c++, i++; + } + c++; + while (*c && strncmp(c, endwith, i)) + while (*c++ != '\n'); + while (*c++ != '\n'); + break; + } + case V('n', 'f'): + if (fillout) { + out_html(change_to_font(0)); + out_html(change_to_size('0')); + out_html("
\n");
+ 			}
+ 			curpos = 0;
+ 			fillout = 0;
+ 			c = skip_till_newline(c);
+ 			break;
+ 		case V('p', 's'):
+ 			c = c + j;
+ 			if (*c == '\n') {
+ 				out_html(change_to_size('0'));
+ 			} else {
+ 				j = 0;
+ 				i = 0;
+ 				if (*c == '-') {
+ 					j = -1;
+ 					c++;
+ 				} else if (*c == '+') {
+ 					j = 1;
+ 					c++;
+ 				}
+ 				c = scan_expression(c, &i);
+ 				if (!j) {
+ 					j = 1;
+ 					if (i > 5)
+ 						i = i - 10;
+ 				}
+ 				out_html(change_to_size(i * j));
+ 			}
+ 			c = skip_till_newline(c);
+ 			break;
+ 		case V('s', 'p'):
+ 			c = c + j;
+ 			if (fillout)
+ 				out_html("

"); + else { + out_html(NEWLINE); + NEWLINE[0] = '\n'; + } + curpos = 0; + c = skip_till_newline(c); + break; + case V('s', 'o'): + { + FILE *f; + struct stat stbuf; + int l = 0; + char *buf; + char *name = NULL; + + curpos = 0; + c = c + j; + if (*c == '/') { + h = c; + } else { + h = c - 3; + h[0] = '.'; + h[1] = '.'; + h[2] = '/'; + } + while (*c != '\n') + c++; + *c = '\0'; + scan_troff(h, 1, &name); + if (name[3] == '/') + h = name + 3; + else + h = name; + if (stat(h, &stbuf) != -1) + l = stbuf.st_size; + buf = stralloc(l + 4); + #if NOCGI + if (!out_length) { + char *t, *s; + + t = strrchr(fname, '/'); + if (!t) + t = fname; + fprintf(stderr, "ln -s %s.html %s.html\n", h, t); + s = strrchr(t, '.'); + if (!s) + s = t; + printf(" Manpage of %s\n" + "\n" + "See the manpage for %s.\n" + "\n", + s, h, h); + } else + #endif + { + /* + * this works alright, except for + * section 3 + */ + buf = read_man_page(h); + if (!buf) { + + fprintf(stderr, "man2html: unable to open or read file %s.\n", + h); + out_html("

" + "man2html: unable to open or read file.\n"); + out_html(h); + out_html("
\n"); + } else { + buf[0] = buf[l] = '\n'; + buf[l + 1] = buf[l + 2] = '\0'; + scan_troff(buf + 1, 0, NULL); + } + if (buf) + free(buf); + } + *c++ = '\n'; + break; + } + case V('t', 'a'): + c = c + j; + j = 0; + while (*c != '\n') { + sl = scan_expression(c, &tabstops[j]); + if (*c == '-' || *c == '+') + tabstops[j] += tabstops[j - 1]; + c = sl; + while (*c == ' ' || *c == '\t') + c++; + j++; + } + maxtstop = j; + curpos = 0; + break; + case V('t', 'i'): + /* + * while (itemdepth || dl_set[itemdepth]) { + * out_html("\n"); if (dl_set[itemdepth]) + * dl_set[itemdepth]=0; else itemdepth--; } + */ + out_html("
\n"); + c = c + j; + c = scan_expression(c, &j); + for (i = 0; i < j; i++) + out_html(" "); + curpos = j; + c = skip_till_newline(c); + break; + case V('t', 'm'): + c = c + j; + h = c; + while (*c != '\n') + c++; + *c = '\0'; + /* fprintf(stderr,"%s\n", h); */ + *c = '\n'; + break; + case V('B', ' '): + case V('B', '\n'): + case V('I', ' '): + case V('I', '\n'): + /* parse one line in a certain font */ + out_html(change_to_font(*c)); + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + c = scan_troff(c, 1, NULL); + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('O', 'P'): /* groff manpages use this + * construction */ + /* .OP a b : [ a b ] */ + mode = 1; + c[0] = 'B'; + c[1] = 'I'; + out_html(change_to_font('R')); + out_html("["); + curpos++; + case V('B', 'R'): + case V('B', 'I'): + case V('I', 'B'): + case V('I', 'R'): + case V('R', 'B'): + case V('R', 'I'): + { + char font[2]; + + font[0] = c[0]; + font[1] = c[1]; + c = c + j; + if (*c == '\n') + c++; + sl = fill_words(c, wordlist, &words); + c = sl + 1; + /* + * .BR name (section) indicates a link. It + * will be added in the output routine. + */ + for (i = 0; i < words; i++) { + if (mode) { + out_html(" "); + curpos++; + } + wordlist[i][-1] = ' '; + out_html(change_to_font(font[i & 1])); + scan_troff(wordlist[i], 1, NULL); + } + out_html(change_to_font('R')); + if (mode) { + out_html(" ]"); + curpos++; + } + out_html(NEWLINE); + if (!fillout) + curpos = 0; + else + curpos++; + } + break; + case V('D', 'T'): + for (j = 0; j < 20; j++) + tabstops[j] = (j + 1) * 8; + maxtstop = 20; + c = skip_till_newline(c); + break; + case V('I', 'P'): + sl = fill_words(c + j, wordlist, &words); + c = sl + 1; + if (!dl_set[itemdepth]) { + out_html("
\n"); + dl_set[itemdepth] = 1; + } + out_html("
"); + if (words) { + scan_troff(wordlist[0], 1, NULL); + } + out_html("
"); + curpos = 0; + break; + case V('T', 'P'): + if (!dl_set[itemdepth]) { + out_html("
\n"); + dl_set[itemdepth] = 1; + } + out_html("
"); + c = skip_till_newline(c); + /* somewhere a definition ends with '.TP' */ + if (!*c) + still_dd = 1; + else { + c = scan_troff(c, 1, NULL); + out_html("
"); + } + curpos = 0; + break; + case V('I', 'X'): + /* general index */ + sl = fill_words(c + j, wordlist, &words); + c = sl + 1; + j = 4; + while (idxlabel[j] == 'Z') + idxlabel[j--] = 'A'; + idxlabel[j]++; + #ifdef MAKEINDEX + fprintf(idxfile, "%s@%s@", fname, idxlabel); + for (j = 0; j < words; j++) { + h = NULL; + scan_troff(wordlist[j], 1, &h); + fprintf(idxfile, "_\b@%s", h); + free(h); + } + fprintf(idxfile, "\n"); + #endif + out_html("' and '<' solves it, but + * creates some space. A normal space does not work. + */ + out_html("\">"); + break; + case V('L', 'P'): + case V('P', 'P'): + if (dl_set[itemdepth]) { + out_html("
\n"); + dl_set[itemdepth] = 0; + } + if (fillout) + out_html("

\n"); + else { + out_html(NEWLINE); + NEWLINE[0] = '\n'; + } + curpos = 0; + c = skip_till_newline(c); + break; + case V('H', 'P'): + if (!dl_set[itemdepth]) { + out_html("

"); + dl_set[itemdepth] = 1; + } + out_html("
\n"); + still_dd = 1; + c = skip_till_newline(c); + curpos = 0; + break; + case V('P', 'D'): + c = skip_till_newline(c); + break; + case V('R', 's'): /* BSD mandoc */ + case V('R', 'S'): + sl = fill_words(c + j, wordlist, &words); + j = 1; + if (words > 0) + scan_expression(wordlist[0], &j); + if (j >= 0) { + itemdepth++; + dl_set[itemdepth] = 0; + out_html("
"); + c = skip_till_newline(c); + curpos = 0; + break; + } + case V('R', 'e'): /* BSD mandoc */ + case V('R', 'E'): + if (itemdepth > 0) { + if (dl_set[itemdepth]) + out_html("
"); + out_html("
\n"); + itemdepth--; + } + c = skip_till_newline(c); + curpos = 0; + break; + case V('S', 'B'): + out_html(change_to_size(-1)); + out_html(change_to_font('B')); + c = scan_troff(c + j, 1, NULL); + out_html(change_to_font('R')); + out_html(change_to_size('0')); + break; + case V('S', 'M'): + c = c + j; + if (*c == '\n') + c++; + out_html(change_to_size(-1)); + trans_char(c, '"', '\a'); + c = scan_troff(c, 1, NULL); + out_html(change_to_size('0')); + break; + case V('S', 's'): /* BSD mandoc */ + mandoc_command = 1; + case V('S', 'S'): + mode = 1; + case V('S', 'h'): /* BSD mandoc */ + /* hack for fallthru from above */ + mandoc_command = !mode || mandoc_command; + case V('S', 'H'): + c = c + j; + if (*c == '\n') + c++; + while (itemdepth || dl_set[itemdepth]) { + out_html("
\n"); + if (dl_set[itemdepth]) + dl_set[itemdepth] = 0; + else if (itemdepth > 0) + itemdepth--; + } + out_html(change_to_font(0)); + out_html(change_to_size(0)); + if (!fillout) { + fillout = 1; + out_html("
"); + } + trans_char(c, '"', '\a'); + add_to_index(mode, c); + out_html(" \n

"); + else + out_html("\"> \n

"); + mandoc_synopsis = strncmp(c, "SYNOPSIS", 8) == 0; + c = mandoc_command ? scan_troff_mandoc(c, 1, NULL) : scan_troff(c, 1, NULL); + if (mode) + out_html("

\n"); + else + out_html("\n"); + curpos = 0; + break; + case V('T', 'S'): + c = scan_table(c); + break; + case V('D', 't'): /* BSD mandoc */ + mandoc_command = 1; + case V('T', 'H'): + if (!output_possible) { + sl = fill_words(c + j, wordlist, &words); + if (words > 1) { + char page_and_sec[128]; + + for (i = 1; i < words; i++) + wordlist[i][-1] = '\0'; + *sl = '\0'; + output_possible = 1; + sprintf(page_and_sec, "%s(%s)", wordlist[0], wordlist[1]); + out_html("\n"); + out_html(page_and_sec); + out_html(" Manual Page"); + out_html("\n\n"); + out_html("\n"); + out_html("
"); + out_html(page_and_sec); + out_html(""); + out_html(wordlist[2]); + out_html(""); + out_html(page_and_sec); + out_html("\n
\n"); + out_html("
Index\n"); + *sl = '\n'; + out_html("
\n"); + if (mandoc_command) + out_html("
BSD mandoc
"); + } + c = sl + 1; + } else + c = skip_till_newline(c); + curpos = 0; + break; + case V('T', 'X'): + sl = fill_words(c + j, wordlist, &words); + *sl = '\0'; + out_html(change_to_font('I')); + if (words > 1) + wordlist[1][-1] = '\0'; + c = lookup_abbrev(wordlist[0]); + curpos += strlen(c); + out_html(c); + out_html(change_to_font('R')); + if (words > 1) + out_html(wordlist[1]); + *sl = '\n'; + c = sl + 1; + break; + case V('r', 'm'): + /* .rm xx : Remove request, macro or string */ + case V('r', 'n'): + /* + * .rn xx yy : Rename request, macro or string xx to + * yy + */ + { + STRDEF *de; + + c = c + j; + i = V(c[0], c[1]); + c = c + 2; + while (isspace(*c) && *c != '\n') + c++; + j = V(c[0], c[1]); + while (*c && *c != '\n') + c++; + c++; + de = strdef; + while (de && de->nr != j) + de = de->next; + if (de) { + if (de->st) + free(de->st); + de->nr = 0; + } + de = strdef; + while (de && de->nr != i) + de = de->next; + if (de) + de->nr = j; + break; + } + case V('n', 'x'): + /* .nx filename : next file. */ + case V('i', 'n'): + /* .in +-N : Indent */ + c = skip_till_newline(c); + break; + case V('n', 'r'): + /* + * .nr R +-N M: define and set number register R by + * +-N; auto-increment by M + */ + { + INTDEF *intd; + + c = c + j; + i = V(c[0], c[1]); + c = c + 2; + intd = intdef; + while (intd && intd->nr != i) + intd = intd->next; + if (!intd) { + intd = (INTDEF *) malloc(sizeof(INTDEF)); + intd->nr = i; + intd->val = 0; + intd->incr = 0; + intd->next = intdef; + intdef = intd; + } + while (*c == ' ' || *c == '\t') + c++; + c = scan_expression(c, &intd->val); + if (*c != '\n') { + while (*c == ' ' || *c == '\t') + c++; + c = scan_expression(c, &intd->incr); + } + c = skip_till_newline(c); + break; + } + case V('a', 'm'): + /* .am xx yy : append to a macro. */ + /* define or handle as .ig yy */ + mode = 1; + case V('d', 'e'): + /* + * .de xx yy : define or redefine macro xx; end at + * .yy (..) + */ + /* define or handle as .ig yy */ + { + STRDEF *de; + int olen = 0; + + c = c + j; + sl = fill_words(c, wordlist, &words); + i = V(c[0], c[1]); + j = 2; + if (words == 1) + wordlist[1] = ".."; + else { + wordlist[1]--; + wordlist[1][0] = '.'; + j = 3; + } + c = sl + 1; + sl = c; + while (*c && strncmp(c, wordlist[1], j)) + c = skip_till_newline(c); + de = defdef; + while (de && de->nr != i) + de = de->next; + if (mode && de) + olen = strlen(de->st); + j = olen + c - sl; + h = stralloc(j * 2 + 4); + if (h) { + for (j = 0; j < olen; j++) + h[j] = de->st[j]; + if (!j || h[j - 1] != '\n') + h[j++] = '\n'; + while (sl != c) { + if (sl[0] == '\\' && sl[1] == '\\') { + h[j++] = '\\'; + sl++; + } else + h[j++] = *sl; + sl++; + } + h[j] = '\0'; + if (de) { + if (de->st) + free(de->st); + de->st = h; + } else { + de = (STRDEF *) malloc(sizeof(STRDEF)); + de->nr = i; + de->next = defdef; + de->st = h; + defdef = de; + } + } + } + c = skip_till_newline(c); + break; + case V('B', 'l'): /* BSD mandoc */ + { + char list_options[NULL_TERMINATED(MED_STR_MAX)]; + char *nl = strchr(c, '\n'); + + c = c + j; + if (dl_set[itemdepth]) { /* These things can + * nest. */ + itemdepth++; + } + if (nl) { /* Parse list options */ + strlimitcpy(list_options, c, nl - c, MED_STR_MAX); + } + if (strstr(list_options, "-bullet")) { /* HTML Unnumbered List */ + dl_set[itemdepth] = BL_BULLET_LIST; + out_html("
    \n"); + } else if (strstr(list_options, "-enum")) { /* HTML Ordered List */ + dl_set[itemdepth] = BL_ENUM_LIST; + out_html("
      \n"); + } else { /* HTML Descriptive List */ + dl_set[itemdepth] = BL_DESC_LIST; + out_html("
      \n"); + } + if (fillout) + out_html("

      \n"); + else { + out_html(NEWLINE); + NEWLINE[0] = '\n'; + } + curpos = 0; + c = skip_till_newline(c); + break; + } + case V('E', 'l'): /* BSD mandoc */ + c = c + j; + if (dl_set[itemdepth] & BL_DESC_LIST) { + out_html("

      \n"); + } else if (dl_set[itemdepth] & BL_BULLET_LIST) { + out_html("
\n"); + } else if (dl_set[itemdepth] & BL_ENUM_LIST) { + out_html("\n"); + } + dl_set[itemdepth] = 0; + if (itemdepth > 0) + itemdepth--; + if (fillout) + out_html("

\n"); + else { + out_html(NEWLINE); + NEWLINE[0] = '\n'; + } + curpos = 0; + c = skip_till_newline(c); + break; + case V('I', 't'): /* BSD mandoc */ + c = c + j; + if (strncmp(c, "Xo", 2) == 0 && isspace(*(c + 2))) { + c = skip_till_newline(c); + } + if (dl_set[itemdepth] & BL_DESC_LIST) { + out_html("

"); + out_html(change_to_font('B')); + if (*c == '\n') { /* Don't allow embedded + * comms after a newline */ + c++; + c = scan_troff(c, 1, NULL); + } else { /* Do allow embedded comms on + * the same line. */ + c = scan_troff_mandoc(c, 1, NULL); + } + out_html(change_to_font('R')); + out_html(NEWLINE); + out_html("
"); + } else if (dl_set[itemdepth] & (BL_BULLET_LIST | BL_ENUM_LIST)) { + out_html("
  • "); + c = scan_troff_mandoc(c, 1, NULL); + out_html(NEWLINE); + } + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('B', 'k'): /* BSD mandoc */ + case V('E', 'k'): /* BSD mandoc */ + case V('D', 'd'): /* BSD mandoc */ + case V('O', 's'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + c = scan_troff_mandoc(c, 1, NULL); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('B', 't'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + out_html(" is currently in beta test."); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('B', 'x'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + out_html("BSD "); + c = scan_troff_mandoc(c, 1, NULL); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('D', 'l'): /* BSD mandoc */ + c = c + j; + out_html(NEWLINE); + out_html("
    "); + out_html(change_to_font('L')); + if (*c == '\n') + c++; + c = scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html("
    "); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('B', 'd'): /* BSD mandoc */ + { /* Seems like a kind of example/literal mode */ + char bd_options[NULL_TERMINATED(MED_STR_MAX)]; + char *nl = strchr(c, '\n'); + + c = c + j; + if (nl) { + strlimitcpy(bd_options, c, nl - c, MED_STR_MAX); + } + out_html(NEWLINE); + mandoc_bd_options = 0; /* Remember options for + * terminating Bl */ + if (strstr(bd_options, "-offset indent")) { + mandoc_bd_options |= BD_INDENT; + out_html("
    \n"); + } + if (strstr(bd_options, "-literal") + || strstr(bd_options, "-unfilled")) { + if (fillout) { + mandoc_bd_options |= BD_LITERAL; + out_html(change_to_font(0)); + out_html(change_to_size('0')); + out_html("
    \n");
    + 					}
    + 					curpos = 0;
    + 					fillout = 0;
    + 				}
    + 				c = skip_till_newline(c);
    + 				break;
    + 			}
    + 		case V('E', 'd'):	/* BSD mandoc */
    + 			if (mandoc_bd_options & BD_LITERAL) {
    + 				if (!fillout) {
    + 					out_html(change_to_font(0));
    + 					out_html(change_to_size('0'));
    + 					out_html("
    \n"); + } + } + if (mandoc_bd_options & BD_INDENT) + out_html("
    \n"); + curpos = 0; + fillout = 1; + c = skip_till_newline(c); + break; + case V('B', 'e'): /* BSD mandoc */ + c = c + j; + if (fillout) + out_html("

    "); + else { + out_html(NEWLINE); + NEWLINE[0] = '\n'; + } + curpos = 0; + c = skip_till_newline(c); + break; + case V('X', 'r'): /* BSD mandoc */ + { + /* + * Translate xyz 1 to xyz(1) Allow for + * multiple spaces. Allow the section to be + * missing. + */ + char buff[NULL_TERMINATED(MED_STR_MAX)]; + char *bufptr; + + trans_char(c, '"', '\a'); + bufptr = buff; + c = c + j; + if (*c == '\n') + c++; /* Skip spaces */ + while (isspace(*c) && *c != '\n') + c++; + while (isalnum(*c)) { /* Copy the xyz part */ + *bufptr = *c; + bufptr++; + if (bufptr >= buff + MED_STR_MAX) + break; + c++; + } + while (isspace(*c) && *c != '\n') + c++; /* Skip spaces */ + if (isdigit(*c)) { /* Convert the number if + * there is one */ + *bufptr = '('; + bufptr++; + if (bufptr < buff + MED_STR_MAX) { + while (isalnum(*c)) { + *bufptr = *c; + bufptr++; + if (bufptr >= buff + MED_STR_MAX) + break; + c++; + } + if (bufptr < buff + MED_STR_MAX) { + *bufptr = ')'; + bufptr++; + } + } + } + while (*c != '\n') { /* Copy the remainder */ + if (!isspace(*c)) { + *bufptr = *c; + bufptr++; + if (bufptr >= buff + MED_STR_MAX) + break; + } + c++; + } + *bufptr = '\n'; + scan_troff_mandoc(buff, 1, NULL); + + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + } + break; + case V('F', 'l'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + out_html("-"); + if (*c != '\n') { + out_html(change_to_font('B')); + c = scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + } + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('P', 'a'): /* BSD mandoc */ + case V('P', 'f'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + c = scan_troff_mandoc(c, 1, NULL); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('P', 'p'): /* BSD mandoc */ + if (fillout) + out_html("

    \n"); + else { + out_html(NEWLINE); + NEWLINE[0] = '\n'; + } + curpos = 0; + c = skip_till_newline(c); + break; + case V('D', 'q'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + out_html("``"); + c = scan_troff_mandoc(c, 1, NULL); + out_html("''"); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('O', 'p'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + out_html(change_to_font('R')); + out_html("["); + c = scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html("]"); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('O', 'o'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + out_html(change_to_font('R')); + out_html("["); + c = scan_troff_mandoc(c, 1, NULL); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('O', 'c'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + c = scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html("]"); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('P', 'q'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + out_html("("); + c = scan_troff_mandoc(c, 1, NULL); + out_html(")"); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('Q', 'l'): /* BSD mandoc */ + { /* Single quote first word in the line */ + char *sp; + + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + sp = c; + do { /* Find first whitespace after the + * first word that isn't a mandoc + * macro */ + while (*sp && isspace(*sp)) + sp++; + while (*sp && !isspace(*sp)) + sp++; + } while (*sp && isupper(*(sp - 2)) && islower(*(sp - 1))); + + /* + * Use a newline to mark the end of text to + * be quoted + */ + if (*sp) + *sp = '\n'; + out_html("`"); /* Quote the text */ + c = scan_troff_mandoc(c, 1, NULL); + out_html("'"); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + } + case V('S', 'q'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + out_html("`"); + c = scan_troff_mandoc(c, 1, NULL); + out_html("'"); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('A', 'r'): /* BSD mandoc */ + /* parse one line in italics */ + out_html(change_to_font('I')); + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') { /* An empty Ar means "file + * ..." */ + out_html("file ..."); + } else { + c = scan_troff_mandoc(c, 1, NULL); + } + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('A', 'd'): /* BSD mandoc */ + case V('E', 'm'): /* BSD mandoc */ + case V('V', 'a'): /* BSD mandoc */ + case V('X', 'c'): /* BSD mandoc */ + /* parse one line in italics */ + out_html(change_to_font('I')); + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + c = scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('N', 'd'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + out_html(" - "); + c = scan_troff_mandoc(c, 1, NULL); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('N', 'm'): /* BSD mandoc */ + { + static char mandoc_name[NULL_TERMINATED(SMALL_STR_MAX)] = ""; + + trans_char(c, '"', '\a'); + c = c + j; + if (mandoc_synopsis) { /* Break lines only in + * the Synopsis. The + * Synopsis section + * seems to be treated + * as a special case - + * Bummer! */ + static int count = 0; /* Don't break on the + * first Nm */ + + if (count) { + out_html("
    "); + } else { + char *end = strchr(c, '\n'); + + if (end) { /* Remember the name for + * later. */ + strlimitcpy(mandoc_name, c, end - c, SMALL_STR_MAX); + } + } + count++; + } + out_html(change_to_font('B')); + while (*c == ' ' || *c == '\t') + c++; + if (*c == '\n') { /* If Nm has no + * argument, use one + * from an earlier Nm + * command that did have + * one. Hope there + * aren't too many + * commands that do + * this. */ + out_html(mandoc_name); + } else { + c = scan_troff_mandoc(c, 1, NULL); + } + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + } + case V('C', 'd'): /* BSD mandoc */ + case V('C', 'm'): /* BSD mandoc */ + case V('I', 'c'): /* BSD mandoc */ + case V('M', 's'): /* BSD mandoc */ + case V('O', 'r'): /* BSD mandoc */ + case V('S', 'y'): /* BSD mandoc */ + /* parse one line in bold */ + out_html(change_to_font('B')); + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + c = scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('D', 'v'): /* BSD mandoc */ + case V('E', 'v'): /* BSD mandoc */ + case V('F', 'r'): /* BSD mandoc */ + case V('L', 'i'): /* BSD mandoc */ + case V('N', 'o'): /* BSD mandoc */ + case V('N', 's'): /* BSD mandoc */ + case V('T', 'n'): /* BSD mandoc */ + case V('n', 'N'): /* BSD mandoc */ + trans_char(c, '"', '\a'); + c = c + j; + if (*c == '\n') + c++; + out_html(change_to_font('B')); + c = scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('%', 'A'): /* BSD mandoc biblio stuff */ + case V('%', 'D'): + case V('%', 'N'): + case V('%', 'O'): + case V('%', 'P'): + case V('%', 'Q'): + case V('%', 'V'): + c = c + j; + if (*c == '\n') + c++; + c = scan_troff(c, 1, NULL); /* Don't allow embedded + * mandoc coms */ + if (fillout) + curpos++; + else + curpos = 0; + break; + case V('%', 'B'): + case V('%', 'J'): + case V('%', 'R'): + case V('%', 'T'): + c = c + j; + out_html(change_to_font('I')); + if (*c == '\n') + c++; + c = scan_troff(c, 1, NULL); /* Don't allow embedded + * mandoc coms */ + out_html(change_to_font('R')); + if (fillout) + curpos++; + else + curpos = 0; + break; + default: + /* search macro database of self-defined macros */ + owndef = defdef; + while (owndef && owndef->nr != i) + owndef = owndef->next; + if (owndef) { + char **oldargument; + int deflen; + int onff; + + sl = fill_words(c + j, wordlist, &words); + c = sl + 1; + *sl = '\0'; + for (i = 1; i < words; i++) + wordlist[i][-1] = '\0'; + for (i = 0; i < words; i++) { + char *h = NULL; + + if (mandoc_command) { + scan_troff_mandoc(wordlist[i], 1, &h); + } else { + scan_troff(wordlist[i], 1, &h); + } + wordlist[i] = h; + } + for (i = words; i < 20; i++) + wordlist[i] = NULL; + deflen = strlen(owndef->st); + for (i = 0; owndef->st[deflen + 2 + i] = owndef->st[i]; i++); + oldargument = argument; + argument = wordlist; + onff = newline_for_fun; + if (mandoc_command) { + scan_troff_mandoc(owndef->st + deflen + 2, 0, NULL); + } else { + scan_troff(owndef->st + deflen + 2, 0, NULL); + } + newline_for_fun = onff; + argument = oldargument; + for (i = 0; i < words; i++) + if (wordlist[i]) + free(wordlist[i]); + *sl = '\n'; + } else if (mandoc_command && + ((isupper(*c) && islower(*(c + 1))) + || (islower(*c) && isupper(*(c + 1)))) + ) { /* Let through any BSD mandoc + * commands that haven't been delt + * with. I don't want to miss + * anything out of the text. */ + char buf[4]; + + strncpy(buf, c, 2); + buf[2] = ' '; + buf[3] = '\0'; + out_html(buf); /* Print the command (it + * might just be text). */ + c = c + j; + trans_char(c, '"', '\a'); + if (*c == '\n') + c++; + out_html(change_to_font('R')); + c = scan_troff(c, 1, NULL); + out_html(NEWLINE); + if (fillout) + curpos++; + else + curpos = 0; + } else { + c = skip_till_newline(c); + } + break; + } + } + if (fillout) { + out_html(NEWLINE); + curpos++; + } + NEWLINE[0] = '\n'; + return c; + } + + static void + flush(void) + { + } + + static int contained_tab = 0; + static int mandoc_line = 0; /* Signals whether to look for embedded + * mandoc commands. */ + + /* san : stop at newline */ + static char * + scan_troff(char *c, int san, char **result) + { + char *h; + char intbuff[NULL_TERMINATED(MED_STR_MAX)]; + int ibp = 0; + int i; + char *exbuffer; + int exbuffpos, exbuffmax, exscaninbuff, exnewline_for_fun; + int usenbsp = 0; + + #define FLUSHIBP if (ibp) { intbuff[ibp]=0; out_html(intbuff); ibp=0; } + + exbuffer = buffer; + exbuffpos = buffpos; + exbuffmax = buffmax; + exnewline_for_fun = newline_for_fun; + exscaninbuff = scaninbuff; + newline_for_fun = 0; + if (result) { + if (*result) { + buffer = *result; + buffpos = strlen(buffer); + buffmax = buffpos; + } else { + buffer = stralloc(LARGE_STR_MAX); + buffpos = 0; + buffmax = LARGE_STR_MAX; + } + scaninbuff = 1; + } + h = c; + /* start scanning */ + + while (*h && (!san || newline_for_fun || *h != '\n')) { + + if (*h == escapesym) { + h++; + FLUSHIBP; + h = scan_escape(h); + } else if (*h == controlsym && h[-1] == '\n') { + h++; + FLUSHIBP; + h = scan_request(h); + if (san && h[-1] == '\n') + h--; + } else if (mandoc_line + && *(h) && isupper(*(h)) + && *(h + 1) && islower(*(h + 1)) + && *(h + 2) && isspace(*(h + 2))) { + /* + * BSD imbedded command eg ".It Fl Ar arg1 Fl Ar + * arg2" + */ + FLUSHIBP; + h = scan_request(h); + if (san && h[-1] == '\n') + h--; + } else if (*h == nobreaksym && h[-1] == '\n') { + h++; + FLUSHIBP; + h = scan_request(h); + if (san && h[-1] == '\n') + h--; + } else { + int mx; + + if (h[-1] == '\n' && still_dd && isalnum(*h)) { + /* + * sometimes a .HP request is not followed by + * a .br request + */ + FLUSHIBP; + out_html("

    "); + curpos = 0; + still_dd = 0; + } + switch (*h) { + case '&': + intbuff[ibp++] = '&'; + intbuff[ibp++] = 'a'; + intbuff[ibp++] = 'm'; + intbuff[ibp++] = 'p'; + intbuff[ibp++] = ';'; + curpos++; + break; + case '<': + intbuff[ibp++] = '&'; + intbuff[ibp++] = 'l'; + intbuff[ibp++] = 't'; + intbuff[ibp++] = ';'; + curpos++; + break; + case '>': + intbuff[ibp++] = '&'; + intbuff[ibp++] = 'g'; + intbuff[ibp++] = 't'; + intbuff[ibp++] = ';'; + curpos++; + break; + case '"': + intbuff[ibp++] = '&'; + intbuff[ibp++] = 'q'; + intbuff[ibp++] = 'u'; + intbuff[ibp++] = 'o'; + intbuff[ibp++] = 't'; + intbuff[ibp++] = ';'; + curpos++; + break; + case '\n': + if (h[-1] == '\n' && fillout) { + intbuff[ibp++] = '<'; + intbuff[ibp++] = 'P'; + intbuff[ibp++] = '>'; + } + if (contained_tab && fillout) { + intbuff[ibp++] = '<'; + intbuff[ibp++] = 'B'; + intbuff[ibp++] = 'R'; + intbuff[ibp++] = '>'; + } + contained_tab = 0; + curpos = 0; + usenbsp = 0; + intbuff[ibp++] = '\n'; + break; + case '\t': + { + int curtab = 0; + + contained_tab = 1; + FLUSHIBP; + /* like a typewriter, not like TeX */ + tabstops[19] = curpos + 1; + while (curtab < maxtstop && tabstops[curtab] <= curpos) + curtab++; + if (curtab < maxtstop) { + if (!fillout) { + while (curpos < tabstops[curtab]) { + intbuff[ibp++] = ' '; + if (ibp > 480) { + FLUSHIBP; + } + curpos++; + } + } else { + out_html(""); + while (curpos < tabstops[curtab]) { + out_html(" "); + curpos++; + } + out_html(""); + } + } + } + break; + default: + if (*h == ' ' && (h[-1] == '\n' || usenbsp)) { + FLUSHIBP; + if (!usenbsp && fillout) { + out_html("
    "); + curpos = 0; + } + usenbsp = fillout; + if (usenbsp) + out_html(" "); + else + intbuff[ibp++] = ' '; + } else if (*h > 31 && *h < 127) + intbuff[ibp++] = *h; + else if (((unsigned char) (*h)) > 127) { + intbuff[ibp++] = '&'; + intbuff[ibp++] = '#'; + intbuff[ibp++] = '0' + ((unsigned char) (*h)) / 100; + intbuff[ibp++] = '0' + (((unsigned char) (*h)) % 100) / 10; + intbuff[ibp++] = '0' + ((unsigned char) (*h)) % 10; + intbuff[ibp++] = ';'; + } + curpos++; + break; + } + if (ibp > (MED_STR_MAX - 20)) + FLUSHIBP; + h++; + } + } + FLUSHIBP; + if (buffer) + buffer[buffpos] = '\0'; + if (san && *h) + h++; + newline_for_fun = exnewline_for_fun; + if (result) { + *result = buffer; + buffer = exbuffer; + buffpos = exbuffpos; + buffmax = exbuffmax; + scaninbuff = exscaninbuff; + } + return h; + } + + + static char * + scan_troff_mandoc(char *c, int san, char **result) + { + char *ret, *end = c; + int oldval = mandoc_line; + + mandoc_line = 1; + while (*end && *end != '\n') { + end++; + } + + if (end > c + 2 + && ispunct(*(end - 1)) + && isspace(*(end - 2)) && *(end - 2) != '\n') { + /* + * Don't format lonely punctuation E.g. in "xyz ," format the + * xyz and then append the comma removing the space. + */ + *(end - 2) = '\n'; + ret = scan_troff(c, san, result); + *(end - 2) = *(end - 1); + *(end - 1) = ' '; + } else { + ret = scan_troff(c, san, result); + } + mandoc_line = oldval; + return ret; + } + + main(int argc, char **argv) + { + FILE *f; + char *t; + int l, i; + char *buf; + char *h, *fullname; + STRDEF *stdf; + + t = NULL; + while ((i = getopt(argc, argv, "")) != EOF) { + switch (i) { + default: + usage(); + exit(EXIT_USAGE); + } + } + + if (argc != 2) { + usage(); + exit(EXIT_USAGE); + } + h = t = argv[1]; + i = 0; + + buf = read_man_page(h); + if (!buf) { + fprintf(stderr, "man2html: cannot read %s: %s\n", h, strerror(errno)); + exit(1); + } + #ifdef MAKEINDEX + idxfile = fopen(INDEXFILE, "a"); + #endif + stdf = &standardchar[0]; + i = 0; + while (stdf->nr) { + stdf->next = &standardchar[i]; + stdf = stdf->next; + i++; + } + chardef = &standardchar[0]; + + stdf = &standardstring[0]; + i = 0; + while (stdf->nr) { + stdf->next = &standardstring[i]; + stdf = stdf->next; + i++; + } + strdef = &standardstring[0]; + + intdef = &standardint[0]; + i = 0; + while (intdef->nr) { + intdef->next = &standardint[i]; + intdef = intdef->next; + i++; + } + intdef = &standardint[0]; + + defdef = NULL; + + scan_troff(buf + 1, 0, NULL); + + while (itemdepth || dl_set[itemdepth]) { + out_html("\n"); + if (dl_set[itemdepth]) + dl_set[itemdepth] = 0; + else if (itemdepth > 0) + itemdepth--; + } + + out_html(change_to_font(0)); + out_html(change_to_size(0)); + if (!fillout) { + fillout = 1; + out_html(""); + } + out_html(NEWLINE); + + if (output_possible) { + /*   for mosaic users */ + fputs("
    \n 

    Index

    \n
    \n", stdout); + manidx[mip] = 0; + fputs(manidx, stdout); + if (subs) + fputs("
    \n", stdout); + fputs("\n", stdout); + print_sig(); + fputs("\n\n", stdout); + } else + fprintf(stderr, "man2html: no output produced\n"); + #ifdef MAKEINDEX + if (idxfile) + fclose(idxfile); + #endif + exit(EXIT_SUCCESS); + } diff -Nrc2 bash-2.01.1/support/texi2html bash-2.02/support/texi2html *** bash-2.01.1/support/texi2html Tue Nov 12 12:47:42 1996 --- bash-2.02/support/texi2html Tue Mar 3 14:30:51 1998 *************** *** 1,3 **** ! #!/usr/local/bin/perl 'di '; 'ig 00 '; --- 1,3 ---- ! #!/usr/bin/perl 'di '; 'ig 00 '; diff -Nrc2 bash-2.01.1/test.c bash-2.02/test.c *** bash-2.01.1/test.c Mon Aug 18 12:28:36 1997 --- bash-2.02/test.c Tue Sep 23 13:03:26 1997 *************** *** 55,60 **** --- 55,64 ---- #include "shell.h" + #include "pathexp.h" + #include "test.h" #include "builtins/common.h" + #include + #if !defined (STRLEN) # define STRLEN(s) ((s)[0] ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0) *************** *** 100,107 **** do { test_error_return = val; longjmp (test_exit_buf, 1); } while (0) #if defined (AFS) - /* We have to use access(2) for machines running AFS, because it's - not a Unix file system. This may produce incorrect answers for - non-AFS files. I hate AFS. */ # define EACCESS(path, mode) access(path, mode) #else --- 104,111 ---- do { test_error_return = val; longjmp (test_exit_buf, 1); } while (0) + /* We have to use access(2) for machines running AFS, because it's + not a Unix file system. This may produce incorrect answers for + non-AFS files. I hate AFS. */ #if defined (AFS) # define EACCESS(path, mode) access(path, mode) #else *************** *** 114,119 **** static int noeval; - static int unop (); - static int binop (); static int unary_operator (); static int binary_operator (); --- 118,121 ---- *************** *** 144,147 **** --- 146,168 ---- } + /* + * beyond - call when we're beyond the end of the argument list (an + * error condition) + */ + static void + beyond () + { + test_syntax_error ("argument expected", (char *)NULL); + } + + /* Syntax error for when an integer argument was expected, but + something else was found. */ + static void + integer_expected_error (pch) + char *pch; + { + test_syntax_error ("%s: integer expression expected", pch); + } + /* A wrapper for stat () which disallows pathnames that are empty strings and handles /dev/fd emulation on systems that don't have it. */ *************** *** 184,188 **** and don't make the mistake of telling root that any file is executable. */ ! static int test_eaccess (path, mode) char *path; --- 205,209 ---- and don't make the mistake of telling root that any file is executable. */ ! int test_eaccess (path, mode) char *path; *************** *** 214,217 **** --- 235,239 ---- return (0); + errno = EACCES; return (-1); } *************** *** 224,243 **** /* ! * beyond - call when we're beyond the end of the argument list (an ! * error condition) */ ! static void ! beyond () { ! test_syntax_error ("argument expected", (char *)NULL); } ! /* Syntax error for when an integer argument was expected, but ! something else was found. */ ! static void ! integer_expected_error (pch) ! char *pch; { ! test_syntax_error ("%s: integer expression expected", pch); } --- 246,300 ---- /* ! * expr: ! * or */ ! static int ! expr () { ! if (pos >= argc) ! beyond (); ! ! return (FALSE ^ or ()); /* Same with this. */ } ! /* ! * or: ! * and ! * and '-o' or ! */ ! static int ! or () { ! int value, v2; ! ! value = and (); ! while (pos < argc && argv[pos][0] == '-' && argv[pos][1] == 'o' && !argv[pos][2]) ! { ! advance (0); ! v2 = or (); ! return (value || v2); ! } ! ! return (value); ! } ! ! /* ! * and: ! * term ! * term '-a' and ! */ ! static int ! and () ! { ! int value, v2; ! ! value = term (); ! while (pos < argc && argv[pos][0] == '-' && argv[pos][1] == 'a' && !argv[pos][2]) ! { ! advance (0); ! v2 = and (); ! return (value && v2); ! } ! return (value); } *************** *** 247,254 **** * * term ::= ! * '-'('a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'p'|'r'|'s'|'u'|'w'|'x') filename ! * '-'('G'|'L'|'O'|'S') filename * '-t' [int] * '-'('z'|'n') string * string * string ('!='|'='|'==') string --- 304,312 ---- * * term ::= ! * '-'('a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'k'|'p'|'r'|'s'|'u'|'w'|'x') filename ! * '-'('G'|'L'|'O'|'S'|'N') filename * '-t' [int] * '-'('z'|'n') string + * '-o' option * string * string ('!='|'='|'==') string *************** *** 293,316 **** } - #if 1 /* are there enough arguments left that this could be dyadic? */ ! if ((pos + 3 <= argc) && binop (argv[pos + 1])) value = binary_operator (); - #else - /* If this is supposed to be a binary operator, make sure there are - enough arguments and fail if there are not. */ - if ((pos + 1 < argc) && binop (argv[pos+1])) - { - if (pos + 3 <= argc) - value = binary_operator (); - else - beyond (); - } - #endif /* Might be a switch type argument */ else if (argv[pos][0] == '-' && argv[pos][2] == '\0') { ! if (unop (argv[pos][1])) value = unary_operator (); else --- 351,362 ---- } /* are there enough arguments left that this could be dyadic? */ ! if ((pos + 3 <= argc) && test_binop (argv[pos + 1])) value = binary_operator (); /* Might be a switch type argument */ else if (argv[pos][0] == '-' && argv[pos][2] == '\0') { ! if (test_unop (argv[pos])) value = unary_operator (); else *************** *** 345,358 **** static int ! arithcomp (s, t, op) char *s, *t; ! int op; { long l, r; - if (legal_number (s, &l) == 0) - integer_expected_error (s); - if (legal_number (t, &r) == 0) - integer_expected_error (t); switch (op) { --- 391,418 ---- static int ! arithcomp (s, t, op, flags) char *s, *t; ! int op, flags; { long l, r; + int expok; + + if (flags & TEST_ARITHEXP) + { + l = evalexp (s, &expok); + if (expok == 0) + return (FALSE); /* should probably longjmp here */ + r = evalexp (t, &expok); + if (expok == 0) + return (FALSE); /* ditto */ + } + else + { + if (legal_number (s, &l) == 0) + integer_expected_error (s); + if (legal_number (t, &r) == 0) + integer_expected_error (t); + } switch (op) { *************** *** 364,371 **** case GE: return (l >= r); } return (FALSE); } - #if defined (PATTERN_MATCHING) static int patcomp (string, pat, op) --- 424,431 ---- case GE: return (l >= r); } + return (FALSE); } static int patcomp (string, pat, op) *************** *** 375,386 **** int m; ! m = fnmatch (pat, string, 0); ! switch (op) { ! case EQ: return (m == 0); ! case NE: return (m != 0); } } ! #endif /* PATTERN_MATCHING */ static int --- 435,491 ---- int m; ! m = fnmatch (pat, string, FNMATCH_EXTFLAG); ! return ((op == EQ) ? (m == 0) : (m != 0)); ! } ! ! int ! binary_test (op, arg1, arg2, flags) ! char *op, *arg1, *arg2; ! int flags; ! { ! int patmatch; ! ! patmatch = (flags & TEST_PATMATCH); ! ! if (op[0] == '=' && (op[1] == '\0' || (op[1] == '=' && op[2] == '\0'))) ! return (patmatch ? patcomp (arg1, arg2, EQ) : STREQ (arg1, arg2)); ! ! else if ((op[0] == '>' || op[0] == '<') && op[1] == '\0') ! return ((op[0] == '>') ? (strcmp (arg1, arg2) > 0) : (strcmp (arg1, arg2) < 0)); ! ! else if (op[0] == '!' && op[1] == '=' && op[2] == '\0') ! return (patmatch ? patcomp (arg1, arg2, NE) : (STREQ (arg1, arg2) == 0)); ! ! else if (op[2] == 't') ! { ! switch (op[1]) ! { ! case 'n': return (filecomp (arg1, arg2, NT)); /* -nt */ ! case 'o': return (filecomp (arg1, arg2, OT)); /* -ot */ ! case 'l': return (arithcomp (arg1, arg2, LT, flags)); /* -lt */ ! case 'g': return (arithcomp (arg1, arg2, GT, flags)); /* -gt */ ! } ! } ! else if (op[1] == 'e') { ! switch (op[2]) ! { ! case 'f': return (filecomp (arg1, arg2, EF)); /* -ef */ ! case 'q': return (arithcomp (arg1, arg2, EQ, flags)); /* -eq */ ! } ! } ! else if (op[2] == 'e') ! { ! switch (op[1]) ! { ! case 'n': return (arithcomp (arg1, arg2, NE, flags)); /* -ne */ ! case 'g': return (arithcomp (arg1, arg2, GE, flags)); /* -ge */ ! case 'l': return (arithcomp (arg1, arg2, LE, flags)); /* -le */ ! } } + + return (FALSE); /* should never get here */ } ! static int *************** *** 391,407 **** w = argv[pos + 1]; ! if (w[0] == '=' && (w[1] == '\0' || (w[1] == '=' && w[2] == '\0'))) { ! value = STREQ (argv[pos], argv[pos + 2]); ! pos += 3; ! return (value); ! } ! if ((w[0] == '>' || w[0] == '<') && w[1] == '\0') ! { ! value = (w[0] == '>') ? strcmp (argv[pos], argv[pos + 2]) > 0 ! : strcmp (argv[pos], argv[pos + 2]) < 0; pos += 3; return (value); } #if defined (PATTERN_MATCHING) if ((w[0] == '=' || w[0] == '!') && w[1] == '~' && w[2] == '\0') --- 496,508 ---- w = argv[pos + 1]; ! if ((w[0] == '=' && (w[1] == '\0' || (w[1] == '=' && w[2] == '\0'))) || /* =, == */ ! ((w[0] == '>' || w[0] == '<') && w[1] == '\0') || /* <, > */ ! (w[0] == '!' && w[1] == '=' && w[2] == '\0')) /* != */ { ! value = binary_test (w, argv[pos], argv[pos + 2], 0); pos += 3; return (value); } + #if defined (PATTERN_MATCHING) if ((w[0] == '=' || w[0] == '!') && w[1] == '~' && w[2] == '\0') *************** *** 412,423 **** } #endif - if (w[0] == '!' && w[1] == '=' && w[2] == '\0') - { - value = STREQ (argv[pos], argv[pos + 2]) == 0; - pos += 3; - return (value); - } ! if (w[0] != '-' || w[3] != '\0') { test_syntax_error ("%s: binary operator expected", w); --- 513,518 ---- } #endif ! if ((w[0] != '-' || w[3] != '\0') || test_binop (w) == 0) { test_syntax_error ("%s: binary operator expected", w); *************** *** 426,463 **** } ! w++; ! if (w[1] == 't') ! { ! switch (w[0]) ! { ! case 'n': value = filecomp (argv[pos], argv[pos + 2], NT); break; ! case 'o': value = filecomp (argv[pos], argv[pos + 2], OT); break; ! case 'l': value = arithcomp (argv[pos], argv[pos + 2], LT); break; ! case 'g': value = arithcomp (argv[pos], argv[pos + 2], GT); break; ! default: test_syntax_error ("-%s: binary operator expected", w); ! } ! } ! else if (w[0] == 'e') ! { ! switch (w[1]) ! { ! case 'q': value = arithcomp (argv[pos], argv[pos + 2], EQ); break; ! case 'f': value = filecomp (argv[pos], argv[pos + 2], EF); break; ! default: test_syntax_error ("-%s: binary operator expected", w); ! } ! } ! else if (w[1] == 'e') ! { ! switch (w[0]) ! { ! case 'n': value = arithcomp (argv[pos], argv[pos + 2], NE); break; ! case 'g': value = arithcomp (argv[pos], argv[pos + 2], GE); break; ! case 'l': value = arithcomp (argv[pos], argv[pos + 2], LE); break; ! default: test_syntax_error ("-%s: binary operator expected", w); ! } ! } ! else ! test_syntax_error ("-%s: binary operator expected", w); ! pos += 3; return value; --- 521,525 ---- } ! value = binary_test (w, argv[pos], argv[pos + 2], 0); pos += 3; return value; *************** *** 467,513 **** unary_operator () { long r; - struct stat stat_buf; ! switch (argv[pos][1]) { ! default: ! return (FALSE); ! /* All of the following unary operators use unary_advance (), which ! checks to make sure that there is an argument, and then advances ! pos right past it. This means that pos - 1 is the location of the ! argument. */ case 'a': /* file exists in the file system? */ case 'e': ! unary_advance (); ! return (test_stat (argv[pos - 1], &stat_buf) == 0); case 'r': /* file is readable? */ ! unary_advance (); ! return (EACCESS (argv[pos - 1], R_OK) == 0); case 'w': /* File is writeable? */ ! unary_advance (); ! return (EACCESS (argv[pos - 1], W_OK) == 0); case 'x': /* File is executable? */ ! unary_advance (); ! return (EACCESS (argv[pos - 1], X_OK) == 0); case 'O': /* File is owned by you? */ ! unary_advance (); ! return (test_stat (argv[pos - 1], &stat_buf) == 0 && (uid_t) current_user.euid == (uid_t) stat_buf.st_uid); case 'G': /* File is owned by your group? */ ! unary_advance (); ! return (test_stat (argv[pos - 1], &stat_buf) == 0 && (gid_t) current_user.egid == (gid_t) stat_buf.st_gid); case 'f': /* File is a file? */ ! unary_advance (); ! if (test_stat (argv[pos - 1], &stat_buf) < 0) return (FALSE); --- 529,596 ---- unary_operator () { + char *op, *arg; long r; ! op = argv[pos]; ! if (test_unop (op) == 0) ! return (FALSE); ! ! /* the only tricky case is `-t', which may or may not take an argument. */ ! if (op[1] == 't') { ! advance (0); ! if (pos < argc && legal_number (argv[pos], &r)) ! { ! advance (0); ! return (unary_test (op, argv[pos - 1])); ! } ! else ! return (unary_test (op, "1")); ! } ! /* All of the unary operators take an argument, so we first call ! unary_advance (), which checks to make sure that there is an ! argument, and then advances pos right past it. This means that ! pos - 1 is the location of the argument. */ ! unary_advance (); ! return (unary_test (op, argv[pos - 1])); ! } + int + unary_test (op, arg) + char *op, *arg; + { + long r; + struct stat stat_buf; + + switch (op[1]) + { case 'a': /* file exists in the file system? */ case 'e': ! return (test_stat (arg, &stat_buf) == 0); case 'r': /* file is readable? */ ! return (EACCESS (arg, R_OK) == 0); case 'w': /* File is writeable? */ ! return (EACCESS (arg, W_OK) == 0); case 'x': /* File is executable? */ ! return (EACCESS (arg, X_OK) == 0); case 'O': /* File is owned by you? */ ! return (test_stat (arg, &stat_buf) == 0 && (uid_t) current_user.euid == (uid_t) stat_buf.st_uid); case 'G': /* File is owned by your group? */ ! return (test_stat (arg, &stat_buf) == 0 && (gid_t) current_user.egid == (gid_t) stat_buf.st_gid); + case 'N': + return (test_stat (arg, &stat_buf) == 0 && + stat_buf.st_atime <= stat_buf.st_mtime); + case 'f': /* File is a file? */ ! if (test_stat (arg, &stat_buf) < 0) return (FALSE); *************** *** 520,531 **** case 'd': /* File is a directory? */ ! unary_advance (); ! return (test_stat (argv[pos - 1], &stat_buf) == 0 && ! (S_ISDIR (stat_buf.st_mode))); case 's': /* File has something in it? */ ! unary_advance (); ! return (test_stat (argv[pos - 1], &stat_buf) == 0 && ! stat_buf.st_size > (off_t) 0); case 'S': /* File is a socket? */ --- 603,610 ---- case 'd': /* File is a directory? */ ! return (test_stat (arg, &stat_buf) == 0 && (S_ISDIR (stat_buf.st_mode))); case 's': /* File has something in it? */ ! return (test_stat (arg, &stat_buf) == 0 && stat_buf.st_size > (off_t) 0); case 'S': /* File is a socket? */ *************** *** 533,719 **** return (FALSE); #else ! unary_advance (); ! return (test_stat (argv[pos - 1], &stat_buf) == 0 && ! S_ISSOCK (stat_buf.st_mode)); #endif /* S_ISSOCK */ case 'c': /* File is character special? */ ! unary_advance (); ! return (test_stat (argv[pos - 1], &stat_buf) == 0 && ! S_ISCHR (stat_buf.st_mode)); case 'b': /* File is block special? */ ! unary_advance (); ! return (test_stat (argv[pos - 1], &stat_buf) == 0 && ! S_ISBLK (stat_buf.st_mode)); case 'p': /* File is a named pipe? */ - unary_advance (); #ifndef S_ISFIFO return (FALSE); #else ! return (test_stat (argv[pos - 1], &stat_buf) == 0 && ! S_ISFIFO (stat_buf.st_mode)); #endif /* S_ISFIFO */ case 'L': /* Same as -h */ case 'h': /* File is a symbolic link? */ - unary_advance (); #if !defined (S_ISLNK) || !defined (HAVE_LSTAT) return (FALSE); #else ! return ((argv[pos - 1][0] != '\0') && ! (lstat (argv[pos - 1], &stat_buf) == 0) && ! S_ISLNK (stat_buf.st_mode)); #endif /* S_IFLNK && HAVE_LSTAT */ case 'u': /* File is setuid? */ ! unary_advance (); ! return (test_stat (argv[pos - 1], &stat_buf) == 0 && ! (stat_buf.st_mode & S_ISUID) != 0); case 'g': /* File is setgid? */ ! unary_advance (); ! return (test_stat (argv[pos - 1], &stat_buf) == 0 && ! (stat_buf.st_mode & S_ISGID) != 0); case 'k': /* File has sticky bit set? */ - unary_advance (); #if !defined (S_ISVTX) /* This is not Posix, and is not defined on some Posix systems. */ return (FALSE); #else ! return (test_stat (argv[pos - 1], &stat_buf) == 0 && ! (stat_buf.st_mode & S_ISVTX) != 0); #endif ! case 't': /* File fd is a terminal? fd defaults to stdout. */ ! advance (0); ! if (pos < argc && legal_number (argv[pos], &r)) ! { ! advance (0); ! return (isatty ((int)r)); ! } ! return (isatty (1)); case 'n': /* True if arg has some length. */ ! unary_advance (); ! return (argv[pos - 1][0] != '\0'); case 'z': /* True if arg has no length. */ ! unary_advance (); ! return (argv[pos - 1][0] == '\0'); ! ! case 'o': ! unary_advance (); ! return (minus_o_option_value (argv[pos - 1]) == 1); ! } ! } ! ! /* ! * and: ! * term ! * term '-a' and ! */ ! static int ! and () ! { ! int value, v2; ! value = term (); ! while (pos < argc && argv[pos][0] == '-' && argv[pos][1] == 'a' && !argv[pos][2]) ! { ! advance (0); ! v2 = and (); ! return (value && v2); } - return (value); } ! /* ! * or: ! * and ! * and '-o' or ! */ ! static int ! or () { ! int value, v2; ! ! value = and (); ! while (pos < argc && argv[pos][0] == '-' && argv[pos][1] == 'o' && !argv[pos][2]) ! { ! advance (0); ! v2 = or (); ! return (value || v2); ! } ! ! return (value); ! } ! ! /* ! * expr: ! * or ! */ ! static int ! expr () ! { ! if (pos >= argc) ! beyond (); ! ! return (FALSE ^ or ()); /* Same with this. */ ! } ! ! /* Return TRUE if S is one of the test command's binary operators. */ ! static int ! binop (s) ! char *s; ! { ! char *t; ! ! if (s[0] == '=' && s[1] == '\0') return (1); /* '=' */ ! else if ((s[0] == '<' || s[0] == '>') && s[1] == '\0') /* string <, > */ return (1); ! else if ((s[0] == '=' || s[0] == '!') && s[1] == '=' && s[2] == '\0') return (1); /* `==' and `!=' */ #if defined (PATTERN_MATCHING) ! else if (s[2] == '\0' && s[1] == '~' && (s[0] == '=' || s[0] == '!')) return (1); #endif ! else if (s[0] != '-' || s[2] == '\0' || s[3] != '\0') return (0); else { ! t = s + 1; ! if (t[1] == 't') ! switch (t[0]) { ! case 'n': /* -nt */ ! case 'o': /* -ot */ ! case 'l': /* -lt */ ! case 'g': /* -gt */ ! return (1); ! default: ! return (0); } ! else if (t[0] == 'e') ! switch (t[1]) { ! case 'q': /* -eq */ ! case 'f': /* -ef */ ! return (1); ! default: ! return (0); } ! else if (t[1] == 'e') ! switch (t[0]) { ! case 'n': /* -ne */ ! case 'l': /* -le */ ! case 'g': /* -ge */ ! return (1); ! default: ! return (0); } else --- 612,718 ---- return (FALSE); #else ! return (test_stat (arg, &stat_buf) == 0 && S_ISSOCK (stat_buf.st_mode)); #endif /* S_ISSOCK */ case 'c': /* File is character special? */ ! return (test_stat (arg, &stat_buf) == 0 && S_ISCHR (stat_buf.st_mode)); case 'b': /* File is block special? */ ! return (test_stat (arg, &stat_buf) == 0 && S_ISBLK (stat_buf.st_mode)); case 'p': /* File is a named pipe? */ #ifndef S_ISFIFO return (FALSE); #else ! return (test_stat (arg, &stat_buf) == 0 && S_ISFIFO (stat_buf.st_mode)); #endif /* S_ISFIFO */ case 'L': /* Same as -h */ case 'h': /* File is a symbolic link? */ #if !defined (S_ISLNK) || !defined (HAVE_LSTAT) return (FALSE); #else ! return ((arg[0] != '\0') && ! (lstat (arg, &stat_buf) == 0) && S_ISLNK (stat_buf.st_mode)); #endif /* S_IFLNK && HAVE_LSTAT */ case 'u': /* File is setuid? */ ! return (test_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISUID) != 0); case 'g': /* File is setgid? */ ! return (test_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISGID) != 0); case 'k': /* File has sticky bit set? */ #if !defined (S_ISVTX) /* This is not Posix, and is not defined on some Posix systems. */ return (FALSE); #else ! return (test_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISVTX) != 0); #endif ! case 't': /* File fd is a terminal? */ ! if (legal_number (arg, &r) == 0) ! return (FALSE); ! return (isatty ((int)r)); case 'n': /* True if arg has some length. */ ! return (arg[0] != '\0'); case 'z': /* True if arg has no length. */ ! return (arg[0] == '\0'); ! case 'o': /* True if option `arg' is set. */ ! return (minus_o_option_value (arg) == 1); } } ! /* Return TRUE if OP is one of the test command's binary operators. */ ! int ! test_binop (op) ! char *op; { ! if (op[0] == '=' && op[1] == '\0') return (1); /* '=' */ ! else if ((op[0] == '<' || op[0] == '>') && op[1] == '\0') /* string <, > */ return (1); ! else if ((op[0] == '=' || op[0] == '!') && op[1] == '=' && op[2] == '\0') return (1); /* `==' and `!=' */ #if defined (PATTERN_MATCHING) ! else if (op[2] == '\0' && op[1] == '~' && (op[0] == '=' || op[0] == '!')) return (1); #endif ! else if (op[0] != '-' || op[2] == '\0' || op[3] != '\0') return (0); else { ! if (op[2] == 't') ! switch (op[1]) { ! case 'n': /* -nt */ ! case 'o': /* -ot */ ! case 'l': /* -lt */ ! case 'g': /* -gt */ ! return (1); ! default: ! return (0); } ! else if (op[1] == 'e') ! switch (op[2]) { ! case 'q': /* -eq */ ! case 'f': /* -ef */ ! return (1); ! default: ! return (0); } ! else if (op[2] == 'e') ! switch (op[1]) { ! case 'n': /* -ne */ ! case 'g': /* -ge */ ! case 'l': /* -le */ ! return (1); ! default: ! return (0); } else *************** *** 723,740 **** /* Return non-zero if OP is one of the test command's unary operators. */ ! static int ! unop (op) ! int op; { ! switch (op) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'k': case 'n': ! case 'p': case 'r': case 's': case 't': case 'u': ! case 'w': case 'x': case 'z': ! case 'G': case 'L': case 'O': case 'S': ! case 'o': return (1); } return (0); } --- 722,742 ---- /* Return non-zero if OP is one of the test command's unary operators. */ ! int ! test_unop (op) ! char *op; { ! if (op[0] != '-') ! return (0); ! ! switch (op[1]) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'k': case 'n': ! case 'o': case 'p': case 'r': case 's': case 't': ! case 'u': case 'w': case 'x': case 'z': ! case 'G': case 'L': case 'O': case 'S': case 'N': return (1); } + return (0); } *************** *** 747,751 **** else if (argv[pos][0] == '-' && argv[pos][2] == '\0') { ! if (unop (argv[pos][1])) return (unary_operator ()); else --- 749,753 ---- else if (argv[pos][0] == '-' && argv[pos][2] == '\0') { ! if (test_unop (argv[pos])) return (unary_operator ()); else *************** *** 767,771 **** int value; ! if (binop (argv[pos+1])) { value = binary_operator (); --- 769,773 ---- int value; ! if (test_binop (argv[pos+1])) { value = binary_operator (); *************** *** 780,784 **** pos = argc; } ! else if (argv[pos][0] == '!' && !argv[pos][1]) { advance (1); --- 782,786 ---- pos = argc; } ! else if (argv[pos][0] == '!' && argv[pos][1] == '\0') { advance (1); diff -Nrc2 bash-2.01.1/test.h bash-2.02/test.h *** bash-2.01.1/test.h Wed Dec 31 19:00:00 1969 --- bash-2.02/test.h Tue Sep 23 13:04:28 1997 *************** *** 0 **** --- 1,40 ---- + /* test.h -- external interface to the conditional command code. */ + + /* Copyright (C) 1997 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, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ + + #ifndef _TEST_H_ + #define _TEST_H_ + + #include "stdc.h" + + /* Values for the flags argument to binary_test */ + #define TEST_PATMATCH 0x01 + #define TEST_ARITHEXP 0x02 + + extern int test_eaccess __P((char *, int)); + + extern int test_unop __P((char *)); + extern int test_binop __P((char *)); + + extern int unary_test __P((char *, char *)); + extern int binary_test __P((char *, char *, char *, int)); + + extern int test_command __P((int, char **)); + + #endif /* _TEST_H_ */ diff -Nrc2 bash-2.01.1/tests/arith.right bash-2.02/tests/arith.right *** bash-2.01.1/tests/arith.right Thu Feb 27 11:23:34 1997 --- bash-2.02/tests/arith.right Tue Nov 18 11:32:51 1997 *************** *** 116,117 **** --- 116,122 ---- 7 4 + 32767 + 32768 + 131072 + 2147483647 + 1 diff -Nrc2 bash-2.01.1/tests/arith.tests bash-2.02/tests/arith.tests *** bash-2.01.1/tests/arith.tests Wed Apr 16 11:12:14 1997 --- bash-2.02/tests/arith.tests Tue Nov 18 11:32:45 1997 *************** *** 214,215 **** --- 214,222 ---- echo $x + + # exponentiation + echo $(( 2**15 - 1)) + echo $(( 2**(16-1))) + echo $(( 2**16*2 )) + echo $(( 2**31-1)) + echo $(( 2**0 )) diff -Nrc2 bash-2.01.1/tests/array-at-star bash-2.02/tests/array-at-star *** bash-2.01.1/tests/array-at-star Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/array-at-star Tue Sep 23 14:36:13 1997 *************** *** 0 **** --- 1,120 ---- + # test the expansion of ${array[@]} and ${array[*]}, both quoted and + # unquoted. the expansions should be exactly analogous to the + # expansions of $@ and $* quoted and unquoted + A=(a b) + + recho "${A[*]}" + + # If IFS is null, the parameters are joined without separators + IFS='' + recho "${A[*]}" + + # If IFS is unset, the parameters are separated by spaces + unset IFS + recho "${A[*]}" + + recho "${A[@]}" + recho ${A[@]} + + IFS='/' + A=(bob 'tom dick harry' joe) + set ${A[*]} + recho $# + recho $1 + recho $2 + recho $3 + + A=(bob 'tom dick harry' joe) + set ${A[*]} + recho $# + recho $1 + recho $2 + recho $3 + + A=(bob 'tom dick harry' joe) + set ${A[@]} + recho $# + recho $1 + recho $2 + recho $3 + + A=(bob 'tom dick harry' joe) + set ${A[@]} + recho $# + recho $1 + recho $2 + recho $3 + + # according to POSIX.2, unquoted $* should expand to multiple words if + # $IFS is null, just like unquoted $@ + IFS='' + A=(bob 'tom dick harry' joe) + set "${A[*]}" + recho $# + recho $1 + recho $2 + recho $3 + + A=(bob 'tom dick harry' joe) + set ${A[*]} + recho $# + recho $1 + recho $2 + recho $3 + + A=(bob 'tom dick harry' joe) + set ${A[@]} + recho $# + recho $1 + recho $2 + recho $3 + + # if IFS is unset, the individual positional parameters are split on + # " \t\n" if $* or $@ are unquoted + unset IFS + A=(bob 'tom dick harry' joe) + set ${A[*]} + recho $# + recho $1 + recho $2 + recho $3 + + A=(bob 'tom dick harry' joe) + set ${A[@]} + recho $# + recho $1 + recho $2 + recho $3 + + # but not for "$@" or "$*" + A=(bob 'tom dick harry' joe) + set "${A[*]}" + recho $# + recho $1 + recho $2 + recho $3 + + A=(bob 'tom dick harry' joe) + set "${A[@]}" + recho $# + recho $1 + recho $2 + recho $3 + + # these should both expand the value of A to multiple words + A=(a b c d e) + IFS="" + recho ${A[@]} + recho "${A[@]}" + + # this example is straight from the POSIX.2 rationale and adapted to arrays + A=(foo bar bam) + + recho "${A[@]}" + recho "${A[*]}" + + unset IFS + + recho "${A[@]}" + recho ${A[@]} + recho "${A[*]}" diff -Nrc2 bash-2.01.1/tests/array.right bash-2.02/tests/array.right *** bash-2.01.1/tests/array.right Fri Jul 18 14:26:44 1997 --- bash-2.02/tests/array.right Mon Nov 17 14:38:43 1997 *************** *** 23,26 **** --- 23,28 ---- declare -ar a='([1]="" [2]="bdef" [5]="hello world" [6]="test expression")' declare -ar c='()' + readonly -a a='([1]="" [2]="bdef" [5]="hello world" [6]="test expression")' + readonly -a c='()' ./array.tests: declare: e: cannot assign to array variables in this way a test *************** *** 53,56 **** --- 55,60 ---- this of this is a test of read using arrays + this test + this is a test of arrays declare -a DIRSTACK='()' declare -ar a='([1]="" [2]="bdef" [5]="hello world" [6]="test expression")' *************** *** 95,97 **** --- 99,103 ---- 6 7 9 6 7 9 5 + length = 3 + value = new1 new2 new3 ./array.tests: narray: unbound variable diff -Nrc2 bash-2.01.1/tests/array.tests bash-2.02/tests/array.tests *** bash-2.01.1/tests/array.tests Wed Mar 19 10:32:48 1997 --- bash-2.02/tests/array.tests Mon Nov 17 14:38:10 1997 *************** *** 63,68 **** --- 63,73 ---- 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")' *************** *** 113,116 **** --- 118,130 ---- echo ${rv[@]} + # the variable should be converted to an array when `read -a' is done + vv=1 + read -a vv < + argv[1] = + argv[1] = + argv[1] = + argv[2] = + argv[1] = + argv[2] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <1> + argv[1] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <5> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <5> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <1> + argv[1] = + argv[2] = + argv[3] = + argv[4] = + argv[5] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[2] = + argv[3] = + argv[1] = + argv[1] = + argv[2] = + argv[3] = + argv[4] = + argv[5] = + argv[1] = + argv[2] = + argv[3] = + argv[4] = + argv[5] = + argv[1] = + argv[2] = + argv[3] = + argv[1] = + argv[1] = + argv[2] = + argv[3] = + argv[1] = + argv[2] = + argv[3] = + argv[1] = diff -Nrc2 bash-2.01.1/tests/builtins.right bash-2.02/tests/builtins.right *** bash-2.01.1/tests/builtins.right Thu Mar 13 14:35:48 1997 --- bash-2.02/tests/builtins.right Mon Nov 17 12:24:48 1997 *************** *** 1,2 **** --- 1,4 ---- + alias: 0 + alias: 0 a end-1 *************** *** 48,51 **** --- 50,55 ---- 002 u=rwx,g=rwx,o=rx + umask 002 + umask -S u=rwx,g=rwx,o=rx u=rwx,g=rwx,o=rwx enable . *************** *** 82,88 **** --- 86,94 ---- enable test worked specialname + -specialname FOO=BAR FOO=BAR hash: hash table empty + 0 AVAR foo *************** *** 100,103 **** --- 106,112 ---- /tmp/bash-dir-a /tmp/bash-dir-a + ./source5.sub: /tmp/source-notthere: No such file or directory + after bad source 1 + ./source5.sub: /tmp/source-notthere: No such file or directory AVAR foo *************** *** 108,113 **** --- 117,127 ---- AVAR foo + declare -x foo="" + declare -x FOO="\$\$" + ./builtins.tests: declare: FOO: not found + declare -x FOO="\$\$" ok ok ./builtins.tests: kill: bad signal number: 4096 1 + ./builtins.tests: exit: bad non-numeric arg `status' diff -Nrc2 bash-2.01.1/tests/builtins.tests bash-2.02/tests/builtins.tests *** bash-2.01.1/tests/builtins.tests Mon Mar 17 13:00:34 1997 --- bash-2.02/tests/builtins.tests Mon Nov 17 12:24:16 1997 *************** *** 5,8 **** --- 5,20 ---- ulimit -c 0 2>/dev/null + # alias/unalias tests + + unalias -a + # this should return success, according to POSIX.2 + alias + echo alias: $? + alias foo=bar + unalias foo + # this had better return success, according to POSIX.2 + alias + echo alias: $? + # check that break breaks loops for i in a b c; do echo $i; break; echo bad-$i; done *************** *** 81,84 **** --- 93,98 ---- umask umask -S + umask -p + umask -p -S umask 0 umask -S *************** *** 108,115 **** # test options to exec (exec -a specialname ${THIS_SH} -c 'echo $0' ) # test `clean' environment. if /bin/sh is bash, and the script version of # printenv is run, there will be variables in the environment that bash ! # sets on startup. ! (export FOO=BAR ; exec -c printenv ) | grep FOO (FOO=BAR exec -c printenv ) | grep FOO --- 122,130 ---- # test options to exec (exec -a specialname ${THIS_SH} -c 'echo $0' ) + (exec -l -a specialname ${THIS_SH} -c 'echo $0' ) # test `clean' environment. if /bin/sh is bash, and the script version of # printenv is run, there will be variables in the environment that bash ! # sets on startup. Also test code that prefixes argv[0] with a dash. ! (export FOO=BAR ; exec -c -l printenv ) | grep FOO (FOO=BAR exec -c printenv ) | grep FOO *************** *** 121,136 **** hash # check out source/. AVAR=AVAR ! . ./source.sub1 ! AVAR=foo . ./source.sub1 ! . ./source.sub2 echo $? set -- a b c ! . ./source.sub3 # make sure source with arguments does not change the shell's positional --- 136,162 ---- hash + # this had better succeed, since command -p guarantees we will find the + # standard utilties + command -p hash rm + # check out source/. + # sourcing a zero-length-file had better not be an error + rm -f /tmp/zero-length-file + cp /dev/null /tmp/zero-length-file + . /tmp/zero-length-file + echo $? + rm /tmp/zero-length-file + AVAR=AVAR ! . ./source1.sub ! AVAR=foo . ./source1.sub ! . ./source2.sub echo $? set -- a b c ! . ./source3.sub # make sure source with arguments does not change the shell's positional *************** *** 138,142 **** # positional parameters echo "$@" ! . ./source.sub3 x y z echo "$@" --- 164,168 ---- # positional parameters echo "$@" ! . ./source3.sub x y z echo "$@" *************** *** 147,151 **** echo "$@" shopt -u sourcepath ! . source.sub4 echo "$@" --- 173,177 ---- echo "$@" shopt -u sourcepath ! . source4.sub echo "$@" *************** *** 154,158 **** set -- a b c echo "$@" ! . source.sub4 x y z echo "$@" --- 180,184 ---- set -- a b c echo "$@" ! . source4.sub x y z echo "$@" *************** *** 160,163 **** --- 186,192 ---- ${THIS_SH} ./builtins.sub1 + # test behavior of `.' when given a non-existant file argument + ${THIS_SH} ./source5.sub + # in posix mode, assignment statements preceding special builtins are # reflected in the shell environment. `.' and `eval' need special-case *************** *** 165,169 **** set -o posix echo $AVAR ! AVAR=foo . ./source.sub1 echo $AVAR --- 194,198 ---- set -o posix echo $AVAR ! AVAR=foo . ./source1.sub echo $AVAR *************** *** 177,183 **** AVAR=foo : echo $AVAR # test out kill -l. bash versions prior to 2.01 did `kill -l num' wrong - set +o posix sigone=$(kill -l | sed -n 's:^ 1) *\([^ ]*\)[ ].*$:\1:p') --- 206,229 ---- AVAR=foo : echo $AVAR + set +o posix + + # but assignment statements preceding `export' are always reflected in + # the environment + foo="" export foo + declare -p foo + unset foo + + # assignment statements preceding `declare' should be displayed correctly, + # but not persist after the command + FOO='$$' declare -p FOO + declare -p FOO + unset FOO + + # except for `declare -x', which should be equivalent to `export' + FOO='$$' declare -x FOO + declare -p FOO + unset FOO # test out kill -l. bash versions prior to 2.01 did `kill -l num' wrong sigone=$(kill -l | sed -n 's:^ 1) *\([^ ]*\)[ ].*$:\1:p') *************** *** 187,190 **** --- 233,243 ---- esac + # kill -l and trap -l should display exactly the same output + sigonea=$(trap -l | sed -n 's:^ 1) *\([^ ]*\)[ ].*$:\1:p') + + if [ "$sigone" != "$sigonea" ]; then + echo oops -- kill -l and trap -l differ + fi + # POSIX.2 says that exit statuses > 128 are mapped to signal names by # subtracting 128 so you can find out what signal killed a process *************** *** 200,201 **** --- 253,259 ---- # kill -l NAME should return the signal number kill -l ${sigone/SIG/} + + # this must be last -- it is a fatal error + exit status + + echo after bad exit diff -Nrc2 bash-2.01.1/tests/cond.right bash-2.02/tests/cond.right *** bash-2.01.1/tests/cond.right Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/cond.right Tue Nov 18 13:55:04 1997 *************** *** 0 **** --- 1,31 ---- + returns: 0 + returns: 0 + returns: 1 + returns: 0 + returns: 1 + returns: 0 + returns: 0 + returns: 1 + returns: 1 + returns: 1 + returns: 1 + returns: 0 + returns: 0 + returns: 0 + returns: 1 + returns: 0 + returns: 1 + returns: 0 + returns: 1 + returns: 1 + returns: 0 + ./cond.tests: [[: 4+: syntax error: operand expected (error token is "+") + returns: 1 + returns: 0 + returns: 0 + returns: 1 + returns: 0 + returns: 0 + returns: 1 + returns: 0 + ok diff -Nrc2 bash-2.01.1/tests/cond.tests bash-2.02/tests/cond.tests *** bash-2.01.1/tests/cond.tests Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/cond.tests Tue Nov 18 13:54:35 1997 *************** *** 0 **** --- 1,142 ---- + # + # the test/[ code is tested elsewhere, and the [[...]] just uses the same + # code. this tests the special features of [[...]] + # + TDIR=/usr/homes/chet + + # this one is straight out of the ksh88 book + [[ foo > bar && $PWD -ef . ]] + echo returns: $? + + # [[ x ]] is equivalent to [[ -n x ]] + [[ x ]] + echo returns: $? + + # [[ ! x ]] is equivalent to [[ ! -n x ]] + [[ ! x ]] + echo returns: $? + + # ! binds tighter than test/[ -- it binds to a term, not an expression + [[ ! x || x ]] + echo returns: $? + + # unset variables don't need to be quoted + [[ -n $UNSET ]] + echo returns: $? + + [[ -z $UNSET ]] + echo returns: $? + + # the ==/= and != operators do pattern matching + [[ $TDIR == /usr/homes/* ]] + echo returns: $? + + # ...but you can quote any part of the pattern to have it matched as a string + [[ $TDIR == /usr/homes/\* ]] + echo returns: $? + + [[ $TDIR == '/usr/homes/*' ]] + echo returns: $? + + # if the first part of && fails, the second is not executed + [[ -n $UNSET && $UNSET == foo ]] + echo returns: $? + + [[ -z $UNSET && $UNSET == foo ]] + echo returns: $? + + # if the first part of || succeeds, the second is not executed + [[ -z $UNSET || -d $PWD ]] + echo returns: $? + + # if the rhs were executed, it would be an error + [[ -n $TDIR || $HOME -ef ${H*} ]] + echo returns: $? + + [[ -n $TDIR && -z $UNSET || $HOME -ef ${H*} ]] + echo returns: $? + + # && has a higher parsing precedence than || + [[ -n $TDIR && -n $UNSET || $TDIR -ef . ]] + echo returns: $? + + # ...but expressions in parentheses may be used to override precedence rules + [[ -n $TDIR || -n $UNSET && $PWD -ef xyz ]] + echo returns: $? + + [[ ( -n $TDIR || -n $UNSET ) && $PWD -ef xyz ]] + echo returns: $? + + # some arithmetic tests for completeness -- see what happens with missing + # operands, bad expressions, makes sure arguments are evaluated as + # arithmetic expressions, etc. + + unset IVAR A + [[ 7 -gt $IVAR ]] + echo returns: $? + + [[ $IVAR -gt 7 ]] + echo returns: $? + + IVAR=4 + [[ $IVAR -gt 7 ]] + echo returns: $? + + [[ 7 -eq 4+3 ]] + echo returns: $? + + [[ 7 -eq 4+ ]] + echo returns: $? + + IVAR=4+3 + [[ $IVAR -eq 7 ]] + echo returns: $? + + A=7 + [[ $IVAR -eq A ]] + echo returns: $? + + unset IVAR A + + # more pattern matching tests + + [[ $filename == *.c ]] + echo returns: $? + + filename=patmatch.c + + [[ $filename == *.c ]] + echo returns: $? + + # the extended globbing features may be used when matching patterns + shopt -s extglob + + arg=-7 + + [[ $arg == -+([0-9]) ]] + echo returns: $? + + arg=-H + + [[ $arg == -+([0-9]) ]] + echo returns: $? + + arg=+4 + [[ $arg == ++([0-9]) ]] + echo returns: $? + + # make sure the null string is never matched if the string is not null + STR=file.c + PAT= + + if [[ $STR = $PAT ]]; then + echo oops + fi + + # but that if the string is null, a null pattern is matched correctly + STR= + PAT= + + if [[ $STR = $PAT ]]; then + echo ok + fi diff -Nrc2 bash-2.01.1/tests/dirstack.right bash-2.02/tests/dirstack.right *** bash-2.01.1/tests/dirstack.right Mon Mar 3 13:04:11 1997 --- bash-2.02/tests/dirstack.right Wed Dec 31 19:00:00 1969 *************** *** 1,51 **** - ./dirstack.tests: pushd: no other directory - ./dirstack.tests: popd: directory stack empty - ./dirstack.tests: pushd: -m: bad argument - pushd: usage: pushd [dir | +N | -N] [-n] - ./dirstack.tests: popd: -m: bad argument - popd: usage: popd [+N | -N] [-n] - ./dirstack.tests: dirs: -m: bad argument - dirs: usage: dirs [-clpv] [+N] [-N] - ok - /usr / - /usr / - /usr / - /usr / - /usr / - / - /usr / - /etc /usr / - /etc /usr / - /etc /usr / - 0 /etc - 1 /usr - 2 / - /usr /etc / - /etc /usr / - /tmp /etc /usr / - /tmp - /tmp - /usr - /usr - ./dirstack.tests: dirs: 9: bad directory stack index - ./dirstack.tests: dirs: 9: bad directory stack index - ./dirstack.tests: pushd: +9: bad directory stack index - ./dirstack.tests: pushd: -9: bad directory stack index - ./dirstack.tests: popd: +9: bad directory stack index - ./dirstack.tests: popd: -9: bad directory stack index - /tmp /etc / - /tmp /etc / - /tmp /etc / - /tmp /usr /etc / - /tmp - /tmp /usr /etc / - /tmp /usr /etc / - /tmp - /tmp /bin /etc / - /tmp - /tmp /bin / - /tmp - /bin / /tmp - /bin / /tmp - /bin - /bin --- 0 ---- diff -Nrc2 bash-2.01.1/tests/dirstack.tests bash-2.02/tests/dirstack.tests *** bash-2.01.1/tests/dirstack.tests Mon Mar 3 13:12:09 1997 --- bash-2.02/tests/dirstack.tests Wed Dec 31 19:00:00 1969 *************** *** 1,79 **** - dirs -c - # errors -- empty stack - pushd - popd - - # errors -- bad numeric arguments -- should not cause the script to exit - pushd -m - popd -m - dirs -m - - MYDIR=$PWD - unalias cd 2>/dev/null - - unalias -a - - command cd -P / - - case "$OLDPWD" in - $MYDIR) echo ok ;; - *) echo oops -- bad \$OLDPWD ;; - esac - - pushd /usr - echo $PWD $OLDPWD - dirs - echo ${DIRSTACK[@]} - - # this should not change the directory stack at all - pushd -n +0 - dirs - - popd - pushd /usr - - pushd /etc - dirs - dirs -l - dirs -v - - # two consecutive `pushd's should swap the top two stack elements, then - # swap them back, leaving the stack intact - pushd - pushd - - pushd /tmp - echo ${DIRSTACK[0]} ; dirs +0 - echo ${DIRSTACK[2]} ; dirs +2 - - # these should be errors, but not affect the directory stack - dirs +9; dirs -9 - pushd +9 ; pushd -9 - popd +9 ; popd -9 - - popd -n +2 - dirs - echo ${DIRSTACK[@]} - - pushd -n /usr - echo $PWD - dirs - echo ${DIRSTACK[@]} - - builtin pwd - - DIRSTACK[1]=/bin - dirs - - builtin pwd - popd +2 - builtin pwd -L - pushd -1 - dirs - echo ${DIRSTACK[0]} - - dirs -c - dirs - - # this is for the benefit of pure coverage - cd $MYDIR --- 0 ---- diff -Nrc2 bash-2.01.1/tests/dollar-at-star bash-2.02/tests/dollar-at-star *** bash-2.01.1/tests/dollar-at-star Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/dollar-at-star Tue Aug 26 10:38:04 1997 *************** *** 0 **** --- 1,119 ---- + # first, let's start with the basics + + recho "$@" + recho "$*" + + recho $@ + recho $* + + set a b + + recho "$*" + + # If IFS is null, the parameters are joined without separators + IFS='' + recho "$*" + + # If IFS is unset, the parameters are separated by spaces + unset IFS + recho "${*}" + + recho "$@" + recho $@ + + IFS='/' + set bob 'tom dick harry' joe + set $* + recho $# + recho $1 + recho $2 + recho $3 + + set bob 'tom dick harry' joe + set ${*} + recho $# + recho $1 + recho $2 + recho $3 + + set bob 'tom dick harry' joe + set $@ + recho $# + recho $1 + recho $2 + recho $3 + + set bob 'tom dick harry' joe + set ${@} + recho $# + recho $1 + recho $2 + recho $3 + + # according to POSIX.2, unquoted $* should expand to multiple words if + # $IFS is null, just like unquoted $@ + IFS='' + set bob 'tom dick harry' joe + set $* + recho $# + recho $1 + recho $2 + recho $3 + + set bob 'tom dick harry' joe + set $@ + recho $# + recho $1 + recho $2 + recho $3 + + # if IFS is unset, the individual positional parameters are split on + # " \t\n" if $* or $@ are unquoted + unset IFS + set bob 'tom dick harry' joe + set $* + recho $# + recho $1 + recho $2 + recho $3 + + set bob 'tom dick harry' joe + set $@ + recho $# + recho $1 + recho $2 + recho $3 + + # but not for "$@" or "$*" + set bob 'tom dick harry' joe + set "$*" + recho $# + recho $1 + recho $2 + recho $3 + + set bob 'tom dick harry' joe + set "$@" + recho $# + recho $1 + recho $2 + recho $3 + + # POSIX.2 says these should both expand the positional parameters + # to multiple words + set a b c d e + IFS="" + recho $@ + recho "$@" + + # this example is straight from the POSIX.2 rationale + set foo bar bam + + recho "$@" + recho "$*" + + unset IFS + + recho "$@" + recho $@ + recho "$*" diff -Nrc2 bash-2.01.1/tests/dollar-at.sh bash-2.02/tests/dollar-at.sh *** bash-2.01.1/tests/dollar-at.sh Wed Jun 15 15:56:25 1994 --- bash-2.02/tests/dollar-at.sh Wed Dec 31 19:00:00 1969 *************** *** 1 **** - recho "$@" --- 0 ---- diff -Nrc2 bash-2.01.1/tests/dollar-star.sh bash-2.02/tests/dollar-star.sh *** bash-2.01.1/tests/dollar-star.sh Tue Feb 25 14:06:36 1997 --- bash-2.02/tests/dollar-star.sh Wed Dec 31 19:00:00 1969 *************** *** 1,9 **** - recho "$*" - - # If IFS is null, the parameters are joined without separators - IFS='' - recho "$*" - - # If IFS is unset, the parameters are separated by spaces - unset IFS - recho "${*}" --- 0 ---- diff -Nrc2 bash-2.01.1/tests/dollar.right bash-2.02/tests/dollar.right *** bash-2.01.1/tests/dollar.right Tue Feb 25 14:05:53 1997 --- bash-2.02/tests/dollar.right Tue Aug 26 10:38:13 1997 *************** *** 1,2 **** --- 1,3 ---- + argv[1] = <> argv[1] = argv[1] = *************** *** 4,5 **** --- 5,73 ---- argv[1] = argv[2] = + argv[1] = + argv[2] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <5> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <5> + argv[1] = + argv[1] = + argv[1] = + argv[1] = <1> + argv[1] = + argv[2] = + argv[3] = + argv[4] = + argv[5] = + argv[1] = <3> + argv[1] = + argv[1] = + argv[2] = + argv[3] = + argv[1] = + argv[1] = + argv[2] = + argv[3] = + argv[4] = + argv[5] = + argv[1] = + argv[2] = + argv[3] = + argv[4] = + argv[5] = + argv[1] = + argv[2] = + argv[3] = + argv[1] = + argv[1] = + argv[2] = + argv[3] = + argv[1] = + argv[2] = + argv[3] = + argv[1] = diff -Nrc2 bash-2.01.1/tests/dstack.right bash-2.02/tests/dstack.right *** bash-2.01.1/tests/dstack.right Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/dstack.right Fri Nov 14 12:31:05 1997 *************** *** 0 **** --- 1,55 ---- + ./dstack.tests: pushd: /tmp/xxx-notthere: No such file or directory + ./dstack.tests: pushd: no other directory + ./dstack.tests: popd: directory stack empty + ./dstack.tests: pushd: -m: bad argument + pushd: usage: pushd [dir | +N | -N] [-n] + ./dstack.tests: popd: -m: bad argument + popd: usage: popd [+N | -N] [-n] + ./dstack.tests: dirs: -m: bad argument + dirs: usage: dirs [-clpv] [+N] [-N] + ./dstack.tests: dirs: unknown option: 7 + dirs: usage: dirs [-clpv] [+N] [-N] + / + ok + /usr / + /usr / + /usr / + /usr / + /usr / + / + /usr / + /etc /usr / + /etc /usr / + /etc /usr / + 0 /etc + 1 /usr + 2 / + /usr /etc / + /etc /usr / + /tmp /etc /usr / + /tmp + /tmp + /usr + /usr + ./dstack.tests: dirs: 9: bad directory stack index + ./dstack.tests: dirs: 9: bad directory stack index + ./dstack.tests: pushd: +9: bad directory stack index + ./dstack.tests: pushd: -9: bad directory stack index + ./dstack.tests: popd: +9: bad directory stack index + ./dstack.tests: popd: -9: bad directory stack index + /tmp /etc / + /tmp /etc / + /tmp /etc / + /tmp /usr /etc / + /tmp + /tmp /usr /etc / + /tmp /usr /etc / + /tmp + /tmp /bin /etc / + /tmp + /tmp /bin / + /tmp + /bin / /tmp + /bin / /tmp + /bin + /bin diff -Nrc2 bash-2.01.1/tests/dstack.tests bash-2.02/tests/dstack.tests *** bash-2.01.1/tests/dstack.tests Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/dstack.tests Fri Nov 14 12:31:36 1997 *************** *** 0 **** --- 1,87 ---- + export LC_ALL=C + export LANG=C + + dirs -c + # error -- nonexistant directory + pushd /tmp/xxx-notthere + + # errors -- empty stack + pushd + popd + + # errors -- bad numeric arguments -- should not cause the script to exit + pushd -m + popd -m + dirs -m + dirs 7 + + MYDIR=$PWD + unalias cd 2>/dev/null + + unalias -a + + command cd -P / + command pwd -P # better be `/' + + case "$OLDPWD" in + $MYDIR) echo ok ;; + *) echo oops -- bad \$OLDPWD ;; + esac + + pushd /usr + echo $PWD $OLDPWD + dirs + echo ${DIRSTACK[@]} + + # this should not change the directory stack at all + pushd -n +0 + dirs + + popd + pushd /usr + + pushd /etc + dirs + dirs -l + dirs -v + + # two consecutive `pushd's should swap the top two stack elements, then + # swap them back, leaving the stack intact + pushd + pushd + + pushd /tmp + echo ${DIRSTACK[0]} ; dirs +0 + echo ${DIRSTACK[2]} ; dirs +2 + + # these should be errors, but not affect the directory stack + dirs +9; dirs -9 + pushd +9 ; pushd -9 + popd +9 ; popd -9 + + popd -n +2 + dirs + echo ${DIRSTACK[@]} + + pushd -n /usr + echo $PWD + dirs + echo ${DIRSTACK[@]} + + builtin pwd + + DIRSTACK[1]=/bin + dirs + + builtin pwd + popd +2 + builtin pwd -L + pushd -1 + dirs + echo ${DIRSTACK[0]} + + dirs -c + dirs + + # this is for the benefit of pure coverage + cd $MYDIR diff -Nrc2 bash-2.01.1/tests/dstack2.right bash-2.02/tests/dstack2.right *** bash-2.01.1/tests/dstack2.right Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/dstack2.right Fri Nov 14 12:28:21 1997 *************** *** 0 **** --- 1,24 ---- + expect ~1 + ~1 + /usr / + /tmp /usr / + /tmp /usr / + these lines should be the same + /tmp + /tmp /tmp + these lines should be the same + /usr + /usr /usr + these lines should be the same + / + / / + these lines should be the same + /tmp + /tmp /tmp + these lines should be the same + /usr + /usr /usr + 1 /usr + these lines should be the same + / + / / diff -Nrc2 bash-2.01.1/tests/dstack2.tests bash-2.02/tests/dstack2.tests *** bash-2.01.1/tests/dstack2.tests Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/dstack2.tests Fri Nov 14 12:27:22 1997 *************** *** 0 **** --- 1,33 ---- + cd / + + echo expect '~1' + echo ~1 + + pushd /usr + pushd /tmp + dirs + + echo these lines should be the same + dirs +0 + echo ~0 ${DIRSTACK[0]} + echo these lines should be the same + dirs +1 + echo ~1 ${DIRSTACK[1]} + echo these lines should be the same + dirs +2 + echo ~2 ${DIRSTACK[2]} + + NDIRS=$(( ${#DIRSTACK[@]} - 1 )) + + echo these lines should be the same + dirs -2 + echo ~-2 ${DIRSTACK[NDIRS-2]} + + echo these lines should be the same + dirs -1 + echo ~-1 ${DIRSTACK[NDIRS-1]} + dirs -v -1 + + echo these lines should be the same + dirs -0 + echo ~-0 ${DIRSTACK[NDIRS]} diff -Nrc2 bash-2.01.1/tests/errors.right bash-2.02/tests/errors.right *** bash-2.01.1/tests/errors.right Mon Mar 3 13:36:47 1997 --- bash-2.02/tests/errors.right Mon Nov 17 14:05:35 1997 *************** *** 1,9 **** --- 1,18 ---- + ./errors.tests: alias: illegal option: -x + alias: usage: alias [-p] [name[=value] ... ] + ./errors.tests: unalias: illegal option: -x + unalias: usage: unalias [-a] [name ...] + ./errors.tests: alias: `hoowah' not found + ./errors.tests: unalias: `hoowah': not an alias ./errors.tests: `1': not a valid identifier declare -fr func ./errors.tests: func: readonly function + ./errors.tests: unset: illegal option: -x + unset: usage: unset [-f] [-v] [name ...] ./errors.tests: unset: func: cannot unset: readonly function ./errors.tests: declare: func: readonly function ./errors.tests: unset: XPATH: cannot unset: readonly variable ./errors.tests: unset: `/bin/sh': not a valid identifier + ./errors.tests: unset: cannot simultaneously unset a function and a variable ./errors.tests: declare: unknown option: `-z' declare: usage: declare [-afFrxi] [-p] name[=value] ... *************** *** 11,14 **** --- 20,25 ---- ./errors.tests: declare: `/bin/sh': not a valid identifier ./errors.tests: declare: cannot use `-f' to make functions + ./errors.tests: exec: illegal option: -i + exec: usage: exec [-cl] [-a name] file [redirection ...] ./errors.tests: export: XPATH: not a function ./errors.tests: break: only meaningful in a `for', `while', or `until' loop *************** *** 18,22 **** --- 29,36 ---- ./errors.tests: let: expression expected ./errors.tests: local: can only be used in a function + ./errors.tests: logout: not login shell: use `exit' ./errors.tests: hash: notthere: not found + ./errors.tests: hash: illegal option: -v + hash: usage: hash [-r] [-p pathname] [name ...] ./errors.tests: hash: hashing disabled ./errors.tests: export: `AA[4]': not a valid identifier *************** *** 24,27 **** --- 38,43 ---- ./errors.tests: [-2]: bad array subscript ./errors.tests: AA: readonly variable + ./errors.tests: AA: readonly variable + ./errors.tests: readonly: ZZZ: cannot assign to array variables in this way ./errors.tests: shift: shift count must be <= $# ./errors.tests: shift: shift count must be >= 0 *************** *** 31,36 **** ./errors.tests: umask: bad character in symbolic mode: : ./errors.tests: umask: bad symbolic mode operator: : ! ./errors.tests: umask: illegal option: -p ! umask: usage: umask [-S] [mode] ./errors.tests: VAR: readonly variable ./errors.tests: declare: VAR: readonly variable --- 47,52 ---- ./errors.tests: umask: bad character in symbolic mode: : ./errors.tests: umask: bad symbolic mode operator: : ! ./errors.tests: umask: illegal option: -i ! umask: usage: umask [-p] [-S] [mode] ./errors.tests: VAR: readonly variable ./errors.tests: declare: VAR: readonly variable *************** *** 42,46 **** --- 58,65 ---- ./errors.tests: command substitution: line 1: ` for z in 1 2 3; done ' ./errors.tests: cd: HOME not set + ./errors.tests: cd: /tmp/xyz.bash: No such file or directory ./errors.tests: cd: OLDPWD not set + ./errors.tests: cd: /bin/sh: Not a directory + ./errors.tests: cd: /tmp/cd-notthere: No such file or directory ./errors.tests: .: filename argument required .: usage: . filename *************** *** 53,62 **** --- 72,87 ---- ./errors.tests: enable: bash: not a shell builtin ./errors.tests: shopt: cannot set and unset shell options simultaneously + ./errors.tests: read: illegal option: -t + read: usage: read [-r] [-p prompt] [-a array] [-e] [name ...] ./errors.tests: read: `/bin/sh': not a valid identifier ./errors.tests: VAR: readonly variable + ./errors.tests: readonly: illegal option: -x + readonly: usage: readonly [-anf] [name ...] or readonly -p ./errors.tests: eval: illegal option: -i eval: usage: eval [arg ...] ./errors.tests: command: illegal option: -i command: usage: command [-pVv] command [arg ...] + ./errors.tests: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0") + ./errors.tests: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0") ./errors.tests: trap: NOSIG: not a signal specification ./errors.tests: trap: illegal option: -s *************** *** 71,73 **** --- 96,101 ---- ./errors.tests: kill: -s requires an argument ./errors.tests: kill: bad signal spec `S' + ./errors.tests: kill: `': not a pid or valid job spec + kill: usage: kill [-s sigspec | -n signum | -sigspec] [pid | job]... or kill -l [sigspec] + ./errors.tests: set: trackall: unknown option name ./errors.tests: `!!': not a valid identifier diff -Nrc2 bash-2.01.1/tests/errors.tests bash-2.02/tests/errors.tests *** bash-2.01.1/tests/errors.tests Mon Mar 3 13:36:32 1997 --- bash-2.02/tests/errors.tests Wed Dec 3 17:33:36 1997 *************** *** 11,14 **** --- 11,23 ---- set +o posix + # various alias/unalias errors + + # at some point, this may mean to `export' an alias, like ksh, but + # for now it is an error + alias -x foo=barz + unalias -x fooaha + alias hoowah + unalias hoowah + # the iteration variable must be a valid identifier for 1 in a b c; do echo $1; done *************** *** 27,30 **** --- 36,42 ---- } + # bad option + unset -x func + # cannot unset readonly functions or variables unset -f func *************** *** 40,43 **** --- 52,58 ---- unset /bin/sh + # cannot unset function and variable at the same time + unset -f -v SHELL + # bad option declare -z *************** *** 50,53 **** --- 65,71 ---- declare -f func='() { echo "this is func"; }' + # bad option to exec -- this should not exit the script + exec -i /bin/sh + # try to export -f something that is not a function -- this should be # an error, not create an `invisible function' *************** *** 75,81 **** --- 93,105 ---- local + # logout of a non-login shell is an error + logout + # try to hash a non-existant command hash notthere + # bad option to hash, although it may mean `verbose' at some future point + hash -v + # turn off hashing, then try to hash something set +o hashall *************** *** 93,96 **** --- 117,127 ---- AA=( one two three ) + # make sure `readonly -n' doesn't turn off readonly status + readonly -n AA + AA=(one two three) + + # try to assign a readonly array with bad assignment syntax + readonly -a ZZZ=bbb + # bad counts to `shift' shopt -s shift_verbose *************** *** 106,112 **** umask -S u=rwx:g=rwx:o=rx >/dev/null # 002 umask -S u:rwx,g:rwx,o:rx >/dev/null # 002 ! # this may behave identically to umask without arguments in the future, ! # but for now it is an error ! umask -p # assignment to a readonly variable in environment --- 137,143 ---- umask -S u=rwx:g=rwx:o=rx >/dev/null # 002 umask -S u:rwx,g:rwx,o:rx >/dev/null # 002 ! ! # at some point, this may mean `invert', but for now it is an error ! umask -i # assignment to a readonly variable in environment *************** *** 130,134 **** # various `cd' errors ( unset HOME ; cd ) ! ( unset OLDPWD ; cd - ) # various `source/.' errors --- 161,170 ---- # various `cd' errors ( unset HOME ; cd ) ! ( HOME=/tmp/xyz.bash ; cd ) ! # errors from cd ! cd - ! cd /bin/sh # error - not a directory ! OLDPWD=/tmp/cd-notthere ! cd - # various `source/.' errors *************** *** 148,151 **** --- 184,190 ---- shopt -s -u checkhash + # someday, this may give `read' a timeout, but for now it is an error + read -t var < /dev/null + # try to read into an invalid identifier read /bin/sh < /dev/null *************** *** 154,161 **** --- 193,207 ---- read VAR < /dev/null + # bad option to readonly/export + readonly -x foo + # someday these may mean something, but for now they're errors eval -i "echo $-" command -i "echo $-" + # this caused a core dump in bash-2.01 (fixed in bash-2.01.1) + eval echo \$[/bin/sh + 0] + eval echo '$((/bin/sh + 0))' + # error to list trap for an unknown signal trap -p NOSIG *************** *** 192,195 **** --- 238,248 ---- # bad argument kill -S + # null argument + kill -INT '' + # argument required + kill -INT + + # bad shell option names + set -o trackall # bash is not ksh # this must be last! diff -Nrc2 bash-2.01.1/tests/exec.right bash-2.02/tests/exec.right *** bash-2.01.1/tests/exec.right Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/exec.right Fri Nov 14 12:14:00 1997 *************** *** 0 **** --- 1,39 ---- + before exec1.sub: one two three + calling exec1.sub + aa bb cc dd ee + after exec1.sub with args: 0 + + after exec1.sub without args: 0 + ./execscript: notthere: command not found + 127 + notthere: notthere: No such file or directory + 127 + /bin/sh: /bin/sh: cannot execute binary file + 126 + ./execscript: /: is a directory + 126 + /: /: cannot execute binary file + 126 + ./execscript: .: /: is a directory + 1 + 126 + ./execscript: .: /dev/null: not a regular file + 1 + this is bashenv + ./exec3.sub: /tmp/bash-notthere: No such file or directory + ./exec3.sub: exec: /tmp/bash-notthere: cannot execute: No such file or directory + 126 + ./execscript: notthere: No such file or directory + 127 + ./execscript: notthere: No such file or directory + 127 + ./execscript: notthere: No such file or directory + 127 + this is sh + this is sh + unset + ok + 5 + ./exec5.sub: exec: bash-notthere: not found + 127 + this is ohio-state diff -Nrc2 bash-2.01.1/tests/exec1.sub bash-2.02/tests/exec1.sub *** bash-2.01.1/tests/exec1.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/exec1.sub Wed Feb 19 14:06:50 1997 *************** *** 0 **** --- 1 ---- + echo "$@" diff -Nrc2 bash-2.01.1/tests/exec2.sub bash-2.02/tests/exec2.sub *** bash-2.01.1/tests/exec2.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/exec2.sub Tue Feb 25 13:26:25 1997 *************** *** 0 **** --- 1,5 ---- + # make sure an exit command in an exit trap sets the shell's exit status + trap - 0 + trap 'exit 5' 0 + + exit 0 diff -Nrc2 bash-2.01.1/tests/exec3.sub bash-2.02/tests/exec3.sub *** bash-2.01.1/tests/exec3.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/exec3.sub Mon Mar 3 12:58:01 1997 *************** *** 0 **** --- 1,6 ---- + shopt -s execfail + + exec /tmp/bash-notthere + # make sure we're still around + echo $? + diff -Nrc2 bash-2.01.1/tests/exec4.sub bash-2.02/tests/exec4.sub *** bash-2.01.1/tests/exec4.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/exec4.sub Mon Mar 3 13:00:22 1997 *************** *** 0 **** --- 1,8 ---- + # let's test out the noexec code + set -n + + fail + whoops + wow + + set +n diff -Nrc2 bash-2.01.1/tests/exec5.sub bash-2.02/tests/exec5.sub *** bash-2.01.1/tests/exec5.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/exec5.sub Fri Nov 14 12:13:25 1997 *************** *** 0 **** --- 1,9 ---- + # try exec'ing a command that cannot be found in $PATH + shopt -s execfail + + exec bash-notthere + # make sure we're still around + echo $? + + # now we need to go away, but this should echo 'this is ohio-state' + exec -a ohio-state ${THIS_SH} -c 'echo this is $0' diff -Nrc2 bash-2.01.1/tests/execscript bash-2.02/tests/execscript *** bash-2.01.1/tests/execscript Tue May 27 10:48:36 1997 --- bash-2.02/tests/execscript Fri Nov 14 12:07:15 1997 *************** *** 3,12 **** set -- one two three ! echo before execscript.sub: "$@" ! echo calling execscript.sub ! ./execscript.sub aa bb cc dd ee ! echo after execscript.sub with args: $? ! ./execscript.sub ! echo after execscript.sub without args: $? # set up a fixed path so we know notthere will not be found --- 3,12 ---- set -- one two three ! echo before exec1.sub: "$@" ! echo calling exec1.sub ! ./exec1.sub aa bb cc dd ee ! echo after exec1.sub with args: $? ! ./exec1.sub ! echo after exec1.sub without args: $? # set up a fixed path so we know notthere will not be found *************** *** 45,49 **** echo echo this is bashenv > /tmp/bashenv export BASH_ENV=/tmp/bashenv ! ${THIS_SH} ./execscript.sub3 rm -f /tmp/bashenv unset BASH_ENV --- 45,49 ---- echo echo this is bashenv > /tmp/bashenv export BASH_ENV=/tmp/bashenv ! ${THIS_SH} ./exec3.sub rm -f /tmp/bashenv unset BASH_ENV *************** *** 73,78 **** echo "echo ok" | ${THIS_SH} -t ! ${THIS_SH} ./execscript.sub2 echo $? ! ${THIS_SH} ./execscript.sub4 --- 73,81 ---- echo "echo ok" | ${THIS_SH} -t ! ${THIS_SH} ./exec2.sub echo $? ! ${THIS_SH} ./exec4.sub ! ! # try exec'ing a command that cannot be found in $PATH ! ${THIS_SH} ./exec5.sub diff -Nrc2 bash-2.01.1/tests/execscript.right bash-2.02/tests/execscript.right *** bash-2.01.1/tests/execscript.right Mon Mar 3 13:15:03 1997 --- bash-2.02/tests/execscript.right Wed Dec 31 19:00:00 1969 *************** *** 1,36 **** - before execscript.sub: one two three - calling execscript.sub - aa bb cc dd ee - after execscript.sub with args: 0 - - after execscript.sub without args: 0 - ./execscript: notthere: command not found - 127 - notthere: notthere: No such file or directory - 127 - /bin/sh: /bin/sh: cannot execute binary file - 126 - ./execscript: /: is a directory - 126 - /: /: cannot execute binary file - 126 - ./execscript: .: /: is a directory - 1 - 126 - ./execscript: .: /dev/null: not a regular file - 1 - this is bashenv - ./execscript.sub3: /tmp/bash-notthere: No such file or directory - ./execscript.sub3: exec: /tmp/bash-notthere: cannot execute: No such file or directory - 126 - ./execscript: notthere: No such file or directory - 127 - ./execscript: notthere: No such file or directory - 127 - ./execscript: notthere: No such file or directory - 127 - this is sh - this is sh - unset - ok - 5 --- 0 ---- diff -Nrc2 bash-2.01.1/tests/execscript.sub bash-2.02/tests/execscript.sub *** bash-2.01.1/tests/execscript.sub Wed Feb 19 14:06:50 1997 --- bash-2.02/tests/execscript.sub Wed Dec 31 19:00:00 1969 *************** *** 1 **** - echo "$@" --- 0 ---- diff -Nrc2 bash-2.01.1/tests/execscript.sub2 bash-2.02/tests/execscript.sub2 *** bash-2.01.1/tests/execscript.sub2 Tue Feb 25 13:26:25 1997 --- bash-2.02/tests/execscript.sub2 Wed Dec 31 19:00:00 1969 *************** *** 1,5 **** - # make sure an exit command in an exit trap sets the shell's exit status - trap - 0 - trap 'exit 5' 0 - - exit 0 --- 0 ---- diff -Nrc2 bash-2.01.1/tests/execscript.sub3 bash-2.02/tests/execscript.sub3 *** bash-2.01.1/tests/execscript.sub3 Mon Mar 3 12:58:01 1997 --- bash-2.02/tests/execscript.sub3 Wed Dec 31 19:00:00 1969 *************** *** 1,6 **** - shopt -s execfail - - exec /tmp/bash-notthere - # make sure we're still around - echo $? - --- 0 ---- diff -Nrc2 bash-2.01.1/tests/execscript.sub4 bash-2.02/tests/execscript.sub4 *** bash-2.01.1/tests/execscript.sub4 Mon Mar 3 13:00:22 1997 --- bash-2.02/tests/execscript.sub4 Wed Dec 31 19:00:00 1969 *************** *** 1,8 **** - # let's test out the noexec code - set -n - - fail - whoops - wow - - set +n --- 0 ---- diff -Nrc2 bash-2.01.1/tests/extglob.right bash-2.02/tests/extglob.right *** bash-2.01.1/tests/extglob.right Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/extglob.right Thu Aug 7 14:11:58 1997 *************** *** 0 **** --- 1,59 ---- + ok 1 + ok 2 + ok 3 + ok 4 + ok 5 + ok 6 + ok 7 + ok 8 + ok 9 + ok 10 + ok 11 + ok 12 + ok 13 + ok 14 + ok 15 + ok 16 + ok 17 + ok 18 + ok 19 + ok 20 + ok 21 + ok 22 + ok 23 + ok 24 + ok 25 + ok 26 + ok 27 + ok 28 + ok 29 + ok 30 + ok 31 + ok 32 + ok 33 + ok 34 + ok 35 + ok 36 + !([*)* + +(a|b[)* + [a*(]*)z + +()c + +()x + abc + +(*)x + abc + no-file+(a|b)stuff + no-file+(a*(c)|b)stuff + abd acd + acd + abd + no + yes + yes + 1: bcdef + 2: def + 3: abcde + 4: abc + 5: ef + 6: ef + 7: abcdef diff -Nrc2 bash-2.01.1/tests/extglob.tests bash-2.02/tests/extglob.tests *** bash-2.01.1/tests/extglob.tests Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/extglob.tests Wed Aug 6 15:50:55 1997 *************** *** 0 **** --- 1,286 ---- + # test the ksh-like extended globbing features: [!@*?+](patlist) + + shopt -s extglob + + expect() + { + echo expect "$@" + } + + case "/dev/udp/129.22.8.102/45" in + /dev/@(tcp|udp)/*/*) echo ok 1;; + *) echo bad 1;; + esac + + # valid numbers + case 12 in + 0|[1-9]*([0-9])) echo ok 2;; + *) echo bad 2;; + esac + + case 12abc in + 0|[1-9]*([0-9])) echo bad 3;; + *) echo ok 3;; + esac + + case 1 in + 0|[1-9]*([0-9])) echo ok 4;; + *) echo bad 4;; + esac + + # octal numbers + case 07 in + +([0-7])) echo ok 5;; + *) echo bad 5;; + esac + + case 0377 in + +([0-7])) echo ok 6;; + *) echo bad 6;; + esac + + case 09 in + +([0-7])) echo bad 7;; + *) echo ok 7;; + esac + + # stuff from korn's book + case paragraph in + para@(chute|graph)) echo ok 8;; + *) echo bad 8;; + esac + + case paramour in + para@(chute|graph)) echo bad 9;; + *) echo ok 9;; + esac + + case para991 in + para?([345]|99)1) echo ok 10;; + *) echo bad 10;; + esac + + case para381 in + para?([345]|99)1) echo bad 11;; + *) echo ok 11;; + esac + + case paragraph in + para*([0-9])) echo bad 12;; + *) echo ok 12;; + esac + + case para in + para*([0-9])) echo ok 13;; + *) echo bad 13;; + esac + + case para13829383746592 in + para*([0-9])) echo ok 14;; + *) echo bad 14;; + esac + + case paragraph in + para*([0-9])) echo bad 15;; + *) echo ok 15;; + esac + + case para in + para+([0-9])) echo bad 16;; + *) echo ok 16;; + esac + + case para987346523 in + para+([0-9])) echo ok 17;; + *) echo bad 17;; + esac + + case paragraph in + para!(*.[0-9])) echo ok 18;; + *) echo bad 18;; + esac + + case para.38 in + para!(*.[0-9])) echo ok 19;; + *) echo bad 19;; + esac + + case para.graph in + para!(*.[0-9])) echo ok 20;; + *) echo bad 20;; + esac + + case para39 in + para!(*.[0-9])) echo ok 21;; + *) echo bad 21;; + esac + + # tests derived from those in rosenblatt's korn shell book + + case "" in + *(0|1|3|5|7|9)) echo ok 22;; + *) echo bad 22; + esac + + case 137577991 in + *(0|1|3|5|7|9)) echo ok 23;; + *) echo bad 23; + esac + + case 2468 in + *(0|1|3|5|7|9)) echo bad 24;; + *) echo ok 24; + esac + + case file.c in + *.c?(c)) echo ok 25;; + *) echo bad 25;; + esac + + case file.C in + *.c?(c)) echo bad 26;; + *) echo ok 26;; + esac + + case file.cc in + *.c?(c)) echo ok 27;; + *) echo bad 27;; + esac + + case file.ccc in + *.c?(c)) echo bad 28;; + *) echo ok 28;; + esac + + case parse.y in + !(*.c|*.h|Makefile.in|config*|README)) echo ok 29;; + *) echo bad 29;; + esac + + case shell.c in + !(*.c|*.h|Makefile.in|config*|README)) echo bad 30;; + *) echo ok 30;; + esac + + case Makefile in + !(*.c|*.h|Makefile.in|config*|README)) echo ok 31;; + *) echo bad 31;; + esac + + case "VMS.FILE;1" in + *\;[1-9]*([0-9])) echo ok 32;; + *) echo bad 32;; + esac + + case "VMS.FILE;0" in + *\;[1-9]*([0-9])) echo bad 33;; + *) echo ok 33;; + esac + case "VMS.FILE;" in + *\;[1-9]*([0-9])) echo bad 34;; + *) echo ok 34;; + esac + case "VMS.FILE;139" in + *\;[1-9]*([0-9])) echo ok 35;; + *) echo bad 35;; + esac + case "VMS.FILE;1N" in + *\;[1-9]*([0-9])) echo bad 36;; + *) echo ok 36;; + esac + + # tests derived from the pd-ksh test suite + + MYDIR=$PWD # save where we are + + TESTDIR=/tmp/eglob-test + mkdir $TESTDIR + builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; } + rm -rf * + + touch abcx abcz bbc + expect '!([*)*' + echo !([*)* + + expect '+(a|b[)*' + echo +(a|b[)* + + expect '[a*(]*z' + echo [a*(]*)z + + rm -f abcx abcz bbc + + touch abc + + expect '+()c' + echo +()c + expect '+()x' + echo +()x + expect abc + echo +(*)c + expect '+(*)x' + echo +(*)x + + # extended globbing should not be performed on the output of substitutions + x='@(*)' + expect '@(*)' + echo $x + + expect 'no-file+(a|b)stuff' + echo no-file+(a|b)stuff + expect 'no-file+(a*(c)|b)stuff' + echo no-file+(a*(c)|b)stuff + + touch abd acd + + expect 'abd acd' + echo a+(b|c)d + + expect 'acd' + echo a!(@(b|B))d + + expect 'abd' + echo a[b*(foo|bar)]d + + # simple kleene star tests + expect no + case foo in *(a|b[)) echo yes;; *) echo no;; esac + + expect yes + case foo in *(a|b[)|f*) echo yes;; *) echo no;; esac + + # this doesn't work right yet; it is an incorrectly formed pattern + expect yes + case '*(a|b[)' in *(a|b[)) echo yes;; *) echo no;; esac + + # check extended globbing in pattern removal -- these don't work right yet + x=abcdef + + expect '1: bcdef' + echo 1: ${x#+(a|abc)} + expect '2: def' + echo 2: ${x##+(a|abc)} + expect '3: abcde' + echo 3: ${x%+(def|f)} + expect '4: abc' + echo 4: ${x%%+(f|def)} + + # these work ok + + expect '5: ef' + echo 5: ${x#*(a|b)cd} + expect '6: ef' + echo 6: "${x#*(a|b)cd}" + expect '7: abcdef' + echo 7: ${x#"*(a|b)cd"} + + # clean up and exit + + builtin cd / + rm -rf $TESTDIR + + # this is for the benefit of pure coverage, so it writes the pcv file + # in the right place + builtin cd $MYDIR + + exit 0 diff -Nrc2 bash-2.01.1/tests/getopts.right bash-2.02/tests/getopts.right *** bash-2.01.1/tests/getopts.right Thu Mar 6 15:56:54 1997 --- bash-2.02/tests/getopts.right Thu Jul 3 11:58:14 1997 *************** *** 11,16 **** -b bval specified remaining args: one two three four five six seven eight nine ten eleven twelve ! ./getopts.sub1: option requires an argument -- b ! Usage: ./getopts.sub1 [-a] [-b value] args -a specified -c cval specified --- 11,16 ---- -b bval specified remaining args: one two three four five six seven eight nine ten eleven twelve ! ./getopts1.sub: option requires an argument -- b ! Usage: ./getopts1.sub [-a] [-b value] args -a specified -c cval specified *************** *** 25,32 **** -b bval specified remaining args: one two three ! ./getopts.sub4: error: option `b' requires an argument ! Usage: ./getopts.sub4 [-a] [-b value] args ! ./getopts.sub4: error: illegal option character `c' ! Usage: ./getopts.sub4 [-a] [-b value] args -a specified remaining args: -b bval one two three --- 25,32 ---- -b bval specified remaining args: one two three ! ./getopts4.sub: error: option `b' requires an argument ! Usage: ./getopts4.sub [-a] [-b value] args ! ./getopts4.sub: error: illegal option character `c' ! Usage: ./getopts4.sub [-a] [-b value] args -a specified remaining args: -b bval one two three *************** *** 37,45 **** getop: OPTERR=1 a here ! ./getopts.sub5: illegal option -- c something else here ! ./getopts.sub5: illegal option -- d something else here ! ./getopts.sub5: illegal option -- e something else here getop: OPTIND=5 --- 37,45 ---- getop: OPTERR=1 a here ! ./getopts5.sub: illegal option -- c something else here ! ./getopts5.sub: illegal option -- d something else here ! ./getopts5.sub: illegal option -- e something else here getop: OPTIND=5 *************** *** 53,56 **** remaining args: 0 ! ./getopts.sub7: getopts: `opt-var': not a valid identifier remaining args: --- 53,56 ---- remaining args: 0 ! ./getopts7.sub: getopts: `opt-var': not a valid identifier remaining args: diff -Nrc2 bash-2.01.1/tests/getopts.sub1 bash-2.02/tests/getopts.sub1 *** bash-2.01.1/tests/getopts.sub1 Tue Jul 26 16:54:05 1994 --- bash-2.02/tests/getopts.sub1 Wed Dec 31 19:00:00 1969 *************** *** 1,26 **** - aflag= - bflag= - - while getopts ab: name - do - case $name in - a) aflag=1 ;; - b) bflag=1 - bval=$OPTARG;; - ?) echo Usage: $0 [-a] [-b value] args - exit 2;; - esac - - done - - if [ ! -z "$aflag" ] ; then echo -a specified ; fi - if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi - - if [ "$OPTIND" -gt 1 ] - then - shift $(( $OPTIND - 1 )) - fi - - echo remaining args: "$*" - - exit 0 --- 0 ---- diff -Nrc2 bash-2.01.1/tests/getopts.sub2 bash-2.02/tests/getopts.sub2 *** bash-2.01.1/tests/getopts.sub2 Wed May 8 19:36:10 1996 --- bash-2.02/tests/getopts.sub2 Wed Dec 31 19:00:00 1969 *************** *** 1,26 **** - aflag= - bflag= - - while getopts ab:c:de name "$@" - do - case $name in - a) aflag=1 ;; - b) bflag=1 - bval=$OPTARG;; - c) cflag=1 - cval=$OPTARG ;; - d) dflag=1 ;; - e) eflag=1;; - ?) echo Usage: $0 [-a] [-b value] [-c value] -[de] args - exit 2;; - esac - - done - - [ ! -z "$aflag" ] && echo -a specified - [ ! -z "$bflag" ] && echo -b $bval specified - [ ! -z "$cflag" ] && echo -c $cval specified - [ ! -z "$dflag" ] && echo -d specified - [ ! -z "$eflag" ] && { echo -n - ; echo e specified; } - - exit 0 --- 0 ---- diff -Nrc2 bash-2.01.1/tests/getopts.sub3 bash-2.02/tests/getopts.sub3 *** bash-2.01.1/tests/getopts.sub3 Tue Feb 7 13:48:42 1995 --- bash-2.02/tests/getopts.sub3 Wed Dec 31 19:00:00 1969 *************** *** 1,27 **** - aflag= - bflag= - - while getopts ab: name -a -b 1 -a -a -a -b 5 -b 3 -a one two three four five - do - case $name in - a) aflag=1 ;; - b) bflag=1 - bval=$OPTARG;; - ?) echo Usage: $0 [-a] [-b value] args - exit 2;; - esac - - done - - if [ ! -z "$aflag" ] ; then echo -a specified ; fi - if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi - - set -- -a -b 1 -a -a -a -b 5 -b 3 -a one two three four five - if [ "$OPTIND" -gt 1 ] - then - shift $(( $OPTIND - 1 )) - fi - - echo remaining args: "$*" - - exit 0 --- 0 ---- diff -Nrc2 bash-2.01.1/tests/getopts.sub4 bash-2.02/tests/getopts.sub4 *** bash-2.01.1/tests/getopts.sub4 Fri Feb 28 15:47:34 1997 --- bash-2.02/tests/getopts.sub4 Wed Dec 31 19:00:00 1969 *************** *** 1,30 **** - aflag= - bflag= - - while getopts :ab: name "$@" - do - case $name in - a) aflag=1 ;; - b) bflag=1 - bval=$OPTARG;; - :) echo $0: error: option \`$OPTARG\' requires an argument - echo Usage: $0 [-a] [-b value] args - exit 2;; - ?) echo $0: error: illegal option character \`$OPTARG\' - echo Usage: $0 [-a] [-b value] args - exit 2;; - esac - - done - - if [ ! -z "$aflag" ] ; then echo -a specified ; fi - if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi - - if [ "$OPTIND" -gt 1 ] - then - shift $(( $OPTIND - 1 )) - fi - - echo remaining args: "$*" - - exit 0 --- 0 ---- diff -Nrc2 bash-2.01.1/tests/getopts.sub5 bash-2.02/tests/getopts.sub5 *** bash-2.01.1/tests/getopts.sub5 Mon Feb 24 15:15:20 1997 --- bash-2.02/tests/getopts.sub5 Wed Dec 31 19:00:00 1969 *************** *** 1,50 **** - #!/local/bin/bash - #Time-stamp: <95/06/07 07:40:40 hrue@imf.unit.no> - - getop () { - - local OPTIND - local OPTERR=1 - - echo getop: OPTERR=$OPTERR - while getopts ab arg "$@"; do - case $arg in - a) - echo a here - ;; - b) - echo b here - ;; - :|?|*) - echo something else here - ;; - esac - done - echo getop: OPTIND=$OPTIND - } - - OPTIND= - OPTERR=0 - - echo OPTERR=$OPTERR - while getopts ab arg; do - case $arg in - a) - echo a here - ;; - b) - echo b here - ;; - :|?|*) - - echo something else here - ;; - esac - done - - echo OPTIND=$OPTIND - - getop "$@" -d -e - - echo OPTIND=$OPTIND - echo OPTERR=$OPTERR --- 0 ---- diff -Nrc2 bash-2.01.1/tests/getopts.sub6 bash-2.02/tests/getopts.sub6 *** bash-2.01.1/tests/getopts.sub6 Fri Feb 28 13:38:30 1997 --- bash-2.02/tests/getopts.sub6 Wed Dec 31 19:00:00 1969 *************** *** 1,27 **** - aflag= - bflag= - - while getopts :ac name "$@" - do - case $name in - a) aflag=1 ;; - c) cflag=1 ;; - ?) exit 2;; - esac - - # this came in in a bug report -- it's really a usage error - # but it shouldn't cause the shell to crash - shift - done - - if [ ! -z "$aflag" ] ; then echo -a specified ; fi - if [ ! -z "$cflag" ] ; then echo -c specified ; fi - - if [ "$OPTIND" -gt 1 ] - then - shift $(( $OPTIND - 1 )) - fi - - echo remaining args: "$*" - - exit 0 --- 0 ---- diff -Nrc2 bash-2.01.1/tests/getopts.sub7 bash-2.02/tests/getopts.sub7 *** bash-2.01.1/tests/getopts.sub7 Fri Feb 28 16:03:31 1997 --- bash-2.02/tests/getopts.sub7 Wed Dec 31 19:00:00 1969 *************** *** 1,30 **** - aflag= - bflag= - - while getopts :ab: opt-var "$@" - do - case $name in - a) aflag=1 ;; - b) bflag=1 - bval=$OPTARG;; - :) echo $0: error: option \`$OPTARG\' requires an argument - echo Usage: $0 [-a] [-b value] args - exit 2;; - ?) echo $0: error: illegal option character \`$OPTARG\' - echo Usage: $0 [-a] [-b value] args - exit 2;; - esac - - done - - if [ ! -z "$aflag" ] ; then echo -a specified ; fi - if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi - - if [ "$OPTIND" -gt 1 ] - then - shift $(( $OPTIND - 1 )) - fi - - echo remaining args: "$*" - - exit 0 --- 0 ---- diff -Nrc2 bash-2.01.1/tests/getopts.tests bash-2.02/tests/getopts.tests *** bash-2.01.1/tests/getopts.tests Fri Feb 28 16:03:45 1997 --- bash-2.02/tests/getopts.tests Thu Jul 3 11:56:23 1997 *************** *** 10,38 **** getopts -a opts name ! ${THIS_SH} ./getopts.sub1 -a -b bval one two three # make sure getopts works when there are more than 9 positional parameters ! ${THIS_SH} ./getopts.sub1 -a -b bval one two three four five six seven eight nine ten eleven twelve ! ${THIS_SH} ./getopts.sub1 -a -b ! ${THIS_SH} ./getopts.sub2 -ad -c cval three four five ! ${THIS_SH} ./getopts.sub3 # make sure that `-b bval' and `-bbval' are equivalent ! ${THIS_SH} ./getopts.sub4 -a -b bval one two three ! ${THIS_SH} ./getopts.sub4 -a -bbval one two three # this tests `silent' error reporting ! ${THIS_SH} ./getopts.sub4 -a -b ! ${THIS_SH} ./getopts.sub4 -a -c # make sure that `--' can be used to end the list of options ! ${THIS_SH} ./getopts.sub4 -a -- -b bval one two three ! ${THIS_SH} ./getopts.sub5 -a -c ! ${THIS_SH} ./getopts.sub6 -a ! ${THIS_SH} ./getopts.sub6 -a -c ! ${THIS_SH} ./getopts.sub6 -ac echo $? # this should be 2 ! ${THIS_SH} ./getopts.sub7 -a --- 10,38 ---- getopts -a opts name ! ${THIS_SH} ./getopts1.sub -a -b bval one two three # make sure getopts works when there are more than 9 positional parameters ! ${THIS_SH} ./getopts1.sub -a -b bval one two three four five six seven eight nine ten eleven twelve ! ${THIS_SH} ./getopts1.sub -a -b ! ${THIS_SH} ./getopts2.sub -ad -c cval three four five ! ${THIS_SH} ./getopts3.sub # make sure that `-b bval' and `-bbval' are equivalent ! ${THIS_SH} ./getopts4.sub -a -b bval one two three ! ${THIS_SH} ./getopts4.sub -a -bbval one two three # this tests `silent' error reporting ! ${THIS_SH} ./getopts4.sub -a -b ! ${THIS_SH} ./getopts4.sub -a -c # make sure that `--' can be used to end the list of options ! ${THIS_SH} ./getopts4.sub -a -- -b bval one two three ! ${THIS_SH} ./getopts5.sub -a -c ! ${THIS_SH} ./getopts6.sub -a ! ${THIS_SH} ./getopts6.sub -a -c ! ${THIS_SH} ./getopts6.sub -ac echo $? # this should be 2 ! ${THIS_SH} ./getopts7.sub -a diff -Nrc2 bash-2.01.1/tests/getopts1.sub bash-2.02/tests/getopts1.sub *** bash-2.01.1/tests/getopts1.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/getopts1.sub Tue Jul 26 16:54:05 1994 *************** *** 0 **** --- 1,26 ---- + aflag= + bflag= + + while getopts ab: name + do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + ?) echo Usage: $0 [-a] [-b value] args + exit 2;; + esac + + done + + if [ ! -z "$aflag" ] ; then echo -a specified ; fi + if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi + + if [ "$OPTIND" -gt 1 ] + then + shift $(( $OPTIND - 1 )) + fi + + echo remaining args: "$*" + + exit 0 diff -Nrc2 bash-2.01.1/tests/getopts2.sub bash-2.02/tests/getopts2.sub *** bash-2.01.1/tests/getopts2.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/getopts2.sub Wed May 8 19:36:10 1996 *************** *** 0 **** --- 1,26 ---- + aflag= + bflag= + + while getopts ab:c:de name "$@" + do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + c) cflag=1 + cval=$OPTARG ;; + d) dflag=1 ;; + e) eflag=1;; + ?) echo Usage: $0 [-a] [-b value] [-c value] -[de] args + exit 2;; + esac + + done + + [ ! -z "$aflag" ] && echo -a specified + [ ! -z "$bflag" ] && echo -b $bval specified + [ ! -z "$cflag" ] && echo -c $cval specified + [ ! -z "$dflag" ] && echo -d specified + [ ! -z "$eflag" ] && { echo -n - ; echo e specified; } + + exit 0 diff -Nrc2 bash-2.01.1/tests/getopts3.sub bash-2.02/tests/getopts3.sub *** bash-2.01.1/tests/getopts3.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/getopts3.sub Tue Feb 7 13:48:42 1995 *************** *** 0 **** --- 1,27 ---- + aflag= + bflag= + + while getopts ab: name -a -b 1 -a -a -a -b 5 -b 3 -a one two three four five + do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + ?) echo Usage: $0 [-a] [-b value] args + exit 2;; + esac + + done + + if [ ! -z "$aflag" ] ; then echo -a specified ; fi + if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi + + set -- -a -b 1 -a -a -a -b 5 -b 3 -a one two three four five + if [ "$OPTIND" -gt 1 ] + then + shift $(( $OPTIND - 1 )) + fi + + echo remaining args: "$*" + + exit 0 diff -Nrc2 bash-2.01.1/tests/getopts4.sub bash-2.02/tests/getopts4.sub *** bash-2.01.1/tests/getopts4.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/getopts4.sub Fri Feb 28 15:47:34 1997 *************** *** 0 **** --- 1,30 ---- + aflag= + bflag= + + while getopts :ab: name "$@" + do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + :) echo $0: error: option \`$OPTARG\' requires an argument + echo Usage: $0 [-a] [-b value] args + exit 2;; + ?) echo $0: error: illegal option character \`$OPTARG\' + echo Usage: $0 [-a] [-b value] args + exit 2;; + esac + + done + + if [ ! -z "$aflag" ] ; then echo -a specified ; fi + if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi + + if [ "$OPTIND" -gt 1 ] + then + shift $(( $OPTIND - 1 )) + fi + + echo remaining args: "$*" + + exit 0 diff -Nrc2 bash-2.01.1/tests/getopts5.sub bash-2.02/tests/getopts5.sub *** bash-2.01.1/tests/getopts5.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/getopts5.sub Mon Feb 24 15:15:20 1997 *************** *** 0 **** --- 1,50 ---- + #!/local/bin/bash + #Time-stamp: <95/06/07 07:40:40 hrue@imf.unit.no> + + getop () { + + local OPTIND + local OPTERR=1 + + echo getop: OPTERR=$OPTERR + while getopts ab arg "$@"; do + case $arg in + a) + echo a here + ;; + b) + echo b here + ;; + :|?|*) + echo something else here + ;; + esac + done + echo getop: OPTIND=$OPTIND + } + + OPTIND= + OPTERR=0 + + echo OPTERR=$OPTERR + while getopts ab arg; do + case $arg in + a) + echo a here + ;; + b) + echo b here + ;; + :|?|*) + + echo something else here + ;; + esac + done + + echo OPTIND=$OPTIND + + getop "$@" -d -e + + echo OPTIND=$OPTIND + echo OPTERR=$OPTERR diff -Nrc2 bash-2.01.1/tests/getopts6.sub bash-2.02/tests/getopts6.sub *** bash-2.01.1/tests/getopts6.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/getopts6.sub Fri Feb 28 13:38:30 1997 *************** *** 0 **** --- 1,27 ---- + aflag= + bflag= + + while getopts :ac name "$@" + do + case $name in + a) aflag=1 ;; + c) cflag=1 ;; + ?) exit 2;; + esac + + # this came in in a bug report -- it's really a usage error + # but it shouldn't cause the shell to crash + shift + done + + if [ ! -z "$aflag" ] ; then echo -a specified ; fi + if [ ! -z "$cflag" ] ; then echo -c specified ; fi + + if [ "$OPTIND" -gt 1 ] + then + shift $(( $OPTIND - 1 )) + fi + + echo remaining args: "$*" + + exit 0 diff -Nrc2 bash-2.01.1/tests/getopts7.sub bash-2.02/tests/getopts7.sub *** bash-2.01.1/tests/getopts7.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/getopts7.sub Fri Feb 28 16:03:31 1997 *************** *** 0 **** --- 1,30 ---- + aflag= + bflag= + + while getopts :ab: opt-var "$@" + do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + :) echo $0: error: option \`$OPTARG\' requires an argument + echo Usage: $0 [-a] [-b value] args + exit 2;; + ?) echo $0: error: illegal option character \`$OPTARG\' + echo Usage: $0 [-a] [-b value] args + exit 2;; + esac + + done + + if [ ! -z "$aflag" ] ; then echo -a specified ; fi + if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi + + if [ "$OPTIND" -gt 1 ] + then + shift $(( $OPTIND - 1 )) + fi + + echo remaining args: "$*" + + exit 0 diff -Nrc2 bash-2.01.1/tests/glob-test bash-2.02/tests/glob-test *** bash-2.01.1/tests/glob-test Fri May 2 12:08:12 1997 --- bash-2.02/tests/glob-test Mon Nov 17 15:22:52 1997 *************** *** 8,11 **** --- 8,14 ---- } + # First, a test that bash-2.01.1 fails + ${THIS_SH} ./glob1.sub + MYDIR=$PWD # save where we are *************** *** 15,19 **** rm -rf * ! touch a b c d abc abd abe bb bcd ca cb dd de mkdir bdir --- 18,22 ---- rm -rf * ! touch a b c d abc abd abe bb bcd ca cb dd de Beware mkdir bdir *************** *** 82,86 **** touch .x .y ! expect '
    ' recho [^a-c]* --- 85,89 ---- touch .x .y ! expect '
    ' recho [^a-c]* *************** *** 289,292 **** --- 292,300 ---- esac + # a backslash should just escape the next character in this context + case p in + [a-\z]) echo ok 36 ;; + esac + # none of these should output anything *************** *** 323,326 **** --- 331,342 ---- esac + # let's start testing the case-insensitive globbing code + recho b* + + shopt -s nocaseglob + recho b* + + recho [b]* + shopt -u nocaseglob # make sure set -f works right diff -Nrc2 bash-2.01.1/tests/glob.right bash-2.02/tests/glob.right *** bash-2.01.1/tests/glob.right Wed Mar 19 14:53:27 1997 --- bash-2.02/tests/glob.right Mon Nov 17 15:27:22 1997 *************** *** 1,2 **** --- 1,3 ---- + foo/bar foobar/bar argv[1] = argv[2] = *************** *** 44,50 **** argv[1] = argv[2] = ! argv[1] = ! argv[2] =
    ! argv[3] = argv[1] = argv[1] = --- 45,52 ---- argv[1] = argv[2] = ! argv[1] = ! argv[2] = ! argv[3] =
    ! argv[4] = argv[1] = argv[1] = *************** *** 92,95 **** --- 94,112 ---- ok 34 ok 35 + ok 36 + argv[1] = + argv[2] = + argv[3] = + argv[4] = + argv[1] = + argv[2] = + argv[3] = + argv[4] = + argv[5] = + argv[1] = + argv[2] = + argv[3] = + argv[4] = + argv[5] = argv[1] = <*> argv[1] = *************** *** 104,113 **** argv[10] =
    argv[11] = ! argv[1] = ! argv[2] = ! argv[3] = ! argv[4] = ! argv[5] = ! argv[6] = argv[1] = <*> argv[1] = --- 121,131 ---- argv[10] =
    argv[11] = ! argv[1] = ! argv[2] = ! argv[3] = ! argv[4] = ! argv[5] = ! argv[6] = ! argv[7] = argv[1] = <*> argv[1] = diff -Nrc2 bash-2.01.1/tests/glob1.sub bash-2.02/tests/glob1.sub *** bash-2.01.1/tests/glob1.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/glob1.sub Mon Nov 17 15:21:53 1997 *************** *** 0 **** --- 1,14 ---- + # bash-2.01.1 failed this test + FN=/tmp/bash-glob.$$ + mkdir $FN + cd $FN + mkdir foo + mkdir foobar + touch foo/bar + touch foobar/bar + chmod 311 foo foobar + echo f*/bar + + chmod 777 foo foobar + cd / + rm -rf $FN diff -Nrc2 bash-2.01.1/tests/histexp.right bash-2.02/tests/histexp.right *** bash-2.01.1/tests/histexp.right Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/histexp.right Tue Nov 18 14:00:54 1997 *************** *** 0 **** --- 1,129 ---- + echo $BASH_VERSION + ./histexp.tests: history: !!:z: history expansion failed + 1 for i in one two three; do echo $i; done + 2 /bin/sh -c 'echo this is $0' + 3 ls + 4 echo $BASH_VERSION + 1 for i in one two three; do echo $i; done + 2 /bin/sh -c 'echo this is $0' + 3 ls + 4 echo $BASH_VERSION + 5 HISTFILE=/tmp/newhistory + 6 echo line 2 for history + echo line 2 for history + echo line 2 for history + set -H + echo line 2 for history + line 2 for history + 1 for i in one two three; do echo $i; done + 2 /bin/sh -c 'echo this is $0' + 3 ls + 4 echo $BASH_VERSION + 5 HISTFILE=/tmp/newhistory + 6 echo line 2 for history + 7 set -H + 8 echo line 2 for history + a b c d e + echo a b c d e + a b c d e + echo line 2 for history + line 2 for history + echo line 8 for history + line 8 for history + /bin/sh -c 'echo this is $0' + this is /bin/sh + echo sh + sh + echo /bin + /bin + echo e + e + a b c d e + echo b c d e + b c d e + echo b c d + b c d + echo d e + d e + echo d e + d e + echo b c d + b c d + file.c + echo file + file + echo .c + .c + echo 'file' + file + bax.c + echo $file + bax + echo .c + .c + echo '$file' + $file + a b c d e + echo 'a' 'b' 'c' 'd' 'e' + a b c d e + echo 'a b c d e' + a b c d e + foo.c foo.o foo.html foo.h + echo bar.c foo.o foo.html foo.h + bar.c foo.o foo.html foo.h + echo bar.c bar.o bar.html bar.h + bar.c bar.o bar.html bar.h + echo xbar.c xbar.o xbar.html xbar.h + xbar.c xbar.o xbar.html xbar.h + echo xbar.c xbar.o xbar.html xbar.h + xbar.c xbar.o xbar.html xbar.h + echo xwhix.c xwhix.o xwhix.html xwhix.h + xwhix.c xwhix.o xwhix.html xwhix.h + echo xwhix.c xwhix.o xwhix.html xwhix.h + echo 'xwhix' + xwhix + echo 'xwhix.h' + xwhix.h + echo 'xwhix.h' + xwhix.h + echo 'xwhix.h' + xwhix.h + 8 echo line 2 for history + 9 echo a b c d e + 10 echo line 2 for history + 11 echo line 8 for history + 12 /bin/sh -c 'echo this is $0' + 13 echo sh + 14 echo /bin + 15 echo e + 16 echo a b c d e + 17 echo b c d e + 18 echo b c d + 19 echo d e + 20 echo b c d + 21 echo file.c + 22 echo file + 23 echo .c + 24 echo 'file' + 25 echo $file.c + 26 echo $file + 27 echo .c + 28 echo '$file' + 29 echo a b c d e + 30 echo 'a' 'b' 'c' 'd' 'e' + 31 echo 'a b c d e' + 32 echo foo.c foo.o foo.html foo.h + 33 echo bar.c foo.o foo.html foo.h + 34 echo bar.c bar.o bar.html bar.h + 35 echo xbar.c xbar.o xbar.html xbar.h + 36 echo xwhix.c xwhix.o xwhix.html xwhix.h + 37 echo xwhix.c xwhix.o xwhix.html xwhix.h + 38 echo 'xwhix' + 39 echo 'xwhix.h' + !! + !! + echo '!!' \!\! + !! !! + ok 1 + ok 2 + ok 3 diff -Nrc2 bash-2.01.1/tests/histexp.tests bash-2.02/tests/histexp.tests *** bash-2.01.1/tests/histexp.tests Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/histexp.tests Mon Feb 9 12:10:41 1998 *************** *** 0 **** --- 1,122 ---- + LC_ALL=C + LANG=C + trap 'rm /tmp/newhistory' 0 + + file=bax + histchars='!^#' # make sure history comment char is set correctly + + history -c + + HISTFILE=history.list + HISTCONTROL=ignoreboth + HISTIGNORE='&:#*:history*:fc*' + # we will end up exercising the history stifling code as a result + HISTSIZE=32 + + shopt -s cmdhist + set -o history + + history -p '!!' + + # this should result in a failed history expansion error + history -p '!!:z' + + history + + HISTFILE=/tmp/newhistory + history -a + + history -w + + history -s "echo line 2 for history" + history + history -p '!e' + history -p '!!' + + set -H + !! + !e + + history + + echo a b c d e + !?ch? + !-2 + ^2^8 + + !2 + + # we're selecting /bin/sh -c ...; we want `sh' + echo !-1:0:t + # we're selecting /bin/sh -c ...; we want `/bin' + echo !-2:0:h + # we're selecting `echo a b c d e'; we want `e' + echo !?d?:5 + + echo a b c d e + echo !-1:2-$ + echo !-2:2-4 + echo !-2:3* + echo !!:* + + echo !?a?:2- + + echo file.c + echo !!:$:r + echo !-2:$:e + echo !-3:$:r:q + + echo $file.c + echo !!:$:r + echo !-2:^:e + echo !-3:$:r:q + + echo a b c d e + echo !!:1-$:x + echo !-2:1-$:q + + echo foo.c foo.o foo.html foo.h + !!:s/foo/bar/ + !-2:gs/foo/bar/ + !!:gs/bar/x&/ + !-2:g& + + # make sure we can use any delimiter in the substitution, not just `/' + !!:gs+bar+whix+ + + !!:p + + # wow + echo !?.o?:%:r:q + + !!:0 !?.h?:%:q + !!:-$ + !:-$ + + history + + # make sure single quotes inhibit history expansion + echo '!!' + + # make sure backslashes can quote the history expansion character + echo \!\! + + # but other expansions on the line should still be processed + + echo '!!' !!:* + history -c + unset HISTFILE + + # make sure that the special bash cases are not history expanded + case p in + [!A-Z]) echo ok 1;; + esac + + var1='ok 2' + var2=var1 + + echo ${!var2} + + # Bash-2.01[.1] fails this test -- it attempts history expansion after the + # history_expansion_char + echo ok 3 # !1200 diff -Nrc2 bash-2.01.1/tests/histexpand.right bash-2.02/tests/histexpand.right *** bash-2.01.1/tests/histexpand.right Wed Mar 26 14:01:41 1997 --- bash-2.02/tests/histexpand.right Wed Dec 31 19:00:00 1969 *************** *** 1,127 **** - echo $BASH_VERSION - 1 for i in one two three; do echo $i; done - 2 /bin/sh -c 'echo this is $0' - 3 ls - 4 echo $BASH_VERSION - 1 for i in one two three; do echo $i; done - 2 /bin/sh -c 'echo this is $0' - 3 ls - 4 echo $BASH_VERSION - 5 HISTFILE=/tmp/newhistory - 6 echo line 2 for history - echo line 2 for history - echo line 2 for history - set -H - echo line 2 for history - line 2 for history - 1 for i in one two three; do echo $i; done - 2 /bin/sh -c 'echo this is $0' - 3 ls - 4 echo $BASH_VERSION - 5 HISTFILE=/tmp/newhistory - 6 echo line 2 for history - 7 set -H - 8 echo line 2 for history - a b c d e - echo a b c d e - a b c d e - echo line 2 for history - line 2 for history - echo line 8 for history - line 8 for history - /bin/sh -c 'echo this is $0' - this is /bin/sh - echo sh - sh - echo /bin - /bin - echo e - e - a b c d e - echo b c d e - b c d e - echo b c d - b c d - echo d e - d e - echo d e - d e - echo b c d - b c d - file.c - echo file - file - echo .c - .c - echo 'file' - file - bax.c - echo $file - bax - echo .c - .c - echo '$file' - $file - a b c d e - echo 'a' 'b' 'c' 'd' 'e' - a b c d e - echo 'a b c d e' - a b c d e - foo.c foo.o foo.html foo.h - echo bar.c foo.o foo.html foo.h - bar.c foo.o foo.html foo.h - echo bar.c bar.o bar.html bar.h - bar.c bar.o bar.html bar.h - echo xbar.c xbar.o xbar.html xbar.h - xbar.c xbar.o xbar.html xbar.h - echo xbar.c xbar.o xbar.html xbar.h - xbar.c xbar.o xbar.html xbar.h - echo xwhix.c xwhix.o xwhix.html xwhix.h - xwhix.c xwhix.o xwhix.html xwhix.h - echo xwhix.c xwhix.o xwhix.html xwhix.h - echo 'xwhix' - xwhix - echo 'xwhix.h' - xwhix.h - echo 'xwhix.h' - xwhix.h - echo 'xwhix.h' - xwhix.h - 8 echo line 2 for history - 9 echo a b c d e - 10 echo line 2 for history - 11 echo line 8 for history - 12 /bin/sh -c 'echo this is $0' - 13 echo sh - 14 echo /bin - 15 echo e - 16 echo a b c d e - 17 echo b c d e - 18 echo b c d - 19 echo d e - 20 echo b c d - 21 echo file.c - 22 echo file - 23 echo .c - 24 echo 'file' - 25 echo $file.c - 26 echo $file - 27 echo .c - 28 echo '$file' - 29 echo a b c d e - 30 echo 'a' 'b' 'c' 'd' 'e' - 31 echo 'a b c d e' - 32 echo foo.c foo.o foo.html foo.h - 33 echo bar.c foo.o foo.html foo.h - 34 echo bar.c bar.o bar.html bar.h - 35 echo xbar.c xbar.o xbar.html xbar.h - 36 echo xwhix.c xwhix.o xwhix.html xwhix.h - 37 echo xwhix.c xwhix.o xwhix.html xwhix.h - 38 echo 'xwhix' - 39 echo 'xwhix.h' - !! - !! - echo '!!' \!\! - !! !! - ok 1 - ok 2 --- 0 ---- diff -Nrc2 bash-2.01.1/tests/histexpand.tests bash-2.02/tests/histexpand.tests *** bash-2.01.1/tests/histexpand.tests Wed Mar 26 14:01:21 1997 --- bash-2.02/tests/histexpand.tests Wed Dec 31 19:00:00 1969 *************** *** 1,112 **** - trap 'rm /tmp/newhistory' 0 - - file=bax - - history -c - - HISTFILE=history.list - HISTCONTROL=ignoreboth - HISTIGNORE='&:#*:history*:fc*' - # we will end up exercising the history stifling code as a result - HISTSIZE=32 - - shopt -s cmdhist - set -o history - - history -p '!!' - - history - - HISTFILE=/tmp/newhistory - history -a - - history -w - - history -s "echo line 2 for history" - history - history -p '!e' - history -p '!!' - - set -H - !! - !e - - history - - echo a b c d e - !?ch? - !-2 - ^2^8 - - !2 - - # we're selecting /bin/sh -c ...; we want `sh' - echo !-1:0:t - # we're selecting /bin/sh -c ...; we want `/bin' - echo !-2:0:h - # we're selecting `echo a b c d e'; we want `e' - echo !?d?:5 - - echo a b c d e - echo !-1:2-$ - echo !-2:2-4 - echo !-2:3* - echo !!:* - - echo !?a?:2- - - echo file.c - echo !!:$:r - echo !-2:$:e - echo !-3:$:r:q - - echo $file.c - echo !!:$:r - echo !-2:^:e - echo !-3:$:r:q - - echo a b c d e - echo !!:1-$:x - echo !-2:1-$:q - - echo foo.c foo.o foo.html foo.h - !!:s/foo/bar/ - !-2:gs/foo/bar/ - !!:gs/bar/x&/ - !-2:g& - - # make sure we can use any delimiter in the substitution, not just `/' - !!:gs+bar+whix+ - - !!:p - - # wow - echo !?.o?:%:r:q - - !!:0 !?.h?:%:q - !!:-$ - !:-$ - - history - - # make sure single quotes inhibit history expansion - echo '!!' - - # make sure backslashes can quote the history expansion character - echo \!\! - - # but other expansions on the line should still be processed - - echo '!!' !!:* - history -c - unset HISTFILE - - # make sure that the special bash cases are not history expanded - case p in - [!A-Z]) echo ok 1;; - esac - - var1='ok 2' - var2=var1 - - echo ${!var2} --- 0 ---- diff -Nrc2 bash-2.01.1/tests/history.right bash-2.02/tests/history.right *** bash-2.01.1/tests/history.right Mon Mar 3 12:20:47 1997 --- bash-2.02/tests/history.right Wed Nov 12 14:19:47 1997 *************** *** 1,2 **** --- 1,7 ---- + ./history.tests: history: illegal option: -x + history: usage: history [-c] [n] or history -awrn [filename] or history -ps arg [arg...] + ./history.tests: history: cannot use more than one of -anrw + ./history.tests: fc: illegal option: -v + fc: usage: fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [cmd] 1 for i in one two three; do echo $i; done 2 /bin/sh -c 'echo this is $0' *************** *** 94,97 **** --- 99,103 ---- 8 cat $HISTFILE ./history.tests: fc: history specification out of range + ./history.tests: fc: history specification out of range 14 set -H 15 echo line 2 for history *************** *** 101,104 **** --- 107,112 ---- echo xx xb xc xx xb xc + echo 44 48 4c + 44 48 4c ./history.tests: fc: no command found 1 diff -Nrc2 bash-2.01.1/tests/history.tests bash-2.02/tests/history.tests *** bash-2.01.1/tests/history.tests Mon Mar 3 13:40:39 1997 --- bash-2.02/tests/history.tests Wed Nov 12 14:20:32 1997 *************** *** 1,4 **** --- 1,16 ---- trap 'rm /tmp/newhistory' 0 + # bad options + history -x + # cannot use -r and -w at the same time + history -r -w /dev/null + + # bad option + fc -v + + # all of these should result in an empty history list + history -c + history -r /dev/null + history -n /dev/null history -c *************** *** 60,63 **** --- 72,76 ---- fc -l 502 + fc -l one=two three=four 502 history 4 *************** *** 71,74 **** --- 84,88 ---- r a=x + r x=4 b=8 # this had better fail with `no command found' diff -Nrc2 bash-2.01.1/tests/ifs-1.right bash-2.02/tests/ifs-1.right *** bash-2.01.1/tests/ifs-1.right Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/ifs-1.right Thu Jan 6 12:10:51 1994 *************** *** 0 **** --- 1 ---- + a:b:c diff -Nrc2 bash-2.01.1/tests/ifs-1.test bash-2.02/tests/ifs-1.test *** bash-2.01.1/tests/ifs-1.test Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/ifs-1.test Tue Aug 14 20:35:40 1990 *************** *** 0 **** --- 1,5 ---- + OIFS="$IFS" + IFS=":$IFS" + eval foo="a:b:c" + IFS="$OIFS" + echo $foo diff -Nrc2 bash-2.01.1/tests/ifs-2.right bash-2.02/tests/ifs-2.right *** bash-2.01.1/tests/ifs-2.right Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/ifs-2.right Thu Jan 6 12:11:16 1994 *************** *** 0 **** --- 1 ---- + a:b:c diff -Nrc2 bash-2.01.1/tests/ifs-2.test bash-2.02/tests/ifs-2.test *** bash-2.01.1/tests/ifs-2.test Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/ifs-2.test Tue Aug 14 20:37:44 1990 *************** *** 0 **** --- 1,9 ---- + OIFS=$IFS + IFS=":$IFS" + foo=$(echo a:b:c) + IFS=$OIFS + + for i in $foo + do + echo $i + done diff -Nrc2 bash-2.01.1/tests/ifs-3.right bash-2.02/tests/ifs-3.right *** bash-2.01.1/tests/ifs-3.right Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/ifs-3.right Thu Jan 6 12:11:55 1994 *************** *** 0 **** --- 1 ---- + a:b:c diff -Nrc2 bash-2.01.1/tests/ifs-3.test bash-2.02/tests/ifs-3.test *** bash-2.01.1/tests/ifs-3.test Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/ifs-3.test Fri Jun 12 16:44:51 1992 *************** *** 0 **** --- 1,9 ---- + OIFS=$IFS + IFS=":$IFS" + foo=`echo a:b:c` + IFS=$OIFS + + for i in $foo + do + echo $i + done diff -Nrc2 bash-2.01.1/tests/ifs-test-1.sh bash-2.02/tests/ifs-test-1.sh *** bash-2.01.1/tests/ifs-test-1.sh Tue Aug 14 20:35:40 1990 --- bash-2.02/tests/ifs-test-1.sh Wed Dec 31 19:00:00 1969 *************** *** 1,5 **** - OIFS="$IFS" - IFS=":$IFS" - eval foo="a:b:c" - IFS="$OIFS" - echo $foo --- 0 ---- diff -Nrc2 bash-2.01.1/tests/ifs-test-2.sh bash-2.02/tests/ifs-test-2.sh *** bash-2.01.1/tests/ifs-test-2.sh Tue Aug 14 20:37:44 1990 --- bash-2.02/tests/ifs-test-2.sh Wed Dec 31 19:00:00 1969 *************** *** 1,9 **** - OIFS=$IFS - IFS=":$IFS" - foo=$(echo a:b:c) - IFS=$OIFS - - for i in $foo - do - echo $i - done --- 0 ---- diff -Nrc2 bash-2.01.1/tests/ifs-test-3.sh bash-2.02/tests/ifs-test-3.sh *** bash-2.01.1/tests/ifs-test-3.sh Fri Jun 12 16:44:51 1992 --- bash-2.02/tests/ifs-test-3.sh Wed Dec 31 19:00:00 1969 *************** *** 1,9 **** - OIFS=$IFS - IFS=":$IFS" - foo=`echo a:b:c` - IFS=$OIFS - - for i in $foo - do - echo $i - done --- 0 ---- diff -Nrc2 bash-2.01.1/tests/ifs.1.right bash-2.02/tests/ifs.1.right *** bash-2.01.1/tests/ifs.1.right Thu Jan 6 12:10:51 1994 --- bash-2.02/tests/ifs.1.right Wed Dec 31 19:00:00 1969 *************** *** 1 **** - a:b:c --- 0 ---- diff -Nrc2 bash-2.01.1/tests/ifs.2.right bash-2.02/tests/ifs.2.right *** bash-2.01.1/tests/ifs.2.right Thu Jan 6 12:11:16 1994 --- bash-2.02/tests/ifs.2.right Wed Dec 31 19:00:00 1969 *************** *** 1 **** - a:b:c --- 0 ---- diff -Nrc2 bash-2.01.1/tests/ifs.3.right bash-2.02/tests/ifs.3.right *** bash-2.01.1/tests/ifs.3.right Thu Jan 6 12:11:55 1994 --- bash-2.02/tests/ifs.3.right Wed Dec 31 19:00:00 1969 *************** *** 1 **** - a:b:c --- 0 ---- diff -Nrc2 bash-2.01.1/tests/jobs.right bash-2.02/tests/jobs.right *** bash-2.01.1/tests/jobs.right Tue May 13 10:01:02 1997 --- bash-2.02/tests/jobs.right Mon Nov 17 12:32:31 1997 *************** *** 1,3 **** --- 1,7 ---- + ./jobs2.sub: fg: job %1 started without job control + fg: 1 0 + ./jobs.tests: wait: job control not enabled + ./jobs.tests: fg: no job control wait-for-pid wait-errors *************** *** 30,65 **** ./jobs.tests: bg: illegal option: -s bg: usage: bg [job_spec] ! ./jobs.tests: disown: illegal option: -r ! disown: usage: disown [-h] [jobspec ...] ./jobs.tests: disown: %1: no such job wait-for-non-child ./jobs.tests: wait: pid 1 is not a child of this shell 127 3 -- 1 2 3 -- 1 - 2 - 3 ! [1] Running sleep 300 & ! [2]- Running sleep 350 & ! [3]+ Running sleep 400 & running jobs: ! [1] Running sleep 300 & ! [2]- Running sleep 350 & ! [3]+ Running sleep 400 & ./jobs.tests: kill: %4: no such job after kill -STOP running jobs: ! [1] Running sleep 300 & ! [3]- Running sleep 400 & stopped jobs: ! [2]+ Stopped sleep 350 after disown ! [2]+ Stopped sleep 350 ! [3]- Running sleep 400 & running jobs: ! [3]- Running sleep 400 & stopped jobs: ! [2]+ Stopped sleep 350 after kill -s CONT running jobs: ! [2]+ Running sleep 350 & ! [3]- Running sleep 400 & stopped jobs: after kill -STOP, backgrounding %3: --- 34,75 ---- ./jobs.tests: bg: illegal option: -s bg: usage: bg [job_spec] ! ./jobs.tests: disown: illegal option: -s ! disown: usage: disown [-h] [-ar] [jobspec ...] ./jobs.tests: disown: %1: no such job + ./jobs.tests: disown: %2: no such job wait-for-non-child ./jobs.tests: wait: pid 1 is not a child of this shell 127 3 -- 1 2 3 -- 1 - 2 - 3 ! [1] Running sleep 300 & ! [2]- Running sleep 350 & ! [3]+ Running sleep 400 & running jobs: ! [1] Running sleep 300 & ! [2]- Running sleep 350 & ! [3]+ Running sleep 400 & ./jobs.tests: kill: %4: no such job + ./jobs.tests: jobs: no such job %4 + current job: + [3]+ Running sleep 400 & + previous job: + [2]- Running sleep 350 & after kill -STOP running jobs: ! [1] Running sleep 300 & ! [3]- Running sleep 400 & stopped jobs: ! [2]+ Stopped sleep 350 after disown ! [2]+ Stopped sleep 350 ! [3]- Running sleep 400 & running jobs: ! [3]- Running sleep 400 & stopped jobs: ! [2]+ Stopped sleep 350 after kill -s CONT running jobs: ! [2]+ Running sleep 350 & ! [3]- Running sleep 400 & stopped jobs: after kill -STOP, backgrounding %3: diff -Nrc2 bash-2.01.1/tests/jobs.tests bash-2.02/tests/jobs.tests *** bash-2.01.1/tests/jobs.tests Thu Mar 6 16:07:41 1997 --- bash-2.02/tests/jobs.tests Mon Nov 17 12:32:15 1997 *************** *** 1,5 **** --- 1,25 ---- + # test out %+, jobs -p, and $! agreement in a subshell first + ${THIS_SH} ./jobs1.sub + + # test out fg/bg failure in a subshell + ${THIS_SH} ./jobs2.sub + jobs echo $? + # should be a job-control-not-enabled error + wait %1 + + # make sure we can't fg a job started when job control was not active + sleep 30 & + pid=$! + fg %1 + # make sure the killed processes don't cause a message + exec 5>&2 + exec 2>/dev/null + kill -n 9 $pid + wait # make sure we reap the processes while stderr is still redirected + exec 2>&5 + echo wait-for-pid sleep 10 & *************** *** 69,79 **** wait ! # someday this may mean to disown all running jobs, but for now it is # an error ! disown -r ! # this is an error disown %1 echo wait-for-non-child wait 1 --- 89,103 ---- wait ! # someday this may mean to disown all stopped jobs, but for now it is # an error ! disown -s ! # this is an error -- the job with the pid that is the value of $! is ! # retained only until a `wait' is performed disown %1 + # this, however, is an error + disown %2 + echo wait-for-non-child wait 1 *************** *** 94,97 **** --- 118,127 ---- # should be an error kill -n 1 %4 + # should be an error + jobs %4 + echo current job: + jobs %+ + echo previous job: + jobs %- kill -STOP %2 diff -Nrc2 bash-2.01.1/tests/jobs1.sub bash-2.02/tests/jobs1.sub *** bash-2.01.1/tests/jobs1.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/jobs1.sub Fri Nov 14 14:12:46 1997 *************** *** 0 **** --- 1,17 ---- + # make sure that jobs -p, %+, and $! all agree + set -m + sleep 60 & + + FN=/tmp/jobs-pid.$$ + + pid1=$! + jobs -p %+ > $FN + pid2=$(< $FN) + rm $FN + + if [ $pid1 -ne $pid2 ]; then + echo 'oops - $! and jobs -p %+ disagree!' + fi + + exec 2>/dev/null + kill -9 $pid1 diff -Nrc2 bash-2.01.1/tests/jobs2.sub bash-2.02/tests/jobs2.sub *** bash-2.01.1/tests/jobs2.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/jobs2.sub Mon Nov 17 12:31:04 1997 *************** *** 0 **** --- 1,13 ---- + # make sure fg and bg don't work on jobs started without job control, + # even if they are executed when job control is active + set +o monitor + + sleep 30 & + pid=$! + + set -m + fg %1 + echo fg: $? + + exec 2>/dev/null + kill -9 $pid diff -Nrc2 bash-2.01.1/tests/misc/haertel.perftest bash-2.02/tests/misc/haertel.perftest *** bash-2.01.1/tests/misc/haertel.perftest Fri May 6 10:18:11 1994 --- bash-2.02/tests/misc/haertel.perftest Wed Dec 31 19:00:00 1969 *************** *** 1,9 **** - foo() { case $1 in a*) ;; *) ;; esac ;} - bar() { case $1 in [abc]*) ;; *);; esac ;} - baz() { case $1 in xyzzy) ;; *) ;; esac ;} - for x in /usr/lib/*/* - do - foo $x - bar $x - baz $x - done --- 0 ---- diff -Nrc2 bash-2.01.1/tests/misc/perftest bash-2.02/tests/misc/perftest *** bash-2.01.1/tests/misc/perftest Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/misc/perftest Thu Jul 3 12:25:13 1997 *************** *** 0 **** --- 1,10 ---- + # originally from Mike Haertel + foo() { case $1 in a*) ;; *) ;; esac ;} + bar() { case $1 in [abc]*) ;; *);; esac ;} + baz() { case $1 in xyzzy) ;; *) ;; esac ;} + for x in /usr/lib/*/* + do + foo $x + bar $x + baz $x + done diff -Nrc2 bash-2.01.1/tests/misc/redir-t2.sh bash-2.02/tests/misc/redir-t2.sh *** bash-2.01.1/tests/misc/redir-t2.sh Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/misc/redir-t2.sh Sat Feb 29 18:55:17 1992 *************** *** 0 **** --- 1,17 ---- + read line1 + + echo read line 1 \"$line1\" + + exec 4<&0 + + exec 0 argv[1] = + argv[1] = + argv[1] = + argv[1] = + argv[1] = <> + argv[1] = <> + argv[1] = + argv[1] = + argv[1] = + argv[1] = + argv[1] = + argv[1] = argv[1] = <> argv[1] = <> *************** *** 145,146 **** --- 156,194 ---- argv[3] = <}> argv[1] = + Number of args: 0 + <${*-x}>: + <${@-x}>: + Number of args: 1 + <${*-x}>: <> + <${@-x}>: <> + Number of args: 2 + <${*-x}>: < > + <${@-x}>: < > + argv[1] = <5> + argv[1] = <5> + argv[1] = <5> + argv[1] = <5> + argv[1] = <5> + argv[1] = <0> + argv[1] = <0> + argv[1] = <0> + argv[1] = <0> + argv[1] = <0> + argv[1] = <0> + argv[1] = + argv[1] = + argv[1] = <2> + argv[1] = <0> + argv[1] = <0> + argv[1] = <1> + argv[1] = <5> + argv[1] = <5> + argv[1] = <0> + ./more-exp.tests: ${#:}: bad substitution + ./more-exp.tests: ${#/}: bad substitution + ./more-exp.tests: ${#%}: bad substitution + ./more-exp.tests: ${#=}: bad substitution + ./more-exp.tests: ${#+}: bad substitution + ./more-exp.tests: ${#1xyz}: bad substitution + ./more-exp.tests: #: %: syntax error: operand expected (error token is "%") + argv[1] = <0> diff -Nrc2 bash-2.01.1/tests/more-exp.tests bash-2.02/tests/more-exp.tests *** bash-2.01.1/tests/more-exp.tests Wed Sep 11 16:04:28 1996 --- bash-2.02/tests/more-exp.tests Wed Aug 20 17:04:59 1997 *************** *** 190,193 **** --- 190,199 ---- expect '' recho "xy$*" + expect '' + recho x"$*"y + expect '' + recho xy"$*" + expect '' + recho "$*"xy expect '<>' recho "$*" *************** *** 197,209 **** --- 203,244 ---- unset undef ; set "" + expect '<>' + recho ${undef-"$*"} + expect '' + recho ${undef-"x$*y"} + expect '' + recho ${undef-"$*xy"} + expect '' + recho ${undef-"xy$*"} + expect '' + recho ${undef-x"$*"y} + expect '' + recho ${undef-xy"$*"} + expect '' + recho ${undef-"$*"xy} + expect '<>' + recho "${undef-$*}" + expect nothing + recho ${undef-$*} + + expect '<>' recho ${undef-"$zzz"} + expect '' recho x${undef-"$zzz"} + expect '' recho x${undef-"$@"} + expect nothing recho ${undef-"$@"} + expect '' recho ${undef-"$zzz"}x + expect '' recho ${undef-"$@"}x + expect '' recho "$@"x + expect '' recho "$zzz"x + expect '<^?>' recho ${undef-} + expect '<^?>' recho ${undef-""} *************** *** 302,303 **** --- 337,436 ---- unset foo recho "${foo:-"a"}*" + + f () + { + echo "Number of args: $#" + echo "<\${*-x}>: <${*-x}>" + echo "<\${@-x}>: <${@-x}>" + } + + f + f '' + f '' '' + + set 1 2 3 4 5 + + expect '<5>' + recho ${#} + expect '<5>' + recho ${#:foo} + expect '<5>' + recho ${#:-foo} + expect '<5>' + recho ${#-posparams} + expect '<5>' + recho ${#:-posparams} + + expect '<0>' + recho ${#!} + + expect nothing + recho $! + expect nothing + recho ${!} + + expect nothing + recho $8 + expect nothing + recho ${8} + + shift $# + + expect '<0>' + recho ${#} + expect '<0>' + recho ${#:foo} + expect '<0>' + recho ${#:-foo} + expect '<0>' + recho ${#-posparams} + expect '<0>' + recho ${#:-posparams} + + expect '' + recho ${!-posparams} + expect '' + recho ${!:-posparams} + + expect '<2>' + recho ${#-} + + expect '<0>' + recho ${#-posparams} + + expect '<0>' + recho ${#?:-xyz} + + expect '<1>' + recho ${#?} + + set a b c d e + + expect '<5>' + recho ${#} + expect '<5>' + recho ${#?:-xyz} + + shift $# + + expect '<0>' + recho ${#:-foo} + + expect a bad substitution error + recho ${#:} + expect a bad substitution error + recho ${#/} + expect a bad substitution error + recho ${#%} + expect a bad substitution error + recho ${#=} + expect a bad substitution error + recho ${#+} + expect a bad substitution error + recho ${#1xyz} + + expect a math syntax error + recho ${#:%} + + expect '<0>' + recho ${#:-} diff -Nrc2 bash-2.01.1/tests/new-exp.right bash-2.02/tests/new-exp.right *** bash-2.01.1/tests/new-exp.right Thu Feb 27 12:39:09 1997 --- bash-2.02/tests/new-exp.right Fri Nov 14 13:40:42 1997 *************** *** 23,27 **** argv[2] = <-> argv[1] = <-abcd-> - argv[1] = bar foo bar foo --- 23,26 ---- *************** *** 152,156 **** this is a test of proc subst this is test 2 ! ./new-exp.tests: ${#:-foo}: bad substitution ./new-exp.tests: ${#:}: bad substitution argv[1] = <'> --- 151,158 ---- this is a test of proc subst this is test 2 ! ./new-exp2.sub: /tmp/bashtmp.x*: No such file or directory ! ./new-exp2.sub: /tmp/redir-notthere: No such file or directory ! 1 ! argv[1] = <6> ./new-exp.tests: ${#:}: bad substitution argv[1] = <'> *************** *** 385,387 **** --- 387,393 ---- ./new-exp.tests: UNSET: unbound variable ./new-exp.tests: UNSET: unbound variable + argv[1] = <5> + argv[1] = <#> + argv[1] = <#> + argv[1] = <> ./new-exp.tests: ABXD: parameter unset diff -Nrc2 bash-2.01.1/tests/new-exp.sub1 bash-2.02/tests/new-exp.sub1 *** bash-2.01.1/tests/new-exp.sub1 Wed Mar 26 14:12:33 1997 --- bash-2.02/tests/new-exp.sub1 Wed Dec 31 19:00:00 1969 *************** *** 1,11 **** - expect() - { - echo expect "$@" - } - - expect this is a test of proc subst - cat <(echo this is a test of proc subst) - echo this is test 2 > /tmp/x - expect this is test 2 - cat <(cat /tmp/x) - rm -f /tmp/x --- 0 ---- diff -Nrc2 bash-2.01.1/tests/new-exp.tests bash-2.02/tests/new-exp.tests *** bash-2.01.1/tests/new-exp.tests Wed Mar 26 14:13:16 1997 --- bash-2.02/tests/new-exp.tests Wed Nov 12 13:52:25 1997 *************** *** 26,30 **** expect unset _ENV=oops ! x=${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]} # memory leak echo ${x:-unset} --- 26,30 ---- expect unset _ENV=oops ! x=${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]} echo ${x:-unset} *************** *** 65,75 **** recho -${foo%% *}- # should be -abcd- - set a b c d e - expect '' - IFS="" - recho "$@" - IFS=' - ' - foo=bar expect '' --- 65,68 ---- *************** *** 238,245 **** # caused by a shell not implementing process substitution (e.g., one # built on a NeXT) will not cause the whole test to exit prematurely ! ${THIS_SH} ./new-exp.sub1 ! expect $0: '${#:-foo}: bad substitution' ! echo ${#:-foo} expect $0: '${#:}: bad substitution' echo ${#:} --- 231,242 ---- # caused by a shell not implementing process substitution (e.g., one # built on a NeXT) will not cause the whole test to exit prematurely ! ${THIS_SH} ./new-exp1.sub ! # run the tests of $(' ! recho ${#:-foo} expect $0: '${#:}: bad substitution' echo ${#:} *************** *** 449,452 **** --- 446,458 ---- ( recho "${#UNSET}" ; echo after 7) set +u + + RECEIVED="12345" + recho "${RECEIVED:$((${#RECEIVED}-1)):1}" + RECEIVED="12345#" + recho "${RECEIVED:$((${#RECEIVED}-1)):1}" + RECEIVED="#" + recho "${RECEIVED:$((${#RECEIVED}-1)):1}" + RECEIVED="" + recho "${RECEIVED:$((${#RECEIVED}-1)):1}" # this must be last! diff -Nrc2 bash-2.01.1/tests/new-exp1.sub bash-2.02/tests/new-exp1.sub *** bash-2.01.1/tests/new-exp1.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/new-exp1.sub Wed Mar 26 14:12:33 1997 *************** *** 0 **** --- 1,11 ---- + expect() + { + echo expect "$@" + } + + expect this is a test of proc subst + cat <(echo this is a test of proc subst) + echo this is test 2 > /tmp/x + expect this is test 2 + cat <(cat /tmp/x) + rm -f /tmp/x diff -Nrc2 bash-2.01.1/tests/new-exp2.sub bash-2.02/tests/new-exp2.sub *** bash-2.01.1/tests/new-exp2.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/new-exp2.sub Fri Nov 14 13:40:27 1997 *************** *** 0 **** --- 1,36 ---- + export LC_ALL=C + export LANG=C + + # test out the new $(< filename) code + # it should be exactly equivalent to $(cat filename) + + FILENAME=/tmp/bashtmp.x$$ + + trap 'rm -f $FILENAME' 0 + + cat >$FILENAME << EOF + line 1 + line 2 + line 3 + EOF + + LINES1=$(cat $FILENAME) + LINES2=$(< $FILENAME) + + if [[ $LINES1 != $LINES2 ]]; then + echo 'whoops: $(< filename) failed' + fi + + LINES2=$(< /tmp/bashtmp.x*) + if [[ $LINES1 != $LINES2 ]]; then + echo 'whoops: $(< filename) with glob expansion failed' + fi + + # but the glob expansion in the redirection should fail in posix mode + set -o posix + LINES2=$(< /tmp/bashtmp.x*) + set +o posix + + # now see what happens when we try it with a non-existant file + LINES3=$(< /tmp/redir-notthere) + echo $? diff -Nrc2 bash-2.01.1/tests/posix2.tests bash-2.02/tests/posix2.tests *** bash-2.01.1/tests/posix2.tests Wed Jun 19 12:25:21 1996 --- bash-2.02/tests/posix2.tests Mon Nov 17 13:13:59 1997 *************** *** 141,144 **** --- 141,173 ---- fi + newtest + SQUOTE="'" + val1=$(set | sed -n 's:^SQUOTE=::p') + # if I change the default quoting style for variable values, this must change + if [ "$val1" != "''\'''" ]; then + testfail "variable quoting 1" + fi + + newtest + VTILDE='~' + val1=$(set | sed -n 's:^VTILDE=::p') + if [ "$val1" != "'~'" ]; then + testfail "variable quoting 2" + fi + + newtest + VHASH=ab#cd + val1=$(set | sed -n 's:^VHASH=::p') + if [ "$val1" != "ab#cd" ]; then + testfail "variable quoting 3" + fi + + newtest + VHASH2=#abcd + val1=$(set | sed -n 's:^VHASH2=::p') + if [ "$val1" != "'#abcd'" ]; then + testfail "variable quoting 4" + fi + if [ $exitval = 0 ]; then echo "All tests passed" diff -Nrc2 bash-2.01.1/tests/posixpat.right bash-2.02/tests/posixpat.right *** bash-2.01.1/tests/posixpat.right Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/posixpat.right Mon Nov 17 15:03:15 1997 *************** *** 0 **** --- 1,42 ---- + ok 1 + ok 2 + ok 3 + ok 4 + ok 5 + ok 6 + ok 7 + ok 8 + ok 9 + ok 10 + ok 11 + ok 12 + ok 13 + ok 14 + ok 15 + ok 16 + ok 17 + ok 18 + ok 19 + ok 20 + ok 21 + ok -- space + ok -- blank + ok 1 + ok 2 + ok 3 + ok 4 + ok 5 + ok 6 + ok 7 + ok 8 + ok 9 + ok 10 + ok 11 + ok 12 + ok 13 + ok 14 + ok 15 + ok 16 + ok 1 + ok 2 + ok 3 diff -Nrc2 bash-2.01.1/tests/posixpat.tests bash-2.02/tests/posixpat.tests *** bash-2.01.1/tests/posixpat.tests Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/posixpat.tests Mon Feb 9 11:21:18 1998 *************** *** 0 **** --- 1,233 ---- + # A test suite for the POSIX.2 (BRE) pattern matching code + LC_ALL=C + LANG=C + + # First, test POSIX.2 character classes + + case e in + [[:xdigit:]]) echo ok 1;; + esac + + case a in + [[:alpha:]123]) echo ok 2;; + esac + + case 1 in + [[:alpha:]123]) echo ok 3;; + esac + + case 9 in + [![:alpha:]]) echo ok 4;; + esac + + # invalid character class expressions are just characters to be matched + case a in + [:al:]) echo ok 5;; + esac + + case a in + [[:al:]) echo ok 6;; + esac + + case '!' in + [abc[:punct:][0-9]) echo ok 7;; + esac + + # let's try to match the start of a valid sh identifier + case 'PATH' in + [_[:alpha:]]*) echo ok 8;; + esac + + # let's try to match the first two characters of a valid sh identifier + case PATH in + [_[:alpha:]][_[:alnum:]]*) echo ok 9;; + esac + + # is ^C a cntrl character? + case $'\003' in + [[:cntrl:]]) echo ok 10;; + esac + + # how about A? + case A in + [[:cntrl:]]) echo oops -- cntrl ;; + *) echo ok 11;; + esac + + case 9 in + [[:digit:]]) echo ok 12;; + esac + + case X in + [[:digit:]]) echo oops -- digit;; + *) echo ok 13;; + esac + + case $'\033' in + [[:graph:]]) echo oops -- graph;; + *) echo ok 14;; + esac + + case $'\040' in + [[:graph:]]) echo oops -- graph 2;; + *) echo ok 15;; + esac + + case ' ' in + [[:graph:]]) echo oops -- graph 3;; + *) echo ok 16;; + esac + + case 'aB' in + [[:lower:]][[:upper:]]) echo ok 17;; + esac + + case $'\040' in + [[:print:]]) echo ok 18;; + *) echo oops -- print;; + esac + + case PS3 in + [_[:alpha:]][_[:alnum:]][_[:alnum:]]*) echo ok 19;; + esac + + case a in + [[:alpha:][:digit:]]) echo ok 20;; + *) echo oops - skip brackpat ;; + esac + + case a in + [[:alpha:]\]) echo oops -- dangling backslash in brackpat ;; + *) echo ok 21 ;; + esac + + # what's a newline? is it a blank? a space? + case $'\n' in + [[:blank:]]) echo ok -- blank ;; + [[:space:]]) echo ok -- space ;; + *) echo oops newline ;; + esac + + # OK, what's a tab? is it a blank? a space? + case $'\t' in + [[:blank:]]) echo ok -- blank ;; + [[:space:]]) echo ok -- space ;; + *) echo oops newline ;; + esac + + # let's check out characters in the ASCII range + case $'\377' in + [[:ascii:]]) echo oops -- ascii\?;; + esac + + case 9 in + [1[:alpha:]123]) echo oops 1;; + esac + + # however, an unterminated brace expression containing a valid char class + # that matches had better fail + case a in + [[:alpha:]) echo oops 2;; + esac + + case $'\b' in + [[:graph:]]) echo oops 3;; + esac + + case $'\b' in + [[:print:]]) echo oops 4;; + esac + + case $' ' in + [[:punct:]]) echo oops 5;; + esac + + # Next, test POSIX.2 collating symbols + + case 'a' in + [[.a.]]) echo ok 1;; + esac + + case '-' in + [[.hyphen.]-9]) echo ok 2;; + esac + + case 'p' in + [[.a.]-[.z.]]) echo ok 3;; + esac + + case '-' in + [[.-.]]) echo ok 4;; + esac + + case ' ' in + [[.space.]]) echo ok 5;; + esac + + case ' ' in + [[.grave-accent.]]) echo oops - grave;; + *) echo ok 6;; + esac + + case '4' in + [[.-.]-9]) echo ok 7;; + esac + + # an invalid collating symbol cannot be the first part of a range + case 'c' in + [[.yyz.]-[.z.]]) echo oops - yyz;; + *) echo ok 8;; + esac + + case 'c' in + [[.yyz.][.a.]-z]) echo ok 9;; + esac + + # but when not part of a range is not an error + case 'c' in + [[.yyz.][.a.]-[.z.]]) echo ok 10 ;; + esac + + case 'p' in + [[.a.]-[.Z.]]) echo oops -- bad range ;; + *) echo ok 11;; + esac + + case p in + [[.a.]-[.zz.]p]) echo ok 12;; + *) echo oops -- bad range 2;; + esac + + case p in + [[.aa.]-[.z.]p]) echo ok 13;; + *) echo oops -- bad range 3;; + esac + + case c in + [[.yyz.]cde]) echo ok 14;; + esac + + case abc in + [[.cb.]a-Za]*) echo ok 15;; + esac + + case $'\t' in + [[.space.][.tab.][.newline.]]) echo ok 16;; + esac + + # and finally, test POSIX.2 equivalence classes + + case "abc" in + [[:alpha:]][[=b=]][[:ascii:]]) echo ok 1;; + esac + + case "abc" in + [[:alpha:]][[=B=]][[:ascii:]]) echo oops -- =B=;; + *) echo ok 2 ;; + esac + + case a in + [[=b=]) echo oops;; # an incomplete equiv class is just a string + *) echo ok 3;; + esac + Binary files bash-2.01.1/tests/printf.right and bash-2.02/tests/printf.right differ diff -Nrc2 bash-2.01.1/tests/printf.tests bash-2.02/tests/printf.tests *** bash-2.01.1/tests/printf.tests Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/printf.tests Fri Jan 30 13:08:00 1998 *************** *** 0 **** --- 1,176 ---- + LC_ALL=C + + # these should output error messages -- the format is required + printf + printf -- + + # these should output nothing + printf "" + printf -- "" + + # this should expand escape sequences in the format string, nothing else + printf "\tone\n" + + # this should not cut off output after the \c + printf "one\ctwo\n" + + # and unrecognized backslash escapes should have the backslash preserverd + printf "4\.2\n" + + printf "no newline " ; printf "now newline\n" + + # %% -> % + printf "%%\n" + + # simple character output + printf "%c\n" ABCD + + # test simple string output + printf "%s\n" unquoted + + # test quoted string output + printf "%s %q\n" unquoted quoted + printf "%s%10q\n" unquoted quoted + + printf "%q\n" 'this&that' + + # make sure the format string is reused to use up arguments + printf "%d " 1 2 3 4 5; printf "\n" + + # make sure that extra format characters get null arguments + printf "%s %d %d %d\n" onestring + + printf "%s %d %u %4.2f\n" onestring + + printf -- "--%s %s--\n" 4.2 '' + printf -- "--%s %s--\n" 4.2 + + # test %b escapes + + # 8 is a non-octal digit, so the `81' should be output + printf -- "--%b--\n" '\n\081' + + printf -- "--%b--\n" '\t\0101' + printf -- "--%b--\n" '\t\101' + + # these should all display `A7' + echo -e "\1017" + echo -e "\x0417" + + printf "%b\n" '\01017' + printf "%b\n" '\1017' + printf "%b\n" '\x0417' + + printf -- "--%b--\n" '\"abcd\"' + printf -- "--%b--\n" "\'abcd\'" + + printf -- "--%b--\n" 'a\\x' + + printf -- "--%b--\n" '\x' + + Z1=$(printf -- "%b\n" '\a\b\e\f\r\v') + Z2=$'\a\b\e\f\r\v' + + if [ "$Z1" != "$Z2" ]; then + echo "whoops: printf %b and $'' differ" >&2 + fi + unset Z1 Z2 + + printf -- "--%b--\n" '' + printf -- "--%b--\n" + + # the stuff following the \c should be ignored, as well as the rest + # of the format string + printf -- "--%b--\n" '4.2\c5.4\n'; printf "\n" + + # make sure that a fieldwidth and precision of `*' are handled right + printf "%10.8s\n" 4.4BSD + printf "%*.*s\n" 10 8 4.4BSD + + printf "%10.8q\n" 4.4BSD + printf "%*.*q\n" 10 8 4.4BSD + + printf "%6b\n" 4.4BSD + printf "%*b\n" 6 4.4BSD + + # we handle this crap with homemade code in printf.def + printf "%10b\n" 4.4BSD + printf -- "--%-10b--\n" 4.4BSD + printf "%4.2b\n" 4.4BSD + printf "%.3b\n" 4.4BSD + printf -- "--%-8b--\n" 4.4BSD + + # test numeric conversions -- these four lines should echo identically + printf "%d %u %i 0%o 0x%x 0x%X\n" 255 255 255 255 255 255 + printf "%d %u %i %#o %#x %#X\n" 255 255 255 255 255 255 + + printf "%ld %lu %li 0%o 0x%x 0x%X\n" 255 255 255 255 255 255 + printf "%ld %lu %li %#o %#x %#X\n" 255 255 255 255 255 255 + + printf "%10d\n" 42 + printf "%10d\n" -42 + + printf "%*d\n" 10 42 + printf "%*d\n" 10 -42 + + # test some simple floating point formats + printf "%4.2f\n" 4.2 + printf "%#4.2f\n" 4.2 + printf "%#4.1f\n" 4.2 + + printf "%*.*f\n" 4 2 4.2 + printf "%#*.*f\n" 4 2 4.2 + printf "%#*.*f\n" 4 1 4.2 + + printf "%E\n" 4.2 + printf "%e\n" 4.2 + printf "%6.1E\n" 4.2 + printf "%6.1e\n" 4.2 + + printf "%G\n" 4.2 + printf "%g\n" 4.2 + printf "%6.2G\n" 4.2 + printf "%6.2g\n" 4.2 + + # test some of the more esoteric features of POSIX.1 printf + printf "%d\n" "'string'" + printf "%d\n" '"string"' + + printf "%#o\n" "'string'" + printf "%#o\n" '"string"' + + printf "%#x\n" "'string'" + printf "%#X\n" '"string"' + + printf "%6.2f\n" "'string'" + printf "%6.2f\n" '"string"' + + # output from these two lines had better be the same + printf -- "--%6.4s--\n" abcdefghijklmnopqrstuvwxyz + printf -- "--%6.4b--\n" abcdefghijklmnopqrstuvwxyz + + # and these two also + printf -- "--%12.10s--\n" abcdefghijklmnopqrstuvwxyz + printf -- "--%12.10b--\n" abcdefghijklmnopqrstuvwxyz + + # error messages + + # this should be an overflow, but error messages vary between systems + # printf "%lu\n" 4294967296 + + # ...but we cannot use this because some systems (SunOS4, for example), + # happily ignore overflow conditions in strtol(3) + #printf "%ld\n" 4294967296 + + # in the future this may mean to put the output into VAR, but for + # now it is an error + printf -v var "%10d" $RANDOM + + printf "%10" + printf "ab%Mcd\n" + + # this caused an infinite loop in older versions of printf + printf "%y" 0 + + printf "%d\n" GNU + printf "%o\n" GNU diff -Nrc2 bash-2.01.1/tests/read.right bash-2.02/tests/read.right *** bash-2.01.1/tests/read.right Fri Mar 14 11:09:25 1997 --- bash-2.02/tests/read.right Mon Nov 17 14:17:51 1997 *************** *** 10,13 **** --- 10,18 ---- -\-a b\- -\ a b\- + argv[1] = <^A> + argv[1] = <^A> + argv[1] = <^?> + argv[1] = <^?> + argv[1] = 1: x[A] y[B] z[] 1a: diff -Nrc2 bash-2.01.1/tests/read.tests bash-2.02/tests/read.tests *** bash-2.01.1/tests/read.tests Fri Mar 14 11:08:53 1997 --- bash-2.02/tests/read.tests Mon Nov 17 14:17:03 1997 *************** *** 14,17 **** --- 14,29 ---- echo " \ a b\ " | ( read -r x ; echo -"$x"- ) + # make sure that CTLESC and CTLNUL are passed through correctly + echo $'\001' | ( read var ; recho "$var" ) + echo $'\001' | ( read ; recho "$REPLY" ) + + echo $'\177' | ( read var ; recho "$var" ) + echo $'\177' | ( read ; recho "$REPLY" ) + + # make sure a backslash-quoted \\n still disappears from the input when + # we're not reading in `raw' mode, and no stray CTLESC chars are left in + # the input stream + echo $'ab\\\ncd' | ( read ; recho "$REPLY" ) + echo "A B " > /tmp/IN unset x y z *************** *** 67,69 **** echo " foo" | { IFS=$':' ; read line; recho "$line"; } - --- 79,80 ---- diff -Nrc2 bash-2.01.1/tests/rsh.right bash-2.02/tests/rsh.right *** bash-2.01.1/tests/rsh.right Thu Feb 27 11:38:39 1997 --- bash-2.02/tests/rsh.right Thu Nov 20 12:07:19 1997 *************** *** 9,12 **** --- 9,13 ---- ./rsh.tests: set: unknown option: +r set: usage: set [--abefhkmnptuvxBCHP] [-o option] [arg ...] + ./rsh.tests: set: restricted: unknown option name ./rsh.tests: exec: restricted ./rsh.tests: after exec diff -Nrc2 bash-2.01.1/tests/rsh.tests bash-2.02/tests/rsh.tests *** bash-2.01.1/tests/rsh.tests Fri Feb 28 12:46:43 1997 --- bash-2.02/tests/rsh.tests Thu Nov 20 12:05:05 1997 *************** *** 27,30 **** --- 27,31 ---- set +r + set +o restricted exec /bin/date diff -Nrc2 bash-2.01.1/tests/run-array bash-2.02/tests/run-array *** bash-2.01.1/tests/run-array Fri Feb 2 16:09:48 1996 --- bash-2.02/tests/run-array Tue Sep 23 14:38:45 1997 *************** *** 1,2 **** --- 1,4 ---- + echo "warning: all of these tests will fail if arrays have not" >&2 + echo "warning: been compiled into the shell" >&2 ${THIS_SH} ./array.tests > /tmp/xx 2>&1 diff /tmp/xx array.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-array2 bash-2.02/tests/run-array2 *** bash-2.01.1/tests/run-array2 Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/run-array2 Tue Sep 23 14:38:49 1997 *************** *** 0 **** --- 1,4 ---- + echo "warning: all of these tests will fail if arrays have not" >&2 + echo "warning: been compiled into the shell" >&2 + ${THIS_SH} ./array-at-star > /tmp/xx 2>&1 + diff /tmp/xx array2.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-cond bash-2.02/tests/run-cond *** bash-2.01.1/tests/run-cond Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/run-cond Tue Sep 16 11:48:26 1997 *************** *** 0 **** --- 1,7 ---- + echo "warning: all of these tests will fail if the conditional command has not" >&2 + echo "warning: been compiled into the shell" >&2 + echo "warning: some of these tests will fail if extended pattern matching has not" >&2 + echo "warning: been compiled into the shell" >&2 + + ${THIS_SH} ./cond.tests > /tmp/xx 2>&1 + diff /tmp/xx cond.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-dirstack bash-2.02/tests/run-dirstack *** bash-2.01.1/tests/run-dirstack Mon Feb 24 12:52:30 1997 --- bash-2.02/tests/run-dirstack Thu Sep 25 14:26:47 1997 *************** *** 1,2 **** ! ${THIS_SH} ./dirstack.tests > /tmp/xx 2>&1 ! diff /tmp/xx dirstack.right && rm -f /tmp/xx --- 1,5 ---- ! ${THIS_SH} ./dstack.tests > /tmp/xx 2>&1 ! diff /tmp/xx dstack.right && rm -f /tmp/xx ! ! ${THIS_SH} ./dstack2.tests > /tmp/xx 2>&1 ! diff /tmp/xx dstack2.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-dollars bash-2.02/tests/run-dollars *** bash-2.01.1/tests/run-dollars Fri Feb 2 16:10:18 1996 --- bash-2.02/tests/run-dollars Mon Aug 25 17:23:07 1997 *************** *** 1,3 **** ! ${THIS_SH} ./dollar-star.sh a b > /tmp/xx 2>&1 ! ${THIS_SH} ./dollar-at.sh a b >>/tmp/xx 2>&1 diff /tmp/xx dollar.right && rm -f /tmp/xx --- 1,2 ---- ! ${THIS_SH} ./dollar-at-star > /tmp/xx 2>&1 diff /tmp/xx dollar.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-execscript bash-2.02/tests/run-execscript *** bash-2.01.1/tests/run-execscript Fri Mar 7 16:00:39 1997 --- bash-2.02/tests/run-execscript Thu Jul 3 12:13:31 1997 *************** *** 5,7 **** echo "warning: produce diff output, please do not consider this a test failure" >&2 ${THIS_SH} ./execscript > /tmp/xx 2>&1 ! diff /tmp/xx execscript.right && rm -f /tmp/xx --- 5,7 ---- echo "warning: produce diff output, please do not consider this a test failure" >&2 ${THIS_SH} ./execscript > /tmp/xx 2>&1 ! diff /tmp/xx exec.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-extglob bash-2.02/tests/run-extglob *** bash-2.01.1/tests/run-extglob Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/run-extglob Thu Aug 7 14:11:31 1997 *************** *** 0 **** --- 1,4 ---- + PATH=$PATH:`pwd` + export PATH + ${THIS_SH} ./extglob.tests | grep -v '^expect' > /tmp/xx + diff /tmp/xx extglob.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-histexpand bash-2.02/tests/run-histexpand *** bash-2.01.1/tests/run-histexpand Thu Mar 6 16:08:44 1997 --- bash-2.02/tests/run-histexpand Thu Jul 3 11:51:55 1997 *************** *** 1,4 **** echo "warning: all of these tests will fail if history has not been compiled" >&2 echo "warning: into the shell" >&2 ! ${THIS_SH} ./histexpand.tests > /tmp/xx 2>&1 ! diff /tmp/xx histexpand.right && rm -f /tmp/xx --- 1,4 ---- echo "warning: all of these tests will fail if history has not been compiled" >&2 echo "warning: into the shell" >&2 ! ${THIS_SH} ./histexp.tests > /tmp/xx 2>&1 ! diff /tmp/xx histexp.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-ifs-tests bash-2.02/tests/run-ifs-tests *** bash-2.01.1/tests/run-ifs-tests Fri Feb 2 16:10:57 1996 --- bash-2.02/tests/run-ifs-tests Thu Jul 3 12:19:39 1997 *************** *** 2,13 **** # show that IFS is only applied to the result of expansions # ! ${THIS_SH} ifs-test-1.sh > /tmp/xx ! diff /tmp/xx ./ifs.1.right ! ${THIS_SH} ifs-test-2.sh > /tmp/xx ! diff /tmp/xx ./ifs.2.right ! ${THIS_SH} ifs-test-3.sh > /tmp/xx ! diff /tmp/xx ./ifs.3.right rm -f /tmp/xx --- 2,13 ---- # show that IFS is only applied to the result of expansions # ! ${THIS_SH} ifs-1.test > /tmp/xx ! diff /tmp/xx ./ifs-1.right ! ${THIS_SH} ifs-2.test > /tmp/xx ! diff /tmp/xx ./ifs-2.right ! ${THIS_SH} ifs-3.test > /tmp/xx ! diff /tmp/xx ./ifs-3.right rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-minimal bash-2.02/tests/run-minimal *** bash-2.01.1/tests/run-minimal Mon Mar 24 15:51:32 1997 --- bash-2.02/tests/run-minimal Thu Jul 3 13:11:57 1997 *************** *** 26,29 **** --- 26,30 ---- run-dollars|run-execscript|run-func|run-getopts|run-heredoc) echo $x ; sh $x ;; run-ifs-tests|run-input-test|run-more-exp|run-nquote|run-posix2) echo $x ; sh $x ;; + run-posixpat) echo $x ; sh $x ;; run-precedence|run-quote|run-read|run-rhs-exp|run-strip|run-tilde) echo $x ; sh $x ;; *) ;; diff -Nrc2 bash-2.01.1/tests/run-new-exp bash-2.02/tests/run-new-exp *** bash-2.01.1/tests/run-new-exp Fri Feb 2 16:11:32 1996 --- bash-2.02/tests/run-new-exp Thu Oct 2 15:03:58 1997 *************** *** 1,2 **** --- 1,7 ---- + echo "warning: two of these tests will fail if your OS does not support" >&2 + echo "warning: named pipes or the /dev/fd filesystem. If the tests of the" >&2 + echo "warning: process substitution mechanism fail, please do not consider" >&2 + echo "warning: this a test failure" >&2 + ${THIS_SH} ./new-exp.tests 2>&1 | grep -v '^expect' > /tmp/xx diff /tmp/xx new-exp.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-posixpat bash-2.02/tests/run-posixpat *** bash-2.01.1/tests/run-posixpat Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/run-posixpat Thu Jul 3 13:10:11 1997 *************** *** 0 **** --- 1,2 ---- + ${THIS_SH} ./posixpat.tests > /tmp/xx + diff /tmp/xx posixpat.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-printf bash-2.02/tests/run-printf *** bash-2.01.1/tests/run-printf Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/run-printf Wed Aug 13 16:53:57 1997 *************** *** 0 **** --- 1,2 ---- + ${THIS_SH} ./printf.tests > /tmp/xx 2>&1 + diff /tmp/xx printf.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-set-e bash-2.02/tests/run-set-e *** bash-2.01.1/tests/run-set-e Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/run-set-e Fri Feb 2 16:11:58 1996 *************** *** 0 **** --- 1,2 ---- + ${THIS_SH} ./set-e-test > /tmp/xx + diff /tmp/xx set-e.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-set-e-test bash-2.02/tests/run-set-e-test *** bash-2.01.1/tests/run-set-e-test Fri Feb 2 16:11:58 1996 --- bash-2.02/tests/run-set-e-test Wed Dec 31 19:00:00 1969 *************** *** 1,2 **** - ${THIS_SH} ./set-e-test > /tmp/xx - diff /tmp/xx set-e.right && rm -f /tmp/xx --- 0 ---- diff -Nrc2 bash-2.01.1/tests/run-shopt bash-2.02/tests/run-shopt *** bash-2.01.1/tests/run-shopt Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/run-shopt Fri Nov 14 14:37:47 1997 *************** *** 0 **** --- 1,2 ---- + ${THIS_SH} ./shopt.tests > /tmp/xx 2>&1 + diff /tmp/xx shopt.right && rm -f /tmp/xx diff -Nrc2 bash-2.01.1/tests/run-trap bash-2.02/tests/run-trap *** bash-2.01.1/tests/run-trap Fri Feb 21 14:17:31 1997 --- bash-2.02/tests/run-trap Tue Dec 16 10:31:51 1997 *************** *** 1,2 **** --- 1,6 ---- + echo "warning: UNIX versions number signals differently. If output differing" >&2 + echo "warning: only in line numbers is produced, please do not consider this" >&2 + echo "warning: a test failure." >&2 + ${THIS_SH} ./trap.tests > /tmp/xx 2>&1 diff /tmp/xx trap.right && rm -f /tmp/xx Binary files bash-2.01.1/tests/sh.core and bash-2.02/tests/sh.core differ diff -Nrc2 bash-2.01.1/tests/shopt.right bash-2.02/tests/shopt.right *** bash-2.01.1/tests/shopt.right Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/shopt.right Thu Nov 20 12:00:33 1997 *************** *** 0 **** --- 1,189 ---- + ./shopt.tests: shopt: illegal option: -z + shopt: usage: shopt [-pqsu] [-o long-option] optname [optname...] + -- + shopt -u cdable_vars + shopt -s cdspell + shopt -u checkhash + shopt -u checkwinsize + shopt -s cmdhist + shopt -u dotglob + shopt -u execfail + shopt -s expand_aliases + shopt -u extglob + shopt -u histreedit + shopt -u histappend + shopt -u histverify + shopt -s hostcomplete + shopt -u huponexit + shopt -s interactive_comments + shopt -u lithist + shopt -u mailwarn + shopt -u nocaseglob + shopt -u nullglob + shopt -s promptvars + shopt -u shift_verbose + shopt -s sourcepath + -- + shopt -u huponexit + shopt -u checkwinsize + shopt -s sourcepath + -- + shopt -s cdspell + shopt -s cmdhist + shopt -s expand_aliases + shopt -s hostcomplete + shopt -s interactive_comments + shopt -s promptvars + shopt -s sourcepath + -- + shopt -u cdable_vars + shopt -u checkhash + shopt -u checkwinsize + shopt -u dotglob + shopt -u execfail + shopt -u extglob + shopt -u histreedit + shopt -u histappend + shopt -u histverify + shopt -u huponexit + shopt -u lithist + shopt -u mailwarn + shopt -u nocaseglob + shopt -u nullglob + shopt -u shift_verbose + -- + cdable_vars off + checkhash off + checkwinsize off + dotglob off + execfail off + extglob off + histreedit off + histappend off + histverify off + huponexit off + lithist off + mailwarn off + nocaseglob off + nullglob off + shift_verbose off + -- + set +o allexport + set -o braceexpand + set +o errexit + set -o hashall + set -o histexpand + set +o keyword + set -o monitor + set +o noclobber + set +o noexec + set +o noglob + set +o notify + set +o nounset + set +o onecmd + set +o physical + set -o privileged + set +o verbose + set +o xtrace + set -o history + set +o ignoreeof + set +o interactive-comments + set +o posix + set -o emacs + set +o vi + -- + allexport off + braceexpand on + errexit off + hashall on + histexpand on + keyword off + monitor on + noclobber off + noexec off + noglob off + notify off + nounset off + onecmd off + physical off + privileged on + verbose off + xtrace off + history on + ignoreeof off + interactive-comments off + posix off + emacs on + vi off + -- + set +o allexport + set -o braceexpand + set +o errexit + set -o hashall + set -o histexpand + set +o keyword + set -o monitor + set +o noclobber + set +o noexec + set +o noglob + set +o notify + set +o nounset + set +o onecmd + set +o physical + set -o privileged + set +o verbose + set +o xtrace + set -o history + set +o ignoreeof + set +o interactive-comments + set +o posix + set -o emacs + set +o vi + -- + set -o history + set +o verbose + -- + set -o braceexpand + set -o hashall + set -o histexpand + set -o monitor + set -o privileged + set -o history + set -o emacs + -- + set +o allexport + set +o errexit + set +o keyword + set +o noclobber + set +o noexec + set +o noglob + set +o notify + set +o nounset + set +o onecmd + set +o physical + set +o verbose + set +o xtrace + set +o ignoreeof + set +o interactive-comments + set +o posix + set +o vi + -- + allexport off + errexit off + keyword off + noclobber off + noexec off + noglob off + notify off + nounset off + onecmd off + physical off + verbose off + xtrace off + ignoreeof off + interactive-comments off + posix off + vi off + -- + ./shopt.tests: shopt: xyz1: unknown shell option name + ./shopt.tests: shopt: xyz1: unknown option name diff -Nrc2 bash-2.01.1/tests/shopt.tests bash-2.02/tests/shopt.tests *** bash-2.01.1/tests/shopt.tests Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/shopt.tests Thu Nov 20 11:59:32 1997 *************** *** 0 **** --- 1,93 ---- + # let's try an error message first + shopt -z + + # first, set up a known environment + shopt -u cdable_vars + shopt -s cdspell + shopt -u checkhash + shopt -u checkwinsize + shopt -s cmdhist + shopt -u dotglob + shopt -u execfail + shopt -s expand_aliases + shopt -u extglob + shopt -u histreedit + shopt -u histappend + shopt -u histverify + shopt -s hostcomplete + shopt -u huponexit + shopt -s interactive_comments + shopt -u lithist + shopt -u mailwarn + shopt -u nocaseglob + shopt -u nullglob + shopt -s promptvars + shopt -u shift_verbose + shopt -s sourcepath + + # Now, start checking the output + builtin printf -- "--\n" + shopt -p # list 'em all + builtin printf -- "--\n" + # test specific variables + shopt -p huponexit + shopt -p checkwinsize + shopt -p sourcepath + + builtin printf -- "--\n" + shopt -s -p + builtin printf -- "--\n" + shopt -u -p + builtin printf -- "--\n" + shopt -u + + # Now set up another known environment + set +o allexport + set -o braceexpand + set +o errexit + set -o hashall + set -o histexpand + set +o keyword + set -o monitor + set +o noclobber + set +o noexec + set +o noglob + set +o notify + set +o nounset + set +o onecmd + set +o physical + set -o privileged + set +o verbose + set +o xtrace + set -o history + set +o ignoreeof + set -o interactive-comments + set +o posix + set -o emacs + set +o vi + + # list 'em all + builtin printf -- "--\n" + shopt -o -p + + builtin printf -- "--\n" + set -o + builtin printf -- "--\n" + set +o + + # test specific variables + builtin printf -- "--\n" + shopt -p -o history + shopt -p -o verbose + + builtin printf -- "--\n" + shopt -s -p -o + builtin printf -- "--\n" + shopt -u -p -o + builtin printf -- "--\n" + shopt -u -o + + # errors + builtin printf -- "--\n" + shopt -p xyz1 + shopt -o -p xyz1 diff -Nrc2 bash-2.01.1/tests/source.sub1 bash-2.02/tests/source.sub1 *** bash-2.01.1/tests/source.sub1 Mon Feb 24 14:48:40 1997 --- bash-2.02/tests/source.sub1 Wed Dec 31 19:00:00 1969 *************** *** 1 **** - echo $AVAR --- 0 ---- diff -Nrc2 bash-2.01.1/tests/source.sub2 bash-2.02/tests/source.sub2 *** bash-2.01.1/tests/source.sub2 Mon Feb 24 14:51:02 1997 --- bash-2.02/tests/source.sub2 Wed Dec 31 19:00:00 1969 *************** *** 1,5 **** - echo in source.sub2, calling return - - return 5 - - echo oops -- return in source.sub2 failed --- 0 ---- diff -Nrc2 bash-2.01.1/tests/source.sub3 bash-2.02/tests/source.sub3 *** bash-2.01.1/tests/source.sub3 Thu Feb 27 11:33:00 1997 --- bash-2.02/tests/source.sub3 Wed Dec 31 19:00:00 1969 *************** *** 1 **** - echo "$@" --- 0 ---- diff -Nrc2 bash-2.01.1/tests/source.sub4 bash-2.02/tests/source.sub4 *** bash-2.01.1/tests/source.sub4 Fri Feb 28 12:33:26 1997 --- bash-2.02/tests/source.sub4 Wed Dec 31 19:00:00 1969 *************** *** 1 **** - set -- m n o p --- 0 ---- diff -Nrc2 bash-2.01.1/tests/source1.sub bash-2.02/tests/source1.sub *** bash-2.01.1/tests/source1.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/source1.sub Mon Feb 24 14:48:40 1997 *************** *** 0 **** --- 1 ---- + echo $AVAR diff -Nrc2 bash-2.01.1/tests/source2.sub bash-2.02/tests/source2.sub *** bash-2.01.1/tests/source2.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/source2.sub Mon Feb 24 14:51:02 1997 *************** *** 0 **** --- 1,5 ---- + echo in source.sub2, calling return + + return 5 + + echo oops -- return in source.sub2 failed diff -Nrc2 bash-2.01.1/tests/source3.sub bash-2.02/tests/source3.sub *** bash-2.01.1/tests/source3.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/source3.sub Thu Feb 27 11:33:00 1997 *************** *** 0 **** --- 1 ---- + echo "$@" diff -Nrc2 bash-2.01.1/tests/source4.sub bash-2.02/tests/source4.sub *** bash-2.01.1/tests/source4.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/source4.sub Fri Feb 28 12:33:26 1997 *************** *** 0 **** --- 1 ---- + set -- m n o p diff -Nrc2 bash-2.01.1/tests/source5.sub bash-2.02/tests/source5.sub *** bash-2.01.1/tests/source5.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/source5.sub Tue Nov 18 14:13:40 1997 *************** *** 0 **** --- 1,19 ---- + LC_ALL=en_US + unset LC_ALL + unset LANG + export LC_ALL=C + export LANG=C + + set +o posix + + # attempting to source a non-existant file is not an error... + . /tmp/source-notthere + + echo after bad source 1 + + set -o posix + + # ...unless you're in posix mode + . /tmp/source-notthere + + echo after bad source 2 diff -Nrc2 bash-2.01.1/tests/test-tests bash-2.02/tests/test-tests *** bash-2.01.1/tests/test-tests Mon Mar 3 15:12:36 1997 --- bash-2.02/tests/test-tests Tue Nov 18 12:14:00 1997 *************** *** 162,165 **** --- 162,175 ---- rm -f /tmp/test.owner + touch /tmp/test.socket + echo 't -S /tmp/test.socket' + t -S /tmp/test.socket # false + rm -f /tmp/test.socket + + touch /tmp/test.newer + echo 't -N /tmp/test.newer' + t -N /tmp/test.newer + rm -f /tmp/test.newer + echo 't "hello" = "hello"' t "hello" = "hello" diff -Nrc2 bash-2.01.1/tests/test.right bash-2.02/tests/test.right *** bash-2.01.1/tests/test.right Tue Feb 25 13:22:07 1997 --- bash-2.02/tests/test.right Tue Nov 18 12:14:28 1997 *************** *** 85,88 **** --- 85,92 ---- t -O /tmp/test.owner 0 + t -S /tmp/test.socket + 1 + t -N /tmp/test.newer + 0 t "hello" = "hello" 0 diff -Nrc2 bash-2.01.1/tests/trap.right bash-2.02/tests/trap.right *** bash-2.01.1/tests/trap.right Tue Feb 25 15:36:16 1997 --- bash-2.02/tests/trap.right Fri Nov 14 12:24:18 1997 *************** *** 49,51 **** --- 49,55 ---- caught a child death trap -- 'echo caught a child death' SIGCHLD + trap -- 'echo exiting' EXIT + trap -- 'echo aborting' SIGABRT + trap -- 'echo caught a child death' SIGCHLD + trap -- '' SIGUSR2 exiting diff -Nrc2 bash-2.01.1/tests/trap.sub1 bash-2.02/tests/trap.sub1 *** bash-2.01.1/tests/trap.sub1 Tue Feb 25 14:28:46 1997 --- bash-2.02/tests/trap.sub1 Wed Dec 31 19:00:00 1969 *************** *** 1,4 **** - # signals ignored at shell startup cannot be trapped or reset - trap 'echo USR2' USR2 - - trap -p USR2 --- 0 ---- diff -Nrc2 bash-2.01.1/tests/trap.tests bash-2.02/tests/trap.tests *** bash-2.01.1/tests/trap.tests Thu Mar 6 11:17:06 1997 --- bash-2.02/tests/trap.tests Fri Nov 14 12:23:20 1997 *************** *** 43,47 **** # hmmm...should this set the handling to SIG_IGN for children, too? trap '' USR2 ! ./trap.sub1 # --- 43,47 ---- # hmmm...should this set the handling to SIG_IGN for children, too? trap '' USR2 ! ./trap1.sub # *************** *** 57,58 **** --- 57,64 ---- trap -p SIGCHLD + + # Now reset some of the signals the shell handles specially back to + # their default values (with or without the SIG prefix) + trap SIGINT QUIT TERM + + trap diff -Nrc2 bash-2.01.1/tests/trap1.sub bash-2.02/tests/trap1.sub *** bash-2.01.1/tests/trap1.sub Wed Dec 31 19:00:00 1969 --- bash-2.02/tests/trap1.sub Tue Feb 25 14:28:46 1997 *************** *** 0 **** --- 1,4 ---- + # signals ignored at shell startup cannot be trapped or reset + trap 'echo USR2' USR2 + + trap -p USR2 diff -Nrc2 bash-2.01.1/tests/type.right bash-2.02/tests/type.right *** bash-2.01.1/tests/type.right Mon Mar 3 13:09:54 1997 --- bash-2.02/tests/type.right Wed Nov 12 15:01:29 1997 *************** *** 9,12 **** --- 9,13 ---- file file + file func is a function func () *************** *** 40,41 **** --- 41,46 ---- /tmp/bash bash is hashed (/tmp/bash) + file + hits command + 1 /bin/sh + 3 /tmp/bash diff -Nrc2 bash-2.01.1/tests/type.tests bash-2.02/tests/type.tests *** bash-2.01.1/tests/type.tests Mon Mar 3 13:09:32 1997 --- bash-2.02/tests/type.tests Wed Nov 12 15:00:59 1997 *************** *** 24,27 **** --- 24,28 ---- type -t /bin/sh type -t ${THIS_SH} + type -t mv type func *************** *** 52,55 **** --- 53,58 ---- type m + hash -r + hash -p /bin/sh sh type -p sh *************** *** 59,60 **** --- 62,68 ---- type -p $SHBASE type $SHBASE + + type -t $SHBASE + + # make sure the hash table looks right + hash diff -Nrc2 bash-2.01.1/tests/varenv.right bash-2.02/tests/varenv.right *** bash-2.01.1/tests/varenv.right Fri Apr 11 13:55:04 1997 --- bash-2.02/tests/varenv.right Wed Nov 12 16:03:34 1997 *************** *** 33,34 **** --- 33,35 ---- hPB braceexpand:hashall:physical + declare -r SHELLOPTS="braceexpand:hashall:physical" diff -Nrc2 bash-2.01.1/tests/varenv.sh bash-2.02/tests/varenv.sh *** bash-2.01.1/tests/varenv.sh Fri Mar 7 15:41:04 1997 --- bash-2.02/tests/varenv.sh Tue Nov 18 12:46:40 1997 *************** *** 158,161 **** --- 158,174 ---- declare -p ivar + # make sure set [-+]o ignoreeof and $IGNOREEOF are reflected + unset IGNOREEOF + set +o ignoreeof + set -o ignoreeof + if [ "$IGNOREEOF" -ne 10 ]; then + echo "./varenv.sh: set -o ignoreeof is not reflected in IGNOREEOF" >&2 + fi + unset IGNOREEOF + set +o ignoreeof + + # older versions of bash used to not reset RANDOM in subshells correctly + [[ $RANDOM -eq $(echo $RANDOM) ]] && echo "RANDOM: problem with subshells" + # make sure that shopt -o is reflected in $SHELLOPTS # first, get rid of things that might be set automatically via shell *************** *** 163,166 **** --- 176,180 ---- set +o posix set +o ignoreeof + set +o monitor echo $- echo ${SHELLOPTS} *************** *** 168,169 **** --- 182,186 ---- echo $- echo ${SHELLOPTS} + + # and make sure it is readonly + readonly -p | grep SHELLOPTS Binary files bash-2.01.1/tests/zecho.core and bash-2.02/tests/zecho.core differ diff -Nrc2 bash-2.01.1/trap.c bash-2.02/trap.c *** bash-2.01.1/trap.c Mon Aug 18 12:08:37 1997 --- bash-2.02/trap.c Wed Mar 25 12:16:09 1998 *************** *** 22,27 **** #include "config.h" - #include - #if defined (HAVE_UNISTD_H) # include --- 22,25 ---- *************** *** 29,36 **** #include "bashtypes.h" - #include "trap.h" - #include "bashansi.h" #include "shell.h" #include "signames.h" --- 27,36 ---- #include "bashtypes.h" #include "bashansi.h" + #include + + #include "trap.h" + #include "shell.h" #include "signames.h" *************** *** 136,140 **** int sig; { ! return ((sig > NSIG || sig < 0) ? "bad signal number" : signal_names[sig]); } --- 136,146 ---- int sig; { ! char *ret; ! ! /* on cygwin32, signal_names[sig] could be null */ ! ret = (sig > NSIG || sig < 0) ? "bad signal number" : signal_names[sig]; ! if (ret == NULL) ! ret = "unrecognized signal number"; ! return ret; } *************** *** 247,250 **** --- 253,258 ---- #if defined (JOB_CONTROL) && defined (SIGCHLD) + + #ifdef INCLUDE_UNUSED /* Make COMMAND_STRING be executed when SIGCHLD is caught. */ void *************** *** 254,257 **** --- 262,266 ---- set_signal (SIGCHLD, command_string); } + #endif /* Make COMMAND_STRING be executed when SIGCHLD is caught iff the current *************** *** 273,276 **** --- 282,286 ---- } + #ifdef INCLUDE_UNUSED void set_sigint_trap (command) *************** *** 279,282 **** --- 289,293 ---- set_signal (SIGINT, command); } + #endif /* Reset the SIGINT handler so that subshells that are doing `shellsy' *************** *** 516,520 **** if (code == 0) ! parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST); else if (code == EXITPROG) return (last_command_exit_value); --- 527,534 ---- if (code == 0) ! { ! reset_parser (); ! parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST); ! } else if (code == EXITPROG) return (last_command_exit_value); *************** *** 588,591 **** --- 602,606 ---- } + #ifdef INCLUDE_UNUSED /* Free all the allocated strings in the list of traps and reset the trap values to the default. */ *************** *** 603,606 **** --- 618,622 ---- trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = (char *)NULL; } + #endif /* Reset the handler for SIG to the original value. */ diff -Nrc2 bash-2.01.1/variables.c bash-2.02/variables.c *** bash-2.01.1/variables.c Tue Jul 29 10:59:25 1997 --- bash-2.02/variables.c Tue Mar 24 13:00:21 1998 *************** *** 40,43 **** --- 40,44 ---- #include "flags.h" #include "execute_cmd.h" + #include "findcmd.h" #include "mailcheck.h" #include "input.h" *************** *** 45,52 **** #include "builtins/getopt.h" #include "builtins/common.h" ! #include #if defined (HISTORY) # include "bashhist.h" #endif /* HISTORY */ --- 46,60 ---- #include "builtins/getopt.h" #include "builtins/common.h" ! ! #if defined (READLINE) ! # include "bashline.h" ! # include ! #else ! # include ! #endif #if defined (HISTORY) # include "bashhist.h" + # include #endif /* HISTORY */ *************** *** 130,138 **** do { var->attributes |= att_exported; array_needs_making = 1; } while (0) ! /* Initialize the shell variables from the current environment. */ void ! initialize_shell_variables (env, no_functions) char **env; ! int no_functions; /* If set, don't import functions from ENV. */ { char *name, *string, *temp_string; --- 138,148 ---- do { var->attributes |= att_exported; array_needs_making = 1; } while (0) ! /* Initialize the shell variables from the current environment. ! If PRIVMODE is nonzero, don't import functions from ENV or ! parse $SHELLOPTS. */ void ! initialize_shell_variables (env, privmode) char **env; ! int privmode; { char *name, *string, *temp_string; *************** *** 140,147 **** SHELL_VAR *temp_var; ! if (!shell_variables) shell_variables = make_hash_table (0); ! if (!shell_functions) shell_functions = make_hash_table (0); --- 150,157 ---- SHELL_VAR *temp_var; ! if (shell_variables == 0) shell_variables = make_hash_table (0); ! if (shell_functions == 0) shell_functions = make_hash_table (0); *************** *** 166,170 **** /* If exported function, define it now. */ ! if (no_functions == 0 && STREQN ("() {", string, 4)) { string_length = strlen (string); --- 176,180 ---- /* If exported function, define it now. */ ! if (privmode == 0 && STREQN ("() {", string, 4)) { string_length = strlen (string); *************** *** 234,238 **** if (temp_string) { ! bind_variable ("PWD", temp_string); free (temp_string); } --- 244,249 ---- if (temp_string) { ! temp_var = bind_variable ("PWD", temp_string); ! set_auto_export (temp_var); free (temp_string); } *************** *** 501,505 **** else if (shell_level > 1000) { ! internal_error ("warning: shell level (%d) too high, resetting to 1", shell_level); shell_level = 1; } --- 512,516 ---- else if (shell_level > 1000) { ! internal_warning ("shell level (%d) too high, resetting to 1", shell_level); shell_level = 1; } *************** *** 627,631 **** v = find_variable (name); ! if (!v) v = bind_variable (name, value); return (v); --- 638,642 ---- v = find_variable (name); ! if (v == 0) v = bind_variable (name, value); return (v); *************** *** 874,878 **** char *value; { ! seconds_value_assigned = string_to_long (value); shell_start_time = NOW; return (self); --- 885,889 ---- char *value; { ! seconds_value_assigned = strtol (value, (char **)NULL, 10); shell_start_time = NOW; return (self); *************** *** 901,905 **** /* A linear congruential random number generator based on the ANSI ! C standard. A more complicated one is overkill. */ /* Returns a pseudo-random number between 0 and 32767. */ --- 912,917 ---- /* A linear congruential random number generator based on the ANSI ! C standard. This one isn't very good (the values are alternately ! odd and even, for example), but a more complicated one is overkill. */ /* Returns a pseudo-random number between 0 and 32767. */ *************** *** 908,916 **** { rseed = rseed * 1103515245 + 12345; ! #if 0 ! return ((unsigned int)(rseed / 65536) % 32768); ! #else ! return ((unsigned int)(rseed % 32768)); ! #endif } --- 920,924 ---- { rseed = rseed * 1103515245 + 12345; ! return ((unsigned int)(rseed & 32767)); /* was % 32768 */ } *************** *** 1144,1148 **** /* Return the string value of a variable. Return NULL if the variable doesn't exist, or only has a function as a value. Don't cons a new ! string. */ char * get_string_value (var_name) --- 1152,1157 ---- /* Return the string value of a variable. Return NULL if the variable doesn't exist, or only has a function as a value. Don't cons a new ! string. This is a potential memory leak if the variable is found ! in the temporary environment. */ char * get_string_value (var_name) *************** *** 1452,1455 **** --- 1461,1466 ---- } + /* Perform a compound assignment statement for array NAME, where VALUE is + the text between the parens: NAME=( VALUE ) */ SHELL_VAR * assign_array_from_string (name, value) *************** *** 1468,1475 **** else if (array_p (var) == 0) var = convert_var_to_array (var); - #if 0 - else - empty_array (array_cell (var)); - #endif return (assign_array_var_from_string (var, value)); --- 1479,1482 ---- *************** *** 1493,1496 **** --- 1500,1505 ---- } + /* Perform a compound array assignment: VAR->name=( VALUE ). The + VALUE has already had the parentheses stripped. */ SHELL_VAR * assign_array_var_from_string (var, value) *************** *** 1503,1528 **** int ni, len, ind, last_ind; ! a = array_cell (var); ! /* Expand the value string into a list of words, performing all the ! shell expansions including word splitting. */ ! if (*value == '(') { ni = 1; val = extract_array_assignment_list (value, &ni); if (val == 0) ! return var; ! nlist = expand_string (val, 0); ! free (val); } else ! nlist = expand_string (value, 0); #if 1 /* Now that we are ready to assign values to the array, kill the existing value. */ if (a) empty_array (a); - #endif for (last_ind = 0, list = nlist; list; list = list->next) --- 1512,1554 ---- int ni, len, ind, last_ind; ! if (value == 0) ! return var; ! /* If this is called from declare_builtin, value[0] == '(' and ! strchr(value, ')') != 0. In this case, we need to extract ! the value from between the parens before going on. */ ! if (*value == '(') /*)*/ { ni = 1; val = extract_array_assignment_list (value, &ni); if (val == 0) ! return var; } else ! val = value; + /* Expand the value string into a list of words, performing all the + shell expansions including word splitting. */ #if 1 + /* First we split the string on whitespace, using the shell parser + (ksh93 seems to do this). */ + list = parse_string_to_word_list (val, "array assign"); + /* Now that we've split it, perform the shell expansions on each + word in the list. */ + nlist = list ? expand_words_shellexp (list) : (WORD_LIST *)NULL; + dispose_words (list); + #else + nlist = expand_string (val, 0); + #endif + + if (val != value) + free (val); + + a = array_cell (var); + /* Now that we are ready to assign values to the array, kill the existing value. */ if (a) empty_array (a); for (last_ind = 0, list = nlist; list; list = list->next) *************** *** 1657,1662 **** char *name; { ! SHELL_VAR *var = find_variable (name); if (!var) return (-1); --- 1683,1689 ---- char *name; { ! SHELL_VAR *var; + var = find_variable (name); if (!var) return (-1); *************** *** 1948,1951 **** --- 1975,1979 ---- } + #ifdef INCLUDE_UNUSED /* Make the function associated with NAME be readonly. If NAME does not exist, we just punt, like auto_export code below. */ *************** *** 1984,1987 **** --- 2012,2016 ---- set_auto_export (entry); } + #endif #if defined (ARRAY_VARS) *************** *** 2046,2049 **** --- 2075,2080 ---- } + #ifdef READLINE + static int visible_var (var) *************** *** 2079,2082 **** --- 2110,2115 ---- } + #endif /* READLINE */ + /* Return non-zero if the variable VAR is visible and exported. Array variables cannot be exported. */ *************** *** 2162,2166 **** value = (char *)NULL; - #define freetemp nlen if (name[offset] == '=') { --- 2195,2198 ---- *************** *** 2175,2181 **** } temp = name + offset + 1; ! freetemp = strchr (temp, '~') != 0; ! if (freetemp) ! temp = bash_tilde_expand (temp); list = expand_string_unsplit (temp, 0); --- 2207,2211 ---- } temp = name + offset + 1; ! temp = (strchr (temp, '~') != 0) ? bash_tilde_expand (temp) : savestring (temp); list = expand_string_unsplit (temp, 0); *************** *** 2185,2192 **** dispose_words (list); ! if (freetemp) ! free (temp); } - #undef freetemp nlen = strlen (name); --- 2215,2220 ---- dispose_words (list); ! free (temp); } nlen = strlen (name); *************** *** 2249,2258 **** char *w; ! temp = new_shell_variable (name); /* XXX memory leak here */ w = array[i] + l + 1; temp->value = *w ? savestring (w) : (char *)NULL; ! temp->attributes = att_exported; temp->context = 0; temp->prev_context = (SHELL_VAR *)NULL; --- 2277,2289 ---- char *w; ! /* This is a potential memory leak. The code should really save ! the created variables in some auxiliary data structure, which ! can be disposed of at the appropriate time. */ ! temp = new_shell_variable (name); w = array[i] + l + 1; temp->value = *w ? savestring (w) : (char *)NULL; ! temp->attributes = att_exported|att_tempvar; temp->context = 0; temp->prev_context = (SHELL_VAR *)NULL; *************** *** 2276,2280 **** char *name; { ! SHELL_VAR *var = (SHELL_VAR *)NULL; if (temporary_env) --- 2307,2313 ---- char *name; { ! SHELL_VAR *var; ! ! var = (SHELL_VAR *)NULL; if (temporary_env) *************** *** 2380,2384 **** } while (0) ! #define ISFUNC(s, o) ((s[o + 1] == '(') && (s[o + 2] == ')')) /* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the --- 2413,2417 ---- } while (0) ! #define ISFUNCTION(s, o) ((s[o + 1] == '(') && (s[o + 2] == ')')) /* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the *************** *** 2493,2496 **** --- 2526,2530 ---- } + #if 0 /* UNUSED -- it caused too many problems */ void put_gnu_argv_flags_into_env (pid, flags_string) *************** *** 2517,2520 **** --- 2551,2555 ---- export_env = add_or_supercede_exported_var (dummy, 0); } + #endif /* Return a string denoting what our indirection level is. */ *************** *** 2544,2546 **** --- 2579,2952 ---- free (ps4); return (indirection_string); + } + + /************************************************* + * * + * Functions to manage special variables * + * * + *************************************************/ + + /* Extern declarations for variables this code has to manage. */ + extern int eof_encountered, eof_encountered_limit, ignoreeof; + + #if defined (READLINE) + extern int no_line_editing; + extern int hostname_list_initialized; + #endif + + /* An alist of name.function for each special variable. Most of the + functions don't do much, and in fact, this would be faster with a + switch statement, but by the end of this file, I am sick of switch + statements. */ + + #define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0 + + struct name_and_function { + char *name; + VFunction *function; + } special_vars[] = { + { "PATH", sv_path }, + { "MAIL", sv_mail }, + { "MAILPATH", sv_mail }, + { "MAILCHECK", sv_mail }, + + { "POSIXLY_CORRECT", sv_strict_posix }, + { "GLOBIGNORE", sv_globignore }, + + /* Variables which only do something special when READLINE is defined. */ + #if defined (READLINE) + { "TERM", sv_terminal }, + { "TERMCAP", sv_terminal }, + { "TERMINFO", sv_terminal }, + { "HOSTFILE", sv_hostfile }, + #endif /* READLINE */ + + /* Variables which only do something special when HISTORY is defined. */ + #if defined (HISTORY) + { "HISTIGNORE", sv_histignore }, + { "HISTSIZE", sv_histsize }, + { "HISTFILESIZE", sv_histsize }, + { "HISTCONTROL", sv_history_control }, + # if defined (BANG_HISTORY) + { "histchars", sv_histchars }, + # endif /* BANG_HISTORY */ + #endif /* HISTORY */ + + { "IGNOREEOF", sv_ignoreeof }, + { "ignoreeof", sv_ignoreeof }, + + { "OPTIND", sv_optind }, + { "OPTERR", sv_opterr }, + + { "TEXTDOMAIN", sv_locale }, + { "TEXTDOMAINDIR", sv_locale }, + { "LC_ALL", sv_locale }, + { "LC_COLLATE", sv_locale }, + { "LC_CTYPE", sv_locale }, + { "LC_MESSAGES", sv_locale }, + { "LANG", sv_locale }, + + #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE) + { "TZ", sv_tz }, + #endif + + { (char *)0, (VFunction *)0 } + }; + + /* The variable in NAME has just had its state changed. Check to see if it + is one of the special ones where something special happens. */ + void + stupidly_hack_special_variables (name) + char *name; + { + int i; + + for (i = 0; special_vars[i].name; i++) + { + if (STREQ (special_vars[i].name, name)) + { + (*(special_vars[i].function)) (name); + return; + } + } + } + + /* What to do just after the PATH variable has changed. */ + void + sv_path (name) + char *name; + { + /* hash -r */ + flush_hashed_filenames (); + } + + /* What to do just after one of the MAILxxxx variables has changed. NAME + is the name of the variable. This is called with NAME set to one of + MAIL, MAILCHECK, or MAILPATH. */ + void + sv_mail (name) + char *name; + { + /* If the time interval for checking the files has changed, then + reset the mail timer. Otherwise, one of the pathname vars + to the users mailbox has changed, so rebuild the array of + filenames. */ + if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */ + reset_mail_timer (); + else + { + free_mail_files (); + remember_mail_dates (); + } + } + + /* What to do when GLOBIGNORE changes. */ + void + sv_globignore (name) + char *name; + { + setup_glob_ignore (name); + } + + #if defined (READLINE) + /* What to do just after one of the TERMxxx variables has changed. + If we are an interactive shell, then try to reset the terminal + information in readline. */ + void + sv_terminal (name) + char *name; + { + if (interactive_shell && no_line_editing == 0) + rl_reset_terminal (get_string_value ("TERM")); + } + + void + sv_hostfile (name) + char *name; + { + hostname_list_initialized = 0; + } + #endif /* READLINE */ + + #if defined (HISTORY) + /* What to do after the HISTSIZE or HISTFILESIZE variables change. + If there is a value for this HISTSIZE (and it is numeric), then stifle + the history. Otherwise, if there is NO value for this variable, + unstifle the history. If name is HISTFILESIZE, and its value is + numeric, truncate the history file to hold no more than that many + lines. */ + void + sv_histsize (name) + char *name; + { + char *temp; + long num; + + temp = get_string_value (name); + + if (temp && *temp) + { + if (legal_number (temp, &num)) + { + if (name[4] == 'S') + { + stifle_history (num); + num = where_history (); + if (history_lines_this_session > num) + history_lines_this_session = num; + } + else + { + history_truncate_file (get_string_value ("HISTFILE"), (int)num); + if (num <= history_lines_in_file) + history_lines_in_file = num; + } + } + } + else if (name[4] == 'S') + unstifle_history (); + } + + /* What to do after the HISTIGNORE variable changes. */ + void + sv_histignore (name) + char *name; + { + setup_history_ignore (name); + } + + /* What to do after the HISTCONTROL variable changes. */ + void + sv_history_control (name) + char *name; + { + char *temp; + + history_control = 0; + temp = get_string_value (name); + + if (temp && *temp && STREQN (temp, "ignore", 6)) + { + if (temp[6] == 's') /* ignorespace */ + history_control = 1; + else if (temp[6] == 'd') /* ignoredups */ + history_control = 2; + else if (temp[6] == 'b') /* ignoreboth */ + history_control = 3; + } + } + + #if defined (BANG_HISTORY) + /* Setting/unsetting of the history expansion character. */ + void + sv_histchars (name) + char *name; + { + char *temp; + + temp = get_string_value (name); + if (temp) + { + history_expansion_char = *temp; + if (temp[0] && temp[1]) + { + history_subst_char = temp[1]; + if (temp[2]) + history_comment_char = temp[2]; + } + } + else + { + history_expansion_char = '!'; + history_subst_char = '^'; + history_comment_char = '#'; + } + } + #endif /* BANG_HISTORY */ + #endif /* HISTORY */ + + #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE) + void + sv_tz (name) + char *name; + { + tzset (); + } + #endif + + /* If the variable exists, then the value of it can be the number + of times we actually ignore the EOF. The default is small, + (smaller than csh, anyway). */ + void + sv_ignoreeof (name) + char *name; + { + SHELL_VAR *tmp_var; + char *temp; + + eof_encountered = 0; + + tmp_var = find_variable (name); + ignoreeof = tmp_var != 0; + temp = tmp_var ? value_cell (tmp_var) : (char *)NULL; + if (temp) + eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10; + set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */ + } + + void + sv_optind (name) + char *name; + { + char *tt; + int s; + + tt = get_string_value ("OPTIND"); + if (tt && *tt) + { + s = atoi (tt); + + /* According to POSIX, setting OPTIND=1 resets the internal state + of getopt (). */ + if (s < 0 || s == 1) + s = 0; + } + else + s = 0; + getopts_reset (s); + } + + void + sv_opterr (name) + char *name; + { + char *tt; + + tt = get_string_value ("OPTERR"); + sh_opterr = (tt && *tt) ? atoi (tt) : 1; + } + + void + sv_strict_posix (name) + char *name; + { + SET_INT_VAR (name, posixly_correct); + posix_initialize (posixly_correct); + #if defined (READLINE) + if (interactive_shell) + posix_readline_initialize (posixly_correct); + #endif /* READLINE */ + set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */ + } + + void + sv_locale (name) + char *name; + { + char *v; + + v = get_string_value (name); + if (name[0] == 'L' && name[1] == 'A') /* LANG */ + set_lang (name, v); + else + set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */ + } + + #if defined (ARRAY_VARS) + void + set_pipestatus_array (ps) + int *ps; + { + SHELL_VAR *v; + ARRAY *a; + register int i; + char *t; + + v = find_variable ("PIPESTATUS"); + if (v == 0) + v = make_new_array_variable ("PIPESTATUS"); + if (array_p (v) == 0) + return; /* Do nothing if not an array variable. */ + a = array_cell (v); + if (a) + empty_array (a); + for (i = 0; ps[i] != -1; i++) + { + t = itos (ps[i]); + array_add_element (a, i, t); + free (t); + } + } + #endif + + void + set_pipestatus_from_exit (s) + int s; + { + #if defined (ARRAY_VARS) + static int v[2] = { 0, -1 }; + + v[0] = s; + set_pipestatus_array (v); + #endif } diff -Nrc2 bash-2.01.1/variables.h bash-2.02/variables.h *** bash-2.01.1/variables.h Fri Apr 11 12:09:28 1997 --- bash-2.02/variables.h Wed Oct 29 15:31:29 1997 *************** *** 28,42 **** } SHELL_VAR; ! /* The various attributes that a given variable can have. ! We only reserve one byte of the INT. */ ! #define att_exported 0x01 /* export to environment */ ! #define att_readonly 0x02 /* cannot change */ ! #define att_invisible 0x04 /* cannot see */ ! #define att_array 0x08 /* value is an array */ ! #define att_nounset 0x10 /* cannot unset */ ! #define att_function 0x20 /* value is a function */ ! #define att_integer 0x40 /* internal representation is int */ ! #define att_imported 0x80 /* came from environment */ #define att_local 0x100 /* variable is local to a function */ #define exported_p(var) ((((var)->attributes) & (att_exported))) --- 28,42 ---- } SHELL_VAR; ! /* The various attributes that a given variable can have. */ ! #define att_exported 0x001 /* export to environment */ ! #define att_readonly 0x002 /* cannot change */ ! #define att_invisible 0x004 /* cannot see */ ! #define att_array 0x008 /* value is an array */ ! #define att_nounset 0x010 /* cannot unset */ ! #define att_function 0x020 /* value is a function */ ! #define att_integer 0x040 /* internal representation is int */ ! #define att_imported 0x080 /* came from environment */ #define att_local 0x100 /* variable is local to a function */ + #define att_tempvar 0x200 /* variable came from the temp environment */ #define exported_p(var) ((((var)->attributes) & (att_exported))) *************** *** 49,52 **** --- 49,53 ---- #define imported_p(var) ((((var)->attributes) & (att_imported))) #define local_p(var) ((((var)->attributes) & (att_local))) + #define tempvar_p(var) ((((var)->attributes) & (att_tempvar))) #define value_cell(var) ((var)->value) *************** *** 132,136 **** --- 133,165 ---- extern int skipsubscript __P((char *, int)); extern void print_array_assignment __P((SHELL_VAR *, int)); + + extern void set_pipestatus_array __P((int *)); + #endif + + extern void set_pipestatus_from_exit __P((int)); + + /* The variable in NAME has just had its state changed. Check to see if it + is one of the special ones where something special happens. */ + extern void stupidly_hack_special_variables __P((char *)); + + /* The `special variable' functions that get called when a particular + variable is set. */ + void sv_path (), sv_mail (), sv_ignoreeof (), sv_strict_posix (); + void sv_optind (), sv_opterr (), sv_globignore (), sv_locale (); + + #if defined (READLINE) + void sv_terminal (), sv_hostfile (); + #endif + + #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE) + void sv_tz (); #endif + + #if defined (HISTORY) + void sv_histsize (), sv_histignore (), sv_history_control (); + # if defined (BANG_HISTORY) + void sv_histchars (); + # endif + #endif /* HISTORY */ #endif /* !_VARIABLES_H_ */ diff -Nrc2 bash-2.01.1/version.c bash-2.02/version.c *** bash-2.01.1/version.c Wed Jul 9 14:37:21 1997 --- bash-2.02/version.c Tue Mar 17 12:30:24 1998 *************** *** 64,67 **** printf ("GNU bash, version %s (%s)\n", shell_version_string (), MACHTYPE); if (extended) ! printf ("Copyright 1997 Free Software Foundation, Inc.\n"); } --- 64,67 ---- printf ("GNU bash, version %s (%s)\n", shell_version_string (), MACHTYPE); if (extended) ! printf ("Copyright 1998 Free Software Foundation, Inc.\n"); } diff -Nrc2 bash-2.01.1/vprint.c bash-2.02/vprint.c *** bash-2.01.1/vprint.c Mon Jul 22 14:43:09 1996 --- bash-2.02/vprint.c Wed Dec 31 19:00:00 1969 *************** *** 1,85 **** - /* vprint.c -- v[fs]printf() for 4.[23] BSD systems. */ - - /* Copyright (C) 1987,1989 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. */ - - #include "config.h" - - #if defined (USE_VFPRINTF_EMULATION) - - #include - - #if !defined (NULL) - # if defined (__STDC__) - # define NULL ((void *)0) - # else - # define NULL 0x0 - # endif /* __STDC__ */ - #endif /* !NULL */ - - /* - * Beware! Don't trust the value returned by either of these functions; it - * seems that pre-4.3-tahoe implementations of _doprnt () return the first - * argument, i.e. a char *. - */ - #include - - int - vfprintf (iop, fmt, ap) - FILE *iop; - char *fmt; - va_list ap; - { - int len; - char localbuf[BUFSIZ]; - - if (iop->_flag & _IONBF) - { - iop->_flag &= ~_IONBF; - iop->_ptr = iop->_base = localbuf; - len = _doprnt (fmt, ap, iop); - (void) fflush (iop); - iop->_flag |= _IONBF; - iop->_base = NULL; - iop->_bufsiz = 0; - iop->_cnt = 0; - } - else - len = _doprnt (fmt, ap, iop); - return (ferror (iop) ? EOF : len); - } - - /* - * Ditto for vsprintf - */ - int - vsprintf (str, fmt, ap) - char *str, *fmt; - va_list ap; - { - FILE f; - int len; - - f._flag = _IOWRT|_IOSTRG; - f._ptr = str; - f._cnt = 32767; - len = _doprnt (fmt, ap, &f); - *f._ptr = 0; - return (len); - } - #endif /* USE_VFPRINTF_EMULATION */ --- 0 ---- diff -Nrc2 bash-2.01.1/y.tab.c bash-2.02/y.tab.c *** bash-2.01.1/y.tab.c Thu Sep 4 10:59:28 1997 --- bash-2.02/y.tab.c Wed Mar 25 12:16:44 1998 *************** *** 1,4 **** ! /* A Bison parser, made from /usr/homes/chet/src/bash/bash-2.01.1/parse.y by GNU Bison version 1.25 */ --- 1,4 ---- ! /* A Bison parser, made from /usr/homes/chet/src/bash/src/parse.y by GNU Bison version 1.25 */ *************** *** 20,44 **** #define DONE 270 #define FUNCTION 271 ! #define IN 272 ! #define BANG 273 ! #define TIME 274 ! #define TIMEOPT 275 ! #define WORD 276 ! #define ASSIGNMENT_WORD 277 ! #define NUMBER 278 ! #define AND_AND 279 ! #define OR_OR 280 ! #define GREATER_GREATER 281 ! #define LESS_LESS 282 ! #define LESS_AND 283 ! #define GREATER_AND 284 ! #define SEMI_SEMI 285 ! #define LESS_LESS_MINUS 286 ! #define AND_GREATER 287 ! #define LESS_GREATER 288 ! #define GREATER_BAR 289 ! #define yacc_EOF 290 ! #line 21 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" #include "config.h" --- 20,49 ---- #define DONE 270 #define FUNCTION 271 ! #define COND_START 272 ! #define COND_END 273 ! #define COND_ERROR 274 ! #define IN 275 ! #define BANG 276 ! #define TIME 277 ! #define TIMEOPT 278 ! #define WORD 279 ! #define ASSIGNMENT_WORD 280 ! #define NUMBER 281 ! #define ARITH_CMD 282 ! #define COND_CMD 283 ! #define AND_AND 284 ! #define OR_OR 285 ! #define GREATER_GREATER 286 ! #define LESS_LESS 287 ! #define LESS_AND 288 ! #define GREATER_AND 289 ! #define SEMI_SEMI 290 ! #define LESS_LESS_MINUS 291 ! #define AND_GREATER 292 ! #define LESS_GREATER 293 ! #define GREATER_BAR 294 ! #define yacc_EOF 295 ! #line 21 "/usr/homes/chet/src/bash/src/parse.y" #include "config.h" *************** *** 87,93 **** #if defined (PROMPT_STRING_DECODE) ! #include ! #include ! #include "maxpath.h" #endif /* PROMPT_STRING_DECODE */ --- 92,100 ---- #if defined (PROMPT_STRING_DECODE) ! # ifndef _MINIX ! # include ! # endif ! # include ! # include "maxpath.h" #endif /* PROMPT_STRING_DECODE */ *************** *** 97,100 **** --- 104,114 ---- #define YYDEBUG 0 + #if defined (EXTENDED_GLOB) + #define PATTERN_CHAR(c) \ + ((c) == '@' || (c) == '*' || (c) == '+' || (c) == '?' || (c) == '!') + + extern int extended_glob; + #endif + extern int eof_encountered; extern int no_line_editing, running_under_emacs; *************** *** 108,112 **** extern char *dist_version; extern int patch_level; ! extern int dump_translatable_strings; extern Function *last_shell_builtin, *this_shell_builtin; #if defined (BUFFERED_INPUT) --- 122,126 ---- extern char *dist_version; extern int patch_level; ! extern int dump_translatable_strings, dump_po_strings; extern Function *last_shell_builtin, *this_shell_builtin; #if defined (BUFFERED_INPUT) *************** *** 126,129 **** --- 140,146 ---- static int yylex (); static int parse_arith_cmd (); + #if defined (COND_COMMAND) + static COMMAND *parse_cond_command (); + #endif static int read_token_word (); static void discard_parser_constructs (); *************** *** 190,194 **** static REDIRECTEE redir; ! #line 171 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" typedef union { WORD_DESC *word; /* the word that we read. */ --- 207,211 ---- static REDIRECTEE redir; ! #line 183 "/usr/homes/chet/src/bash/src/parse.y" typedef union { WORD_DESC *word; /* the word that we read. */ *************** *** 210,227 **** ! #define YYFINAL 263 #define YYFLAG -32768 ! #define YYNTBASE 47 ! #define YYTRANSLATE(x) ((unsigned)(x) <= 290 ? yytranslate[x] : 78) static const char yytranslate[] = { 0, ! 2, 2, 2, 2, 2, 2, 2, 2, 2, 37, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 2, 2, 2, 2, 2, 2, 2, 35, 2, 45, ! 46, 2, 2, 2, 42, 2, 2, 2, 2, 2, ! 2, 2, 2, 2, 2, 2, 2, 2, 36, 41, ! 2, 40, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, --- 227,244 ---- ! #define YYFINAL 269 #define YYFLAG -32768 ! #define YYNTBASE 52 ! #define YYTRANSLATE(x) ((unsigned)(x) <= 295 ? yytranslate[x] : 85) static const char yytranslate[] = { 0, ! 2, 2, 2, 2, 2, 2, 2, 2, 2, 42, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 2, 2, 2, 2, 2, 2, 2, 40, 2, 50, ! 51, 2, 2, 2, 47, 2, 2, 2, 2, 2, ! 2, 2, 2, 2, 2, 2, 2, 2, 41, 46, ! 2, 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, *************** *** 229,233 **** 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 2, 2, 43, 39, 44, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, --- 246,250 ---- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 2, 2, 48, 44, 49, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, *************** *** 245,249 **** 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, ! 26, 27, 28, 29, 30, 31, 32, 33, 34, 38 }; --- 262,267 ---- 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, ! 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, ! 36, 37, 38, 39, 43 }; *************** *** 255,319 **** 99, 102, 105, 109, 111, 113, 115, 117, 120, 122, 125, 127, 129, 132, 134, 136, 142, 148, 150, 152, ! 154, 156, 158, 165, 172, 180, 188, 199, 210, 217, ! 224, 232, 240, 251, 262, 269, 277, 284, 290, 297, ! 302, 306, 312, 320, 327, 331, 336, 343, 349, 351, ! 354, 359, 364, 370, 376, 379, 383, 385, 389, 392, ! 394, 397, 401, 405, 409, 414, 419, 424, 429, 434, ! 436, 438, 440, 442, 443, 446, 448, 451, 454, 459, ! 464, 468, 472, 474, 476, 479, 482, 486, 490, 495, ! 497, 499 }; ! static const short yyrhs[] = { 73, ! 37, 0, 37, 0, 1, 37, 0, 38, 0, 21, ! 0, 48, 21, 0, 40, 21, 0, 41, 21, 0, ! 23, 40, 21, 0, 23, 41, 21, 0, 26, 21, ! 0, 23, 26, 21, 0, 27, 21, 0, 23, 27, ! 21, 0, 28, 23, 0, 23, 28, 23, 0, 29, ! 23, 0, 23, 29, 23, 0, 28, 21, 0, 23, ! 28, 21, 0, 29, 21, 0, 23, 29, 21, 0, ! 31, 21, 0, 23, 31, 21, 0, 29, 42, 0, ! 23, 29, 42, 0, 28, 42, 0, 23, 28, 42, ! 0, 32, 21, 0, 23, 33, 21, 0, 33, 21, ! 0, 34, 21, 0, 23, 34, 21, 0, 21, 0, ! 22, 0, 49, 0, 49, 0, 51, 49, 0, 50, ! 0, 52, 50, 0, 52, 0, 54, 0, 54, 51, ! 0, 55, 0, 57, 0, 12, 68, 14, 68, 15, ! 0, 13, 68, 14, 68, 15, 0, 56, 0, 60, ! 0, 59, 0, 61, 0, 58, 0, 10, 21, 72, ! 14, 68, 15, 0, 10, 21, 72, 43, 68, 44, ! 0, 10, 21, 36, 72, 14, 68, 15, 0, 10, ! 21, 36, 72, 43, 68, 44, 0, 10, 21, 72, ! 17, 48, 71, 72, 14, 68, 15, 0, 10, 21, ! 72, 17, 48, 71, 72, 43, 68, 44, 0, 11, ! 21, 72, 14, 67, 15, 0, 11, 21, 72, 43, ! 67, 44, 0, 11, 21, 36, 72, 14, 67, 15, ! 0, 11, 21, 36, 72, 43, 67, 44, 0, 11, ! 21, 72, 17, 48, 71, 72, 14, 67, 15, 0, ! 11, 21, 72, 17, 48, 71, 72, 43, 67, 44, ! 0, 8, 21, 72, 17, 72, 9, 0, 8, 21, ! 72, 17, 65, 72, 9, 0, 8, 21, 72, 17, ! 63, 9, 0, 21, 45, 46, 72, 61, 0, 16, ! 21, 45, 46, 72, 61, 0, 16, 21, 72, 61, ! 0, 45, 68, 46, 0, 3, 68, 4, 68, 7, ! 0, 3, 68, 4, 68, 5, 68, 7, 0, 3, ! 68, 4, 68, 62, 7, 0, 43, 67, 44, 0, ! 6, 68, 4, 68, 0, 6, 68, 4, 68, 5, ! 68, 0, 6, 68, 4, 68, 62, 0, 64, 0, ! 65, 64, 0, 72, 66, 46, 68, 0, 72, 66, ! 46, 72, 0, 72, 45, 66, 46, 68, 0, 72, ! 45, 66, 46, 72, 0, 64, 30, 0, 65, 64, ! 30, 0, 21, 0, 66, 39, 21, 0, 72, 69, ! 0, 67, 0, 72, 70, 0, 70, 37, 72, 0, ! 70, 35, 72, 0, 70, 36, 72, 0, 70, 24, ! 72, 70, 0, 70, 25, 72, 70, 0, 70, 35, ! 72, 70, 0, 70, 36, 72, 70, 0, 70, 37, ! 72, 70, 0, 75, 0, 37, 0, 36, 0, 38, ! 0, 0, 72, 37, 0, 74, 0, 74, 35, 0, ! 74, 36, 0, 74, 24, 72, 74, 0, 74, 25, ! 72, 74, 0, 74, 35, 74, 0, 74, 36, 74, ! 0, 75, 0, 76, 0, 18, 76, 0, 77, 76, ! 0, 77, 18, 76, 0, 18, 77, 76, 0, 76, ! 39, 72, 76, 0, 53, 0, 19, 0, 19, 20, 0 }; --- 273,338 ---- 99, 102, 105, 109, 111, 113, 115, 117, 120, 122, 125, 127, 129, 132, 134, 136, 142, 148, 150, 152, ! 154, 156, 158, 160, 162, 169, 176, 184, 192, 203, ! 214, 221, 228, 236, 244, 255, 266, 273, 281, 288, ! 294, 301, 306, 310, 316, 324, 331, 335, 337, 341, ! 346, 353, 359, 361, 364, 369, 374, 380, 386, 389, ! 393, 395, 399, 402, 404, 407, 411, 415, 419, 424, ! 429, 434, 439, 444, 446, 448, 450, 452, 453, 456, ! 458, 461, 464, 469, 474, 478, 482, 484, 486, 489, ! 492, 496, 500, 505, 507, 509 }; ! static const short yyrhs[] = { 80, ! 42, 0, 42, 0, 1, 42, 0, 43, 0, 24, ! 0, 53, 24, 0, 45, 24, 0, 46, 24, 0, ! 26, 45, 24, 0, 26, 46, 24, 0, 31, 24, ! 0, 26, 31, 24, 0, 32, 24, 0, 26, 32, ! 24, 0, 33, 26, 0, 26, 33, 26, 0, 34, ! 26, 0, 26, 34, 26, 0, 33, 24, 0, 26, ! 33, 24, 0, 34, 24, 0, 26, 34, 24, 0, ! 36, 24, 0, 26, 36, 24, 0, 34, 47, 0, ! 26, 34, 47, 0, 33, 47, 0, 26, 33, 47, ! 0, 37, 24, 0, 26, 38, 24, 0, 38, 24, ! 0, 39, 24, 0, 26, 39, 24, 0, 24, 0, ! 25, 0, 54, 0, 54, 0, 56, 54, 0, 55, ! 0, 57, 55, 0, 57, 0, 59, 0, 59, 56, ! 0, 60, 0, 62, 0, 12, 75, 14, 75, 15, ! 0, 13, 75, 14, 75, 15, 0, 61, 0, 65, ! 0, 64, 0, 66, 0, 67, 0, 68, 0, 63, ! 0, 10, 24, 79, 14, 75, 15, 0, 10, 24, ! 79, 48, 75, 49, 0, 10, 24, 41, 79, 14, ! 75, 15, 0, 10, 24, 41, 79, 48, 75, 49, ! 0, 10, 24, 79, 20, 53, 78, 79, 14, 75, ! 15, 0, 10, 24, 79, 20, 53, 78, 79, 48, ! 75, 49, 0, 11, 24, 79, 14, 74, 15, 0, ! 11, 24, 79, 48, 74, 49, 0, 11, 24, 41, ! 79, 14, 74, 15, 0, 11, 24, 41, 79, 48, ! 74, 49, 0, 11, 24, 79, 20, 53, 78, 79, ! 14, 74, 15, 0, 11, 24, 79, 20, 53, 78, ! 79, 48, 74, 49, 0, 8, 24, 79, 20, 79, ! 9, 0, 8, 24, 79, 20, 72, 79, 9, 0, ! 8, 24, 79, 20, 70, 9, 0, 24, 50, 51, ! 79, 66, 0, 16, 24, 50, 51, 79, 66, 0, ! 16, 24, 79, 66, 0, 50, 75, 51, 0, 3, ! 75, 4, 75, 7, 0, 3, 75, 4, 75, 5, ! 75, 7, 0, 3, 75, 4, 75, 69, 7, 0, ! 48, 74, 49, 0, 27, 0, 17, 28, 18, 0, ! 6, 75, 4, 75, 0, 6, 75, 4, 75, 5, ! 75, 0, 6, 75, 4, 75, 69, 0, 71, 0, ! 72, 71, 0, 79, 73, 51, 75, 0, 79, 73, ! 51, 79, 0, 79, 50, 73, 51, 75, 0, 79, ! 50, 73, 51, 79, 0, 71, 35, 0, 72, 71, ! 35, 0, 24, 0, 73, 44, 24, 0, 79, 76, ! 0, 74, 0, 79, 77, 0, 77, 42, 79, 0, ! 77, 40, 79, 0, 77, 41, 79, 0, 77, 29, ! 79, 77, 0, 77, 30, 79, 77, 0, 77, 40, ! 79, 77, 0, 77, 41, 79, 77, 0, 77, 42, ! 79, 77, 0, 82, 0, 42, 0, 41, 0, 43, ! 0, 0, 79, 42, 0, 81, 0, 81, 40, 0, ! 81, 41, 0, 81, 29, 79, 81, 0, 81, 30, ! 79, 81, 0, 81, 40, 81, 0, 81, 41, 81, ! 0, 82, 0, 83, 0, 21, 83, 0, 84, 83, ! 0, 84, 21, 83, 0, 21, 84, 83, 0, 83, ! 44, 79, 83, 0, 58, 0, 22, 0, 22, 23, 0 }; *************** *** 323,339 **** #if YYDEBUG != 0 static const short yyrline[] = { 0, ! 214, 223, 230, 245, 255, 257, 261, 266, 271, 276, ! 281, 286, 291, 297, 303, 308, 313, 318, 323, 328, ! 333, 338, 343, 350, 357, 362, 367, 372, 377, 382, ! 387, 392, 397, 404, 406, 408, 412, 416, 427, 429, ! 433, 435, 437, 466, 468, 470, 472, 474, 476, 478, ! 480, 482, 486, 488, 490, 492, 494, 496, 500, 504, ! 508, 512, 516, 520, 526, 528, 530, 534, 538, 541, ! 545, 549, 551, 553, 558, 562, 564, 566, 570, 571, ! 575, 577, 579, 581, 585, 586, 590, 592, 601, 609, ! 610, 616, 617, 624, 628, 630, 632, 639, 641, 643, ! 647, 648, 649, 652, 653, 662, 668, 677, 685, 687, ! 689, 696, 699, 703, 705, 710, 715, 720, 727, 730, ! 734, 736 }; #endif --- 342,358 ---- #if YYDEBUG != 0 static const short yyrline[] = { 0, ! 232, 241, 248, 263, 273, 275, 279, 284, 289, 294, ! 299, 304, 309, 315, 321, 326, 331, 336, 341, 346, ! 351, 356, 361, 368, 375, 380, 385, 390, 395, 400, ! 405, 410, 415, 422, 424, 426, 430, 434, 445, 447, ! 451, 453, 455, 484, 486, 488, 490, 492, 494, 496, ! 498, 500, 502, 504, 508, 510, 512, 514, 516, 518, ! 522, 526, 530, 534, 538, 542, 548, 550, 552, 556, ! 560, 563, 567, 571, 573, 575, 580, 584, 588, 592, ! 594, 596, 600, 601, 605, 607, 609, 611, 615, 616, ! 620, 622, 631, 639, 640, 646, 647, 654, 658, 660, ! 662, 669, 671, 673, 677, 678, 679, 682, 683, 692, ! 698, 707, 715, 717, 719, 726, 729, 733, 735, 740, ! 745, 750, 757, 760, 764, 766 }; #endif *************** *** 344,354 **** static const char * const yytname[] = { "$","error","$undefined.","IF","THEN", "ELSE","ELIF","FI","CASE","ESAC","FOR","SELECT","WHILE","UNTIL","DO","DONE", ! "FUNCTION","IN","BANG","TIME","TIMEOPT","WORD","ASSIGNMENT_WORD","NUMBER","AND_AND", ! "OR_OR","GREATER_GREATER","LESS_LESS","LESS_AND","GREATER_AND","SEMI_SEMI","LESS_LESS_MINUS", ! "AND_GREATER","LESS_GREATER","GREATER_BAR","'&'","';'","'\\n'","yacc_EOF","'|'", ! "'>'","'<'","'-'","'{'","'}'","'('","')'","inputunit","word_list","redirection", ! "simple_command_element","redirection_list","simple_command","command","shell_command", ! "for_command","select_command","case_command","function_def","subshell","if_command", ! "group_command","elif_clause","case_clause","pattern_list","case_clause_sequence", "pattern","list","compound_list","list0","list1","list_terminator","newline_list", "simple_list","simple_list1","pipeline_command","pipeline","timespec", NULL --- 363,374 ---- static const char * const yytname[] = { "$","error","$undefined.","IF","THEN", "ELSE","ELIF","FI","CASE","ESAC","FOR","SELECT","WHILE","UNTIL","DO","DONE", ! "FUNCTION","COND_START","COND_END","COND_ERROR","IN","BANG","TIME","TIMEOPT", ! "WORD","ASSIGNMENT_WORD","NUMBER","ARITH_CMD","COND_CMD","AND_AND","OR_OR","GREATER_GREATER", ! "LESS_LESS","LESS_AND","GREATER_AND","SEMI_SEMI","LESS_LESS_MINUS","AND_GREATER", ! "LESS_GREATER","GREATER_BAR","'&'","';'","'\\n'","yacc_EOF","'|'","'>'","'<'", ! "'-'","'{'","'}'","'('","')'","inputunit","word_list","redirection","simple_command_element", ! "redirection_list","simple_command","command","shell_command","for_command", ! "select_command","case_command","function_def","subshell","if_command","group_command", ! "arith_command","cond_command","elif_clause","case_clause","pattern_list","case_clause_sequence", "pattern","list","compound_list","list0","list1","list_terminator","newline_list", "simple_list","simple_list1","pipeline_command","pipeline","timespec", NULL *************** *** 357,373 **** static const short yyr1[] = { 0, ! 47, 47, 47, 47, 48, 48, 49, 49, 49, 49, ! 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, ! 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, ! 49, 49, 49, 50, 50, 50, 51, 51, 52, 52, ! 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, ! 54, 54, 55, 55, 55, 55, 55, 55, 56, 56, ! 56, 56, 56, 56, 57, 57, 57, 58, 58, 58, ! 59, 60, 60, 60, 61, 62, 62, 62, 63, 63, ! 64, 64, 64, 64, 65, 65, 66, 66, 67, 68, ! 68, 69, 69, 69, 70, 70, 70, 70, 70, 70, ! 71, 71, 71, 72, 72, 73, 73, 73, 74, 74, ! 74, 74, 74, 75, 75, 75, 75, 75, 76, 76, ! 77, 77 }; --- 377,393 ---- static const short yyr1[] = { 0, ! 52, 52, 52, 52, 53, 53, 54, 54, 54, 54, ! 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, ! 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, ! 54, 54, 54, 55, 55, 55, 56, 56, 57, 57, ! 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, ! 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, ! 61, 61, 61, 61, 61, 61, 62, 62, 62, 63, ! 63, 63, 64, 65, 65, 65, 66, 67, 68, 69, ! 69, 69, 70, 70, 71, 71, 71, 71, 72, 72, ! 73, 73, 74, 75, 75, 76, 76, 76, 77, 77, ! 77, 77, 77, 77, 78, 78, 78, 79, 79, 80, ! 80, 80, 81, 81, 81, 81, 81, 82, 82, 82, ! 82, 82, 83, 83, 84, 84 }; *************** *** 378,578 **** 2, 2, 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 5, 5, 1, 1, 1, ! 1, 1, 6, 6, 7, 7, 10, 10, 6, 6, ! 7, 7, 10, 10, 6, 7, 6, 5, 6, 4, ! 3, 5, 7, 6, 3, 4, 6, 5, 1, 2, ! 4, 4, 5, 5, 2, 3, 1, 3, 2, 1, ! 2, 3, 3, 3, 4, 4, 4, 4, 4, 1, ! 1, 1, 1, 0, 2, 1, 2, 2, 4, 4, ! 3, 3, 1, 1, 2, 2, 3, 3, 4, 1, ! 1, 2 }; static const short yydefact[] = { 0, ! 0, 104, 0, 0, 0, 104, 104, 0, 0, 121, ! 34, 35, 0, 0, 0, 0, 0, 0, 0, 0, ! 0, 2, 4, 0, 0, 104, 104, 36, 39, 41, ! 120, 42, 44, 48, 45, 52, 50, 49, 51, 0, ! 106, 113, 114, 0, 3, 90, 0, 0, 104, 104, ! 104, 0, 0, 104, 115, 0, 122, 0, 0, 0, ! 0, 0, 0, 0, 0, 0, 0, 11, 13, 19, ! 15, 27, 21, 17, 25, 23, 29, 31, 32, 7, ! 8, 0, 0, 0, 34, 40, 37, 43, 1, 104, ! 104, 107, 108, 104, 0, 116, 104, 105, 89, 91, ! 100, 0, 104, 0, 104, 0, 104, 104, 0, 0, ! 118, 104, 12, 14, 20, 16, 28, 22, 18, 26, ! 24, 30, 33, 9, 10, 75, 0, 71, 38, 0, ! 0, 111, 112, 0, 117, 0, 104, 104, 104, 104, ! 104, 104, 0, 104, 0, 104, 0, 104, 0, 104, ! 0, 0, 104, 70, 0, 109, 110, 0, 0, 119, ! 104, 104, 72, 0, 0, 0, 93, 94, 92, 0, ! 79, 104, 0, 104, 104, 0, 5, 0, 0, 104, ! 104, 0, 0, 0, 46, 47, 0, 68, 0, 0, ! 74, 95, 96, 97, 98, 99, 67, 85, 80, 0, ! 65, 87, 0, 0, 0, 0, 53, 6, 102, 101, ! 103, 104, 54, 0, 0, 59, 104, 60, 69, 73, ! 104, 104, 104, 104, 86, 66, 0, 0, 104, 55, ! 56, 0, 61, 62, 0, 76, 0, 0, 0, 104, ! 88, 81, 82, 104, 104, 104, 104, 104, 78, 83, ! 84, 0, 0, 0, 0, 77, 57, 58, 63, 64, ! 0, 0, 0 }; ! static const short yydefgoto[] = { 261, ! 178, 28, 29, 88, 30, 31, 32, 33, 34, 35, ! 36, 37, 38, 39, 164, 170, 171, 172, 204, 46, ! 47, 99, 100, 212, 48, 40, 132, 101, 43, 44 }; ! static const short yypact[] = { 240, ! -25,-32768, -4, 41, 44,-32768,-32768, 49, 348, 0, ! -31,-32768, 476, 53, 55, 3, 29, 61, 63, 66, ! 71,-32768,-32768, 76, 79,-32768,-32768,-32768,-32768, 165, ! -32768, 120,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -12, ! 89,-32768, 12, 384,-32768,-32768, 99, 276,-32768, 93, ! 103, 98, 143, 126, 12, 456,-32768, 127, 151, 153, ! 35, 43, 154, 155, 159, 160, 161,-32768,-32768,-32768, -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, ! -32768, 140, 276, 137,-32768,-32768,-32768, 120,-32768,-32768, ! -32768, 312, 312,-32768, 456, 12,-32768,-32768,-32768, 86, ! -32768, 38,-32768, -1,-32768, 16,-32768,-32768, 157, -28, ! 12,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, ! -32768,-32768,-32768,-32768,-32768,-32768, 86,-32768,-32768, 276, ! 276, 15, 15, 420, 12, 128,-32768,-32768,-32768,-32768, ! -32768,-32768, 4,-32768, 164,-32768, 17,-32768, 164,-32768, ! 174, 189,-32768,-32768, -28,-32768,-32768, 312, 312, 12, ! -32768,-32768,-32768, 201, 276, 276, 276, 276, 276, 200, ! 180,-32768, -2,-32768,-32768, 196,-32768, 57, 168,-32768, ! -32768, 198, 57, 170,-32768,-32768, -28,-32768, 209, 213, ! -32768,-32768,-32768, 142, 142, 142,-32768,-32768, 190, 1, ! -32768,-32768, 205, 40, 204, 177,-32768,-32768,-32768,-32768, ! -32768,-32768,-32768, 207, 183,-32768,-32768,-32768,-32768,-32768, ! -32768,-32768,-32768,-32768,-32768,-32768, 50, 210,-32768,-32768, ! -32768, 20,-32768,-32768, 30, 139, 276, 276, 276,-32768, ! -32768,-32768, 276,-32768,-32768,-32768,-32768,-32768,-32768,-32768, ! 276, 215, 188, 218, 191,-32768,-32768,-32768,-32768,-32768, ! 236, 237,-32768 }; static const short yypgoto[] = {-32768, ! 91, -27, 214,-32768,-32768,-32768,-32768,-32768,-32768,-32768, ! -32768,-32768,-32768, -107, 9,-32768, 74,-32768, 46, -18, ! -6,-32768, -60, 64, -22,-32768, 11, 6, -7, 245 }; ! #define YYLAST 517 ! static const short yytable[] = { 52, ! 53, 55, 154, 83, 87, 42, 201, 82, 98, 226, ! 41, 45, 144, 58, 26, 145, 49, 174, 202, 57, ! 84, 202, 127, 70, 89, 71, 102, 104, 106, 148, ! 180, 110, 149, 244, 98, 98, 96, 98, 90, 91, ! 98, 146, 203, 246, 72, 203, 175, 188, 111, 73, ! 94, 74, 98, 98, 142, 115, 98, 116, 150, 181, ! 129, 50, 245, 118, 51, 119, 98, 130, 131, 54, ! 75, 134, 247, 68, 98, 69, 117, 208, 228, 219, ! 143, 76, 147, 77, 120, 229, 78, 135, 228, 155, ! 136, 79, 209, 210, 211, 240, 80, 42, 42, 81, ! 151, 152, 97, 133, 192, 193, 194, 195, 196, 137, ! 138, 107, 90, 91, 165, 166, 167, 168, 169, 173, ! 139, 140, 141, 92, 93, 83, 160, 83, 103, 182, ! 187, 184, 161, 162, 163, 42, 42, 176, 105, 179, ! 156, 157, 13, 248, 162, 14, 15, 16, 17, 200, ! 18, 19, 20, 21, 189, 190, 108, 83, 83, 24, ! 25, 214, 215, 42, 42, 137, 138, 205, 206, 133, ! 109, 113, 112, 114, 121, 122, 194, 195, 196, 123, ! 124, 125, 128, 126, 177, 85, 12, 13, 185, 232, ! 14, 15, 16, 17, 235, 18, 19, 20, 21, 237, ! 238, 239, 153, 186, 24, 25, 243, 191, 197, 198, ! 207, 213, 216, 218, 236, 220, 221, 251, 230, 225, ! 231, 233, 242, 83, 83, 202, 234, 254, 255, 257, ! 241, 258, 259, 250, 260, 262, 263, 252, 253, 183, ! 1, 256, 2, 86, 249, 199, 217, 3, 227, 4, ! 5, 6, 7, 56, 0, 8, 0, 9, 10, 0, ! 11, 12, 13, 0, 0, 14, 15, 16, 17, 0, ! 18, 19, 20, 21, 0, 0, 22, 23, 2, 24, ! 25, 0, 26, 3, 27, 4, 5, 6, 7, 0, ! 0, 8, 0, 9, 10, 0, 11, 12, 13, 0, ! 0, 14, 15, 16, 17, 0, 18, 19, 20, 21, ! 0, 0, 98, 0, 2, 24, 25, 0, 26, 3, ! 27, 4, 5, 6, 7, 0, 0, 8, 0, 9, ! 10, 0, 11, 12, 13, 0, 0, 14, 15, 16, ! 17, 0, 18, 19, 20, 21, 0, 0, 0, 0, ! 2, 24, 25, 0, 26, 3, 27, 4, 5, 6, ! 7, 0, 0, 8, 0, 0, 10, 0, 11, 12, ! 13, 0, 0, 14, 15, 16, 17, 0, 18, 19, ! 20, 21, 0, 0, 0, 0, 2, 24, 25, 0, ! 26, 3, 27, 4, 5, 6, 7, 0, 0, 8, ! 0, 95, 0, 0, 11, 12, 13, 0, 0, 14, ! 15, 16, 17, 0, 18, 19, 20, 21, 0, 0, ! 0, 0, 2, 24, 25, 0, 26, 3, 27, 4, ! 5, 6, 7, 0, 0, 8, 0, 0, 0, 0, ! 11, 12, 13, 0, 0, 14, 15, 16, 17, 0, ! 18, 19, 20, 21, 0, 0, 98, 0, 2, 24, ! 25, 0, 26, 3, 27, 4, 5, 6, 7, 0, ! 0, 8, 0, 0, 0, 0, 11, 12, 13, 0, ! 0, 14, 15, 16, 17, 0, 18, 19, 20, 21, ! 0, 0, 0, 0, 0, 24, 25, 0, 26, 0, ! 27, 59, 60, 61, 62, 0, 63, 0, 64, 65, ! 0, 0, 0, 0, 0, 66, 67 }; static const short yycheck[] = { 6, ! 7, 9, 110, 26, 32, 0, 9, 26, 37, 9, ! 0, 37, 14, 45, 43, 17, 21, 14, 21, 20, ! 27, 21, 83, 21, 37, 23, 49, 50, 51, 14, ! 14, 54, 17, 14, 37, 37, 44, 37, 24, 25, ! 37, 43, 45, 14, 42, 45, 43, 155, 56, 21, ! 39, 23, 37, 37, 17, 21, 37, 23, 43, 43, ! 88, 21, 43, 21, 21, 23, 37, 90, 91, 21, ! 42, 94, 43, 21, 37, 21, 42, 21, 39, 187, ! 103, 21, 105, 21, 42, 46, 21, 95, 39, 112, ! 97, 21, 36, 37, 38, 46, 21, 92, 93, 21, ! 107, 108, 4, 93, 165, 166, 167, 168, 169, 24, ! 25, 14, 24, 25, 137, 138, 139, 140, 141, 142, ! 35, 36, 37, 35, 36, 148, 134, 150, 36, 148, ! 153, 150, 5, 6, 7, 130, 131, 144, 36, 146, ! 130, 131, 23, 5, 6, 26, 27, 28, 29, 172, ! 31, 32, 33, 34, 161, 162, 14, 180, 181, 40, ! 41, 180, 181, 158, 159, 24, 25, 174, 175, 159, ! 45, 21, 46, 21, 21, 21, 237, 238, 239, 21, ! 21, 21, 46, 44, 21, 21, 22, 23, 15, 212, ! 26, 27, 28, 29, 217, 31, 32, 33, 34, 222, ! 223, 224, 46, 15, 40, 41, 229, 7, 9, 30, ! 15, 44, 15, 44, 221, 7, 4, 240, 15, 30, ! 44, 15, 229, 246, 247, 21, 44, 246, 247, 15, ! 21, 44, 15, 240, 44, 0, 0, 244, 245, 149, ! 1, 248, 3, 30, 236, 172, 183, 8, 203, 10, ! 11, 12, 13, 9, -1, 16, -1, 18, 19, -1, ! 21, 22, 23, -1, -1, 26, 27, 28, 29, -1, ! 31, 32, 33, 34, -1, -1, 37, 38, 3, 40, ! 41, -1, 43, 8, 45, 10, 11, 12, 13, -1, ! -1, 16, -1, 18, 19, -1, 21, 22, 23, -1, ! -1, 26, 27, 28, 29, -1, 31, 32, 33, 34, ! -1, -1, 37, -1, 3, 40, 41, -1, 43, 8, ! 45, 10, 11, 12, 13, -1, -1, 16, -1, 18, ! 19, -1, 21, 22, 23, -1, -1, 26, 27, 28, ! 29, -1, 31, 32, 33, 34, -1, -1, -1, -1, ! 3, 40, 41, -1, 43, 8, 45, 10, 11, 12, ! 13, -1, -1, 16, -1, -1, 19, -1, 21, 22, ! 23, -1, -1, 26, 27, 28, 29, -1, 31, 32, ! 33, 34, -1, -1, -1, -1, 3, 40, 41, -1, ! 43, 8, 45, 10, 11, 12, 13, -1, -1, 16, ! -1, 18, -1, -1, 21, 22, 23, -1, -1, 26, ! 27, 28, 29, -1, 31, 32, 33, 34, -1, -1, ! -1, -1, 3, 40, 41, -1, 43, 8, 45, 10, ! 11, 12, 13, -1, -1, 16, -1, -1, -1, -1, ! 21, 22, 23, -1, -1, 26, 27, 28, 29, -1, ! 31, 32, 33, 34, -1, -1, 37, -1, 3, 40, ! 41, -1, 43, 8, 45, 10, 11, 12, 13, -1, ! -1, 16, -1, -1, -1, -1, 21, 22, 23, -1, ! -1, 26, 27, 28, 29, -1, 31, 32, 33, 34, ! -1, -1, -1, -1, -1, 40, 41, -1, 43, -1, ! 45, 26, 27, 28, 29, -1, 31, -1, 33, 34, ! -1, -1, -1, -1, -1, 40, 41 }; /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ ! #line 3 "/usr/local/lib/bison.simple" /* Skeleton output parser for bison, --- 398,612 ---- 2, 2, 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 5, 5, 1, 1, 1, ! 1, 1, 1, 1, 6, 6, 7, 7, 10, 10, ! 6, 6, 7, 7, 10, 10, 6, 7, 6, 5, ! 6, 4, 3, 5, 7, 6, 3, 1, 3, 4, ! 6, 5, 1, 2, 4, 4, 5, 5, 2, 3, ! 1, 3, 2, 1, 2, 3, 3, 3, 4, 4, ! 4, 4, 4, 1, 1, 1, 1, 0, 2, 1, ! 2, 2, 4, 4, 3, 3, 1, 1, 2, 2, ! 3, 3, 4, 1, 1, 2 }; static const short yydefact[] = { 0, ! 0, 108, 0, 0, 0, 108, 108, 0, 0, 0, ! 125, 34, 35, 0, 78, 0, 0, 0, 0, 0, ! 0, 0, 0, 2, 4, 0, 0, 108, 108, 36, ! 39, 41, 124, 42, 44, 48, 45, 54, 50, 49, ! 51, 52, 53, 0, 110, 117, 118, 0, 3, 94, ! 0, 0, 108, 108, 108, 0, 0, 108, 0, 119, ! 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, ! 0, 0, 11, 13, 19, 15, 27, 21, 17, 25, ! 23, 29, 31, 32, 7, 8, 0, 0, 0, 34, ! 40, 37, 43, 1, 108, 108, 111, 112, 108, 0, ! 120, 108, 109, 93, 95, 104, 0, 108, 0, 108, ! 0, 108, 108, 0, 0, 79, 122, 108, 12, 14, ! 20, 16, 28, 22, 18, 26, 24, 30, 33, 9, ! 10, 77, 0, 73, 38, 0, 0, 115, 116, 0, ! 121, 0, 108, 108, 108, 108, 108, 108, 0, 108, ! 0, 108, 0, 108, 0, 108, 0, 0, 108, 72, ! 0, 113, 114, 0, 0, 123, 108, 108, 74, 0, ! 0, 0, 97, 98, 96, 0, 83, 108, 0, 108, ! 108, 0, 5, 0, 0, 108, 108, 0, 0, 0, ! 46, 47, 0, 70, 0, 0, 76, 99, 100, 101, ! 102, 103, 69, 89, 84, 0, 67, 91, 0, 0, ! 0, 0, 55, 6, 106, 105, 107, 108, 56, 0, ! 0, 61, 108, 62, 71, 75, 108, 108, 108, 108, ! 90, 68, 0, 0, 108, 57, 58, 0, 63, 64, ! 0, 80, 0, 0, 0, 108, 92, 85, 86, 108, ! 108, 108, 108, 108, 82, 87, 88, 0, 0, 0, ! 0, 81, 59, 60, 65, 66, 0, 0, 0 }; ! static const short yydefgoto[] = { 267, ! 184, 30, 31, 93, 32, 33, 34, 35, 36, 37, ! 38, 39, 40, 41, 42, 43, 170, 176, 177, 178, ! 210, 50, 51, 104, 105, 218, 52, 44, 138, 106, ! 47, 48 }; ! static const short yypact[] = { 246, ! -34,-32768, 11, 20, 24,-32768,-32768, 33, -10, 369, ! 29, 19,-32768, 529,-32768, 42, 47, 30, 36, 64, ! 66, 78, 81,-32768,-32768, 84, 92,-32768,-32768,-32768, ! -32768, 155,-32768, 513,-32768,-32768,-32768,-32768,-32768,-32768, ! -32768,-32768,-32768, 89, -15,-32768, 77, 410,-32768,-32768, ! 130, 287,-32768, 95, 99, 127, 131, 97, 132, 77, ! 492,-32768, 100, 128, 129, 44, 56, 134, 135, 136, ! 139, 140,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, ! -32768,-32768,-32768,-32768,-32768,-32768, 105, 287, 104,-32768, ! -32768,-32768, 513,-32768,-32768,-32768, 328, 328,-32768, 492, ! 77,-32768,-32768,-32768, 88,-32768, 1,-32768, -1,-32768, ! 16,-32768,-32768, 116, -32,-32768, 77,-32768,-32768,-32768, -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, ! -32768,-32768, 88,-32768,-32768, 287, 287, 69, 69, 451, ! 77, 79,-32768,-32768,-32768,-32768,-32768,-32768, 3,-32768, ! 144,-32768, 13,-32768, 144,-32768, 141, 157,-32768,-32768, ! -32,-32768,-32768, 328, 328, 77,-32768,-32768,-32768, 166, ! 287, 287, 287, 287, 287, 169, 147,-32768, -4,-32768, ! -32768, 175,-32768, 52, 146,-32768,-32768, 181, 52, 149, ! -32768,-32768, -32,-32768, 192, 199,-32768,-32768,-32768, 71, ! 71, 71,-32768,-32768, 170, 0,-32768,-32768, 180, -22, ! 191, 161,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 196, ! 163,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, ! -32768,-32768, 28, 189,-32768,-32768,-32768, 17,-32768,-32768, ! 25, 114, 287, 287, 287,-32768,-32768,-32768, 287,-32768, ! -32768,-32768,-32768,-32768,-32768,-32768, 287, 200, 167, 202, ! 171,-32768,-32768,-32768,-32768,-32768, 218, 219,-32768 }; static const short yypgoto[] = {-32768, ! 67, -30, 194,-32768,-32768,-32768,-32768,-32768,-32768,-32768, ! -32768,-32768,-32768, -112,-32768,-32768, -19,-32768, 46,-32768, ! 18, -17, -6,-32768, -60, 39, -21,-32768, 6, 12, ! -8, 220 }; ! #define YYLAST 575 ! static const short yytable[] = { 56, ! 57, 60, 160, 92, 207, 45, 88, 49, 232, 103, ! 87, 46, 150, 95, 96, 28, 180, 59, 151, 208, ! 148, 234, 89, 208, 97, 98, 186, 133, 235, 154, ! 250, 107, 109, 111, 53, 155, 115, 103, 252, 101, ! 103, 103, 103, 54, 103, 209, 152, 55, 194, 209, ! 181, 62, 117, 75, 103, 76, 58, 103, 103, 78, ! 187, 79, 135, 156, 251, 73, 103, 121, 63, 122, ! 74, 234, 253, 136, 137, 214, 77, 140, 246, 124, ! 225, 125, 80, 167, 168, 169, 149, 81, 153, 82, ! 123, 141, 215, 216, 217, 142, 161, 95, 96, 143, ! 144, 83, 126, 139, 84, 157, 158, 85, 46, 46, ! 198, 199, 200, 201, 202, 86, 143, 144, 254, 168, ! 99, 171, 172, 173, 174, 175, 179, 145, 146, 147, ! 94, 166, 88, 102, 88, 108, 188, 193, 190, 110, ! 112, 162, 163, 182, 113, 185, 114, 46, 46, 116, ! 118, 119, 120, 132, 134, 191, 206, 127, 128, 129, ! 195, 196, 130, 131, 88, 88, 159, 183, 220, 221, ! 139, 192, 197, 211, 212, 46, 46, 203, 90, 13, ! 14, 204, 200, 201, 202, 16, 17, 18, 19, 213, ! 20, 21, 22, 23, 219, 222, 238, 224, 226, 26, ! 27, 241, 227, 208, 231, 236, 243, 244, 245, 237, ! 239, 240, 247, 249, 263, 264, 265, 268, 269, 266, ! 242, 189, 255, 205, 257, 91, 233, 223, 248, 61, ! 88, 88, 0, 0, 260, 261, 0, 0, 0, 256, ! 0, 0, 0, 258, 259, 0, 1, 262, 2, 0, ! 0, 0, 0, 3, 0, 4, 5, 6, 7, 0, ! 0, 8, 9, 0, 0, 0, 10, 11, 0, 12, ! 13, 14, 15, 0, 0, 0, 16, 17, 18, 19, ! 0, 20, 21, 22, 23, 0, 0, 24, 25, 2, ! 26, 27, 0, 28, 3, 29, 4, 5, 6, 7, ! 0, 0, 8, 9, 0, 0, 0, 10, 11, 0, ! 12, 13, 14, 15, 0, 0, 0, 16, 17, 18, ! 19, 0, 20, 21, 22, 23, 0, 0, 103, 0, ! 2, 26, 27, 0, 28, 3, 29, 4, 5, 6, ! 7, 0, 0, 8, 9, 0, 0, 0, 10, 11, ! 0, 12, 13, 14, 15, 0, 0, 0, 16, 17, ! 18, 19, 0, 20, 21, 22, 23, 0, 0, 0, ! 0, 2, 26, 27, 0, 28, 3, 29, 4, 5, ! 6, 7, 0, 0, 8, 9, 0, 0, 0, 0, ! 11, 0, 12, 13, 14, 15, 0, 0, 0, 16, ! 17, 18, 19, 0, 20, 21, 22, 23, 0, 0, ! 0, 0, 2, 26, 27, 0, 28, 3, 29, 4, ! 5, 6, 7, 0, 0, 8, 9, 0, 0, 0, ! 100, 0, 0, 12, 13, 14, 15, 0, 0, 0, ! 16, 17, 18, 19, 0, 20, 21, 22, 23, 0, ! 0, 0, 0, 2, 26, 27, 0, 28, 3, 29, ! 4, 5, 6, 7, 0, 0, 8, 9, 0, 0, ! 0, 0, 0, 0, 12, 13, 14, 15, 0, 0, ! 0, 16, 17, 18, 19, 0, 20, 21, 22, 23, ! 0, 0, 103, 0, 2, 26, 27, 0, 28, 3, ! 29, 4, 5, 6, 7, 0, 0, 8, 9, 0, ! 0, 0, 0, 0, 0, 12, 13, 14, 15, 0, ! 0, 0, 16, 17, 18, 19, 0, 20, 21, 22, ! 23, 0, 0, 0, 0, 0, 26, 27, 14, 28, ! 0, 29, 0, 16, 17, 18, 19, 0, 20, 21, ! 22, 23, 0, 0, 0, 0, 0, 26, 27, 64, ! 65, 66, 67, 0, 68, 0, 69, 70, 0, 0, ! 0, 0, 0, 71, 72 }; static const short yycheck[] = { 6, ! 7, 10, 115, 34, 9, 0, 28, 42, 9, 42, ! 28, 0, 14, 29, 30, 48, 14, 28, 20, 24, ! 20, 44, 29, 24, 40, 41, 14, 88, 51, 14, ! 14, 53, 54, 55, 24, 20, 58, 42, 14, 48, ! 42, 42, 42, 24, 42, 50, 48, 24, 161, 50, ! 48, 23, 61, 24, 42, 26, 24, 42, 42, 24, ! 48, 26, 93, 48, 48, 24, 42, 24, 50, 26, ! 24, 44, 48, 95, 96, 24, 47, 99, 51, 24, ! 193, 26, 47, 5, 6, 7, 108, 24, 110, 24, ! 47, 100, 41, 42, 43, 102, 118, 29, 30, 29, ! 30, 24, 47, 98, 24, 112, 113, 24, 97, 98, ! 171, 172, 173, 174, 175, 24, 29, 30, 5, 6, ! 44, 143, 144, 145, 146, 147, 148, 40, 41, 42, ! 42, 140, 154, 4, 156, 41, 154, 159, 156, 41, ! 14, 136, 137, 150, 14, 152, 50, 136, 137, 18, ! 51, 24, 24, 49, 51, 15, 178, 24, 24, 24, ! 167, 168, 24, 24, 186, 187, 51, 24, 186, 187, ! 165, 15, 7, 180, 181, 164, 165, 9, 24, 25, ! 26, 35, 243, 244, 245, 31, 32, 33, 34, 15, ! 36, 37, 38, 39, 49, 15, 218, 49, 7, 45, ! 46, 223, 4, 24, 35, 15, 228, 229, 230, 49, ! 15, 49, 24, 235, 15, 49, 15, 0, 0, 49, ! 227, 155, 242, 178, 246, 32, 209, 189, 235, 10, ! 252, 253, -1, -1, 252, 253, -1, -1, -1, 246, ! -1, -1, -1, 250, 251, -1, 1, 254, 3, -1, ! -1, -1, -1, 8, -1, 10, 11, 12, 13, -1, ! -1, 16, 17, -1, -1, -1, 21, 22, -1, 24, ! 25, 26, 27, -1, -1, -1, 31, 32, 33, 34, ! -1, 36, 37, 38, 39, -1, -1, 42, 43, 3, ! 45, 46, -1, 48, 8, 50, 10, 11, 12, 13, ! -1, -1, 16, 17, -1, -1, -1, 21, 22, -1, ! 24, 25, 26, 27, -1, -1, -1, 31, 32, 33, ! 34, -1, 36, 37, 38, 39, -1, -1, 42, -1, ! 3, 45, 46, -1, 48, 8, 50, 10, 11, 12, ! 13, -1, -1, 16, 17, -1, -1, -1, 21, 22, ! -1, 24, 25, 26, 27, -1, -1, -1, 31, 32, ! 33, 34, -1, 36, 37, 38, 39, -1, -1, -1, ! -1, 3, 45, 46, -1, 48, 8, 50, 10, 11, ! 12, 13, -1, -1, 16, 17, -1, -1, -1, -1, ! 22, -1, 24, 25, 26, 27, -1, -1, -1, 31, ! 32, 33, 34, -1, 36, 37, 38, 39, -1, -1, ! -1, -1, 3, 45, 46, -1, 48, 8, 50, 10, ! 11, 12, 13, -1, -1, 16, 17, -1, -1, -1, ! 21, -1, -1, 24, 25, 26, 27, -1, -1, -1, ! 31, 32, 33, 34, -1, 36, 37, 38, 39, -1, ! -1, -1, -1, 3, 45, 46, -1, 48, 8, 50, ! 10, 11, 12, 13, -1, -1, 16, 17, -1, -1, ! -1, -1, -1, -1, 24, 25, 26, 27, -1, -1, ! -1, 31, 32, 33, 34, -1, 36, 37, 38, 39, ! -1, -1, 42, -1, 3, 45, 46, -1, 48, 8, ! 50, 10, 11, 12, 13, -1, -1, 16, 17, -1, ! -1, -1, -1, -1, -1, 24, 25, 26, 27, -1, ! -1, -1, 31, 32, 33, 34, -1, 36, 37, 38, ! 39, -1, -1, -1, -1, -1, 45, 46, 26, 48, ! -1, 50, -1, 31, 32, 33, 34, -1, 36, 37, ! 38, 39, -1, -1, -1, -1, -1, 45, 46, 31, ! 32, 33, 34, -1, 36, -1, 38, 39, -1, -1, ! -1, -1, -1, 45, 46 }; /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ ! #line 3 "/usr/share/misc/bison.simple" /* Skeleton output parser for bison, *************** *** 767,771 **** #endif ! #line 196 "/usr/local/lib/bison.simple" /* The user can define YYPARSE_PARAM as the name of an argument to be passed --- 801,805 ---- #endif ! #line 196 "/usr/share/misc/bison.simple" /* The user can define YYPARSE_PARAM as the name of an argument to be passed *************** *** 1072,1076 **** case 1: ! #line 215 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { /* Case of regular command. Discard the error --- 1106,1110 ---- case 1: ! #line 233 "/usr/homes/chet/src/bash/src/parse.y" { /* Case of regular command. Discard the error *************** *** 1083,1087 **** break;} case 2: ! #line 224 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { /* Case of regular command, but not a very --- 1117,1121 ---- break;} case 2: ! #line 242 "/usr/homes/chet/src/bash/src/parse.y" { /* Case of regular command, but not a very *************** *** 1092,1096 **** break;} case 3: ! #line 231 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { /* Error during parsing. Return NULL command. */ --- 1126,1130 ---- break;} case 3: ! #line 249 "/usr/homes/chet/src/bash/src/parse.y" { /* Error during parsing. Return NULL command. */ *************** *** 1109,1113 **** break;} case 4: ! #line 246 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { /* Case of EOF seen by itself. Do ignoreeof or --- 1143,1147 ---- break;} case 4: ! #line 264 "/usr/homes/chet/src/bash/src/parse.y" { /* Case of EOF seen by itself. Do ignoreeof or *************** *** 1119,1131 **** break;} case 5: ! #line 256 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); ; break;} case 6: ! #line 258 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-1].word_list); ; break;} case 7: ! #line 262 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1153,1165 ---- break;} case 5: ! #line 274 "/usr/homes/chet/src/bash/src/parse.y" { yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); ; break;} case 6: ! #line 276 "/usr/homes/chet/src/bash/src/parse.y" { yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-1].word_list); ; break;} case 7: ! #line 280 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1134,1138 **** break;} case 8: ! #line 267 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1168,1172 ---- break;} case 8: ! #line 285 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1141,1145 **** break;} case 9: ! #line 272 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1175,1179 ---- break;} case 9: ! #line 290 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1148,1152 **** break;} case 10: ! #line 277 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1182,1186 ---- break;} case 10: ! #line 295 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1155,1159 **** break;} case 11: ! #line 282 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1189,1193 ---- break;} case 11: ! #line 300 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1162,1166 **** break;} case 12: ! #line 287 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1196,1200 ---- break;} case 12: ! #line 305 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1169,1173 **** break;} case 13: ! #line 292 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1203,1207 ---- break;} case 13: ! #line 310 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1177,1181 **** break;} case 14: ! #line 298 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1211,1215 ---- break;} case 14: ! #line 316 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1185,1189 **** break;} case 15: ! #line 304 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.dest = yyvsp[0].number; --- 1219,1223 ---- break;} case 15: ! #line 322 "/usr/homes/chet/src/bash/src/parse.y" { redir.dest = yyvsp[0].number; *************** *** 1192,1196 **** break;} case 16: ! #line 309 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.dest = yyvsp[0].number; --- 1226,1230 ---- break;} case 16: ! #line 327 "/usr/homes/chet/src/bash/src/parse.y" { redir.dest = yyvsp[0].number; *************** *** 1199,1203 **** break;} case 17: ! #line 314 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.dest = yyvsp[0].number; --- 1233,1237 ---- break;} case 17: ! #line 332 "/usr/homes/chet/src/bash/src/parse.y" { redir.dest = yyvsp[0].number; *************** *** 1206,1210 **** break;} case 18: ! #line 319 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.dest = yyvsp[0].number; --- 1240,1244 ---- break;} case 18: ! #line 337 "/usr/homes/chet/src/bash/src/parse.y" { redir.dest = yyvsp[0].number; *************** *** 1213,1217 **** break;} case 19: ! #line 324 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1247,1251 ---- break;} case 19: ! #line 342 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1220,1224 **** break;} case 20: ! #line 329 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1254,1258 ---- break;} case 20: ! #line 347 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1227,1231 **** break;} case 21: ! #line 334 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1261,1265 ---- break;} case 21: ! #line 352 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1234,1238 **** break;} case 22: ! #line 339 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1268,1272 ---- break;} case 22: ! #line 357 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1241,1245 **** break;} case 23: ! #line 344 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1275,1279 ---- break;} case 23: ! #line 362 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1250,1254 **** break;} case 24: ! #line 351 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1284,1288 ---- break;} case 24: ! #line 369 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1259,1263 **** break;} case 25: ! #line 358 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.dest = 0L; --- 1293,1297 ---- break;} case 25: ! #line 376 "/usr/homes/chet/src/bash/src/parse.y" { redir.dest = 0L; *************** *** 1266,1270 **** break;} case 26: ! #line 363 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.dest = 0L; --- 1300,1304 ---- break;} case 26: ! #line 381 "/usr/homes/chet/src/bash/src/parse.y" { redir.dest = 0L; *************** *** 1273,1277 **** break;} case 27: ! #line 368 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.dest = 0L; --- 1307,1311 ---- break;} case 27: ! #line 386 "/usr/homes/chet/src/bash/src/parse.y" { redir.dest = 0L; *************** *** 1280,1284 **** break;} case 28: ! #line 373 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.dest = 0L; --- 1314,1318 ---- break;} case 28: ! #line 391 "/usr/homes/chet/src/bash/src/parse.y" { redir.dest = 0L; *************** *** 1287,1291 **** break;} case 29: ! #line 378 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1321,1325 ---- break;} case 29: ! #line 396 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1294,1298 **** break;} case 30: ! #line 383 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1328,1332 ---- break;} case 30: ! #line 401 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1301,1305 **** break;} case 31: ! #line 388 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1335,1339 ---- break;} case 31: ! #line 406 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1308,1312 **** break;} case 32: ! #line 393 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1342,1346 ---- break;} case 32: ! #line 411 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1315,1319 **** break;} case 33: ! #line 398 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { redir.filename = yyvsp[0].word; --- 1349,1353 ---- break;} case 33: ! #line 416 "/usr/homes/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; *************** *** 1322,1338 **** break;} case 34: ! #line 405 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; ; break;} case 35: ! #line 407 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; ; break;} case 36: ! #line 409 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.element.redirect = yyvsp[0].redirect; yyval.element.word = 0; ; break;} case 37: ! #line 413 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.redirect = yyvsp[0].redirect; --- 1356,1372 ---- break;} case 34: ! #line 423 "/usr/homes/chet/src/bash/src/parse.y" { yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; ; break;} case 35: ! #line 425 "/usr/homes/chet/src/bash/src/parse.y" { yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; ; break;} case 36: ! #line 427 "/usr/homes/chet/src/bash/src/parse.y" { yyval.element.redirect = yyvsp[0].redirect; yyval.element.word = 0; ; break;} case 37: ! #line 431 "/usr/homes/chet/src/bash/src/parse.y" { yyval.redirect = yyvsp[0].redirect; *************** *** 1340,1344 **** break;} case 38: ! #line 417 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { register REDIRECT *t; --- 1374,1378 ---- break;} case 38: ! #line 435 "/usr/homes/chet/src/bash/src/parse.y" { register REDIRECT *t; *************** *** 1351,1371 **** break;} case 39: ! #line 428 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_simple_command (yyvsp[0].element, (COMMAND *)NULL); ; break;} case 40: ! #line 430 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_simple_command (yyvsp[0].element, yyvsp[-1].command); ; break;} case 41: ! #line 434 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = clean_simple_command (yyvsp[0].command); ; break;} case 42: ! #line 436 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 43: ! #line 438 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { COMMAND *tc; --- 1385,1405 ---- break;} case 39: ! #line 446 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_simple_command (yyvsp[0].element, (COMMAND *)NULL); ; break;} case 40: ! #line 448 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_simple_command (yyvsp[0].element, yyvsp[-1].command); ; break;} case 41: ! #line 452 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = clean_simple_command (yyvsp[0].command); ; break;} case 42: ! #line 454 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 43: ! #line 456 "/usr/homes/chet/src/bash/src/parse.y" { COMMAND *tc; *************** *** 1396,1584 **** break;} case 44: ! #line 467 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 45: ! #line 469 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 46: ! #line 471 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_while_command (yyvsp[-3].command, yyvsp[-1].command); ; break;} case 47: ! #line 473 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_until_command (yyvsp[-3].command, yyvsp[-1].command); ; break;} case 48: ! #line 475 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 49: ! #line 477 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 50: ! #line 479 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 51: ! #line 481 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 52: ! #line 483 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 53: ! #line 487 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" ! { yyval.command = make_for_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} case 54: ! #line 489 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" ! { yyval.command = make_for_command (yyvsp[-4].word, add_string_to_list ("$@", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} case 55: ! #line 491 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" ! { yyval.command = make_for_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} case 56: ! #line 493 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" ! { yyval.command = make_for_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} case 57: ! #line 495 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" ! { yyval.command = make_for_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command); ; break;} case 58: ! #line 497 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" ! { yyval.command = make_for_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command); ; break;} case 59: ! #line 501 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_select_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} ! case 60: ! #line 505 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_select_command (yyvsp[-4].word, add_string_to_list ("$@", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} ! case 61: ! #line 509 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_select_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} ! case 62: ! #line 513 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_select_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} ! case 63: ! #line 517 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_select_command (yyvsp[-8].word, (WORD_LIST *)reverse_list (yyvsp[-5].word_list), yyvsp[-1].command); ; break;} ! case 64: ! #line 521 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_select_command (yyvsp[-8].word, (WORD_LIST *)reverse_list (yyvsp[-5].word_list), yyvsp[-1].command); ; break;} ! case 65: ! #line 527 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_case_command (yyvsp[-4].word, (PATTERN_LIST *)NULL); ; break;} ! case 66: ! #line 529 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_case_command (yyvsp[-5].word, yyvsp[-2].pattern); ; break;} ! case 67: ! #line 531 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_case_command (yyvsp[-4].word, yyvsp[-1].pattern); ; break;} ! case 68: ! #line 535 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command, function_dstart, function_bstart); ; break;} ! case 69: ! #line 539 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command, function_dstart, function_bstart); ; break;} ! case 70: ! #line 542 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_function_def (yyvsp[-2].word, yyvsp[0].command, function_dstart, function_bstart); ; break;} ! case 71: ! #line 546 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyvsp[-1].command->flags |= CMD_WANT_SUBSHELL; yyval.command = yyvsp[-1].command; ; break;} ! case 72: ! #line 550 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, (COMMAND *)NULL); ; break;} ! case 73: ! #line 552 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_if_command (yyvsp[-5].command, yyvsp[-3].command, yyvsp[-1].command); ; break;} ! case 74: ! #line 554 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[-1].command); ; break;} ! case 75: ! #line 559 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_group_command (yyvsp[-1].command); ; break;} ! case 76: ! #line 563 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_if_command (yyvsp[-2].command, yyvsp[0].command, (COMMAND *)NULL); ; break;} ! case 77: ! #line 565 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[0].command); ; break;} ! case 78: ! #line 567 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, yyvsp[0].command); ; break;} ! case 80: ! #line 572 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyvsp[0].pattern->next = yyvsp[-1].pattern; yyval.pattern = yyvsp[0].pattern; ; break;} ! case 81: ! #line 576 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); ; break;} ! case 82: ! #line 578 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); ; break;} ! case 83: ! #line 580 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); ; break;} ! case 84: ! #line 582 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); ; break;} ! case 86: ! #line 587 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyvsp[-1].pattern->next = yyvsp[-2].pattern; yyval.pattern = yyvsp[-1].pattern; ; break;} ! case 87: ! #line 591 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); ; break;} ! case 88: ! #line 593 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-2].word_list); ; break;} ! case 89: ! #line 602 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; --- 1430,1634 ---- break;} case 44: ! #line 485 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 45: ! #line 487 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 46: ! #line 489 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_while_command (yyvsp[-3].command, yyvsp[-1].command); ; break;} case 47: ! #line 491 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_until_command (yyvsp[-3].command, yyvsp[-1].command); ; break;} case 48: ! #line 493 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 49: ! #line 495 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 50: ! #line 497 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 51: ! #line 499 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 52: ! #line 501 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} case 53: ! #line 503 "/usr/homes/chet/src/bash/src/parse.y" ! { yyval.command = yyvsp[0].command; ; break;} case 54: ! #line 505 "/usr/homes/chet/src/bash/src/parse.y" ! { yyval.command = yyvsp[0].command; ; break;} case 55: ! #line 509 "/usr/homes/chet/src/bash/src/parse.y" ! { yyval.command = make_for_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} case 56: ! #line 511 "/usr/homes/chet/src/bash/src/parse.y" ! { yyval.command = make_for_command (yyvsp[-4].word, add_string_to_list ("$@", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} case 57: ! #line 513 "/usr/homes/chet/src/bash/src/parse.y" ! { yyval.command = make_for_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} case 58: ! #line 515 "/usr/homes/chet/src/bash/src/parse.y" ! { yyval.command = make_for_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} case 59: ! #line 517 "/usr/homes/chet/src/bash/src/parse.y" ! { yyval.command = make_for_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command); ; ! break;} ! case 60: ! #line 519 "/usr/homes/chet/src/bash/src/parse.y" ! { yyval.command = make_for_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command); ; ! break;} ! case 61: ! #line 523 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_select_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} ! case 62: ! #line 527 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_select_command (yyvsp[-4].word, add_string_to_list ("$@", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} ! case 63: ! #line 531 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_select_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} ! case 64: ! #line 535 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_select_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ; break;} ! case 65: ! #line 539 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_select_command (yyvsp[-8].word, (WORD_LIST *)reverse_list (yyvsp[-5].word_list), yyvsp[-1].command); ; break;} ! case 66: ! #line 543 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_select_command (yyvsp[-8].word, (WORD_LIST *)reverse_list (yyvsp[-5].word_list), yyvsp[-1].command); ; break;} ! case 67: ! #line 549 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_case_command (yyvsp[-4].word, (PATTERN_LIST *)NULL); ; break;} ! case 68: ! #line 551 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_case_command (yyvsp[-5].word, yyvsp[-2].pattern); ; break;} ! case 69: ! #line 553 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_case_command (yyvsp[-4].word, yyvsp[-1].pattern); ; break;} ! case 70: ! #line 557 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command, function_dstart, function_bstart); ; break;} ! case 71: ! #line 561 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command, function_dstart, function_bstart); ; break;} ! case 72: ! #line 564 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_function_def (yyvsp[-2].word, yyvsp[0].command, function_dstart, function_bstart); ; break;} ! case 73: ! #line 568 "/usr/homes/chet/src/bash/src/parse.y" { yyvsp[-1].command->flags |= CMD_WANT_SUBSHELL; yyval.command = yyvsp[-1].command; ; break;} ! case 74: ! #line 572 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, (COMMAND *)NULL); ; break;} ! case 75: ! #line 574 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_if_command (yyvsp[-5].command, yyvsp[-3].command, yyvsp[-1].command); ; break;} ! case 76: ! #line 576 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[-1].command); ; break;} ! case 77: ! #line 581 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_group_command (yyvsp[-1].command); ; break;} ! case 78: ! #line 585 "/usr/homes/chet/src/bash/src/parse.y" ! { yyval.command = make_arith_command (yyvsp[0].word_list); ; ! break;} ! case 79: ! #line 589 "/usr/homes/chet/src/bash/src/parse.y" ! { yyval.command = yyvsp[-1].command; ; ! break;} ! case 80: ! #line 593 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_if_command (yyvsp[-2].command, yyvsp[0].command, (COMMAND *)NULL); ; break;} ! case 81: ! #line 595 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[0].command); ; break;} ! case 82: ! #line 597 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, yyvsp[0].command); ; break;} ! case 84: ! #line 602 "/usr/homes/chet/src/bash/src/parse.y" { yyvsp[0].pattern->next = yyvsp[-1].pattern; yyval.pattern = yyvsp[0].pattern; ; break;} ! case 85: ! #line 606 "/usr/homes/chet/src/bash/src/parse.y" { yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); ; break;} ! case 86: ! #line 608 "/usr/homes/chet/src/bash/src/parse.y" { yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); ; break;} ! case 87: ! #line 610 "/usr/homes/chet/src/bash/src/parse.y" { yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); ; break;} ! case 88: ! #line 612 "/usr/homes/chet/src/bash/src/parse.y" { yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); ; break;} ! case 90: ! #line 617 "/usr/homes/chet/src/bash/src/parse.y" { yyvsp[-1].pattern->next = yyvsp[-2].pattern; yyval.pattern = yyvsp[-1].pattern; ; break;} ! case 91: ! #line 621 "/usr/homes/chet/src/bash/src/parse.y" { yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); ; break;} ! case 92: ! #line 623 "/usr/homes/chet/src/bash/src/parse.y" { yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-2].word_list); ; break;} ! case 93: ! #line 632 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; *************** *** 1587,1598 **** ; break;} ! case 91: ! #line 611 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} ! case 93: ! #line 618 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { if (yyvsp[-2].command->type == cm_connection) --- 1637,1648 ---- ; break;} ! case 95: ! #line 641 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} ! case 97: ! #line 648 "/usr/homes/chet/src/bash/src/parse.y" { if (yyvsp[-2].command->type == cm_connection) *************** *** 1602,1615 **** ; break;} ! case 95: ! #line 629 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); ; break;} ! case 96: ! #line 631 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); ; break;} ! case 97: ! #line 633 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { if (yyvsp[-3].command->type == cm_connection) --- 1652,1665 ---- ; break;} ! case 99: ! #line 659 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); ; break;} ! case 100: ! #line 661 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); ; break;} ! case 101: ! #line 663 "/usr/homes/chet/src/bash/src/parse.y" { if (yyvsp[-3].command->type == cm_connection) *************** *** 1619,1636 **** ; break;} ! case 98: ! #line 640 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); ; break;} ! case 99: ! #line 642 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); ; break;} ! case 100: ! #line 644 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} ! case 106: ! #line 663 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; --- 1669,1686 ---- ; break;} ! case 102: ! #line 670 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); ; break;} ! case 103: ! #line 672 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); ; break;} ! case 104: ! #line 674 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} ! case 110: ! #line 693 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; *************** *** 1639,1644 **** ; break;} ! case 107: ! #line 669 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { if (yyvsp[-1].command->type == cm_connection) --- 1689,1694 ---- ; break;} ! case 111: ! #line 699 "/usr/homes/chet/src/bash/src/parse.y" { if (yyvsp[-1].command->type == cm_connection) *************** *** 1650,1655 **** ; break;} ! case 108: ! #line 678 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[-1].command; --- 1700,1705 ---- ; break;} ! case 112: ! #line 708 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[-1].command; *************** *** 1658,1671 **** ; break;} ! case 109: ! #line 686 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); ; break;} ! case 110: ! #line 688 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); ; break;} ! case 111: ! #line 690 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { if (yyvsp[-2].command->type == cm_connection) --- 1708,1721 ---- ; break;} ! case 113: ! #line 716 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); ; break;} ! case 114: ! #line 718 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); ; break;} ! case 115: ! #line 720 "/usr/homes/chet/src/bash/src/parse.y" { if (yyvsp[-2].command->type == cm_connection) *************** *** 1675,1692 **** ; break;} ! case 112: ! #line 697 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = command_connect (yyvsp[-2].command, yyvsp[0].command, ';'); ; break;} ! case 113: ! #line 700 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} ! case 114: ! #line 704 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} ! case 115: ! #line 706 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyvsp[0].command->flags |= CMD_INVERT_RETURN; --- 1725,1742 ---- ; break;} ! case 116: ! #line 727 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = command_connect (yyvsp[-2].command, yyvsp[0].command, ';'); ; break;} ! case 117: ! #line 730 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} ! case 118: ! #line 734 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} ! case 119: ! #line 736 "/usr/homes/chet/src/bash/src/parse.y" { yyvsp[0].command->flags |= CMD_INVERT_RETURN; *************** *** 1694,1699 **** ; break;} ! case 116: ! #line 711 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyvsp[0].command->flags |= yyvsp[-1].number; --- 1744,1749 ---- ; break;} ! case 120: ! #line 741 "/usr/homes/chet/src/bash/src/parse.y" { yyvsp[0].command->flags |= yyvsp[-1].number; *************** *** 1701,1706 **** ; break;} ! case 117: ! #line 716 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyvsp[0].command->flags |= yyvsp[-2].number; --- 1751,1756 ---- ; break;} ! case 121: ! #line 746 "/usr/homes/chet/src/bash/src/parse.y" { yyvsp[0].command->flags |= yyvsp[-2].number; *************** *** 1708,1713 **** ; break;} ! case 118: ! #line 721 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyvsp[0].command->flags |= yyvsp[-1].number|CMD_INVERT_RETURN; --- 1758,1763 ---- ; break;} ! case 122: ! #line 751 "/usr/homes/chet/src/bash/src/parse.y" { yyvsp[0].command->flags |= yyvsp[-1].number|CMD_INVERT_RETURN; *************** *** 1715,1737 **** ; break;} ! case 119: ! #line 729 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, '|'); ; break;} ! case 120: ! #line 731 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.command = yyvsp[0].command; ; break;} ! case 121: ! #line 735 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.number = CMD_TIME_PIPELINE; ; break;} ! case 122: ! #line 737 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" { yyval.number = CMD_TIME_PIPELINE|CMD_TIME_POSIX; ; break;} } /* the action file gets copied in in place of this dollarsign */ ! #line 498 "/usr/local/lib/bison.simple" yyvsp -= yylen; --- 1765,1787 ---- ; break;} ! case 123: ! #line 759 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, '|'); ; break;} ! case 124: ! #line 761 "/usr/homes/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; ; break;} ! case 125: ! #line 765 "/usr/homes/chet/src/bash/src/parse.y" { yyval.number = CMD_TIME_PIPELINE; ; break;} ! case 126: ! #line 767 "/usr/homes/chet/src/bash/src/parse.y" { yyval.number = CMD_TIME_PIPELINE|CMD_TIME_POSIX; ; break;} } /* the action file gets copied in in place of this dollarsign */ ! #line 498 "/usr/share/misc/bison.simple" yyvsp -= yylen; *************** *** 1929,1933 **** goto yynewstate; } ! #line 739 "/usr/homes/chet/src/bash/bash-2.01.1/parse.y" --- 1979,1983 ---- goto yynewstate; } ! #line 769 "/usr/homes/chet/src/bash/src/parse.y" *************** *** 1941,1944 **** --- 1991,1996 ---- #define PST_CMDSUBST 0x040 /* $( ... ) command substitution */ #define PST_CASESTMT 0x080 /* parsing a case statement */ + #define PST_CONDCMD 0x100 /* parsing a [[...]] command */ + #define PST_CONDEXPR 0x200 /* parsing the guts of [[...]] */ /* Initial size to allocate for tokens, and the *************** *** 2278,2281 **** --- 2330,2338 ---- int line_number = 0; + #if defined (COND_COMMAND) + static int cond_lineno; + static int cond_token; + #endif + STREAM_SAVER *stream_list = (STREAM_SAVER *)NULL; *************** *** 2292,2299 **** /* If we have a buffered stream, clear out buffers[fd]. */ if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0) ! { ! saver->bstream = buffers[bash_input.location.buffered_fd]; ! buffers[bash_input.location.buffered_fd] = (BUFFERED_STREAM *)NULL; ! } #endif /* BUFFERED_INPUT */ --- 2349,2354 ---- /* If we have a buffered stream, clear out buffers[fd]. */ if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0) ! saver->bstream = set_buffered_stream (bash_input.location.buffered_fd, ! (BUFFERED_STREAM *)NULL); #endif /* BUFFERED_INPUT */ *************** *** 2341,2345 **** } } ! buffers[bash_input.location.buffered_fd] = saver->bstream; } #endif /* BUFFERED_INPUT */ --- 2396,2400 ---- } } ! set_buffered_stream (bash_input.location.buffered_fd, saver->bstream); } #endif /* BUFFERED_INPUT */ *************** *** 2374,2378 **** */ ! #if defined (ALIAS) #define END_OF_ALIAS 0 --- 2429,2437 ---- */ ! #if defined (ALIAS) || defined (DPAREN_ARITHMETIC) ! ! #if !defined (ALIAS) ! typedef void *alias_t; ! #endif #define END_OF_ALIAS 0 *************** *** 2391,2395 **** --- 2450,2456 ---- int expand_alias; /* Value to set expand_alias to when string is popped. */ char *saved_line; + #if defined (ALIAS) alias_t *expander; /* alias that caused this line to be pushed. */ + #endif int saved_line_size, saved_line_index, saved_line_terminator; } STRING_SAVER; *************** *** 2418,2427 **** --- 2479,2492 ---- temp->saved_line_index = shell_input_line_index; temp->saved_line_terminator = shell_input_line_terminator; + #if defined (ALIAS) temp->expander = ap; + #endif temp->next = pushed_string_list; pushed_string_list = temp; + #if defined (ALIAS) if (ap) ap->flags |= AL_BEINGEXPANDED; + #endif shell_input_line = s; *************** *** 2457,2462 **** --- 2522,2529 ---- pushed_string_list = pushed_string_list->next; + #if defined (ALIAS) if (t->expander) t->expander->flags &= ~AL_BEINGEXPANDED; + #endif free ((char *)t); *************** *** 2472,2476 **** t1 = t->next; FREE (t->saved_line); ! t->expander->flags &= ~AL_BEINGEXPANDED; free ((char *)t); t = t1; --- 2539,2546 ---- t1 = t->next; FREE (t->saved_line); ! #if defined (ALIAS) ! if (t->expander) ! t->expander->flags &= ~AL_BEINGEXPANDED; ! #endif free ((char *)t); t = t1; *************** *** 2479,2483 **** } ! #endif /* ALIAS */ /* Return a line of text, taken from wherever yylex () reads input. --- 2549,2553 ---- } ! #endif /* ALIAS || DPAREN_ARITHMETIC */ /* Return a line of text, taken from wherever yylex () reads input. *************** *** 2604,2607 **** --- 2674,2681 ---- { "}", '}' }, { "!", BANG }, + #if defined (COND_COMMAND) + { "[[", COND_START }, + { "]]", COND_END }, + #endif { (char *)NULL, 0} }; *************** *** 2651,2655 **** QUIT; ! #if defined (ALIAS) /* If shell_input_line[shell_input_line_index] == 0, but there is something on the pushed list of strings, then we don't want to go --- 2725,2729 ---- QUIT; ! #if defined (ALIAS) || defined (DPAREN_ARITHMETIC) /* If shell_input_line[shell_input_line_index] == 0, but there is something on the pushed list of strings, then we don't want to go *************** *** 2658,2664 **** if (!shell_input_line || ((!shell_input_line[shell_input_line_index]) && (pushed_string_list == (STRING_SAVER *)NULL))) ! #else /* !ALIAS */ if (!shell_input_line || !shell_input_line[shell_input_line_index]) ! #endif /* !ALIAS */ { line_number++; --- 2732,2738 ---- if (!shell_input_line || ((!shell_input_line[shell_input_line_index]) && (pushed_string_list == (STRING_SAVER *)NULL))) ! #else /* !ALIAS && !DPAREN_ARITHMETIC */ if (!shell_input_line || !shell_input_line[shell_input_line_index]) ! #endif /* !ALIAS && !DPAREN_ARITHMETIC */ { line_number++; *************** *** 2811,2815 **** } ! #if defined (ALIAS) /* If C is NULL, we have reached the end of the current input string. If pushed_string_list is non-empty, it's time to pop to the previous string --- 2885,2889 ---- } ! #if defined (ALIAS) || defined (DPAREN_ARITHMETIC) /* If C is NULL, we have reached the end of the current input string. If pushed_string_list is non-empty, it's time to pop to the previous string *************** *** 2833,2837 **** } } ! #endif /* ALIAS */ if (!c && shell_input_line_terminator == EOF) --- 2907,2911 ---- } } ! #endif /* ALIAS || DPAREN_ARITHMETIC */ if (!c && shell_input_line_terminator == EOF) *************** *** 2984,2991 **** --- 3058,3071 ---- if ((parser_state & PST_CASEPAT) && (word_token_alist[i].token != ESAC)) \ break; \ + if (word_token_alist[i].token == TIME) \ + break; \ if (word_token_alist[i].token == ESAC) \ parser_state &= ~(PST_CASEPAT|PST_CASESTMT); \ else if (word_token_alist[i].token == CASE) \ parser_state |= PST_CASESTMT; \ + else if (word_token_alist[i].token == COND_END) \ + parser_state &= ~(PST_CONDCMD|PST_CONDEXPR); \ + else if (word_token_alist[i].token == COND_START) \ + parser_state |= PST_CONDCMD; \ else if (word_token_alist[i].token == '{') \ open_brace_count++; \ *************** *** 3041,3044 **** --- 3121,3145 ---- #endif /* ALIAS */ + static int + time_command_acceptable () + { + #if defined (COMMAND_TIMING) + switch (last_read_token) + { + case 0: + case ';': + case '\n': + case AND_AND: + case OR_OR: + case '&': + return 1; + default: + return 0; + } + #else + return 0; + #endif /* COMMAND_TIMING */ + } + /* Handle special cases of token recognition: IN is recognized if the last token was WORD and the token *************** *** 3055,3058 **** --- 3156,3167 ---- `}' is recognized if there is an unclosed `{' prsent. + + `-p' is returned as TIMEOPT if the last read token was TIME. + + ']]' is returned as COND_END if the parser is currently parsing + a conditional expression ((parser_state & PST_CONDEXPR) != 0) + + `time' is returned as TIME if and only if it is immediately + preceded by one of `;', `\n', `||', `&&', or `&'. */ *************** *** 3120,3126 **** --- 3229,3247 ---- } + #if defined (COMMAND_TIMING) /* Handle -p after `time'. */ if (last_read_token == TIME && token[0] == '-' && token[1] == 'p' && !token[2]) return (TIMEOPT); + #endif + + #if defined (COMMAND_TIMING) + if (STREQ (token, "time") && time_command_acceptable ()) + return (TIME); + #endif /* COMMAND_TIMING */ + + #if defined (COND_COMMAND) /* [[ */ + if ((parser_state & PST_CONDEXPR) && token[0] == ']' && token[1] == ']' && token[2] == '\0') + return (COND_END); + #endif return (-1); *************** *** 3137,3147 **** parser_state = 0; ! #if defined (ALIAS) if (pushed_string_list) ! { ! free_string_list (); ! pushed_string_list = (STRING_SAVER *)NULL; ! } ! #endif /* ALIAS */ if (shell_input_line) --- 3258,3265 ---- parser_state = 0; ! #if defined (ALIAS) || defined (DPAREN_ARITHMETIC) if (pushed_string_list) ! free_string_list (); ! #endif /* ALIAS || DPAREN_ARITHMETIC */ if (shell_input_line) *************** *** 3187,3190 **** --- 3305,3328 ---- } + #if defined (COND_COMMAND) + if ((parser_state & (PST_CONDCMD|PST_CONDEXPR)) == PST_CONDCMD) + { + cond_lineno = line_number; + parser_state |= PST_CONDEXPR; + yylval.command = parse_cond_command (); + if (cond_token != COND_END) + { + if (EOF_Reached && cond_token != COND_ERROR) /* [[ */ + parser_error (cond_lineno, "unexpected EOF while looking for `]]'"); + else if (cond_token != COND_ERROR) + parser_error (cond_lineno, "syntax error in conditional expression"); + return (-1); + } + token_to_read = COND_END; + parser_state &= ~(PST_CONDEXPR|PST_CONDCMD); + return (COND_CMD); + } + #endif + #if defined (ALIAS) /* This is a place to jump back to once we have successfully expanded a *************** *** 3274,3277 **** --- 3412,3416 ---- int cmdtyp, sline; char *wval; + WORD_DESC *wd; sline = line_number; *************** *** 3279,3288 **** if (cmdtyp == 1) /* arithmetic command */ { ! word_desc_to_read = make_word (wval); ! word_desc_to_read->flags = W_QUOTED; ! token_to_read = WORD; ! free (wval); ! yylval.word = make_word ("let"); ! return (WORD); } else if (cmdtyp == 0) /* nested subshell */ --- 3418,3426 ---- if (cmdtyp == 1) /* arithmetic command */ { ! wd = make_word (wval); ! wd->flags = W_QUOTED; ! yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL); ! free (wval); /* make_word copies it */ ! return (ARITH_CMD); } else if (cmdtyp == 0) /* nested subshell */ *************** *** 3556,3559 **** --- 3694,3866 ---- #endif /* DPAREN_ARITHMETIC */ + #if defined (COND_COMMAND) + static COND_COM *cond_term (); + static COND_COM *cond_and (); + static COND_COM *cond_or (); + static COND_COM *cond_expr (); + + static COND_COM * + cond_expr () + { + return (cond_or ()); + } + + static COND_COM * + cond_or () + { + COND_COM *l, *r; + + l = cond_and (); + if (cond_token == OR_OR) + { + r = cond_or (); + l = make_cond_node (COND_OR, (WORD_DESC *)NULL, l, r); + } + return l; + } + + static COND_COM * + cond_and () + { + COND_COM *l, *r; + + l = cond_term (); + if (cond_token == AND_AND) + { + r = cond_and (); + l = make_cond_node (COND_AND, (WORD_DESC *)NULL, l, r); + } + return l; + } + + static int + cond_skip_newlines () + { + while ((cond_token = read_token (READ)) == '\n') + { + if (interactive && (bash_input.type == st_stdin || bash_input.type == st_stream)) + prompt_again (); + } + return (cond_token); + } + + #define COND_RETURN_ERROR() \ + do { cond_token = COND_ERROR; return ((COND_COM *)NULL); } while (0) + + static COND_COM * + cond_term () + { + WORD_DESC *op; + COND_COM *term, *tleft, *tright; + int tok, lineno; + + /* Read a token. It can be a left paren, a `!', a unary operator, or a + word that should be the first argument of a binary operator. Start by + skipping newlines, since this is a compound command. */ + tok = cond_skip_newlines (); + lineno = line_number; + if (tok == COND_END) + { + COND_RETURN_ERROR (); + } + else if (tok == '(') + { + term = cond_expr (); + if (cond_token != ')') + { + if (term) + dispose_cond_node (term); /* ( */ + parser_error (lineno, "expected `)'"); + COND_RETURN_ERROR (); + } + term = make_cond_node (COND_EXPR, (WORD_DESC *)NULL, term, (COND_COM *)NULL); + (void)cond_skip_newlines (); + } + else if (tok == BANG || (tok == WORD && (yylval.word->word[0] == '!' && yylval.word->word[1] == '\0'))) + { + if (tok == WORD) + dispose_word (yylval.word); /* not needed */ + term = cond_term (); + if (term) + term->flags |= CMD_INVERT_RETURN; + } + else if (tok == WORD && test_unop (yylval.word->word)) + { + op = yylval.word; + tok = read_token (READ); + if (tok == WORD) + { + tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL); + term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL); + } + else + { + dispose_word (op); + parser_error (line_number, "unexpected argument to conditional unary operator"); + COND_RETURN_ERROR (); + } + + (void)cond_skip_newlines (); + } + else /* left argument to binary operator */ + { + /* lhs */ + tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL); + + /* binop */ + tok = read_token (READ); + if (tok == WORD && test_binop (yylval.word->word)) + op = yylval.word; + else if (tok == '<' || tok == '>') + op = make_word_from_token (tok); + else if (tok == COND_END || tok == AND_AND || tok == OR_OR) + { + /* Special case. [[ x ]] is equivalent to [[ -n x ]], just like + the test command. Similarly for [[ x && expr ]] or + [[ x || expr ]] */ + op = make_word ("-n"); + term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL); + cond_token = tok; + return (term); + } + else + { + parser_error (line_number, "conditional binary operator expected"); + dispose_cond_node (tleft); + COND_RETURN_ERROR (); + } + + /* rhs */ + tok = read_token (READ); + if (tok == WORD) + { + tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL); + term = make_cond_node (COND_BINARY, op, tleft, tright); + } + else + { + parser_error (line_number, "unexpected argument to conditional binary operator"); + dispose_cond_node (tleft); + dispose_word (op); + COND_RETURN_ERROR (); + } + + (void)cond_skip_newlines (); + } + return (term); + } + + /* This is kind of bogus -- we slip a mini recursive-descent parser in + here to handle the conditional statement syntax. */ + static COMMAND * + parse_cond_command () + { + COND_COM *cexp; + + cexp = cond_expr (); + return (make_cond_command (cexp)); + } + #endif + static int read_token_word (character) *************** *** 3652,3655 **** --- 3959,3990 ---- } + #ifdef EXTENDED_GLOB + /* Parse a ksh-style extended pattern matching specification. */ + if (extended_glob && PATTERN_CHAR(character)) + { + peek_char = shell_getc (1); + if (peek_char == '(') /* ) */ + { + push_delimiter (dstack, peek_char); + ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0); + pop_delimiter (dstack); + if (ttok == &matched_pair_error) + return -1; /* Bail immediately. */ + RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2, + token_buffer_size, + TOKEN_DEFAULT_GROW_SIZE); + token[token_index++] = character; + token[token_index++] = peek_char; + strcpy (token + token_index, ttok); + token_index += ttoklen; + FREE (ttok); + dollar_present = all_digits = 0; + goto next_character; + } + else + shell_ungetc (peek_char); + } + #endif /* EXTENDED_GLOB */ + /* If the delimiter character is not single quote, parse some of the shell expansions that must be read as a single word. */ *************** *** 3697,3700 **** --- 4032,4038 ---- else if (character == '$' && (peek_char == '\'' || peek_char == '"')) { + int first_line; + + first_line = line_number; ttok = parse_matched_pair (peek_char, peek_char, peek_char, &ttoklen, 0); if (ttok == &matched_pair_error) *************** *** 3703,3707 **** ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen); else ! ttrans = localeexpand (ttok, 0, ttoklen - 1, &ttranslen); free (ttok); RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 2, --- 4041,4045 ---- ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen); else ! ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen); free (ttok); RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 2, *************** *** 3895,3901 **** if non-null. */ static char * ! localeexpand (string, start, end, lenp) char *string; ! int start, end, *lenp; { int len, tlen; --- 4233,4239 ---- if non-null. */ static char * ! localeexpand (string, start, end, lineno, lenp) char *string; ! int start, end, lineno, *lenp; { int len, tlen; *************** *** 3910,3914 **** if (dump_translatable_strings) { ! printf ("\"%s\"\n", temp); if (lenp) *lenp = tlen; --- 4248,4256 ---- if (dump_translatable_strings) { ! if (dump_po_strings) ! printf ("#: %s:%d\nmsgid \"%s\"\nmsgstr \"\"\n", ! (bash_input.name ? bash_input.name : "stdin"), lineno, temp); ! else ! printf ("\"%s\"\n", temp); if (lenp) *lenp = tlen; *************** *** 4043,4046 **** --- 4385,4390 ---- return "; "; /* (...) subshell */ } + else if (token_before_that == WORD && two_tokens_ago == FUNCTION) + return " "; /* function def using `function name' without `()' */ for (i = 0; no_semi_successors[i]; i++) *************** *** 4243,4246 **** --- 4587,4596 ---- temp[5] = 'p'; } + goto add_string; + + case 'r': + temp = xmalloc (2); + temp[0] = '\r'; + temp[1] = '\0'; goto add_string; diff -Nrc2 bash-2.01.1/y.tab.h bash-2.02/y.tab.h *** bash-2.01.1/y.tab.h Thu Sep 4 10:59:28 1997 --- bash-2.02/y.tab.h Wed Mar 25 12:16:44 1998 *************** *** 22,44 **** #define DONE 270 #define FUNCTION 271 ! #define IN 272 ! #define BANG 273 ! #define TIME 274 ! #define TIMEOPT 275 ! #define WORD 276 ! #define ASSIGNMENT_WORD 277 ! #define NUMBER 278 ! #define AND_AND 279 ! #define OR_OR 280 ! #define GREATER_GREATER 281 ! #define LESS_LESS 282 ! #define LESS_AND 283 ! #define GREATER_AND 284 ! #define SEMI_SEMI 285 ! #define LESS_LESS_MINUS 286 ! #define AND_GREATER 287 ! #define LESS_GREATER 288 ! #define GREATER_BAR 289 ! #define yacc_EOF 290 --- 22,49 ---- #define DONE 270 #define FUNCTION 271 ! #define COND_START 272 ! #define COND_END 273 ! #define COND_ERROR 274 ! #define IN 275 ! #define BANG 276 ! #define TIME 277 ! #define TIMEOPT 278 ! #define WORD 279 ! #define ASSIGNMENT_WORD 280 ! #define NUMBER 281 ! #define ARITH_CMD 282 ! #define COND_CMD 283 ! #define AND_AND 284 ! #define OR_OR 285 ! #define GREATER_GREATER 286 ! #define LESS_LESS 287 ! #define LESS_AND 288 ! #define GREATER_AND 289 ! #define SEMI_SEMI 290 ! #define LESS_LESS_MINUS 291 ! #define AND_GREATER 292 ! #define LESS_GREATER 293 ! #define GREATER_BAR 294 ! #define yacc_EOF 295